SQL 注入日志排查与 MySQL 慢查询审计思路

在 Web 安全事件响应中,SQL 注入往往不是靠“猜”发现的,而是靠日志和数据库行为留下的痕迹被定位。很多团队在遭遇注入后,第一反应是查 WAF 告警,但真正有价值的线索通常藏在 Web 访问日志、MySQL 通用查询日志、慢查询日志以及错误日志里。本文从排查思路和审计方法两个角度展开,帮助安全与运维人员建立一套可落地的分析流程。

一、SQL 注入排查为什么不能只看 WAF

WAF 能拦截部分注入流量,但以下情况会让它失效或漏报:

  • 攻击者使用编码变形、分块传输或注释混淆绕过规则;
  • 注入点位于 WAF 未覆盖的接口,如内部 API、旧版页面;
  • 攻击发生在 HTTPS 加密流量中,若未做解密检测则无法识别;
  • 慢速注入或布尔盲注,单次请求看起来完全正常。

因此,日志排查的核心目标是:从正常请求中识别异常模式,从数据库侧反推可疑 SQL 行为

二、Web 访问日志排查要点

以 Nginx 为例,重点关注 access.logerror.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.tablesinformation_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,应结合访问日志交叉验证。

五、从日志到修复的闭环思路

排查只是第一步,后续应形成闭环:

  1. 定位注入点:根据日志中的 URL 和参数,确认对应代码位置;
  2. 确认数据影响:检查是否发生数据泄露、篡改或写入;
  3. 修复代码:使用参数化查询,避免拼接 SQL;
  4. 加固数据库:最小权限原则,禁用 FILE 权限,限制 information_schema 访问;
  5. 持续监控:保留慢查询审计规则,定期复查异常 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 慢查询审计思路

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