网站日常安全巡检如果还停留在扫端口、查挂马、看日志的阶段,那数据库这个核心资产基本就处于“裸奔”的盲区。很多运维团队都有一种错觉,认为数据库在内网,前面有防火墙,应用层做了防注入,数据库就高枕无忧了。但现实是,数据库被攻破的路径往往不是正面强攻,而是通过弱口令爆破、提权漏洞、配置疏忽或者内部违规操作。这次新增数据库专项排查,本质上就是把安全巡检从“边界防御”向“核心资产内审”延伸。下面直接拆解具体要查什么、怎么查、查出问题怎么处置。

弱口令与空口令的深度扫描

别只盯着root和sa这类超级管理员账户。排查的第一刀必须砍向弱口令,但范围要扩大。很多项目为了方便,会给监控账号、备份账号、只读账号设置123456或与用户名相同的密码。攻击者一旦拿到一个低权限的弱口令,配合数据库自身的高危漏洞(比如UDF提权),分分钟就能拿到系统权限。排查时不要手动去猜,直接用hydra或者专门的数据库爆破脚本跑一遍全量账户字典。重点检查MySQL的mysql.user表、PostgreSQL的pg_shadow视图、SQL Server的登录账户。如果发现auth_string或password_hash字段为空,那就是空口令,属于最高优先级风险,必须立即整改。另外,检查密码策略插件是否开启,比如MySQL的validate_password组件,如果连这个都没装,密码复杂度就形同虚设。

权限分配与角色滥用排查

数据库账户权限最容易出现“懒政”式授权。开发为了省事,直接给应用账户grant all privileges on *.*,这就是一颗定时炸弹。排查时要逐个库查授权表,执行show grants for 'user'@'host',把那些拥有SUPER、FILE、PROCESS、SHUTDOWN权限的非管理账户全部揪出来。特别注意MySQL 8.0的动态权限,比如BINLOG_ADMIN、CONNECTION_ADMIN这些,被授予后同样能做很多危险操作。SQL Server要重点看sysadmin和db_owner角色的成员列表,很多业务账户根本不需要这么高的角色。PostgreSQL要检查pg_roles中的rolsuper、rolcreatedb属性。一个硬性指标是:应用连接账户只能拥有对应业务库的CRUD权限,任何跨库授权、DDL权限、管理权限都必须收回。如果发现应用账户有file权限,那意味着攻击者可以通过select ... into outfile直接写webshell,这是致命风险。

版本与补丁的漏洞关联分析

巡检不是简单看一眼版本号就完事,必须把版本号与公开漏洞库做关联。很多公司数据库跑着MySQL 5.6.x或者更老的5.5.x,这些版本存在大量已知的远程代码执行和提权漏洞。比如经典的CVE-2016-6662,MySQL远程代码执行,影响的版本跨度极大。排查时要记录精确到小版本号,然后用漏洞扫描工具或者手动查询CVE数据库,列出当前版本存在的所有高危漏洞清单。如果业务无法立即升级,必须给出临时缓解措施,比如限制可连接IP、禁用危险函数。对于SQL Server,要特别注意那些已经停止扩展支持的版本,比如2008和2012(部分版本),这些不再接收安全更新的版本,一旦爆出新漏洞就是零日风险。PostgreSQL虽然整体安全性较好,但扩展插件如pg_dump、pg_stat_statements等如果版本过旧,同样存在提权路径。

审计日志与异常行为回溯

很多数据库默认关闭审计日志,或者日志保留时间极短,这导致被入侵后无法溯源。排查第一步就是确认审计功能是否开启。MySQL要检查general_log和log_slow_queries是否开启,但更关键的是企业版才有原生的audit_log插件,社区版需要借助第三方工具如Percona Audit Plugin或者MariaDB的server_audit。SQL Server要确认服务器审核和数据库审核规范是否启用。PostgreSQL可以检查pgaudit扩展的安装和配置情况。日志内容要重点筛查几个异常特征:非工作时间的大量数据导出操作、select into outfile或者xp_cmdshell这类危险函数的调用记录、来自非业务IP的连接请求、连续多次的登录失败记录(可能是爆破行为)。如果发现日志中存在grant或alter user操作,要立刻核实是否为授权变更。一个实用的排查技巧是直接查慢查询日志,攻击者在拖库时往往会产生大量全表扫描的慢查询,这些痕迹非常明显。

配置基线合规检查

数据库的默认配置从来不是为安全设计的,而是为兼容性和易用性。排查要对照安全基线逐项核对。MySQL要检查secure_file_priv是否设置为空或指定目录,如果为空且未限制,那文件读写就完全失控。local_infile必须设为0,防止通过load data local infile读取客户端文件。skip_symbolic_links要开启,防止通过软链接进行权限绕过。SQL Server要检查xp_cmdshell是否禁用,Ole Automation Procedures这类高危扩展存储过程是否关闭。PostgreSQL要检查pg_hba.conf中的认证方式,如果出现trust认证,那就是免密登录,必须改为md5或scram-sha-256。还要检查ssl参数是否开启,数据传输是否加密。这些配置项看似琐碎,但每一条背后都有真实的攻击案例。排查时可以直接写脚本批量抓取这些关键配置,生成合规报告,偏离项逐条标注风险等级。

存储过程与自定义函数风险审查

