不同数据库被”拖库”特征-托管vs自建+是/否开启审计日志取证实测

不同数据库被”拖库”特征-托管vs自建+是/否开启审计日志取证实测

在入侵类应急响应中,客户最常见的诉求之一是:“帮我判断数据库到底有没有被黑客拖库?” 但数据库类型种类众多,每种数据库的拖库手法、留下的痕迹、可用的取证手段都不一样;而且是否开启了审计日志,直接决定了能拿到的证据等级。

本文在腾讯云上用 tccli 真实开通了 7 种托管数据库,插入 10 万行/文档级别的敏感样本数据(身份证、手机号、银行卡、密码哈希),分别在 不开审计 / 开启审计 两种情况下模拟拖库;并对其中差异最大的 SQL Server、Elasticsearch、Redis、MySQL、PostgreSQL 额外做了「自建 vs 托管」对照实测(自建实例上启用原生审计、复现托管版封掉的危险能力)。每个结论都附实际抓取的日志/截图,最后给出应急响应取证清单与加固建议。

全文所有日志、命令、API 输出均为真实实测结果。

测试环境与方法论

项目说明
云平台腾讯云(广州 ap-guangzhou),全部按量计费,测完即销毁
实例共 7 种:CDB MySQL 8.0 / PostgreSQL 15 / Redis 6.2 / MongoDB 6.0(三节点副本集)/ SQL Server 2017 企业版(AlwaysOn)/ ClickHouse 21.8(HA 集群,2 数据+3 ZK)/ Elasticsearch 7.10(2 节点)
样本数据统一一张表/一个集合/一个索引 members,10 万行,字段含 id_card / phone / bank_card / password_hash / address 等典型 PII
攻击侧公网客户端直连(MySQL/PG/Redis/SQLServer)+ VPC 内跳板机直连内网(MongoDB/ClickHouse/Elasticsearch),后者还原“攻击者已拿下内网一台机器后横向拖库”的真实场景
两种场景场景 A:不开审计(默认状态)/ 场景 B:开启审计,逐一对比可取到的痕迹
取证手段全程用 tccli 调云端 API(DescribeAuditLogs / DescribeSlowLog / DescribeXEvents / GetMonitorData 等)+ 数据库内置系统表,模拟应急响应方“只能拿到云控制台/API”的真实条件
自建对照另用 tccli 开 CVM 自建:Windows SQL Server 2022(原生 Audit)/ ES 7.10(X-Pack 全量审计)/ Redis 7(MONITOR+–rdb)/ MySQL 8(INTO OUTFILE)/ PostgreSQL 16(COPY TO PROGRAM),与托管版逐一对照

核心结论先行

云上托管数据库,即使不开审计,也并非“零痕迹”——慢查询日志、命令统计、网络出向流量监控,往往足以发现“大批量数据外带”这一行为本身(实测拖库瞬间出流量可达基线 170 倍)。

审计日志是唯一能还原“具体执行了哪条语句、拖走了哪张表/哪些字段”的证据。不开审计,只能证明“有人导了很多数据”;开了审计,能证明“谁、在什么时间、用什么语句、拖走了 members 表的 10 万行敏感数据”。

各数据库审计能力分三档

第一档(内置/全量,开箱即用):ClickHouse 内置 query_log 默认全量;MySQL / PostgreSQL / MongoDB 一键开启即得完整语句级审计。

第二档(弱/受限):Redis 只有慢日志、无命令级审计;Elasticsearch 托管版无法动态开 X-Pack 审计;SQL Server 托管版只有慢/阻塞 XEvent。

取证便捷度从高到低:ClickHouse ≈ MySQL/PG > MongoDB ≫ Redis / SQLServer / ES。

“开了审计”不等于“一定查得到”:实测 SQL Server 托管版的慢 XEvent 阈值按服务端执行时间计——攻击者用最朴素的 SELECT * FROM 大表 慢慢拉数据,服务端执行飞快(0.1s),即便开了审计也照样绕过。

托管 vs 自建是另一条主线:取证上——SQL Server/Elasticsearch 托管版审计基本残废,自建开原生审计后吊打(连客户端 IP、拖了哪些字段都记)攻击面上——托管把 INTO OUTFILE/COPY TO PROGRAM/SYNC 等危险能力收敛掉了。但自建默认敞开、攻击面更大。

MySQL(腾讯云 CDB)

