确认后端正被盲注探测,需检查日志中是否存在大量结构高度相似的轮询请求(如id=1 and 1=1、id=1 and substring(database(),1,1)='a'),响应状态码均为200但响应体长度或耗时呈现规律性跳变;时间盲注则表现为部分请求响应延迟显著拉长且具统计趋势,同时需排查waf是否启用布尔/时间盲注专项规则,并确保数据库查询强制参数化。

怎么确认后端正在被盲注探测?
看日志里有没有大量结构高度相似的请求,比如 id=1 AND 1=1、id=1 AND 1=2、id=1 AND SUBSTRING(database(),1,1)='a' 这类轮询式参数;同时响应状态码全是 200,但响应体长度或时间出现规律性跳变——这不是正常业务行为,是自动化工具(如 sqlmap --technique=B)在打布尔信道。
更隐蔽的是时间盲注:同一接口连续几十次请求中,部分请求响应耗时突然拉长到 2s+,且恰好对应 SLEEP(3) 或 WAITFOR DELAY '0:0:3' 类 payload。注意,单次延迟不可靠,要观察统计趋势。
- 别只盯错误日志——盲注成功时通常不报错,
error_log里干干净净 - 检查 Nginx/Apache 的 access log,重点过滤
AND、OR、SUBSTRING、ASCII、SLEEP等关键词 - 如果用了 CDN 或反向代理,确认
X-Forwarded-For是否透传,否则你看到的全是 CDN IP,真实攻击源被掩盖
WAF 规则为什么拦不住盲注?
不是 WAF 不行,而是默认配置常关着关键检测项。比如 ModSecurity CRS 默认不开 rule_id: 942100(时间盲注),阿里云/腾讯云 WAF 控制台里“延时型注入防护”开关默认是灰的;规则还常漏掉 JSON 接口——Content-Type: application/json 的响应体里,{"success":true} 和 {"success":false} 的布尔差异,WAF 若没配 JSON 解析器,就当普通文本放过。
- 必须手动启用时间盲注和布尔盲注专项规则,不能只依赖通用 SQL 关键词匹配
- 确认 WAF 能解析你实际返回的格式:HTML、JSON、甚至纯文本 API 都得覆盖
- 若前端套了 Cloudflare 或自建 Nginx,WAF 拿不到原始客户端 IP,IP 限频策略直接失效
代码层真正卡死盲注入口的关键动作
WAF 是减速带,参数化查询才是红绿灯。只要还有 "SELECT * FROM user WHERE id = " + req.query.id 这种拼接,WAF 再强也拦不住——因为请求本身完全合法,数据库执行时才出问题。
- 所有用户输入进 SQL 前,强制走
mysqli_prepare()(PHP)、pg_query_params()(PostgreSQL)、sqlite3_prepare_v2()(SQLite) - 禁止用
findOneOrFail()这类自动抛 404 的 ORM 方法——它等于把“记录存在与否”映射成 HTTP 状态码,直接提供布尔信道 - 统一返回
200+ 结构化 body,用code字段区分业务逻辑(如{"code": 40401, "data": null}),不靠状态码或空响应判断真假 - 数据库账号禁用
SLEEP、BENCHMARK、WAITFOR等函数,MySQL 里设disabled_functions = sleep,benchmark
为什么加随机延迟或混淆响应没用?
给每个请求加 usleep(rand(10000,50000)) 看似打乱节奏,实则白费劲:攻击者发 100 次 id=1 AND 1=1 和 100 次 id=1 AND 1=2,两组响应时间的标准差自然收敛,真假条件的均值差异仍清晰可辨。真正的防御不是藏时间,而是让“真”和“假”在数据库执行层面就不产生可观测的分支——比如把条件判断从 SQL 里移出来,用应用层查完再 if-else。
更危险的是,这类“混淆”容易掩盖真实性能瓶颈,反而干扰监控。盲注能跑起来,说明 SQL 里早就有 IF、CASE WHEN 或子查询嵌套了敏感逻辑,该砍的不是响应时间,是那条不该存在的动态 SQL。











