必须同时禁用服务端local_infile=off、客户端local_infile开关、回收file权限并设secure_file_priv=null,仅关local_infile=off不够,因其只控制服务端是否响应load data local infile请求,而该操作实际由客户端主动读取本地文件(如/etc/passwd)并上传,服务端拒绝后仍可能被sql注入利用。

必须同时禁用服务端 local_infile 和客户端 local_infile 开关,再回收 FILE 权限并设 secure_file_priv = NULL——只做其中一两项,等于没防。
为什么只关 local_infile = OFF 不够?
因为 local_infile 只控制服务端是否响应客户端发来的 LOAD DATA LOCAL INFILE 请求,而该语句实际由客户端(比如 pymysql、mysql CLI)主动读取本地文件再发给服务端。服务端拒绝后,攻击者仍可能通过 SQL 注入诱使客户端读取 /etc/passwd 或 ~/.my.cnf 并回显。
-
SELECT @@local_infile;返回0≠ 安全落地,只是服务端配置生效 - 客户端默认可能仍协商 LOCAL 能力,比如旧版
mysqli或硬编码local_infile=True的 Python 代码 - Docker 镜像、云 RDS 参数组修改后常需手动“应用配置”,重启也不一定生效
服务端怎么关死 LOAD DATA LOCAL INFILE?
不能只靠 SET GLOBAL local_infile = 0,那是临时设置,重启即丢。必须写进配置并验证。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 在
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf的[mysqld]段加:local_infile = OFF
- 重启服务:
sudo systemctl restart mysql(或mariadb) - 连上后立刻执行:
SELECT @@local_infile;—— 必须返回0,不是字符串OFF - 顺手查:
SELECT @@secure_file_priv;,若为NULL,说明服务端侧的LOAD DATA INFILE也被锁死(这是另一层防护)
客户端哪些地方容易漏关?
Web 应用里最常漏掉的是连接库初始化代码,尤其是老项目或 ORM 封装层。
-
mysqlCLI:mysql -u root -p --local-infile=0,别信交互式里SET命令 - Python +
pymysql:pymysql.connect(..., local_infile=False)(注意是布尔值False,不是字符串) - Python +
mysql-connector-python:allow_local_infile=False(8.0.23+ 默认已关,但旧版本必须显式传) - PHP +
mysqli:mysqli_options($conn, MYSQLI_OPT_LOCAL_INFILE, false),且必须在mysqli_real_connect()之前调用 - Java + Connector/J:
&allowLoadLocalInfile=false(URL 参数,即使驱动默认关,也要确认没被显式打开)
怎么验证真的禁死了?
别只看配置或变量值,得用攻击者会用的方式直接试。
- 执行:
LOAD DATA LOCAL INFILE '/etc/passwd' INTO TABLE t1;→ 必须报错ERROR 1148 (42000),而不是权限错误或表不存在 - 执行:
LOAD DATA INFILE '/etc/passwd' INTO TABLE t1;→ 应报ERROR 1290 (HY000)(说明secure_file_priv = NULL生效) - 执行:
SELECT LOAD_FILE('/etc/passwd');→ 应返回NULL或明确权限错误(说明FILE权限已回收) - 检查用户权限:
SELECT User,Host,File_priv FROM mysql.user WHERE File_priv='Y';,特别是root账号要单独REVOKE FILE ON *.* FROM 'root'@'%';
最容易被忽略的是:托管环境(如阿里云 RDS、K8s sidecar)里配置可能被覆盖;应用代码里硬编码的 local_infile=True 比配置文件更优先;还有 secure_file_priv 设成空字符串 '' 或 /,等于完全放开路径校验。