拖库手法

# 手法1:mysqldump 全库导出(最经典)
mysqldump -h <host> -P <port> -uroot -p<pwd> --single-transaction shop members > dump.sql

# 手法2:SELECT * 全表查询(SQL注入/应用层导出)
mysql ... -e "SELECT * FROM members;" > out.txt

# 手法3:分页 LIMIT 慢速抓取(规避检测)
mysql ... -e "SELECT ... FROM members LIMIT 20000 OFFSET 40000;"

# 手法4:SELECT ... INTO OUTFILE(落地文件)

实测关键发现

手法4 INTO OUTFILE 在托管实例上被直接阻断:ERROR 1227 (42000): Access denied; you need (at least one of) the FILE privilege(s) CDB 默认 secure_file_priv=NULL、root 账号无 FILE 权限,攻击者无法在数据库服务端落地文件,只能把数据通过网络外带到客户端。这是云数据库相比自建的一个天然收敛点。

general_log 默认 OFF(开了会全量记录但性能开销大,生产基本不开)。

场景 A:不开审计时的痕迹

CDB 的 long_query_time 默认是 1 秒(不是社区版的 10 秒),而全表导出动辄数秒,必然落入慢查询日志。通过 API DescribeSlowLogData 取到的真实记录:

QueryTime=5.18s  RowsSent=100000  RowsExamined=100000  user=root  host=121.35.101.28
SQL: SELECT /*!40001 SQL_NO_CACHE */ * FROM `members`

重点:SELECT /*!40001 SQL_NO_CACHE */ * FROM … 这个带 SQL_NO_CACHE 注释的语句,是 mysqldump 的指纹(mysqldump 导出时自动加该 hint)。在慢日志里看到它 + RowsSent 等于全表行数,基本可以实锤“有人用 mysqldump 拖了这张表”。

网络出流量监控(API GetMonitorData,指标 BytesSent):

拖库时段峰值:2.94 MB/s    平时基线:~17 KB/s    →  约 170 倍尖峰

即使慢日即使慢日志被关掉或清理,云监控的出向流量尖峰仍是一条独立的旁证。

场景 A 的局限:分页 LIMIT 小批量(每次 < 1 秒)抓取可以绕过慢日志;此时只剩流量监控和连接数能看出异常。

场景 B:开启审计后的痕迹

tccli cdb OpenAuditService --InstanceId cdb-xxx --LogExpireDay 7 --AuditAll true

开启后,通过 DescribeAuditLogs 拿到每一条语句的完整记录(实测样本):

审计日志的核心证据:

  • 完整 SQL 原文 + SentRows(实际外带行数)+ 源 Host/ClientPort + ThreadId,可精确还原拖库过程;
  • 能抓到慢日志抓不到的亚秒级小查询(分页拖库每条都会记录);
  • 可按 SentRows / SqlType=SELECT 过滤,快速筛出“大结果集 SELECT”这类拖库特征。

取证要点

是否开审计取证手段能解决的问题
不开慢查询日志 DescribeSlowLogData + 出流量监控 BytesSent有没有大批量导出?
大概什么时间?
开启审计日志 DescribeAuditLogs(按 SentRows 排序)谁、用什么语句拖走了哪张表的多少行?

对照实测:自建 MySQL

之前提到托管 CDB 把 INTO OUTFILE 封死了(无 FILE 权限、secure_file_priv=NULL)。自建 MySQL 8.0 就完全不一样——secure_file_priv 默认指向 /var/lib/mysql-files/,拥有 FILE 权限的账号可直接把查询结果写到服务器磁盘

差异与影响:

托管版:INTO OUTFILE 直接 ERROR 1227 … FILE privilege,攻击者只能走网络外带;

自建版:结果可落地到服务器磁盘,再借 Web 目录/其他通道二次外带,甚至 INTO OUTFILE 直接往 Web 根目录写 webshell——拖库之外还多了一条落地与持久化通道。

取证侧:自建 MySQL 社区版没有内置 SQL 审计插件,但可开 general_log(实测能全量记录包括 INTO OUTFILE 在内的每条语句 + 来源),或上 MariaDB/Percona 审计插件。

PostgreSQL(腾讯云 PostgreSQL)

拖库手法

pg_dump -h <host> -p <port> -U <user> -t members > dump.sql   # 底层走 COPY
psql ... -c "\copy members TO '/tmp/x.csv' CSV"               # COPY 导出
psql ... -c "SELECT * FROM members;"                          # 全表 SELECT

