上班没有任务你们都干什么,反正我是不会摸鱼的,这辈子都不可能摸鱼的,复现这个漏洞的初衷是看了某公众号关于Vmware Workspace One Access的jdbc注入漏洞,文中值分析到jdbc url可控的部分,但是我不太清楚为什么jdbc可控就会导致任意文件写入,于是上网搜了jdbc注入的文章,于是找到了这儿:
这篇文章里介绍了Mysql 的JDBC驱动可能导致的漏洞的分析,不过这好像不是我需要的,不过我还是学习了一波,具体的调用流程我还没有看,准备咋写完这篇就去看看。后来我又在刚才提到的公众号里找到了另一篇将PostGreSQL的注入分析,于是我就跟着分析了一波。这篇文章里介绍了两个漏洞一个是RCE,另一个是任意文件写入漏洞。
RCE
首先我们创建一个MAVEN项目,然后引入相关的依赖:
然后编写一个漏洞利用POC。
很明显导致漏洞的是jdbcURL的socketFactory与socketFactoryArg这两个参数,在jdbcURL的定义中,参数部分一般被称作扩展参数,其总用是指定连接数据库的一些特性。大胆cancel导致漏洞的就是这两个参数,而这个漏洞的kick-off就是DriverManager.getConnection这个类方法。那么我们接下来要做的就是不断跟踪这个函数的Chain最终找到sink点。直接开干,毫无疑问我们要使用调试模式将代码跑起来,然后键入到getConnection函数里面。
无意义的部分我就直接放图片了,需要关注的地方我会说明
这里注意注意第151行
this.setupLoggerFromProperties(props);
这与我们的任意文件写入有关,当然现在我们不关注他,这个时候我们可以看一下props的值
存储的都是jdbcRUL含有的一些关键信息,具体的实现步骤我当然是一步一步看了的,有新区的可以自己看看。
这里对props进行了处理,最终生成的是一个hostSpecs类型的数组,hostSpecs对象存储了数据库连接的hostnae, port以及一个扩展参数localSocketAddress,
这个时候可以看一波这个info存储的信息了
这里注意第三个参数PGProperty.SOCKET_FACTORY_ARG
,PGProperty是一个枚举类型,其内部定义了get方法,实现的功能是对判断枚举项的值有没有在传入的properties中,如果在则查找返回,如果不在则返回默认值。
可以看到有很多的枚举项,这些内容很大一部分都是JDBC的扩展参数的可选值。
在我们的代码中这个值就是args
也就是我们最开始poc设置的参数socketFactoryArg
还可以看一看第一个参数的值
就是最开始设置的参数socketFactoryClass
然后跟进这个函数instantiate
很明显的反射调用,第一个参数作为类名,第三个参数作为构造方法的参数,那么这个函数ObjectFactory.instantiate
就是我们的sink点了。
现在我们要找到一个gadget能够在在类实例化的过程中实现RCE,作者根据jackson的历史漏洞CVE-2017-17485
找到这么一个类org.springframework.context.support.ClassPathXmlApplicationContext
该类在实例化的时候会下载出入的参数指定的xml文件然后获取java bean,然后通过jpel表达式执行恶意代码。
完整的poc长这样
当然过去jdbc连接的用户名根本不用填,根本用不上。
xml文件长这样:
然后直接运行代码
完美
任意文件写
这个也比较简单,上面有提到过,重点在this.setupLoggerFromProperties(props);
里面设置了日志处理器,在调用该logger的时候就会使用该处理器将日志记录到指定的日志文件中。
这里注意要设置jdbc扩展参数logger_level
设置日志记录的级别,当然不能为off,
设置扩展参数logger_file
指定日志文件的路径,这里没有对路径进行过滤,所以可以进行目录穿越,将文件指定到想要的位置。
这个文件处理器最终被添加到了Parent_LOGGER
这个日志记录器中
在执行完setupLoggerFromProperties(props)
后,马上就有记录日志的操作,该操作将整个jdbcUrl记录到日志中。
注意到这里的日志记录器并不是PARENT_LOGGER
而是LOGGER
,那么他是怎么调用到父记录器的呢,这个可以自己跟一下log的流程看一下怎么获取的,最终的poc与效果