4. 数据库基线(MySQL):账号权限最小化、连接加密、审计日志、密码策略
各位同学好,今天我们来聊聊 MySQL 的基线安全。说实话,数据库这块我踩过的坑最多。早年在一家电商公司,就因为一个测试账号权限没收回,被人拖了库,那场面……嗯,不提了。今天我把这些年总结的四个核心点掰开揉碎讲给你听。
4.1 账号权限最小化:别给 root 当司机
我见过太多人,上来就用 root 连数据库。你想想看,这就像把家里所有钥匙都挂在大门上。万一被偷了,整个家都完了。
核心原则就一条: 每个账号只给够用的权限,多一个都不给。
权限分配黄金法则:
- 应用账号:只给
SELECT、INSERT、UPDATE、DELETE,别给DROP、ALTER - 备份账号:只给
SELECT和LOCK TABLES - 运维账号:按需给
CREATE、ALTER,但别给SUPER - 监控账号:只给
PROCESS和REPLICATION 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 基线安全框架,你可以照着这个思路去落地:
这四个点,说白了就是数据库安全的四个支柱。少一个,你的数据库就像没锁门的金库。我建议你回去之后,先拿测试环境练手,把每个点都配一遍,然后再上生产。
💡 最后说一句: 安全不是一锤子买卖。我每个月都会做一次基线审计,看看有没有新加的账号权限过大,有没有密码快过期了。养成习惯,才能睡得安稳。
公众号:蓝海资料掘金营,微信deep3321