默认日志配置(很关键)

腾讯云 PG 实例出厂即预装 pgaudit,默认参数:

shared_preload_libraries = ...,pgaudit,...
log_destination          = csvlog,auditlog
log_min_duration_statement = 1000     # 慢查询阈值 1 秒
log_statement            = ddl        # 默认只记 DDL,SELECT 不记

也就是说:默认情况下 SELECT 不会进语句日志,但超过 1 秒的会进慢查询日志

场景 A:不开审计时的痕迹

DescribeSlowQueryList 实测抓到(含源地址):

dur=8709ms  client=121.35.101.28:15845  SQL: SELECT * FROM members;
dur=5401ms  client=121.35.101.28:15820  SQL: COPY  members TO STDOUT CSV
dur=4086ms  client=121.35.101.28:15317  SQL: SELECT id_card,phone,bank_card,password_hash FROM members;

划重点:COPY members TO STDOUT 是 pg_dump / \copy 的指纹——正常业务很少对整表 COPY TO STDOUT,它出现在慢日志里基本等于“有人在整表导出”。

场景 B:开启审计后的痕迹

tccli postgres OpenAuditService --InstanceId postgres-xxx \
  --LogExpireDay 7 --HotLogExpireDay 7 --AuditType complex --Product postgres

DescribeAuditLogs 实测样本:

审计相比慢日志多出来的价值:

带 ObjectName=public.members(直接告诉你被拖的是哪张表)+ AffectRows;

那条 0.23 秒的小查询(WHERE id<5000)慢日志根本不会记录,审计日志记下来了 —— 这就是开/不开审计在“分页/小批量拖库”场景下最本质的差距。

对照实测:自建 PostgreSQL

托管 PG 只允许 COPY … TO STDOUT(回客户端),COPY TO 文件 和 COPY TO PROGRAM 都被禁。自建 PG 16 作为超级用户这两条全开,而且比 MySQL 的 INTO OUTFILE 更猛:

差异与影响:

COPY TO PROGRAM 不止是拖库——它是 PostgreSQL 超级用户 RCE 的经典手法,既能落地写文件,又能 curl/nc 把数据直接外带出去,完全不经过客户端;

托管版把 COPY TO 文件/PROGRAM、不可信 PL 等全部收敛,攻击者只能 COPY TO STDOUT 走网络;

取证侧:自建 PG 可把 pgaudit 配 log_statement=all 或直接 log_statement=all,全量记录(COPY … TO PROGRAM 也会进日志),取证能力一样强。

MongoDB 自建的反例:顺带一提,MongoDB 的审计是企业版专属功能,自建社区版根本没有审计——所以自建社区版 Mongo 的拖库取证能力反而不如腾讯云托管版(后者提供了 DescribeAuditLogs)。“自建 > 托管”并非铁律,要看该数据库把能力放在了社区版还是商业版。

Redis(腾讯云 Redis 6.2)

Redis 是 KV 缓存,常被用来存会话 token、缓存的用户 PII,拖库手法和关系型完全不同。。

拖库手法与实测结果

redis-cli ... KEYS '*'              # 全量枚举所有 key(危险)
redis-cli ... --scan               # 游标遍历(隐蔽)
redis-cli ... --rdb dump.rdb       # 走主从复制拉全量 RDB(真·拖库)
redis-cli ... --bigkeys            # 探测大 key

实测关键发现

KEYS * 未被禁用,可一次性枚举全部 60000 个 key;

redis-cli –rdb 被阻断:SYNC with master failed: -ERR ‘SYNC’ is disabled command 腾讯云 Redis 禁用了 SYNC/PSYNC,攻击者无法用“伪装成从库做全量复制”的方式一把拖走整个 RDB,只能退化为 KEYS/SCAN 枚举 + GET/HGETALL 逐个外带——速度更慢、产生的命令量更大、更容易在监控里暴露

检测痕迹

重要:腾讯云 Redis 的日志投递只支持慢日志(DescribeInstanceLogDelivery 实测只有 SlowLog 一项),没有 MySQL/PG 那种全量命令级审计。所以 Redis 拖库主要靠以下三条线索:

慢日志(DescribeSlowLog)—— KEYS * 是慢命令,必被记录:

CommandLine: KEYS *   Duration: 20ms   ExecuteTime: 2026-06-25 11:22:12

