4. 数据库基线(MySQL):账号权限最小化、连接加密、审计日志、密码策略

各位同学好,今天我们来聊聊 MySQL 的基线安全。说实话,数据库这块我踩过的坑最多。早年在一家电商公司,就因为一个测试账号权限没收回,被人拖了库,那场面……嗯,不提了。今天我把这些年总结的四个核心点掰开揉碎讲给你听。

4.1 账号权限最小化:别给 root 当司机

我见过太多人,上来就用 root 连数据库。你想想看,这就像把家里所有钥匙都挂在大门上。万一被偷了,整个家都完了。

核心原则就一条: 每个账号只给够用的权限,多一个都不给。

权限分配黄金法则:

  • 应用账号:只给 SELECTINSERTUPDATEDELETE,别给 DROPALTER
  • 备份账号:只给 SELECTLOCK TABLES
  • 运维账号:按需给 CREATEALTER,但别给 SUPER
  • 监控账号:只给 PROCESSREPLICATION CLIENT

我个人习惯用这样的方式创建账号:

-- 创建只读账号
CREATE USER 'app_read'@'192.168.1.%' IDENTIFIED BY 'StrongPass123!';
GRANT SELECT ON mydb.* TO 'app_read'@'192.168.1.%';

-- 创建应用写账号
CREATE USER 'app_write'@'192.168.1.%' IDENTIFIED BY 'AnotherPass456!';
GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_write'@'192.168.1.%';

-- 记得回收不必要的全局权限
REVOKE ALL PRIVILEGES ON *.* FROM 'app_write'@'192.168.1.%';
FLUSH PRIVILEGES;

⚠️ 我曾经犯过的错: 有一次给应用账号加了 DROP 权限,结果开发同学手滑执行了 DROP TABLE。从那以后,我所有生产环境的 DDL 操作都走审批流程,账号权限严格按角色划分。

4.2 连接加密:别让数据在网络上裸奔

你想想看,如果数据库和应用的连接是明文的,那中间有人抓个包,你的数据就全暴露了。说白了,这就是在裸奔。

MySQL 8.0 默认就开启了 SSL,但很多人不知道,或者嫌麻烦给关了。我建议你这样做:

-- 检查当前 SSL 状态
SHOW VARIABLES LIKE '%ssl%';

-- 强制用户使用 SSL 连接
ALTER USER 'app_write'@'192.168.1.%' REQUIRE SSL;

-- 在连接字符串中指定 SSL
# 应用端配置示例
jdbc:mysql://dbhost:3306/mydb?useSSL=true&requireSSL=true

💡 我的经验: 内网环境很多人觉得没必要加密。但我告诉你,内网攻击才是最可怕的。我曾经在客户现场,用 Wireshark 在内网抓包,十分钟就拿到了明文密码。所以,不管内外网,SSL 必须开。

4.3 审计日志:谁动了我的数据?

出了事总要查吧?没有审计日志,你连谁干的都不知道。MySQL 的审计功能,说白了就是给数据库装个监控摄像头。

我推荐用 MySQL Enterprise Audit 或者开源的 audit_log 插件。配置方法如下:

-- 安装审计插件
INSTALL PLUGIN audit_log SONAME 'audit_log.so';

-- 配置审计策略(在 my.cnf 中)
[mysqld]
audit_log_policy = ALL
audit_log_format = JSON
audit_log_file = /var/log/mysql/audit.log
audit_log_rotate_on_size = 100M
audit_log_rotations = 10

审计日志要记录的关键信息:

  • 谁连接的(用户名、IP)
  • 什么时候连接的(时间戳)
  • 执行了什么 SQL(完整语句)
  • 影响了多少行(影响行数)
  • 执行耗时(慢查询标记)

我记得有一次,客户说数据被删了。我查了审计日志,发现是凌晨三点一个开发账号在测试环境执行了 DELETE。因为没有审计,这个锅差点甩给 DBA。有了日志,真相一目了然。

4.4 密码策略:别再用 123456 了

这个我都不想多说,但每次渗透测试都能扫出一堆弱口令。MySQL 8.0 自带了密码策略组件,咱们得用起来。

-- 安装密码策略组件
INSTALL COMPONENT 'file://component_validate_password';

-- 设置密码策略等级
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 12;
SET GLOBAL validate_password.mixed_case_count = 1;
SET GLOBAL validate_password.number_count = 1;
SET GLOBAL validate_password.special_char_count = 1;

-- 查看当前策略
SHOW VARIABLES LIKE 'validate_password%';
策略等级 要求 适用场景
LOW 只检查长度 开发环境
MEDIUM 长度 + 数字/大小写/特殊字符至少一种 测试环境
STRONG 长度 + 数字 + 大小写 + 特殊字符 生产环境

⚠️ 注意: 密码策略别设得太死。我曾经见过一个公司要求密码 32 位且每 30 天换一次,结果所有人都把密码贴在显示器上。这反而更不安全。我个人建议:生产环境 12 位以上,90 天换一次,配合双因素认证,效果最好。

知识体系总览

下面这张图是我自己整理的 MySQL 基线安全框架,你可以照着这个思路去落地:

MySQL 基线安全框架 🔑 账号权限最小化 • 按角色分配权限 • 回收不必要的全局权限 • 定期审计账号权限 🔒 连接加密 • 启用 SSL/TLS • 强制用户使用加密连接 • 证书定期轮换 📝 审计日志 • 安装 audit_log 插件 • 配置日志轮转策略 • 定期分析审计日志 🔐 密码策略 • 启用 validate_password • 设置 STRONG 等级 • 定期更换密码 四者缺一不可,形成闭环安全体系

这四个点,说白了就是数据库安全的四个支柱。少一个,你的数据库就像没锁门的金库。我建议你回去之后,先拿测试环境练手,把每个点都配一遍,然后再上生产。

💡 最后说一句: 安全不是一锤子买卖。我每个月都会做一次基线审计,看看有没有新加的账号权限过大,有没有密码快过期了。养成习惯,才能睡得安稳。


公众号:蓝海资料掘金营,微信deep3321