最新消息:

Read MySQL Client’s File

渗透流程与思路 admin 2757浏览 0评论

这应该是一个比较老的问题了,前几天看到其他人聊到这个问题,拿出来分析一下。

简单的讲,就是我们可以伪造一个 MySQL 的服务端,甚至不需要实现 MySQL 的任何功能(除了向客户端回复 greeting package),当有客户端连接上这个假服务端的时候,我们就可以任意读取客户端的一个文件,当然前提是运行客户端的用户具有读取该文件的权限。

在复现的时候,有些地方踩到了一些坑,原作者没有说明,特此记录一下。

0x00 LOAD DATA INFILE

这个问题主要是出在LOAD DATA INFILE这个语法上,这个语法主要是用于读取一个文件的内容并且放到一个表中。通常有两种用法,分别是:

load data infile "/data/data.csv" into table TestTable;
load data local infile "/home/lightless/data.csv" into table TestTable;

有时候也会与FIELDS TERMINATED BY '\n'一起使用,效果更佳。这两种用法的区别就是差了一个local,第一个 SQL 语句的意思是,读取服务器上/data/data.csv文件,并写入到TestTable中;第二个 SQL 语句的意思则是,读取本地(客户端)这边的/home/lightless/data.csv文件,并写入到TestTable中。而我们这次要利用的也就是LOAD DATA LOCAL INFILE这种形式。

通过查阅 MySQL 的官方文档,在文档上,官方也指出了这个语法的问题:

那么接下来,我们来看下如何构造一个恶意的 MySQL 服务端来读取客户端的文件。

0x01 Capture The Package

如果想构造这样的服务端,首先要搞明白 MySQL 的交互流程,测试环境如下:

  • Ubuntu 18.04
  • MySQL 官方 APT 仓库安装的 5.7.23

通过 Wireshark 抓取 3306 端口的数据包,一开始发现 MySQL 的数据包全部走了 SSL 通信。

仅有一开始的两个 MySQL 的包,后面全是 SSL 数据了,这样也就没法搞明白是怎么读客户端文件的了。我们需要把 SSL 关掉,只需要关闭 MySQL Client 端的 SSL 即可,在配置文件的[mysql]节添加skip_ssl(或者关掉服务端的 SSL 支持也可以):

这样 Wireshark 中就可以抓到正常的数据包了。会发现一共有这样几步:

  1. greeting 包,获取服务端的 banner;
  2. 登录请求包;
  3. 初始化的一些查询,比如select @@version_comment limit 1之类的;

接下来我们找到关键的LOAD DATA INFILE数据包,第一个包看起来比较正常,是客户端发起的Request Query,如果你无法使用LOAD DATA INFILE语法的话,考虑在连接 MySQL 的时候加上--enable-local-infile选项,或者设置local_infile全局变量为ON

但是紧接着,服务端回复了一个包含刚刚请求中文件名的包,这里把/etc/passwd又给发回去了:

然后客户端向服务端发送了/etc/passwd文件的内容:

看到这里,也许开始有点想法了,如果我们在客户端发送查询之后,返回一个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 statement.”,可以看到,客户端读取哪个文件其实并不是自己说了算的,是服务端说了算的,形象一点的说就是下面这个样子:

  • 客户端:hi~ 我将把我的 data.csv 文件给你插入到 test 表中!
  • 服务端:OK,读取你本地 data.csv 文件并发给我!
  • 客户端:这是文件内容:balabal!

正常情况下,这个流程不会有什么问题,但是如果我们制作了恶意的客户端,并且回复服务端任意一个我们想要获取的文件,那么情况就不一样了。

  • 客户端:hi~ 我将把我的 data.csv 文件给你插入到 test 表中!
  • 服务端:OK,读取你本地的 / etc/passwd 文件并发给我!
  • 客户端:这是文件内容:balabal(/etc/passwd 文件的内容)!

看到这里可能有同学会问,“即便可以读任意文件,那也要等到客户端发起 LOAD DATA INFILE” 的时候才能回复呀!如果你刚才仔细阅读官方文档上的安全风险的话,会发现有这么一句:”A patched server could in fact reply with a file-transfer request to any statement, not just LOAD DATA LOCAL”

伪造的服务端可以在任何时候回复一个 file-transfer 请求,不一定非要是在LOAD DATA LOCAL的时候。这里有一点要说明的是,如果想要利用此特性,客户端必须具有 CLIENT_LOCAL_FILES 属性,这一点也会在下文提到的官方数据包格式文档中有所说明,这也是为什么在前面测试的时候需要添加--enable-local-infile的原因。

0x02 Pseudo Server

那么我们现在可以开始制作我们的服务端了,主要是以下几个步骤:

  1. 向 MySQL Client 发送Server Greeting
  2. 等待 Client 端发送一个Query Package
  3. 回复一个file transfer请求