命令统计监控(DescribeInstanceMonitorTopNCmd),遍历拖库会把 scan/type/strlen/hlen 打到很高:

TopN 命令: type=9929, strlen=8338, hlen=1591, scan=1003, ...

正常业务以 GET/SET/EXPIRE 为主;突然出现海量 SCAN+TYPE+STRLEN,是 –bigkeys/遍历导出的典型指纹。

来源 IP 监控(DescribeInstanceMonitorSIP)、出向流量监控:辅助定位攻击源。

托管的Redis 没有语句审计,应急时优先看慢日志里有没有 KEYS/HGETALL/SMEMBERS 大范围命令 + 命令统计里 SCAN/TYPE 异常飙升 + 出流量尖峰三者结合判断。

对照实测:自建 Redis

自建 Redis 7.0(默认配置)和托管版正好两头反:

托管版被禁的 –rdb 全量复制拖库,自建直接成功:

$ redis-cli -h <host> -a *** --rdb dump.rdb
Transfer finished with success after 3094627 bytes     ← 整库 3.0M 一把拖走

托管 Redis 禁了 SYNC/PSYNC(报 ‘SYNC’ is disabled),自建默认开着——攻击者用 –rdb 或 SLAVEOF 把整个数据库当从库一次性复制走,是最高效的全量拖库通道。

但自建的取证手段也更全。 –rdb 会在 Redis 服务日志里留下“伪装副本发起同步”的铁证:

陌生 IP 发起 SYNC = 有人在克隆整个 Redis,这是自建 Redis 全量拖库最强的取证信号(托管版看不到服务日志)。

而 MONITOR(自建可用、托管不暴露)能实时抓全量命令流,带时间戳 + 真实客户端 IP:

一句话:自建 Redis 拖库攻击面更大(–rdb 全量),但取证能力也更强(MONITOR 命令级 + 服务日志 SYNC 痕迹);托管版反过来——堵了 –rdb,但也没有命令级审计。两者都建议:rename-command 禁危险命令、ACL 限权、bind + 强密码、SYNC 来源 IP 告警。

MongoDB(腾讯云 MongoDB 6.0 副本集)

注:腾讯云 MongoDB 默认不提供公网,本次通过 VPC 内一台跳板机(172.16.48.3) 直连内网 27017 进行测试,这也正好还原了“攻击者已拿下内网一台机器后横向拖库”的真实场景。

拖库手法

col.find({})                                   # 全集合扫描
col.find({}, {"id_card":1,"phone":1,...})      # 敏感字段投影导出
mongodump --uri ...                            # 官方导出工具

场景 A:不开审计时的痕迹

MongoDB 慢日志(DescribeSlowLogs)用原生 JSON 格式记录超过 slowms(默认 100ms)的操作。但实测中,小文档全集合扫描在 VPC 内极快(0.5 秒拉完 10 万文档,单次 getMore 多在 100ms 以内),很多 find/getMore 不会进慢日志——这意味着不开审计时,MongoDB 的快速拖库容易“打慢日志的擦边球”,只能靠 DescribeCurrentOp(实时正在执行的操作)和网络监控发现。

场景 B:开启审计后的痕迹

tccli mongodb OpenAuditService --InstanceId cmgo-xxx --LogExpireDay 7 --AuditAll true

DescribeAuditLogs 实测样本:

Atype=read  Host=172.16.48.3  AffectRows=10000
Param: { ns: shop.members, cmd: { find: "members", filter: {}, batchSize: 10000, ... } }

Atype=read  Host=172.16.48.3  AffectRows=99899
Param: { ns: shop.members, cmd: { getMore: <cursorId>, collection: "members", ... } }

审计核心证据:

  • find: “members”, filter: {} —— filter 为空 = 全集合无条件扫描,这就是拖库的核心指纹(正常业务极少无条件全表 find);
  • 完整记录 ns(库。集合)、源 Host(直接指向跳板机 172.16.48.3,即内网失陷点)、AffectRows、getMore 游标遍历链路;
  • Atype=read 可直接筛出所有读操作。

取证要点

是否开审计手段局限
不开慢日志 + DescribeCurrentOp + 流量监控快速小文档扫描易漏记
开启审计日志(筛 filter:{} 的全集合 find)性能略有开销,但取证完整

SQL Server(腾讯云 SQL Server 2017 企业版)

