慢查询日志和SQL注入,一个是数据库性能的晴雨表,一个是安全防护的生死线。在绝大多数运维体系里,这两件事分属DBA和安全工程师处理,数据不互通,告警不联动。但如果你仔细看过慢查询日志里的原始SQL,会发现大量异常请求在拖垮数据库之前,其实已经留下了明显的注入指纹。把慢查询日志的采集和SQL注入特征的正则匹配结合起来,就能构建一套覆盖性能与安全的自动化巡检机制,不需要额外部署探针,也不需要改造应用代码。
慢查询日志里藏着什么MySQL、PostgreSQL、MariaDB等主流数据库都支持慢查询日志功能。以MySQL为例,通过设置long_query_time参数,任何执行时间超过该阈值的SQL语句都会被记录到慢查询日志文件或mysql.slow_log表中。每条记录包含查询时间、锁定时间、扫描行数、执行时间戳、用户主机信息和完整的SQL文本。很多人只关注执行时间和扫描行数来做索引优化,却忽略了SQL文本本身携带的安全信号。一条执行了8秒的SELECT语句,如果WHERE子句里出现了大量UNION SELECT、SLEEP函数调用或者异常的表结构探测语句,这就不只是性能问题,而是正在发生的SQL注入攻击。
慢查询日志天然适合做安全分析,原因有三。第一,注入攻击往往会导致全表扫描或者大量数据返回,执行时间必然拉长,自然落入慢查询范围。第二,慢查询日志记录的是完整的原始SQL,攻击者构造的恶意载荷一字不差地保留下来,不像应用层日志可能被转义或截断。第三,慢查询日志的采集对数据库性能影响极小,开启log_output=FILE写入磁盘的方式几乎无感知,不会像Query Profiling那样消耗大量资源。
SQL注入攻击的典型特征模式要把慢查询日志变成入侵检测的数据源,必须先梳理SQL注入的常见特征。基于多年的攻击案例分析,可以归纳出以下几类高频出现的模式。第一类是联合查询注入,特征为UNION SELECT语句,攻击者用它来合并查询结果集,窃取其他表的数据。正则特征可以捕获UNION ALL SELECT或者UNION SELECT后面紧跟数字序列的占位列,例如UNION SELECT 1,2,3,4,5这种探测字段数量的经典手法。
第二类是布尔盲注和时间盲注。布尔盲注通过AND 1=1、OR 1=1这类永真条件来判断注入点是否存在,时间盲注则使用SLEEP()、BENCHMARK()、pg_sleep()等函数制造延迟,通过响应时间差异逐字符猜解数据。慢查询日志里如果出现大量包含SLEEP(5)或者BENCHMARK(10000000,MD5('test'))的SQL,几乎可以确定是自动化注入工具在跑数据。第三类是报错注入,利用extractvalue()、updatexml()、floor()等函数触发数据库报错并回显信息。这些函数在正常业务代码中极少出现,一旦在慢查询日志里看到,基本就是攻击行为。
第四类是堆叠查询,通过分号分隔多条SQL语句,一次性执行多个操作。虽然PHP的mysql_query函数不支持堆叠查询,但Python、Java等语言的数据库驱动以及php_mysqli都支持,攻击者会利用这个特性在SELECT语句后拼接INSERT、UPDATE甚至DROP操作。第五类是注释符绕过,使用--、#、//等注释符截断原始SQL逻辑,这是注入攻击最基础的技巧,但至今仍然大量出现在自动化扫描工具的载荷中。
正则表达式规则库的构建思路构建正则规则库不能靠拍脑袋,需要结合OWASP SQL注入测试指南、实际攻防经验以及业务系统的SQL特征来设计。规则要分层分级,避免误报影响业务告警的准确性。第一层是高置信度规则,匹配到就应立即告警,例如包含SLEEP()、BENCHMARK()、pg_sleep()等延时函数的语句,或者出现extractvalue(、updatexml(这类报错注入函数。这些函数在正常业务SQL中几乎不可能出现,误报率极低。
# 时间盲注检测规则 (SLEEP\(\s*\d+\s*\)|BENCHMARK\(\s*\d+\s*,|pg_sleep\(\s*\d+\s*\)) # 报错注入检测规则 (extractvalue\(\s*\d+\s*,|updatexml\(\s*\d+\s*,|floor\(\s*rand\(\s*\d+\s*\)\s*\*\s*\d+\s*\))
第二层是中置信度规则,需要结合上下文判断,例如UNION SELECT语句。正常业务中某些报表查询确实会使用UNION合并多个结果集,但UNION SELECT后面跟着一串数字占位列或者from information_schema这类系统表查询,就高度可疑。规则可以设计为UNION SELECT后紧跟数字逗号序列,且序列长度超过3个字段,同时排除业务白名单中的表名。
# 联合查询注入检测规则
UNION\s+(ALL\s+)?SELECT\s+(\d+\s*,\s*){3,}\d+\s*(--|#|/\*|$)
# 系统表探测检测规则
(from\s+information_schema\.|from\s+sys\.|from\s+pg_catalog\.)
第三层是低置信度规则,用于标记可疑行为但不直接告警,例如出现注释符--或#截断、出现永真条件1=1或'a'='a'、出现大量OR条件拼接等。这些特征在部分业务场景下可能正常出现,比如搜索功能的多条件OR拼接,所以需要结合请求频率、来源IP、执行时间等维度做关联分析。单次匹配不告警,但同一来源短时间内触发多条低置信度规则,就升级为高危事件。
# 注释符截断检测规则 (\s--\s|\s#\s|/\*.*\*/) # 永真条件检测规则 (\bOR\b\s+['\"]?\d+['\"]?\s*=\s*['\"]?\d+['\"]?|\bAND\b\s+['\"]?[a-zA-Z]+['\"]?\s*=\s*['\"]?[a-zA-Z]+['\"]?)自动化巡检脚本的落地实现
有了规则库,下一步是把整个流程自动化。核心逻辑分为四个步骤:慢查询日志采集、SQL文本提取与清洗、正则规则匹配、告警输出与归档。以MySQL为例,如果慢查询日志配置为写入mysql.slow_log表,可以直接通过SQL查询获取最近一个巡检周期内的记录。如果写入文件,则用pt-query-digest工具或者直接tail读取文件增量内容。
-- 从slow_log表获取最近1小时的慢查询
SELECT
start_time,
user_host,
query_time,
lock_time,
rows_sent,
rows_examined,
db,
sql_text
FROM mysql.slow_log
WHERE start_time >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
ORDER BY query_time DESC;
提取到SQL文本后,需要做基础清洗。慢查询日志中的SQL可能包含参数占位符,比如Prepared Statement的?号,也可能被数据库截断。清洗步骤包括去除多余的空白字符、统一换行符、截取前2000个字符防止正则回溯爆炸。然后用预定义的规则库逐条匹配,记录匹配到的规则ID、匹配位置和完整SQL文本。
告警输出环节需要区分严重等级。高置信度规则匹配到直接发送即时告警,通过企业微信、钉钉或者邮件通知安全值班人员。中置信度规则匹配到则写入安全事件队列,由SOC分析师人工研判。低置信度规则匹配到仅记录到日志文件,作为威胁情报的补充数据。所有匹配结果同时写入Elasticsearch或者ClickHouse,方便后续做攻击链回溯和趋势分析。
降低误报的实战技巧正则匹配最大的敌人是误报。业务系统千差万别,一条看似恶意的SQL在特定场景下可能是完全合法的。降低误报需要从多个维度做精细化处理。第一是建立业务白名单,把已知的正常SQL模式排除在外。比如某些BI系统会频繁查询information_schema获取表结构,这类请求的来源IP、执行用户和SQL模板都是固定的,可以精确加白。白名单建议用SQL指纹的方式匹配,而不是简单的字符串包含,避免被攻击者绕过。
第二是引入频率维度。单次匹配可能是误报,但同一来源IP在5分钟内触发10条不同规则,基本可以判定为扫描行为。可以维护一个滑动窗口计数器,按来源IP和规则ID聚合,超过阈值才升级告警。第三是结合执行时间做判断。真正的注入攻击往往会导致执行时间异常,如果一条匹配了UNION SELECT规则的SQL执行时间只有0.01秒,可能只是开发人员在客户端工具里手动查询,但如果执行时间超过5秒且扫描行数巨大,那攻击的可能性就急剧上升。
第四是关注SQL文本的结构特征。正常业务的UNION SELECT通常连接的是业务表,字段名有业务含义。注入攻击的UNION SELECT后面往往是数字序列或者null占位,字段名缺失或者使用concat、group_concat等聚合函数拼接数据。可以通过正则捕获SELECT后面的字段列表,分析字段名的语义特征,进一步提高判断准确度。
与现有安全体系的整合这套机制不是孤立运行的,需要和现有的WAF、SIEM、态势感知平台打通。慢查询日志分析可以作为WAF的补充检测手段。WAF工作在应用层,面对编码绕过、分块传输、HTTP参数污染等高级技巧时可能漏报,但注入载荷最终到达数据库执行时,必然以原始SQL形态出现在慢查询日志里。把慢查询分析的结果回传给WAF,可以形成闭环,让WAF自动更新拦截规则。
与SIEM的整合则侧重于关联分析。慢查询日志中的来源IP、执行用户、时间戳,可以和Web服务器访问日志、系统登录日志做关联,还原完整的攻击路径。比如慢查询日志显示某条恶意SQL来自数据库用户app_user,来源IP是内网地址192.168.1.100,同时Web日志显示该IP在相同时段有大量404请求和敏感路径扫描,就能确认这是一起从Web端发起的SQL注入攻击,且攻击者已经获取了数据库连接凭据。
对于使用云数据库的场景,各大云厂商都提供了慢查询日志的API接口。可以通过定时任务调用API拉取日志,统一存储到自建的分析平台。注意云数据库的慢查询日志可能有延迟,巡检周期建议设置为10到15分钟,既能保证时效性,又不会因为日志未生成而漏报。
持续优化规则库的方法论规则库不是一成不变的,攻击手法在进化,业务系统也在变化。持续优化需要建立反馈机制。每次告警经过人工研判后,把误报的SQL样本加入白名单,把漏报的攻击样本提取新的特征加入规则库。可以按季度对规则库做回顾,统计每条规则的命中率、误报率和贡献度,淘汰长期不命中或者误报率过高的规则。
另一个重要的优化方向是引入机器学习辅助判断。纯正则匹配的局限性在于无法识别未知的攻击模式。可以先用正则规则标注历史数据,把匹配到的SQL标记为恶意,未匹配的标记为正常,训练一个基于SQL语句词法分析的分类模型。模型不需要多复杂,用TF-IDF提取特征加上轻量级的XGBoost就能达到不错的效果。模型判定的恶意SQL如果未被正则规则覆盖,就说明发现了新的攻击模式,可以人工分析后抽象成正则规则加入规则库。
最终目标是把这套机制做成一个自进化的检测系统。慢查询日志源源不断地产生,规则库持续迭代,告警越来越精准,运维人员只需要关注真正的安全事件,而不是被海量误报淹没。数据库的性能数据和安全隐患在同一个管道里被处理,打破了DBA和安全团队之间的信息壁垒,让自动化巡检真正覆盖到数据库层面的攻击检测。