现在要解决的就是两个问题,分别是Server Greeting包和file transfer包的格式,不过也不难,这些包的格式都可以在 MySQL 的官方文档上找到,首先来看File Transfer的包格式,Protocol::LOCAL_INFILE_Request,这幅图也可以发现,我们需要等待一个来自 Client 的查询请求,才能回复这个读文件的请求

官方文档上还贴心的准备了一个 Example:

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的数据包结构。如果感觉自己伪造比较困难的话,可以直接提取前面通过 Wireshark 抓到的包,修改一下长度、文件名之类的字节即可。

这里给一个Greeting包的样例,每个字段的作用均已表明,参考文档不难理解。

'\x0a',  # Protocol
'6.6.6-lightless_Mysql_Server' + '\0',  # Version
'\x36\x00\x00\x00',  # Thread ID
'ABCDABCD' + '\0',  # Salt
'\xff\xf7',  # Capabilities, CLOSE SSL HERE!
'\x08',  # Collation
'\x02\x00',  # Server Status
"\x0f\x80\x15", 
'\0' * 10,  # Unknown
'ABCDABCD' + '\0',
"mysql_native_password" + "\0"

接下来就是动手写 PoC 了,如果不想自己动手,可以参考 “参考文档” 中的 PoC。

一开始构造好的时候,用客户端去连接,总是提示 ERROR 2026 (HY000): SSL connection error: protocol version mismatch 或者 ERROR 2027 (HY000): Malformed packet。如果你在构造 PoC 的时候也出现了这种问题,很大可能是握手包构造的有问题,对照文档仔细检查。客户端默认是支持 SSL 的,服务端需要告诉客户端服务端不支持,我通过两次分别抓 “服务端支持 SSL” 和“服务端不支持 SSL”的包进行比对,再参考文档,找到了关闭 SSL 的方法,就是Capabilities这两个字节,\xf7 则表示不支持 SSL,如果不明白,抓个包比对一下就懂了。

仔细观察下图中的各种字段,避免踩坑。

0x03 Exploit it!

a. MySQL Client

使用 MySQL Client 进行测试,效果拔群:

b. PHP with mysqli

PHP通过mysqli连接恶意数据库,效果拔群:

c. PHP with PDO

默认未开启MYSQL_ATTR_LOCAL_INFILE属性,需要手工开启才可以以。

d. Python with MySQLdb

原作者说无效,但是我测试了一下,效果拔群。

e. Python3 with mysqlclient

效果拔群。

f. Java with JDBC Driver

效果拔群。

z. Others

其他语言各位可以自行测试。

0x04 Defense And Thinking

对于这种攻击的防御,说起来比较简单,首先一点就是客户端要避免使用 LOCAL 来读取本地文件。但是这样并不能避免连接到恶意的服务器上,如果想规避这种情况,可以使用--ssl-mode=VERIFY_IDENTITY来建立可信的连接。

当然最靠谱的方式还是要从配置文件上根治,关于配置上的防御问题,可以参考这篇文档进行设置。

用途的话,做蜜罐是肯定可以的,但是受众面好像不太完整,各种语言的支持都不太一样,比如 Python 中的 MySQLdb 包,原作者说这个包不受影响,但是我测试的时候确是受影响的,而 PHP+PDO 的方式又不受影响,所以能否中招还是要靠一些运气。

而且这些语言中的三方包在连接MySQL的时候,基本上在连接成功之后都会发出一下SELECT语句来查询一些版本号、编码之类的数据,这就达成了前面提到过的第二个攻击条件:等待客户端发来一个QUERY请求,所以如果这些第三方包允许执行LOAD DATA INFILE,危害还是比较大的。

0xFF 参考文档

 

转自:https://lightless.me/archives/read-mysql-client-file.html

参考资料:https://www.freebuf.com/vuls/188910.html

转载请注明:jinglingshu的博客 » Read MySQL Client’s File

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. Remember that first creditors are usually a terrific deal more likely to work with you. In reality, over 90% of customers that are sued for accounts that are time-barred don't appear in court, which may result to reset. There are lots of imitation specialists which should not be confused for the experts who care. You may also include in that letter that they respond with more info about your situation. Even though Texas law permits defendants to answer a lawsuit with a denial that is general there are different problems which needs to be raised with the court prior to an answer is submitted they're waived. Receive a attorney Most courts commonly assume that you would receive a credit score card lawyer in California to assist you with the circumstance. The amount it collects is kept by the debt buyer. http://www.freetle.com/7487/the-true-meaning-of-buffalo-new-york
    debt collection6年前 (2019-03-07)回复
  2. For most up-to-date information you have to go to see internet and on the web I found this web site as a most excellent website for most up-to-date updates.
    Carmon6年前 (2019-06-06)回复