MySQL可以通过伪造服务端读取客户端的文件这个想必大家都知道,其中 mysql jdbc 也是可以通过这个方式来进行任意文件读取的,但是在实践中碰到了不少的问题,记录下来。
有些服务是可以自定义jdbc连接来连接自己的数据库的,在java中是 mysql-connecter-java-xxx.jar ,由于版本的不同,造成文件读取的效果不同,这也导致了接下来出现的问题。
常见的payload如:
https://raw.githubusercontent.com/Gifts/Rogue-MySql-Server/
https://github.com/allyshka/Rogue-MySql-Server
https://github.com/jas502n/CVE-2019-12086-jackson-databind-file-read
等等,都是介绍了该攻击都只要三步即可完成,即:
1.回复mysql client一个greeting包
2.等待client端发送一个查询包
3.回复一个file transfer包
如下图我表示的三步。
但是当我按照该思路对漏洞进行利用的时候,发现了一些问题,jdbc报错了,error为:
Unexpected exception encountered during query
在网上查了很多资料,都说是因为jdbc版本太低,升级jdbc版本即可,进过测试,发现高版本的jdbc利用该漏洞的确可以成功,但是我们可以更改服务器的jdbc版本吗,显然是不可以的,那么就要研究到底问题出现在哪。
在本地调试,发现 mysql-connecter-java-5.x.jar存在此问题,判断服务端也可能为该版本,同时正因为坑爹的百度的答案,一直把我带入了一个误区,就是说jdbc的版本要和mysql服务端的版本匹配,但是当我测试,利用该版本的jdbc与本地的mysql进行连接并进行文件读取,发现并没有任何问题,但是当我和恶意的mysql服务端连接时就出现了error,所以首先排除了版本不匹配的问题。
然后我就怀疑网上的payload可能不对,通过抓取成功的数据包,来对恶意服务端进行替换。
通过替换,实现与成功的payload一模一样,发包,还是失败,还是同样的问题,在这卡了两天,因为明知道这个点有问题,就是没法利用成功,很难受。
通过求助大神,大神说这种有两种办法调试
1.和我调试的办法相同
2.查看jdbc源代码调试
第二种我不会,就让大神代替我做了,大神通过调试,发现有个值带入到jdbc中为负数,导致抛出异常。
我们先来看看 MaxAllowedPacket 这个是干嘛的.
所以这是mysql服务端给客户端的一个值,通过抓包发现,这个的确是服务端给到客户端的,但是前面我们也说了,利用步骤只有三部,第三步为不管客户端向服务端请求什么sql,服务端都要向客户端要他的/etc/passwd的值,先看一下恶意的服务端抓包的情况,大家看红框中的内容,这就是客户端向服务端进行请求该值。
那我们再看看恶意服务端是怎么响应的。
前面也说了,不管客户端向服务端要什么,服务端都会向客户端要他的/etc/passwd值,问题就出现在这里了。
所以解决的方式也很简单,我给他一个响应不就可以解决了嘛,正常的响应如下:
所以我们就要多一步,先给了数据,下次请求再要文件内容即可。