拖库手法与实测

# 手法1:BCP 批量导出(SQL Server 最经典的拖库工具)
bcp "shop.dbo.members" out members.dat -S <host>,<port> -U <user> -P <pwd> -c -u

# 手法2:sqlcmd 查询导出
sqlcmd ... -Q "SELECT * FROM members;" -o out.txt

实测 BCP 7 秒导出 10 万行 / 15 MB:

100000 rows copied.  Average : (15434 rows per sec.)

注意:bcp/sqlcmd(ODBC Driver 18)默认强制加密校验证书,连云实例需加 -u/-C(信任服务器证书),否则报 SSL certificate verify failed。

这是几种数据库里审计能力最弱的一个:

  • 腾讯云 SQL Server 没有暴露完整的语句级审计 API;
  • 唯一的“扩展事件(XEvent)”只支持两类:slow(慢 SQL) 和 blocked(阻塞/死锁),且阈值最低 1000ms

场景 A / B 实测结论

不开 XEvent(默认):几乎只剩网络出流量监控连接审计能发现异常;BCP 这类批量导出在服务端不留语句级痕迹

开启 XEvent(slow)后:实测确实能抓到导出查询。XEvent 把慢 SQL 滚动写入 .xel 文件(存于 COS,经 DescribeXEvents 拿下载地址),解析后能看到完整 SQL 原文。但局限明显:只记超过阈值(≥1000ms)的慢 SQL,小批量、快速的 BCP/分页导出会漏。整体取证能力远弱于 MySQL/PG 的实时全语句审计。

应急建议:对托管 SQL Server,不要依赖云端审计。要真正具备拖库取证能力,应在实例内用原生 SQL Server Audit / Server-level Audit Specification(写到文件/安全日志)或前置数据库审计探针(旁路抓 TDS 流量),并配合网络层 NDR。

对照实测:自建 Windows SQL Server 的原生 Audit

为了验证上面“用原生 SQL Server Audit”的和托管的数据库审计到底有多大差距,我额外用 tccli 开了一台 Windows Server 2022 CVM,自建安装 SQL Server 2022 Developer 版(企业版全功能),启用原生审计后跑同样的拖库:

