local_infile=OFF仅禁用客户端本地文件导入(LOAD DATA LOCAL INFILE),不控制服务端读取服务器文件;真正限制服务端文件操作的是secure_file_priv配置与FILE权限——必须设secure_file_priv=NULL并回收FILE权限,才能彻底禁用LOAD DATA INFILE、SELECT ... INTO OUTFILE和LOAD_FILE()。

为什么local_infile=OFF不能阻止服务端读文件
很多人以为把local_infile设为OFF就能禁掉所有文件读取,其实它只管LOAD DATA LOCAL INFILE——也就是客户端本地读文件再发给服务端的路径。服务端自己读服务器磁盘上的文件(比如LOAD DATA INFILE '/etc/passwd'或LOAD_FILE('/etc/passwd'))完全不经过这个开关。真正控制服务端读文件的是secure_file_priv和FILE权限。
禁用服务端读文件:必须设secure_file_priv=NULL
secure_file_priv是硬性白名单,设为NULL才能彻底禁用LOAD DATA INFILE和SELECT ... INTO OUTFILE。空字符串''等于放行任意路径,极度危险;设成具体目录(如/var/lib/mysql-files/)只是限制范围,不代表安全。
- 修改
my.cnf的[mysqld]段:secure_file_priv = NULL
- 必须重启
mysqld,SET GLOBAL动态设置无效 - 验证命令:
SELECT @@secure_file_priv;返回NULL才算生效
还要回收FILE权限,否则secure_file_priv=NULL形同虚设
即使secure_file_priv为NULL,只要用户仍有FILE权限,攻击者仍可能通过LOAD_FILE()函数绕过——因为LOAD_FILE不走secure_file_priv校验,只检查FILE权限和文件可读性。
- 执行:
REVOKE FILE ON *.* FROM 'username'@'host'; - 特别注意
root账号:默认带FILE权限,但日常管理根本不需要,应单独收回 - 检查残留:
SELECT User,Host,File_priv FROM mysql.user WHERE File_priv='Y';
验证是否真禁死:两个错误要同时触发
配置改完不是就结束了。得用实际语句测试,且必须看到两个不同错误,才说明双层防护都起效:
-
LOAD DATA INFILE '/etc/passwd' INTO TABLE t;→ 应报ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement(说明secure_file_priv=NULL生效) -
SELECT LOAD_FILE('/etc/passwd');→ 应报NULL(无权限时返回NULL,不是错误),或明确报错ERROR 1045 (28000): Access denied for user ... (using password: YES)(说明FILE权限已回收)
漏掉FILE权限回收,或者误把secure_file_priv设为空字符串,都会让防御在关键节点失效。


















