之前Get了h2 initsql的骚姿势,于是想总结总结jdbc url可控情况下的利用方法,经典的场景就是jdbc mysql 文件读取和反序列化,正好前不久的Druid CVE-2021-26919的用的就是jdbc mysql反序列化漏洞,学习学习,居然踩一些坑,单独记录下来。
mysql client任意文件读取漏洞历史悠久,参考【6】中有提到早在13年就有提出,但是作为mysql 正常功能一直保留。直到19年blackhat 张杨和可奕 大佬发现反序列化的利用场景(参考【5】),相关研究达到小高潮,不过多赘述。
MySQL Client文件读取漏洞
原理:load local data
正常的load local data流程
1 | client:申请跑个sql,内容是"load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';" |
攻击流程
1 | client:申请跑个sql,内容是"***"(jdbc-mysql-connector默认认证登录完成之后,会有show variables/select 参数等行为) |
local-infile & allowLoadLocalInfile
local-infile
mysql server 有个配置参数,在my.cnf中对应的是
1 | [mysqld] |
也可以在sql中通过全局参数local_infile实现
1 | SET GLOBAL local_infile = true; |
* 但是这并没有什么卵用 *
需要关注的是mysql-client的参数,可以通过配置
1 | [mysql] |
或者在msyql命令行,显式加上 –local-infile
1 | mysql --local-infile 1 -hlocalhost -uroot -ppassword |
allowLoadLocalInfile
在jdbc-mysql-connector sdk中,控制client是否可以load local file的就是这个参数,在5.x和8.x中默认都是false(参考【7】和【8】),所以需要在jdbc url中配置allowLoadLocalInfile=true
在8.0.22中还引入了allowLoadLocalInfileInPath,不过没什么影响
max_allowed_packet
参考【1】中提到 jdbc-mysql-connector 5.x版本中,遇到max_allowed_packet 的问题,最终排查发现是client sdk中的maxAllowedPacket参数,需要server端下发配置。
作者采取的action是回复了client 的show varialbes请求,并在其中设置相关maxAllowedPacket等参数。
其实在5.x中,maxAllowPacket default -1
在8.*中,maxAllowPacket default 65535
所以这也是jdbc-mysql-connector 5.*版本中需要注意的一个问题,需要显式的在url中加入参数maxAllowedPacket=65535.
poc构造流程
前文 load local data流程中,重点是第二个,也就是server的回包,需要指定client去读取特定文件,在不是很了解mysql协议情况下,改改包最简单
1 | // 8.* |
server 的整个攻击步骤如下:
- 回复mysql client一个greeting包
- 等待client端发送一个查询包
- 回复一个file transfer包
这里直接给通用的利用工具
https://github.com/Gifts/Rogue-MySql-Server
最早的利用工具,三个步骤,通过mysql组包实现。但是没复现成功…估计是mysql协议那里组包有问题,偷懒不详细分析了
https://github.com/fnmsd/MySQL_Fake_Server
fnmsd的,要多看他写的文档,通过username指定读取的文件
https://github.com/yang8e/jdbc_mysql_redfile
yang8e的,直接发包,没关注mysql协议细节,粗暴但是也简单。当时也踩了他这个坑,不过有更通用的jdbc poc url。
小结
本以为一篇文章可以搞定,结果行文还是过长,反序列化的下篇再做研究吧。
简单总结下,本文研究了jdbc-mysql-connector的mysql client任意文件读取漏洞,结论是无论是5.*、8.*都受影响。期间踩了jdbc 5.*版本maxAllowedPacket的坑,发现了yang8e的解决方案,并提出更通用的poc。
抛出个问题:
- 如何禁用jdbc client的load local file功能?阉割sdk?还是allowLoadLocalInfile=false
- 目前的poc只能读取一个文件client就会抛异常,有办法可以持续读取多个文件吗?
参考
- [1] JDBC MySQL任意文件读取中的一些坑(yangxiaocheng )
- [2] MySQL JDBC 客户端反序列化漏洞分析(fnmsd@360)
- [3] MySQL JDBC 客户端反序列化漏洞(四哥)
- [4] MySQL JDBC 反序列化分析(7tem7)
- [5] 《New Exploit Technique In Java Deserialization Attack》(zhangyang & keyi大佬)
- [6] CSS-T | Mysql Client 任意文件读取攻击链拓展
- [7] https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-connp-props-security.html
- [8] https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-security.html
- [9] 恶意MySQL Server读取MySQL Client端文件(四哥)