MySQL系统库安全依赖服务进程可信、操作系统隔离和运行时权限最小化三重防护,硬编码ACL无效;需禁用远程root账户、限制mysql库访问、禁用--skip-grant-tables、加固文件系统权限并定期校验user表哈希值。
MySQL系统库为什么不能靠ACL硬编码来保护
直接在代码里写死 grant 语句或把权限逻辑塞进应用层,等于把锁芯焊死在门框上——表面看着牢,实际绕过成本极低。mysql 的 mysql 系统库(含 user、db、tables_priv 等表)本身由服务端严格管控,任何绕过 mysqld 权限校验路径的访问(如直接读磁盘文件、用 root 启动跳过权限检查、物理备份恢复后提权)都会让硬编码 acl 彻底失效。
真正有效的保护必须落在 MySQL 运行时的权限模型和部署边界上,而不是靠应用代码“假装控制”。
禁用 root 远程登录 + 最小化系统库账户
90% 的未授权访问源于过度宽松的初始账户配置。默认 root@localhost 可以操作 mysql 库,但绝不能有 root@'%' 或 root@'192.168.%' 这类通配符远程账户。
- 执行
DROP USER 'root'@'%';(如果存在) - 确认仅保留
root@localhost,且密码强度足够;用SELECT user,host,authentication_string FROM mysql.user WHERE user='root';核查 - 新建专用管理账户(如
dba_admin),只赋予必要权限:GRANT SELECT,INSERT,UPDATE ON mysql.user TO 'dba_admin'@'localhost';,不给DROP或CREATE USER - 禁止任何应用账户拥有
mysql库的SELECT权限——除非是监控工具且走本地 socket 连接
启用 --skip-grant-tables 是高危操作
运维中临时加 --skip-grant-tables 启动 MySQL,等于拔掉整栋楼的门禁卡系统。此时所有连接(包括网络来的)都能无条件读写 mysql 库,user 表可被任意修改,ACL 规则形同虚设。
真实场景中应避免该参数:
- 仅限本地终端直连、无网络暴露、且启动后立即修复权限并重启的极端故障恢复
- 绝对不可写入 systemd service 文件或 Docker
command中作为常驻配置 - 若必须使用,启动后立刻执行
FLUSH PRIVILEGES;并移除参数重启,否则后续所有权限变更都不生效
文件系统级加固:防止 mysqld 未运行时被篡改
MySQL 停机状态下,mysql 库的 frm、ibd、csv 文件仍可被操作系统用户直接读写。若攻击者获得服务器普通用户权限,就能离线修改 user 表内容,下次启动即生效。
关键防护点:
- 确保
mysqld进程以专用系统用户(如mysql)运行,且数据目录(如/var/lib/mysql)属主为该用户,权限为750或更严 - 禁用数据库目录下所有用户的 shell 登录权限:
usermod -s /usr/sbin/nologin mysql - 对
mysql库所在分区启用文件系统只读挂载(仅限只读从库或归档场景),或用chattr +a限制追加写入 - 定期校验
mysql.user表哈希值(如用SELECT SHA2(GROUP_CONCAT(user,host,authentication_string SEPARATOR '|'),256) FROM mysql.user;),异常变动即告警
--skip-grant-tables 就不是唯一入口。