数据库里的存储过程和函数是权限维持和功能隐藏的重灾区。攻击者拿到高权限后,经常会创建名为sys_clean、db_maintain这类看似正常的存储过程,实际内部封装了提权、执行系统命令、反弹shell的逻辑。排查时要导出所有非系统存储过程和函数的源码,逐个人工审计。MySQL中要重点查mysql.proc表和information_schema.routines视图,关注包含exec、system、eval、xp_cmdshell等关键字的对象。SQL Server要查sys.procedures和sys.sql_modules,特别留意那些被标记为execute as owner且包含动态SQL的存储过程,这可能导致权限提升。PostgreSQL要检查所有用plpythonu、plperlu这类不受信语言编写的函数,它们可以直接执行操作系统命令。如果发现来源不明的存储过程,先禁用再追溯创建时间和创建者,这很可能是入侵痕迹。

数据备份与恢复策略验证

备份本身不是安全措施,但备份文件的安全性和备份策略的有效性直接关系到勒索攻击后的生存能力。排查要关注几个点:备份文件是否加密存储,太多备份直接以.sql或.bak格式明文存放在共享目录,一旦被攻击者获取,等于数据直接泄露。备份频率和保留周期是否满足RPO和RTO要求,最近一次全量备份和增量备份是否成功,必须实际做一次恢复演练,而不是只看备份日志。很多团队以为备份成功了,结果恢复时发现文件损坏或者缺少关键日志,这种教训太惨痛。另外要检查备份账户的权限,备份操作通常需要锁表或全局读锁,这个账户如果被滥用,可能导致业务中断。备份文件的传输通道也要加密,避免在网络上被嗅探。

连接安全与网络隔离核查

数据库端口是否直接暴露在公网,这个问题看似低级,但用shodan一搜就知道有多普遍。排查时用nmap从外网扫一遍公司所有IP段的3306、1433、5432、6379、27017等数据库端口,发现一个封一个。内网层面也要检查数据库是否只监听了必要的网卡接口,MySQL的bind-address是否设为0.0.0.0,如果业务只需要本地连接,就改为127.0.0.1。防火墙规则要细化到只允许应用服务器的IP访问数据库端口,拒绝其他所有内网IP的请求。另外检查是否启用了SSL/TLS加密连接,MySQL的require_secure_transport参数是否设为ON,PostgreSQL的pg_hba.conf中是否配置了hostssl条目。数据在网络上明文传输,等于把敏感信息拱手送人,在等保测评和合规审计中这是直接扣分项。

自动化巡检脚本落地

手动排查效率低且容易遗漏,必须把上述检查项固化为自动化脚本。下面给出一个MySQL专项排查脚本的核心片段,可以直接集成到日常巡检流程中:

#!/bin/bash
# MySQL安全巡检脚本(精简版)
HOST="127.0.0.1"
PORT="3306"
USER="root"
PASS="your_password"

echo "=== 空口令账户检查 ==="
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SELECT user,host FROM mysql.user WHERE authentication_string='' OR authentication_string IS NULL;"

echo "=== 弱口令账户检查(需结合字典) ==="
# 此处可调用hydra或自定义爆破逻辑,示例略

echo "=== 远程访问权限检查 ==="
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SELECT user,host FROM mysql.user WHERE host='%';"

echo "=== FILE权限检查 ==="
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SELECT user,host FROM mysql.user WHERE File_priv='Y';"

echo "=== secure_file_priv配置检查 ==="
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SHOW VARIABLES LIKE 'secure_file_priv';"

echo "=== local_infile配置检查 ==="
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SHOW VARIABLES LIKE 'local_infile';"

echo "=== 审计日志状态检查 ==="
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SHOW VARIABLES LIKE 'general_log%';"
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SHOW VARIABLES LIKE 'log_slow_queries%';"

echo "=== 非系统存储过程检查 ==="
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SELECT db,name,definer FROM mysql.proc WHERE db NOT IN ('mysql','sys','information_schema','performance_schema');"

echo "=== SSL状态检查 ==="
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SHOW VARIABLES LIKE 'have_ssl';"
mysql -h${HOST} -P${PORT} -u${USER} -p${PASS} -e "SHOW VARIABLES LIKE 'require_secure_transport';"

这个脚本可以根据实际环境扩展,加入Redis未授权访问检查、MongoDB空口令检查等。关键是要把输出结果格式化,异常项标红,通过邮件或企业微信推送给安全运维人员。建议每周至少跑一次全量检查,核心业务数据库每天执行轻量级检查。

整改优先级与处置闭环

查出来问题不整改等于白查。整改必须按风险等级排优先级:空口令和弱口令必须当天解决,直接修改密码并通知相关业务方更新连接配置。公网暴露的端口立即通过防火墙封堵,同时追溯是谁开的规则,避免下次再犯。高危版本漏洞如果无法立即升级,先通过网络隔离和禁用危险功能做缓解。权限滥用问题要拉上开发负责人和DBA一起评审,收回多余权限后观察业务是否报错,必要时在测试环境先验证。所有整改操作必须留痕,在工单系统中记录问题描述、风险等级、整改措施、责任人和完成时间。下次巡检时要重点复查历史问题是否复发,形成真正的安全闭环。

数据库专项排查不是一次性运动,而是要把这些检查项融入日常巡检的SOP里。安全团队和DBA之间要建立联动机制,任何数据库变更、新库上线、账户创建都必须经过安全审核。只有把数据库从“内网的保险箱”这个虚假安全感中拉出来,用对待边界防护同等级别的严苛态度去排查,才能真正守住核心数据这条底线。