[toc]
LOAD DATA INFILE
mysql的LOAD DATA INFILE
语句主要用于读取一个文件的内容并且存入一个表中。通常有两种用法,分别是:
1 | load data infile "/etc/passwd" into table TestTable fields terminated by '分隔符'; |
第一个语句是读取服务器上的/etc/passwd
文件并存入TestTable
表中,第二个语句是读取客户端本地的/etc/passwd
文件并存入TestTable
表中。我们要利用的是LOAD DATA LOCAL INFILE
。 官方文档中也提出了这个问题(PS:Google翻译的不是很准确)
分析数据包
测试环境: MacOS 10.14 Mysql 5.7.21 使用tcpdump抓取3306端口的数据包 1.服务器向客户端发送greeting问候包,包含服务端banner信息
2.客户端发送登陆请求包,包含用户名密码,以及含有LOAD DATA LOCAL选项的客户端banner信息。
3.然后是客户端初始化的一些查询,比如
select database();
select @@version_comment;
4.找到我们执行的
LOAD DATA INFILE
数据包,第一个包看起来比较正常,是客户端发起的Request Query
。 5.但是紧接着服务器返回了一个包含刚才所要
LOAD DATA INFILE
的文件名/Users/smi1e/Desktop/test.txt
的数据包。 6.然后客户端向服务端发送了
/Users/smi1e/Desktop/test.txt
文件的内容: 如果我们在客户端发送查询之后,返回一个
Response TABULAR
数据包,即服务端向客户端发送了文件名的数据包,如果我们把这个文件名设置成我们想要读取的文件,那么我们就可以读取客户端的任意文件了。正如官方文档所写的 In theory, a patched server could be built that would tell the client program to transfer a file of the server's choosing rather than the file named by the client in the [LOAD DATA](https://dev.mysql.com/doc/refman/8.0/en/load-data.html "13.2.7 LOAD DATA Syntax") statement.
也就是说想要读取哪个文件是服务端说了算,跟客户端所request的文件名没有关系。 最重要的是伪造的服务端可以在任何时候回复一个file-transfer
请求,不一定非要是在客户端发送LOAD DATA LOCAL
数据包的时候。 不过如果想要利用此特性,客户端必须具有CLIENT_LOCAL_FILES
即(Can use LOAD DATA LOCAL
)属性。如果没有的话,就要在连接mysql的时候加上--enable-local-infile
。
搭建MySQL服务端
主要分为 * 向 MySQL Client 发送Server Greeting * 等待 Client 端发送一个Query Package * 回复一个file transfer请求 我们需要知道如何构造File Transfer
和Server Greeting
数据包,这些包的格式都可以在 MySQL 的官方文档上找到。 File Transfer
数据包格式:Protocol::LOCAL_INFILE_Request 并且我们需要等待一个来自 Client 的查询请求,才能回复这个读文件的请求。不过我们在上面看到客户端在连接成功后会自动的做一些初始化的查询。 官方也给了exmaple
1 | 0c 00 00 01 fb 2f 65 74 63 2f 70 61 73 73 77 64 ...../etc/passwd |
数据包的内容其实是从\xfb
开始的,这个字节代表包的类型,后面紧跟要读取的文件名。前面的0x0c
是数据包的长度(从 \xfb
开始计算),长度后面的三个字节\x00\x00\x01
是数据包的序号。
Greeting
数据包格式:官方文档,如果不会构造可以直接拷贝抓到的数据包然后改一下长度、文件名之类的。 这里直接拷贝大佬归纳的格式。
1 | '\x0a', |
POC
来源于https://www.vesiluoma.com/abusing-mysql-clients/的POC,测了一个多小时都没成功,最后发现里面 #3payload
写错了,我给改了下。
1 | #!/usr/bin/python |
ps: 实测 下面这个项目比较好用,上面的poc还需要改长度和内容的16进制值 Github还有一个项目:https://github.com/allyshka/Rogue-MySql-Server 该特性适用于:MySQL Client、 PHP with mysqli、Python with MySQLdb、Python3 with mysqlclient、Java with JDBC Driver等。