盲注无法被WAF或正则过滤有效防御,因其不依赖报错或回显,只通过响应差异推理数据;根本防御措施是全程使用预编译参数绑定,杜绝SQL字符串拼接。

盲注无法被“防止绕过”——它本身就是绕过防护的手段。真正要做的,是让盲注根本不可行。
为什么 WAF 或正则过滤挡不住盲注
盲注(Boolean-based 或 Time-based)不依赖报错或回显,只靠 AND 1=1 和 AND 1=2 的响应差异(页面变化、延时)来推理数据。WAF 常见的关键词拦截(如 UNION、SELECT)对它完全无效;正则规则也很难覆盖所有布尔逻辑变形(比如用 ||、&&、嵌套括号、十六进制编码等绕过)。
- 常见错误现象:WAF 日志显示拦截了
UNION SELECT,但攻击者用id=1 AND SLEEP(5)成功提取数据 - 本质原因:盲注不触发 SQL 错误,也不返回数据库内容,只消耗服务端资源并产生可观测侧信道
- 性能影响:Time-based 盲注会显著拖慢接口响应,可能引发超时、连接池耗尽甚至服务雪崩
参数必须绑定,且禁止拼接 SQL 字符串
这是唯一能从根源上封死盲注的措施。只要用户输入进了 query()、execute() 或任何动态拼接 SQL 的地方,就等于给盲注留了门缝。
- 正确做法:所有变量一律走预编译参数绑定,例如 PHP 的
$stmt->bind_param()、Python 的cursor.execute("SELECT * FROM user WHERE id = %s", [user_id]) - 绝对禁止:
"SELECT * FROM user WHERE id = " + user_id、f"SELECT * FROM user WHERE name = '{name}'"、format()拼接 - 特别注意 ORM 场景:Django 的
filter(name__contains=request.GET['q'])安全,但extra(where=["name LIKE '%{}%'".format(q)])就是高危
关闭错误回显,但别指望它防盲注
关闭 display_errors、设置 error_reporting(0) 或捕获异常后只返回通用错误页,确实能阻止基于错误的注入(Error-based),但它对盲注毫无作用——盲注本来就不看错误。
- 真实风险点:开发环境误开
SHOW ERRORS或日志中打印完整 SQL,可能泄露表结构,帮攻击者构造更高效的盲注 payload - 兼容性提醒:某些老系统依赖错误信息调试,可改用内部日志(不输出到 HTTP 响应),并确保日志权限严格(
chmod 600) - 额外动作:数据库账号最小权限原则——应用账号只允许
SELECT(或仅需的 DML),禁用LOAD_FILE、BENCHMARK、SLEEP等高危函数
引入请求行为分析与速率限制
盲注必然伴随高频、模式化请求(如连续探测 ASCII 值、逐字猜解),这是它最脆弱的特征。
- 部署 Web 应用防火墙(如 ModSecurity)启用规则集
OWASP-CRS,重点关注942100(SQL 注入布尔型检测)、942110(时间延迟检测) - 在接入层(Nginx / API 网关)配置按 IP 或 token 的请求频率限制,例如 5 秒内超过 10 次含
AND、OR、SLEEP的请求直接封禁 - 关键区别:不要只拦关键词,要结合响应时间突增(如平均 200ms → 突然连续出现 5000ms 响应)做动态判定
盲注防御的核心不在外围规则,而在代码层是否彻底杜绝字符串拼接。所有“加固 WAF”的尝试,都只是给漏洞盖一层薄纸——只要存在一处 mysql_query("SELECT * FROM x WHERE y = '" . $_GET['id'] . "'"),盲注就始终可行。

















