真正要防的是“改了生效”,而非“改不了文件”;需隔离修改入口、限制执行者、增加变更感知,重点防护 my.cnf、mysqld-auto.cnf、启动脚本及容器配置等多处生效通道。

仅靠文件系统权限无法真正防止 my.cnf 被恶意篡改——因为配置文件本身不参与运行时校验,改了也不影响服务,但一旦被改错就可能导致 MySQL 启动失败或降级为不安全模式。 真正要防的是“改了生效”,而不是“改不了文件”。关键在隔离修改入口、限制执行者、增加变更感知能力。
my.cnf 文件权限设置的正确姿势
虽然不能防 SET GLOBAL,但合理的文件权限是基础防线,防止低权限用户意外覆盖或注入恶意配置:
-
my.cnf(通常位于/etc/my.cnf或/etc/mysql/my.cnf)必须由mysql用户所有,且权限设为644或更严(如600),禁止组/其他用户写入 - 若使用多级配置(如
/etc/my.cnf.d/*.cnf),整个目录需设为755,且子文件也必须是644,否则 MySQL 8.0+ 会跳过加载并静默忽略 - 不要把
my.cnf放在普通用户可写的路径(如/home/mysql/my.cnf),MySQL 启动时会按顺序读取多个位置,低优先级路径被篡改可能覆盖高优先级配置
为什么 chmod 600 不等于安全?
常见误区:把 /etc/my.cnf 设成 600 就万事大吉。实际问题在于:
使用ydata-profiling(前身为pandas-profiling)生成全面的数据质量报告,包含相关性分析、缺失值模式和基数检测。导出交互式HTML仪表板和JSON摘要。
- root 用户或具有
sudo权限的运维仍可直接修改——文件权限对 root 无效 - MySQL 启动脚本(如 systemd 的
mysqld.service)若配置了EnvironmentFile=指向可写路径,攻击者可劫持环境变量间接控制参数 - 某些容器化部署中,
my.cnf被挂载为 volume,宿主机上任意有权限的用户都可编辑源文件 - MySQL 8.0 引入
SET PERSIST会自动写入mysqld-auto.cnf,该文件权限默认为600且归mysql用户所有,但它不在my.cnf路径下,容易被忽略
用 inotifywait + 日志审计实时监控配置变更
防御性操作比事后追查更有效。在生产环境中,建议对关键配置路径做轻量级监听:
- 安装
inotify-tools后,用以下命令持续监控:inotifywait -m -e modify,move_self /etc/my.cnf /etc/mysql/my.cnf /var/lib/mysql/mysqld-auto.cnf
- 配合 systemd timer 或 cron,每 5 分钟检查一次
md5sum /etc/my.cnf是否变化,并将结果写入独立日志(如/var/log/mysql-config-audit.log) - 注意:不要监听整个
/etc/,避免误报;也不要依赖 MySQL 自身日志——它不记录配置文件读取行为
最易被忽略的漏洞点:启动脚本与容器 entrypoint
很多团队加固了 my.cnf,却忘了这些“绕过通道”:
- systemd service 文件中
ExecStart直接拼接参数,例如:ExecStart=/usr/bin/mysqld --max-connections=1000 --skip-grant-tables—— 这类硬编码参数优先级高于my.cnf,且修改 service 文件只需 root 权限 - Docker 容器启动时用
--config-file或command: ["mysqld", "--bind-address=0.0.0.0"],完全绕过宿主机的my.cnf - Kubernetes 中 ConfigMap 挂载的
my.cnf若未设置readOnly: true,Pod 内进程可直接覆盖
真正的防护不是锁死一个文件,而是厘清“哪些路径/机制能让配置生效”,然后逐层收敛权限和变更入口。尤其注意 mysqld-auto.cnf 和启动参数这两处,它们比 my.cnf 更隐蔽、更常被遗漏。

















