数据库访问日志不是用来“看有没有人进来过”的流水账,它是攻击发生后最先应该翻查的证据链。很多人排查恶意攻击时习惯先看应用层报错或防火墙拦截记录,但真正能还原攻击路径、确认数据是否被拖走、定位漏洞利用方式的,往往是数据库自身的访问日志。以MySQL为例,general_log 和 slow_query_log 是两类最常用的日志,但默认情况下 general_log 通常关闭,导致很多中小项目在出事之后才发现根本没有开启完整记录。PostgreSQL 的 pg_log 和 SQL Server 的 Error Log 也类似,如果没有提前配置好日志级别和保留策略,事后排查会非常被动。
排查的第一步不是盲目翻日志,而是先确认当前数据库实例上是否存在异常会话。执行
SHOW PROCESSLIST;或
SELECT * FROM pg_stat_activity;可以快速看到当前活跃连接。如果发现同一来源IP建立了大量短连接,或者某个账户在非业务时间段频繁执行
SELECT、
UNION SELECT、
information_schema相关查询,基本可以判断为自动化攻击或手工渗透。攻击者一旦进入数据库,第一件事往往是枚举库表结构,information_schema 和 pg_catalog 的访问频率会异常升高。 从日志中识别SQL注入特征
SQL注入攻击在访问日志里通常表现为大量包含特殊字符的请求参数被拼进SQL语句。比如日志中出现
' OR '1'='1、
UNION SELECT、
sleep(、
benchmark(、
load_file(、
into outfile等关键字,几乎可以确定是注入尝试。更隐蔽的时间盲注不会直接报错,但会在日志里留下大量执行时间异常的查询。此时应结合 slow_query_log,按查询耗时排序,找出那些本应毫秒级返回却耗时数秒的语句。攻击者用
if(condition, sleep(5), 0)这类手法时,日志中会出现同一模板、不同条件的重复慢查询。
对于MySQL,如果开启了 general_log,可以直接搜索
0x开头的十六进制字符串。很多注入工具会把攻击载荷编码成十六进制绕过WAF,数据库日志里会原样记录解码前的语句。PostgreSQL 的日志中则要重点关注
STATEMENT:后面的内容,尤其是包含
pg_read_file、
pg_ls_dir、
COPY命令的语句,这些常被用于读取系统文件或导出数据。 暴力破解与凭据填充的日志特征
数据库账号被暴力破解时,访问日志和错误日志会同时出现大量认证失败记录。MySQL 的 error log 中会出现
Access denied for user,PostgreSQL 日志中则是
password authentication failed。如果同一来源IP在短时间内对多个用户名尝试登录,或者同一用户名从大量不同IP尝试登录,前者是定向爆破,后者是撞库。此时不能只看失败次数,还要检查是否有成功登录紧随其后。一旦发现某个账号在连续失败后突然成功,要立即确认该账号是否已被接管,并回溯该会话执行过的所有语句。
日志中还有一种容易被忽略的特征:攻击者成功登录后,会先执行一些看似无害的语句来测试权限,比如
SELECT @@version、
SELECT current_user、
SELECT user()、
SHOW VARIABLES。这些语句单独出现并不异常,但如果紧跟在一串失败登录之后,且来源IP与爆破来源一致,就构成了完整的攻击链证据。 数据泄露与拖库行为的日志分析
拖库行为在访问日志中的表现非常明显:某个会话在短时间内执行了大量
SELECT * FROM语句,涉及的表数量远超正常业务范围。攻击者通常会先通过
information_schema.tables获取全量表名,然后逐表或批量导出数据。日志中会看到连续的、结构化的查询序列,比如先查
table_name,再对每个表执行
SELECT *。如果开启了 general_log,甚至能看到攻击者使用
SELECT ... INTO OUTFILE或
COPY ... TO将数据写入可访问目录的行为。
判断是否发生数据泄露,不能只看有没有
SELECT。很多攻击者为了减少日志量,会使用分页查询或限制返回行数,比如
LIMIT 1000配合循环。此时日志中会出现大量结构相同、偏移量递增的查询语句。另一个关键指标是网络层流量与日志记录量的比值,如果日志显示某会话只执行了少量查询,但数据库出口流量异常巨大,说明攻击者可能利用了数据库的批量导出功能或存储过程,需要进一步检查
mysqldump、
pg_dump的调用记录。 提权与后门植入的日志痕迹
数据库提权攻击通常伴随着对系统表或配置表的修改。MySQL 中如果日志里出现
UPDATE mysql.user SET、
GRANT ALL PRIVILEGES、
CREATE USER等语句,且执行者并非DBA账号,基本可以确认提权成功。PostgreSQL 中要关注
ALTER ROLE、
CREATE ROLE以及
pg_authid的变更记录。SQL Server 则要检查
sp_addsrvrolemember、
sp_addrolemember的调用。
后门植入的痕迹更隐蔽。攻击者可能创建名为
mysql_、
pg_开头但实际是用户自定义的存储过程或函数,或者修改已有存储过程的定义。日志中会出现
CREATE PROCEDURE、
CREATE FUNCTION、
CREATE TRIGGER等DDL语句。如果这些语句的执行时间在非变更窗口期,且来源IP异常,需要立即导出存储过程定义进行比对。触发器的后门尤其危险,因为它会在正常业务操作时自动执行,日志里可能只看到正常的
INSERT或
UPDATE,但实际触发器内部已经执行了额外的恶意操作。 基于时间线的攻击路径还原
单条日志只能说明一个点,把日志按时间排序后才能还原完整攻击路径。建议将数据库访问日志、应用日志、Web服务器日志放在同一时间轴上对照分析。攻击者从Web漏洞进入应用层,再通过应用连接数据库,这个过程中数据库日志里记录的来源IP往往是应用服务器的IP,而不是攻击者的真实IP。因此需要结合应用日志中的请求头、会话ID、用户ID来关联定位。如果数据库直接暴露在公网,日志里才会出现攻击者的真实来源IP。
还原攻击路径时,重点关注几个关键节点:首次异常登录或异常查询的时间点、权限变更的时间点、大量数据导出的时间点、后门创建的时间点。把这些节点连起来,就能判断攻击者是从哪个入口进来的、进来后做了什么、是否已经完成数据窃取、是否留下了持久化后门。如果日志显示攻击者只进行了探测但未成功登录,风险等级相对较低;一旦出现成功的权限变更或数据导出,必须按数据泄露事件处理。
日志配置与留存的最佳实践很多数据库默认日志配置无法满足安全排查需求。MySQL 的 general_log 记录所有语句,虽然详细但性能开销大,生产环境长期开启会影响性能。折中方案是开启 slow_query_log 并设置合理的
long_query_time,同时开启
log_queries_not_using_indexes,这样至少能记录全表扫描和慢查询。对于高价值系统,建议使用数据库审计插件或外部审计设备,它们能在较低性能损耗下记录完整的访问行为。
PostgreSQL 可以通过
log_statement = 'mod'或
'all'记录DDL和DML语句,配合
log_connections和
log_disconnections记录会话建立与断开。日志保留时间至少30天,涉及金融、医疗等敏感行业的系统建议保留180天以上。日志文件本身要设置严格的访问权限,防止攻击者入侵后清理日志。有条件的情况下,将数据库日志实时同步到独立的日志服务器或SIEM平台,避免单机日志被篡改。
日志分析不是等到出事才做。定期检查数据库访问日志中的异常模式,比如非工作时间的DDL操作、来自陌生IP的登录成功、短时间内的大量结构相似查询,可以在攻击进行到一半时就发现并阻断。数据库访问日志是数据库安全的最后一道证据防线,配置好它、用好它,才能在攻击发生后做到有据可查、有迹可循。
