MySQL 8.0.22+默认禁用LOCAL INFILE,需服务端SET GLOBAL local_infile=ON、客户端显式启用;8.0.24+强化UDF签名校验与符号链接限制;mysql_upgrade异常多因残留--skip-grant-tables;Percona/MariaDB补丁节奏不同,须核对完整版本字符串。
MySQL 5.7 升级到 8.0 后 LOAD DATA LOCAL INFILE 突然失效?不是配置错了,是默认禁用了
mysql 8.0.22+ 默认关闭了客户端侧的 local infile 功能,哪怕服务端 local_infile=on、客户端也加了 --local-infile=1,连接时仍会静默拒绝——错误不报,但 load data local infile 返回空结果或“file not found”这类误导性提示。
根本原因是:客户端库(如 libmysqlclient、mysqlclient)在握手阶段不再主动声明支持 LOCAL INFILE,服务端因此跳过协商。这不是 bug,是安全策略收紧。
- 服务端必须显式启用:
SET GLOBAL local_infile = ON(需 SUPER 权限),且配置文件中local_infile=ON并重启 - 客户端连接时必须传参:
mysql --local-infile=1 -u user -p;程序里要用connect(..., local_infile=True)(Python mysql-connector)或mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, true)(PHP) - MyCLI、DBeaver 等工具默认不启用,需手动勾选“Allow local file loading”或改连接字符串加
?allowLocalInfile=true
用 CREATE FUNCTION 加载 UDF 提权?8.0.24+ 的 secure_file_priv 已拦不住了
旧思路是把恶意 .so 写进 /usr/lib/mysql/plugin/,再用 CREATE FUNCTION pwn RETURNS STRING SONAME 'libpwn.so' 注入执行权限。现在不行了——MySQL 8.0.24 起,UDF 加载强制校验签名,且 plugin_dir 不再允许写入(由包管理器锁定)。
真正危险的是绕过路径限制的加载方式:如果攻击者已有 FILE 权限,可先用 SELECT ... INTO DUMPFILE 把恶意代码写到 secure_file_priv 指向的任意目录(比如 /var/lib/mysql-files/),再通过符号链接把该目录映射到 plugin_dir 下合法子路径——但 MySQL 8.0.29+ 已禁止插件路径包含符号链接。
- 检查当前限制:
SHOW VARIABLES LIKE 'secure_file_priv';和SHOW VARIABLES LIKE 'plugin_dir'; - 禁止符号链接的验证命令:
ls -l $(mysql -Nse "SELECT @@plugin_dir"),若输出含->就得立刻修复 - UDF 文件必须属主为
mysql用户、权限 ≤644,否则加载失败并记入 error log
mysql_upgrade 运行后权限表乱了?别直接跑,先看 mysqld --skip-grant-tables 是否残留
打完安全补丁(如 Oracle 发布的 CPU 补丁)后执行 mysql_upgrade,常出现 Access denied for user 'root'@'localhost' 或 mysql.user 表结构异常——大概率是上一次升级中断,残留了未清理的 --skip-grant-tables 启动项,导致权限系统没加载,后续所有操作都在无鉴权状态下进行,mysql_upgrade 误把空权限表当正常状态覆盖了。
这不是数据损坏,而是元数据状态错位。关键要确认 mysqld 当前是否真在跳过权限验证。
- 查进程:
ps aux | grep mysqld | grep skip-grant,存在即危险 - 查配置:
mysqld --help --verbose 2>/dev/null | grep "default option"看是否加载了含skip-grant-tables的 cnf 文件 - 安全重启步骤:停服务 → 清掉 my.cnf 里所有
skip-行 →mysqld --initialize-insecure不要执行(会重置 root 密码)→ 改用mysqld --user=mysql --datadir=/var/lib/mysql手动启动验证
Percona Server / MariaDB 用户别只盯 MySQL 官方补丁
Oracle 的 CPU 补丁只覆盖官方 MySQL,Percona Server 和 MariaDB 使用独立分支,漏洞修复节奏不同。比如 CVE-2023-21912(通过 INFORMATION_SCHEMA 触发内存越界)在 MySQL 8.0.33 修复,但 Percona Server 8.0.32-24 才跟进,MariaDB 10.11.3 才加入——中间版本看似“打了补丁”,实则仍可被利用。
更隐蔽的是引擎层差异:MySQL 用 InnoDB,Percona 默认用 XtraDB,MariaDB 用 Aria/Maria,它们对 ALTER TABLE ... ENGINE= 的权限校验逻辑不同,某些提权链在官方版已堵死,在 XtraDB 中仍可通过 CREATE TABLE ... COMMENT='/* !50100 ... */' 注入执行。
- 查真实版本:
SELECT VERSION(), @@version_comment;,光看8.0.x不够,得确认末尾是不是-log、-Percona或-MariaDB - 引擎兼容性检查:
SHOW ENGINES;看SUPPORT列是否为YES或DEFAULT,DISABLED的引擎可能被绕过校验 - Percona 用户优先用
pt-upgrade替代mysql_upgrade,它会检测引擎特有字段(如xtradb_read_view)是否同步
最麻烦的从来不是补丁有没有装,而是你根本不知道自己用的到底是不是那个“打了补丁”的版本——VERSION() 返回的字符串里混着发行版签名,不拆开看就容易漏。


















