MySQL客户端任意文件读取
source link: https://www.mi1k7ea.com/2021/04/23/MySQL%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
MySQL客户端任意文件读取
2021-04-23 /0x00 前言
之前学习Jackson一条Gadget的时候涉及过,HW期间又发现类似的恶意利用工具和漏洞,就再补充一些细节。
0x01 MySQL客户端任意文件读取
LOAD DATA LOCAL INFILE
具体可参考:https://dev.mysql.com/doc/mysql-security-excerpt/5.7/en/load-data-local-security.html
MySQL支持使用LOAD DATA LOCAL INFILE语句,即可将客户端本地的文件中的数据insert到MySQL的某张表中。
注意,还有个LOAD DATA INFILE语句,这是加载服务端的文件而非客户端的。
LOAD DATA LOCAL INFILE的工作过程大致如下:
- 用户在客户端输入:load data local file “/data.txt” into table test;
- 客户端->服务端:我想把我本地的/data.txt文件插入到test表中;
- 服务端->客户端:把你本地的/data.txt文件发给我;
- 客户端->服务端:/data.txt文件的内容;
测试看下LOAD DATA LOCAL INFILE语句,用Kali作为客户端远程连接MySQL服务,然后执行如下SQL语句来将/etc/passwd
文件中的内容插入到MySQL的users表中:
load data local infile "/etc/passwd" into table users FIELDS TERMINATED BY '\n';
上述过程存在一个问题,即客户端发送哪个文件的内容,取决于第三步即服务端响应的想要的哪个文件,如果服务端是个恶意的MySQL,那么它可以读取客户端的任意文件内容,比如读取/etc/passwd:
- 用户在客户端输入:load data local file “/data.txt” into table test;
- 客户端->服务端:我想把我本地的/data.txt文件插入到test表中;
- 服务端->客户端:把你本地的/etc/passwd文件发给我;
- 客户端->服务端:/etc/passwd文件的内容;
而且,在大部分客户端(比如MySQL Connect/J)的实现里,第一步和第二部并非是必须的,客户端发送任意查询给服务端,服务端都可以返回文件发送的请求。而大部分客户端在建立连接之后,都会有一些查询服务器配置之类的查询,所以使用这些客户端,只要创建了到恶意MySQL服务器的连接,那么客户端所在的服务器上的所有文件都可能泄露。
注意:如果使用MySQL客户端直接连接的话,是需要添加--enable-local-infile
选项的,而其他大部分MySQL客户端实现中,是默认开启的,比如allowLoadLocalInfile是MySQL的JDBC驱动的一个创建连接的配置项、用来控制是否允许从本地读取文件,默认值为True,具体的MySQL客户端实现得具体看。
攻击流程如下:
- 攻击者开启伪造的恶意MySQL服务器,诱使受害者MySQL客户端访问;
- 受害者向恶意MySQL服务器发起请求,并尝试进行身份认证;
- 恶意MySQL服务器接受到受害者的连接请求后,发送正常的问候、身份验证正确并且发送LOAD DATA LOCAL INFILE语句来读取受害者客户端本地敏感文件;
- 受害者的MySQL客户端认为身份验证正确,执行攻击者的发来的请求,通过LOAD DATA LOCAL INFILE语句将本地文件内容发给恶意MySQL服务器;
- 恶意MySQL服务器接受到客户端敏感文件,Done;
GitHub上恶意MySQL服务相关项目:
开启恶意MySQL服务后,受害者尝试使用MySQL客户端连接恶意服务端(这里metasploitable机子的MySQL版本为5.0.51a-3ubuntu5,无需添加--enable-local-infile
选项即可成功):
恶意MySQL服务端窃取到了/etc/passwd
文件内容:
针对LOAD DATA LOCAL INFILE的安全问题,MySQL官方给出如下说明:
为了避免连接到不受信任的服务器,客户端可以建立安全连接并通过使用
--ssl-mode=VERIFY_IDENTITY
选项和适当的CA证书进行连接来验证服务器身份 。为避免出现
LOAD DATA
问题,客户应避免使用LOCAL
。管理员和应用程序可以配置是否允许本地数据加载,如下所示:
在服务器端:
- 所述
local_infile
系统变量控制服务器端LOCAL
的能力。根据local_infile
设置,服务器会拒绝或允许请求本地数据加载的客户端加载本地数据。- 默认情况下,它
local_infile
是禁用的。要显式地使服务器拒绝或允许LOAD DATA LOCAL
语句(无论在构建时或运行时如何配置客户端程序和库),请在 禁用或启用的情况下启动mysqldlocal_infile
。local_infile
也可以在运行时设置。在客户端:
该CMake的选项控制编译默认的MySQL客户端库能力(见 MySQL源代码的配置选项)。因此,未进行明确安排的客户端将 根据MySQL构建时指定的设置禁用或启用功能 。
ENABLED_LOCAL_INFILE
LOCAL`
LOCAL[
ENABLED_LOCAL_INFILE`](https://dev.mysql.com/doc/refman/5.7/en/source-configuration-options.html#option_cmake_enabled_local_infile)默认情况下,MySQL二进制发行版中的客户端库在
ENABLED_LOCAL_INFILE
启用时进行编译 。如果从源代码编译MySQL,请ENABLED_LOCAL_INFILE
根据未进行显式安排的客户端应LOCAL
禁用还是启用功能,将其配置为禁用或启用。对于使用C API的客户端程序,本地数据加载功能由编译到MySQL客户端库中的默认值决定。要显式启用或禁用它,请调用
mysql_options()
C API函数以禁用或启用该MYSQL_OPT_LOCAL_INFILE
选项。参见 mysql_options()。对于mysql客户端,本地数据加载能力由编译到MySQL客户端库中的默认值决定。要显式禁用或启用它,请使用
--local-infile=0
或--local-infile[=1\]
选项。对于mysqlimport客户端,默认情况下不使用本地数据加载。要显式禁用或启用它,请使用
--local=0
或--local[=1\]
选项。如果
LOAD DATA LOCAL
在Perl脚本或其他[client]
从选项文件中读取该组的程序中使用,则可以向该组添加local-infile
选项设置。为防止不理解此选项的程序出现问题,请使用loose-
前缀指定它 :> [client]
> loose-local-infile=0
>
或者:
> [client]
> loose-local-infile=1
>
- 在所有情况下,
LOCAL
客户端成功使用加载操作还需要服务器允许本地加载。如果
LOCAL
禁用了此功能,则在服务器或客户端上,尝试发出LOAD DATA LOCAL
语句的客户端都会 收到以下错误消息:> ERROR 1148: The used command is not allowed with this MySQL version
>
0x02 MySQL蜜罐
利用该漏洞可以制作MySQL蜜罐来诱使攻击者连接,从而窃取攻击者主机上的敏感信息。GitHub上已有可以读取攻击者微信ID的MySQL蜜罐,具体参见:https://github.com/qigpig/MysqlHoneypot
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK