生产环境的数据库一旦被攻破,业务基本就等同于裸奔。我们不讲虚的,直接看怎么堵住最常见的口子。大部分入侵并非来自什么高深莫测的零日漏洞,而是配置疏忽、权限滥用和审计缺失。加固不是买个盒子或装个软件就完事,它是一套贯穿网络层、系统层、数据库内核和数据本身的动作组合。

网络层的第一道闸门:让数据库彻底“隐身”

数据库最怕的是直接暴露在公网。你只要用扫描器一扫,端口号1433、3306、1521、5432、27017赤裸裸地亮在那里,就等于告诉攻击者“来打我”。第一步,必须把数据库监听的地址绑定在内网IP上,严禁监听0.0.0.0。以MySQL为例,检查my.cnf中的bind-address参数,务必设成具体的内网IP。对于PostgreSQL,修改postgresql.conf里的listen_addresses。如果业务场景确实需要跨网段访问,绝对不要用端口映射这种粗暴方式,必须通过专线或SD-WAN组建的私有网络来承载流量。

防火墙策略要遵循最小化原则,做成白名单模式。只放行业务应用服务器的IP和DBA的跳板机IP,其他一律拒绝。这里有个极易被忽视的细节:云环境下的安全组。很多人安全组规则放得很宽,比如对同VPC内所有IP开放数据库端口。这极其危险,一旦同VPC内某台Web服务器被拿下,数据库就成了囊中之物。安全组的源IP必须精确到单台服务器的私网IP,不要图省事用IP段。

传输与访问通道的强制加密

即使在内网,流量也可能被旁路嗅探。必须强制开启SSL/TLS加密传输。MySQL 8.0默认会尝试使用SSL,但很多老项目为了兼容会配置skip-ssl或者在连接串里写useSSL=false,这等于自废武功。你需要检查用户权限表,对特定用户强制要求SSL连接,命令是:

ALTER USER 'app_user'@'%' REQUIRE X509;

PostgreSQL的pg_hba.conf里,把认证方法从md5改成scram-sha-256,并在hostssl条目里配置客户端证书验证。MongoDB副本集之间的内部通信也必须通过--tlsMode requireTLS开启加密。证书管理是落地难点,建议搭建内部CA,用自动化脚本定期轮换证书,避免证书过期导致业务全挂。

操作系统层面的“去特权化”

绝不要用root或Administrator来运行数据库进程。安装完成后,必须创建专门的低权限操作系统账户,比如mysql、postgres。这个账户的shell要设为/sbin/nologin,禁止交互式登录。数据文件、日志文件、配置文件的属主和属组要严格限定,权限设为600或750。Linux下要特别注意umask设置,确保数据库进程新建的文件默认权限就是受限的。

SELinux或AppArmor是最后一道防线,不要因为“麻烦”就关掉。为数据库进程定制安全策略,限定它能访问的目录、端口和系统调用。一旦Web应用存在SQL注入被用来执行系统命令,强制访问控制系统能阻止数据库进程去访问/etc/passwd或发起外联。你可以先用permissive模式跑一段时间,用audit2allow收集日志生成策略模块,再切到enforcing模式。

数据库引擎自身的安全基线

安装完数据库后的第一件事,就是运行官方提供的安全脚本。MySQL用mysql_secure_installation,它能帮你删除匿名用户、禁止root远程登录、删除test库。PostgreSQL则需要你手动处理,但逻辑一样:删除public schema上的默认权限,收回所有用户对public schema的CREATE权限。

REVOKE CREATE ON SCHEMA public FROM PUBLIC;

数据库的版本要维持在一个稳定的、仍受支持的大版本上,并及时应用安全补丁。别小看补丁,很多提权漏洞就是靠补丁封堵的。另外,数据库自带的示例数据库、无用存储过程要全部清理。MySQL的sys库如果不用就删掉,PostgreSQL里可能残留的扩展如dblink,不用就drop extension。这些组件本身可能成为攻击载体。

账户体系与权限治理的精细化操作

权限管理是重灾区。应用账号绝对不要赋予DDL权限,更别提SUPER、FILE这类高危权限。权限粒度要精确到表级和列级。一个订单表的查询账号,就只给SELECT,并且只限定在它需要的那几列,身份证、手机号这类敏感字段要单独剥离。遵循“应用账号只干活,DBA账号管结构,审计账号盯着看”的三权分立原则。

密码策略要硬性落地。MySQL从8.0开始支持密码过期策略和密码复杂度组件validate_password。设置default_password_lifetime为90天,并安装组件后设置密码长度、混合大小写和特殊字符的策略。但更推荐的做法是,应用层全部改用证书或令牌认证,彻底消灭静态密码。对于仍需密码的DBA个人账号,强制启用多因素认证,比如配合LDAP或PAM模块接入企业微信或飞书的二次验证。

SQL注入的纵深防御

不要指望应用层能百分之百防住SQL注入,数据库自身也要具备防御能力。数据库防火墙或SQL审计网关可以做到语句级的拦截。但如果没有预算采购商业产品,可以利用数据库自身的特性。PostgreSQL可以通过创建只允许参数化查询的规则或利用pg_stat_statements来监控异常模板。MySQL的企业版有Firewall插件,社区版则可以通过ProxySQL这类中间件来设置查询规则白名单,拦截不符合预期的SQL模式。

一个更底层的做法是使用数据库的“只读”视图和存储过程封装。应用账号完全剥离对基表的直接访问权限,只授予调用存储过程的执行权限。存储过程内部严格校验参数类型和长度,这样即使应用层有注入点,攻击者也无法随意篡改SQL语句结构,只能按你预设的逻辑走。

数据静态加密与密钥管理

磁盘加密只防物理盗窃,不防数据库层面的非法访问。必须开启透明数据加密(TDE),MySQL的InnoDB表空间加密、PostgreSQL的pg_tde扩展或者文件系统层的加密。关键点在于密钥管理。绝对不要把加密密钥明文写在配置文件或环境变量里。要使用密钥管理服务,或者用Hashicorp Vault搭建私有密钥管理服务,实现密钥的自动轮换和访问审计。对于敏感字段,如身份证号、银行卡号,还要在应用层先做一层加密再入库,这样即使DBA导出数据,看到的也是密文。

审计日志的全面开启与集中分析

审计不是摆设,要能回溯任何一条数据的来龙去脉。MySQL的企业版审计插件能记录详细的连接、查询和登出信息,社区版可以用Percona的审计插件或者MariaDB的server_audit。PostgreSQL原生的pgAudit扩展能精确到会话级或对象级审计。审计日志必须包含源IP、时间戳、执行的完整SQL语句、影响行数和执行用户。

日志绝不能只存在数据库本地。攻击者一旦拿到高权限,第一件事就是清日志。要配置rsyslog或filebeat,将审计日志实时、异步地传输到远端的集中式日志平台,如ELK栈或ClickHouse集群。针对日志设置告警规则,比如短时间内大量失败登录、执行了drop/truncate操作、或者从非业务IP发起的连接,这些信号要能在分钟级推送到运维群。

备份的安全性与可恢复性验证

备份是抵御勒索病毒的最终手段,但备份本身也是攻击目标。备份文件必须加密,无论是用mysqldump导出的文件还是物理备份的xtrabackup,都要用gpg或openssl进行加密后再传输和存储。备份存储的位置要与生产环境做物理或账号级别的隔离,采用“推”模式而非“拉”模式,即由生产机器主动把备份推到备份服务器,备份服务器没有权限访问生产库。

更重要的是恢复演练。每个季度至少做一次全量恢复演练,验证备份文件是否完好、恢复流程是否顺畅、恢复后的数据是否需要脱敏处理才能用于预发布环境。很多团队备份策略看似完善,真到用时发现备份文件损坏或者恢复脚本早已过时,这种教训比比皆是。

高危操作的变更管控与熔断机制

Drop table、truncate、update without where这类操作,要建立技术层面的硬拦截。在上线前,所有DDL和DML变更脚本必须经过代码审查平台,由另一位DBA或开发负责人审批。在数据库客户端工具上做限制,比如禁用生产环境的自动提交,强制所有事务以begin开始,以commit或rollback结束。对于MySQL,可以设置sql_safe_updates=1,它禁止不带where条件的update和delete,也禁止不带limit的语句,虽然简单但能挡住不少低级错误。

对于核心表,还可以加一个“软删除”层。业务代码不做物理删除,只更新is_deleted标记。数据库侧创建一个规则或触发器,将对主表的delete操作转换为update操作。这样即使有人误操作,数据也能在秒级恢复,而不用走漫长的备份恢复流程。

持续的漏洞扫描与基线核查

加固不是一次性项目。你需要把数据库的安全配置固化成脚本,用Ansible或SaltStack定期巡检。检查项包括:是否有多余的超级管理员账号、密码是否为默认、是否开启了通用日志或慢查询日志(防止日志撑爆磁盘也是一种安全)、关键参数是否被篡改。可以用开源工具如OpenSCAP搭配自定义的数据库检查脚本,每天跑一次报告。发现偏离基线的配置项,自动尝试修复并告警,修复不了的直接通知责任人。

数据库的漏洞库要持续跟踪。CVE详情一出来,就要评估对你所用版本的影响。尤其是那些涉及权限提升和远程代码执行的漏洞,必须建立应急响应流程,在24小时内完成评估和修补。把数据库纳入漏洞管理平台的全生命周期管理,从发现、评级、修复到验证形成闭环。