-- 自建实例可用、托管版没有的原生审计
CREATE SERVER AUDIT IR_Audit TO FILE (FILEPATH='C:\SQLAudit\');   -- 也可 TO APPLICATION_LOG / SECURITY_LOG
ALTER SERVER AUDIT IR_Audit WITH (STATE=ON);
USE shop;
CREATE DATABASE AUDIT SPECIFICATION IR_Spec FOR SERVER AUDIT IR_Audit
  ADD (SELECT ON dbo.members BY public) WITH (STATE=ON);

跑拖库后,用 sys.fn_get_audit_file 直接查回:

对照托管版,自建原生 Audit 在拖库取证上全面碾压

  1. 没有时长阈值 —— 每条 SELECT 都记。那条在托管版因“服务端执行 <1000ms”而绕过 XEvent 的 SELECT * FROM members,在这里被完整记录
  2. 带 client_ip(121.35.101.28,真实攻击源)+ host_name(攻击者机器名)+ application_name——后者直接认出是 bcp 批量导出工具还是 SQLCMD,托管版连客户端 IP 都拿不到。
  3. 可写 Windows Application / Security 事件日志:应急时直接从失陷主机的事件日志里就能取到全部审计,无需依赖云 API、无 COS 分钟级延迟。

同样是 SQL Server,自建 Windows + 原生 Audit 的拖库取证能力,和腾讯云托管版根本不是一个量级。如果业务对 SQL Server 审计有强需求,自建的数据库开启审计比直接用托管实例的 XEvent 靠谱得多。

ClickHouse(腾讯云 CDWCH)

ClickHouse 是列式数仓,单表动辄上亿行,是“大数据量拖库”的高价值目标。本次开的是 HA 集群(2 数据节点 + 3 ZK),经 VPC 内跳板机连接。

拖库手法

# HTTP 接口(8123)
curl 'http://<host>:8123/' -u default:<pwd> --data 'SELECT * FROM members FORMAT CSV'
# 原生 TCP(9000) / clickhouse-client

clickhouse-client --query 'SELECT * FROM members' > dump.csv
# 还暴露 MySQL 协议端口(9004),可用 mysql 客户端直连拖

注:CDWCH 是集群,普通表建在某个分片,需用 ON CLUSTER + Distributed 引擎建分布式表,攻击者拖的就是分布式表。

检测痕迹:内置 system.query_log

CK 最大的不同:自带 system.query_log 系统表,默认开启,不用像 MySQL/PG 那样额外开审计。它用 SQL 直接可查,记录每条查询的 user / address(来源IP) / read_rows / read_bytes / query 原文 / query_duration_ms。

实测拖库后查 query_log(集群模式要用 clusterAllReplicas 跨节点查):

CK 的 query_log 是“开箱即审计”,这是它相比其他数据库的一大优势。但要注意:

  1. query_log 默认只存在 CK 集群本地(system.query_log 表),拿到高权限的攻击者可 TRUNCATE 清除,生产应配置投递到 CLS/外部
  2. 集群模式下要用 clusterAllReplicas(‘default_cluster’, system.query_log) 才能查全。

取证要点

直接 SQL 查 system.query_log,按 read_rows 倒序,即可揪出“读取行数≈全表”的拖库查询 + 来源 IP + SQL 原文,是 7 种库里取证最便捷的之一。

Elasticsearch(腾讯云 ES 7.10)

拖库手法

# 大 size 一次拉万条
GET /members/_search {"size":10000,"query":{"match_all":{}}}

# scroll 游标全量遍历(经典 ES 拖库)
POST /members/_search?scroll=2m {"size":10000} → 反复 POST /_search/scroll

# 工具:elasticdump / esdump

实测 scroll 一次性拖走全部 10 万文档

场景 A:搜索慢日志

ES 默认搜索慢日志阈值较高,快速 _search 不会记录。把阈值调低(index.search.slowlog.threshold.query.warn: 0ms)后,通过 DescribeInstanceLogs –LogType 2 能看到拖库查询:

日志含完整 query source(“size”:10000)、search_type、total_hits、分片信息,但记录的是 ES 节点 IP,不是客户端真实 IP,溯源能力弱。

场景 B:全量审计

ES 的 X-Pack 安全审计(能记录客户端 IP + 用户 + 每个请求)是静态配置,需改 elasticsearch.yml + 重启,托管 ES 无法动态开启:

对照实测:自建 ES 开启全量审计

和 SQL Server 一样,我额外用 tccli 开了一台 CVM 自建 ES 7.10.1,验证“自建能不能补上托管版的审计短板”。关键前提:

ES 的 X-Pack 审计日志是订阅(Platinum)功能,免费 Basic 许可下 audit.enabled 是空操作。自建可开 30 天 Platinum 试用(POST /_license/start_trial?acknowledge=true)激活;

elasticsearch.yml 里 xpack.security.audit.enabled: true(再加 events.include: [authentication_success,…] + emit_request_body: true 即可记录完整请求体),重启生效。

开启后跑同样的 _search size=10000 / scroll 拖库,审计日志 <cluster>_audit.json 实测记录:

对照托管 ES,自建全量审计同样碾压。又一次印证:审计能力的天花板取决于是不是自建。托管 ES 拖库基本只能靠“事后调阈值+慢日志+流量”;自建 ES 开全量审计后,谁、从哪个 IP、用什么查询、拖走了哪些字段,一清二楚。

拖库横向对比

拖库指纹速查

数据库经典拖库工具/命令日志里的指纹特征
MySQLmysqldumpSELECT /*!40001 SQL_NO_CACHE */ * FROM …,RowsSent=全表
PostgreSQLpg_dump / \copyCOPY <表> TO STDOUT,大 SELECT *
RedisKEYS * / –bigkeys / –scan慢日志 KEYS *;命令统计 SCAN/TYPE/STRLEN 飙升
MongoDBfind({}) / mongodump审计 find: …, filter: {}(空过滤全集合扫描)
SQL Serverbcp … out / SELECT *默认无指纹;开 XEvent 后慢 SQL 进 .xel(滚动+延迟)
ClickHouseSELECT *(HTTP/native/MySQL口)query_log 中 read_rows≈全表 + 来源IP
Elasticsearch_search size=10000 / scroll慢日志反复 size:10000+scroll(需调低阈值)

审计能力与取证等级

数据库不开审计能拿到什么开审计能拿到什么审计完整度
MySQL(CDB)慢日志(>1s)+ 出流量全语句 + SentRows + 源IP/端口★★★★★ 完整语句级
PostgreSQL慢日志(>1s)+ 出流量全语句 + 对象名 + 行数,含亚秒查询★★★★★ 完整语句级
ClickHouse内置 query_log(默认全量)read_rows≈全表 + 来源IP + SQL 原文★★★★★ 内置全量·开箱即用
MongoDB慢日志(易漏)+ CurrentOp全命令 + ns + 源IP + 行数★★★★☆ 完整命令级
Redis(托管)慢日志(KEYS等)+ 命令统计(无命令级审计,–rdb 全量被禁)★★☆☆☆ 仅慢日志/监控
Redis(自建)慢日志 + 服务日志 SYNC 痕迹MONITOR 命令级流(时间戳+客户端IP+命令);–rdb 留复制日志★★★☆☆ 有 MONITOR 但非持久
SQL Server(托管)出流量 + 连接仅慢/阻塞 XEvent(需~45min 开启、有延迟、按服务端耗时计会漏全表导出★☆☆☆☆ 残废
SQL Server(自建 Win)出流量 + 连接原生 Audit:每条 SELECT + 完整语句 + client_ip + host_name +(认出 bcp),可写 Windows 事件日志★★★★★ 完整且强
Elasticsearch(托管)搜索慢日志(需提前调低阈值、只记节点IP)X-Pack 审计不可动态开启★★☆☆☆ 无易用全量审计
Elasticsearch(自建)搜索慢日志全量审计:每个请求 + 真实客户端IP + 用户 + 完整请求体(含拖了哪些 _source 敏感字段)★★★★★ 完整且强

拖库通用规律

无论哪种数据库,不开审计并不等于查不到

  • 大批量、慢的拖库 → 慢日志 + 出流量尖峰几乎总能发现;
  • 小批量、快的拖库(分页遍历) → 不开审计基本只能靠流量监控旁证,必须有审计才能坐实。

审计能力的天花板取决于“托管还是自建”。

  • 同样是 SQL Server / Elasticsearch,托管版拖库取证基本残废(SQLServer 慢XEvent 会漏全表导出、ES 根本开不了全量审计);自建版开原生审计后,谁、从哪个 IP、用什么语句/请求、拖走了哪些字段,全都记得清清楚楚。
  • 应急取证有强需求的库,自建 + 原生审计(或前置数据库审计探针/DBAudit 旁路)远比直接用托管实例可靠。
  • 但有反例:MongoDB 审计是企业版功能,自建社区版没有审计,反而不如托管版——“自建 > 托管”要看该库把能力放在社区版还是商业版。

数据库应急取证排查思路

拿到一个“疑似被拖库”的数据库,按以下顺序排查:

  1. 先问:有没有开审计?
    • 开了 → 直接拉审计日志,按“大结果集 SELECT / 全表导出指纹 / 空过滤 find”筛,基本能定性定量。
    • 没开 → 走下面的旁证链。
  2. 拉慢查询日志:找全表 SELECT *、COPY TO STDOUT、KEYS *、mysqldump 指纹语句,看 RowsSent/Duration。
  3. 看网络出流量监控:在可疑时间窗找 BytesSent 尖峰(实测拖库可达基线 ~170 倍)。
  4. 看命令/连接统计:Redis 看 TopNCmd 的 SCAN/TYPE 异常;通用看异常源 IP、异常连接数。
  5. 核对来源 IP:把日志里的 Host/ClientAddr 与已知业务白名单比对,圈出可疑客户端。
  6. 检查落地能力:确认 INTO OUTFILE/FILE 权限、SYNC 等危险能力是否被托管平台收敛(云上通常已收敛,有助于缩小外带路径)。
  7. 形成时间线:把审计/慢日志/流量尖峰对齐到同一时间轴,还原“接入→枚举→批量读取→外带”的完整链路。

应急加固建议

  • 所有生产库默认开启审计(MySQL/PG/MongoDB 云上一键开启,开销可接受)。
  • 把审计日志/慢日志/流量指标集中投递到 SIEM,配置“单查询 RowsSent 超阈值”“出流量突增”“KEYS */COPY TO STDOUT 关键字”等告警规则。
  • 数据库账号最小权限 + 来源 IP 白名单 + 强制审计不可关闭。
赞赏

微信赞赏支付宝赞赏

Zgao

愿有一日,安全圈的师傅们都能用上Zgao写的工具。

发表评论