have_symlink=NO不起作用,因它是只读状态标识而非配置项,仅反映系统是否支持符号链接;真正禁用需设skip_symbolic_links=yes、local_infile=0并回收FILE权限。

必须设 skip_symbolic_links=yes,且同步关闭 local_infile、回收 FILE 权限,否则禁用无效。
为什么 have_symlink=NO 不起作用?
have_symlink 是只读状态变量,不是配置项。它只是 MySQL 启动时探测操作系统是否支持符号链接后自动填的值,类似“体检报告”——返回 YES 仅表示系统能力就绪,NO 可能是容器里压根不支持,和你配没配安全策略完全无关。
常见错误现象:
- 在配置里写了
have_symlink=NO,重启后SHOW VARIABLES LIKE 'have_symlink'依然显示YES - 误以为
have_symlink=NO就安全了,结果仍能执行CREATE TABLE t1 (id INT) DATA DIRECTORY='/tmp/testdir'成功建表
skip_symbolic_links=yes 必须写对位置和写法
MySQL 5.6 起已废弃 symbolic-links=0;8.0.33+ 版本会直接忽略它并静默启用符号链接。唯一可靠写法是:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
[mysqld] skip_symbolic_links=yes local_infile=0
注意点:
- 必须写在
[mysqld]段下,写在[client]或全局段无效 - 不要和
symbolic-links=0共存,避免被后者覆盖或引发冲突 -
local_infile=0必须同步设置——否则攻击者仍可用LOAD DATA LOCAL INFILE '/proc/self/environ'读取敏感文件
验证是否真生效,不能只看变量值
配置重启后,仅查 SELECT @@skip_symbolic_links; 返回 1 还不够。必须实测触发路径解析逻辑:
- 执行
CREATE TABLE t1 (id INT) DATA DIRECTORY='/tmp/testdir';—— 应报错ERROR 1030 (HY000): Got error 168 from storage engine或类似拒绝提示 - 执行
SELECT @@skip_symbolic_links;确认返回1(注意不是have_symlink) - 检查
SHOW VARIABLES LIKE 'local_infile';确保返回OFF - 如果
DATA DIRECTORY仍成功创建,说明配置未加载(比如改错了配置文件路径、没重启服务、或被其他my.cnf覆盖)
权限管控才是最后一道防线
即使 skip_symbolic_links=yes 和 local_infile=0 都开了,只要账号还保留 FILE 权限,攻击者仍可能通过其他方式绕过。所以必须同步做:
- 执行
REVOKE FILE ON *.* FROM 'user'@'host';回收所有非必要账号的FILE权限 - 用这条语句快速揪出高危账号:
SELECT User, Host, File_priv FROM mysql.user WHERE File_priv = 'Y'; - 生产环境禁止任何应用账号拥有
DROP、ALTER、SUPER、GRANT OPTION等权限
配置项只是开关,权限才是闸门——漏掉任意一环,符号链接的防护就形同虚设。

















