盲注类型的SQL注入和普通回显注入不同,它不会把数据库数据直接打印到页面上,而是利用服务端的逻辑分支或响应时间差异来逐个推断字符。很多系统在开发时把底层异常堆栈、SQL错误码直接返回给前端,攻击者只要构造真假条件,对比返回内容长度或文本就能确认注入点。通过统一返回错误页面隐藏差异,是运维和开发常采取的第一道止损线。

盲注为什么依赖错误差异
在布尔盲注场景中,后端代码通常类似下面这段伪代码:当查询结果为空或SQL执行报错时,页面可能返回“系统异常”或空白,而正常查询返回“欢迎”。这种二元差异就是攻击者的判断信号。
<?php
$id = $_GET['id'];
$sql = "SELECT name FROM users WHERE id = $id";
$result = mysqli_query($conn, $sql);
if (!$result) {
echo "系统异常"; // 报错时暴露差异
exit;
}
$row = mysqli_fetch_assoc($result);
if ($row) {
echo "欢迎";
} else {
echo "无数据";
}
?>
攻击者发送 id=1 AND 1=1 与 id=1 AND 1=2,如果前者输出“欢迎”后者输出“系统异常”,就说明注入成立。统一错误页面就是把所有异常都归为同一句话,比如“请求处理失败”,让真假条件在响应体上无法区分。
要注意的是,时间盲注并不依赖错误文本。它使用 SLEEP(5) 这类函数,通过响应耗时判断条件真假。仅靠隐藏错误页面,攻击者在时间维度上依然能攻破系统,所以错误页方案只是缩小了攻击面。
统一返回错误页面的实现方式
在Web服务器或应用框架层,可以拦截未捕获的异常,返回固定模板。以Java Spring Boot为例,使用 @ControllerAdvice 捕获所有异常并返回同一视图,避免把 SQLException 信息带到响应里。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleAll(Exception e) {
// 不记录具体错误到响应体
return ResponseEntity.status(200)
.body("请求处理失败");
}
}
在Nginx等反向代理上,也可以配置错误页:当后端返回500时,直接由Nginx吐出静态页,切断原错误透传。这种做法对老旧系统改动最小,上线快。但它要求运维确保任何语言框架的异常都被外层兜住,否则某个未捕获的接口仍会漏出差异。
统一错误页的缺点是:业务本身需要的正常错误提示(如“验证码错误”)也可能被覆盖,需要在设计上把业务异常与系统异常分开处理,只隐藏底层数据访问异常,保留友好的业务提示。
真正修复盲注的代码层方案
隐藏差异只是辅助,核心修复必须使用参数化查询(预编译语句),让用户输入永远作为数据而非SQL指令。下面是用PHP PDO修复上面漏洞的写法。
<?php
$id = $_GET['id'];
$stmt = $conn->prepare("SELECT name FROM users WHERE id = ?");
$stmt->bindParam(1, $id, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
echo "欢迎";
} else {
echo "无数据";
}
?>
这里 ? 占位符保证 $id 只能作为整数值传入,即使攻击者传入 1 OR 1=1,也会被转义为普通字符串或类型校验失败,不会改变SQL结构。配合ORM框架(如MyBatis的 #{} 写法)也能达到同样效果,切忌使用 ${} 拼接。
除了参数化,还应遵循最小权限原则:给Web数据库连接账号只授予必要的增删改查权限,禁止 FILE、SUPER 等高危权限,这样即便有残留注入点,攻击者也无法通过 INTO OUTFILE 写文件或读系统表。
防御组合建议
实际项目中,推荐“代码层参数化+统一错误页+WAF规则”三层并行。参数化解决根本问题,统一错误页消除信息差,WAF拦截明显恶意载荷。三者互补,才能覆盖布尔盲注、时间盲注及报错盲注的主要路径。
| 手段 | 防布尔盲注 | 防时间盲注 | 改动成本 |
|---|---|---|---|
| 统一错误页 | 有效 | 无效 | 低 |
| 参数化查询 | 有效 | 有效 | 中 |
| WAF拦截 | 部分 | 部分 | 低 |
最后提醒,修复后务必用sqlmap等工具做回归验证,确认原先的注入点不再有差异响应或时间延迟,再上线到生产环境。
SQL_injectionblind_injectionerror_page修改时间:2026-07-31 12:45:27