在 Web 安全事件响应中,SQL 注入往往不是靠“猜”发现的,而是靠日志和数据库行为留下的痕迹被定位。很多团队在遭遇注入后,第一反应是查 WAF 告警,但真正有价值的线索通常藏在 Web 访问日志、MySQL 通用查询日志、慢查询日志以及错误日志里。本文从排查思路和审计方法两个角度展开,帮助安全与运维人员建立一套可落地的分析流程。
一、SQL 注入排查为什么不能只看 WAF
WAF 能拦截部分注入流量,但以下情况会让它失效或漏报:
- 攻击者使用编码变形、分块传输或注释混淆绕过规则;
- 注入点位于 WAF 未覆盖的接口,如内部 API、旧版页面;
- 攻击发生在 HTTPS 加密流量中,若未做解密检测则无法识别;
- 慢速注入或布尔盲注,单次请求看起来完全正常。
因此,日志排查的核心目标是:从正常请求中识别异常模式,从数据库侧反推可疑 SQL 行为。
二、Web 访问日志排查要点
以 Nginx 为例,重点关注 access.log 和 error.log。排查时不要只搜索 union select,更有效的方式是组合特征。
1. 高频可疑参数
以下参数名常被自动化工具扫描:
?id= ?page= ?cat= ?search= ?keyword= ?sort= ?order= ?filter=
如果某个 IP 在短时间内对同一路径的不同参数反复请求,且返回状态码多为 200 或 500,应重点标记。
2. 异常编码与长度
- 参数值中出现
%27、%23、%2d%2d等编码后的引号、井号、注释符; - 单条 URL 长度超过正常业务值,例如超过 500 字符;
- 同一参数值在多次请求中呈现递增或递减的数字特征,可能是盲注探测。
3. 状态码与响应时间
- 大量 500 错误集中在同一接口,可能说明注入触发了 SQL 语法错误;
- 某些请求响应时间明显长于同接口平均值,可能是
sleep()或重查询注入。
4. 排查命令示例
# 统计访问量最高的 IP 和路径
awk '{print $1, $7}' access.log | sort | uniq -c | sort -nr | head -50
# 搜索包含 union、select、sleep 等关键词的请求
grep -Ei "union|select|sleep|benchmark|information_schema" access.log
# 查找参数中带编码引号的请求
grep -E "%27|%23|%2d%2d|--" access.log
三、MySQL 慢查询日志在审计中的作用
慢查询日志原本用于性能优化,但在安全审计中同样有价值。攻击者实施时间盲注时,常使用 SLEEP()、BENCHMARK() 或复杂子查询,这些语句很容易进入慢查询日志。
1. 开启慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = ON;
生产环境建议将 long_query_time 设为 1 到 2 秒,避免日志量过大。
2. 审计关注点
- 查询中出现
SLEEP(、BENCHMARK(、LOAD_FILE(、INTO OUTFILE; - 查询中频繁出现
information_schema.tables、information_schema.columns; - 同一来源在短时间内产生大量结构相似的慢查询;
- 查询语句中包含
UNION SELECT且字段数较多。
3. 分析命令
# 提取慢查询中的可疑语句
mysqldumpslow -s t /var/log/mysql/slow.log | grep -Ei "sleep|benchmark|union|information_schema"
# 统计慢查询出现的频率
pt-query-digest /var/log/mysql/slow.log
如果发现 SLEEP() 出现在业务 SQL 中,而业务代码并没有使用该函数,基本可以判定存在注入行为。
四、MySQL 通用查询日志与错误日志
通用查询日志记录所有 SQL 语句,适合短期排查,不建议长期开启。错误日志则可能记录 SQL 语法错误,间接暴露注入尝试。
SET GLOBAL general_log = ON;
SET GLOBAL log_output = 'TABLE';
之后可查询 mysql.general_log 表:
SELECT event_time, user_host, argument
FROM mysql.general_log
WHERE argument LIKE '%union%'
OR argument LIKE '%sleep%'
OR argument LIKE '%information_schema%'
ORDER BY event_time DESC
LIMIT 100;
错误日志中若出现大量 You have an error in your SQL syntax,且对应请求来自同一 IP,应结合访问日志交叉验证。
五、从日志到修复的闭环思路
排查只是第一步,后续应形成闭环:
- 定位注入点:根据日志中的 URL 和参数,确认对应代码位置;
- 确认数据影响:检查是否发生数据泄露、篡改或写入;
- 修复代码:使用参数化查询,避免拼接 SQL;
- 加固数据库:最小权限原则,禁用
FILE权限,限制information_schema访问; - 持续监控:保留慢查询审计规则,定期复查异常 SQL。
六、常见防御写法与服务器加固的关联
在代码层,防止 SQL 注入的核心是参数化查询。例如 PHP 中使用 PDO:
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute([':id' => $id]);
避免直接拼接:
// 不推荐
$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];
在服务器层,Linux 安全加固同样重要。建议至少做到:
- 数据库仅监听内网地址,不暴露公网;
- 使用独立低权限账号连接数据库;
- 关闭
LOCAL INFILE,限制LOAD_FILE; - 定期审计慢查询日志和错误日志;
- 对 Web 目录设置只读权限,防止写入 webshell。
七、总结
SQL 注入日志排查的关键在于“交叉验证”:Web 访问日志看请求特征,慢查询日志看数据库行为,错误日志看语法异常。三者结合,才能从海量日志中快速定位攻击链。MySQL 慢查询审计不仅是性能工具,也是安全排查的重要补充。建议团队将慢查询日志保留周期与安全审计周期对齐,并建立定期分析机制,而不是等到事件发生后才临时翻日志。
未经允许不得转载:任鹏个人博客 » SQL 注入日志排查与 MySQL 慢查询审计思路


朋友圈点赞图在线生成源码