Attacker Value
High
(1 user assessed)
Exploitability
High
(1 user assessed)
User Interaction
None
Privileges Required
None
Attack Vector
Network
3

CVE-2023-21839

Disclosure Date: January 18, 2023
Exploited in the Wild
Add MITRE ATT&CK tactics and techniques that apply to this CVE.
Initial Access
Techniques
Validation
Validated

Description

Vulnerability in the Oracle WebLogic Server product of Oracle Fusion Middleware (component: Core). Supported versions that are affected are 12.2.1.3.0, 12.2.1.4.0 and 14.1.1.0.0. Easily exploitable vulnerability allows unauthenticated attacker with network access via T3, IIOP to compromise Oracle WebLogic Server. Successful attacks of this vulnerability can result in unauthorized access to critical data or complete access to all Oracle WebLogic Server accessible data. CVSS 3.1 Base Score 7.5 (Confidentiality impacts). CVSS Vector: (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N).

Add Assessment

2
Ratings
Technical Analysis

Oracle Weblogic 12.2.1.3.0, 12.2.1.4.0 and 14.1.1.0.0 prior to the Jan 2023 security update are vulnerable to an unauthenticated remote code execution vulnerability due to a post deserialization vulnerability via IIOP/T3. A PoC for this vulnerability was originally posted by 4ra1n at https://github.com/4ra1n/CVE-2023-21839, and about a week or so later a writeup came out by 14m3ta7k of the company GobySec at https://github.com/gobysec/Weblogic/blob/main/WebLogic_CVE-2023-21931_en_US.md which explained the vulnerability in depth with detailed code walkthroughs and explanations.

As noted in the writeup, CVE-2023-21839 is not your typical deserialization vulnerability. Most deserialization vulnerabilities lead to code execution at the same time that deserialization of the attacker’s object occurs. However for CVE-2023-21839, the vulnerability occurs not in the deserialization of the attacker’s object, but rather the fact that an attacker is able to create an object in the target’s memory and then later trigger another function that utilizes that deserialized object without performing proper sanity checks.

As the writeup explains, we can abuse some behavior of the lookup() method. When receiving a request, Weblogic will parse incoming data using BasicServerRef’s invoke() method, which will in turn call _invoke(), which then calls resolve_any() based on the passed in method name of resolve_any.

In resolve_any(), the incoming binding name is resolved using resolveObject(), which will then call lookup() based on the context information.

Based on the context information, further lookup() calls are made in several classes such as WLContextImpl, WLEventContextImpl, RootNamingNode, ServerNamingNode and BasicNamingNode. All of this will eventually lead to a resolveObject() call in BasicNamingNode class.

At this point the resolveObject() method will realize the obj parameter passed into it is not an instance of the BasicnamingNode class and the mode parameter passed in will be 1 so it will call getObjectInstance() in WLNamingManager.

Finally getObjectInstance() in WLNamingManager will call getReferent() method inside the passed in object based on the object interface type, as can be seen in the screenshot below, taken from the writeup.

Code

The bug for CVE-2023-21839 occurs specifically because the ForeignOpaqueReference is an instance of the OpaqueReference interface that the code above handles. The ForeignOpaqueReference class defines two constructors, and the parameterized one allows a user to specify the env and remoteJNDIName parameters, which are internally assigned to the private variables jndiEnvironment and remoteJNDIName respectively.

Additionally the class ForeignOpaqueReference defines a getReferent() method that overrides the OpaqueReference interface’s default definition. This function will take the remoteJNDIName private variable of the ForeignOpaqueReference class and call retVal = context.lookup(this.remoteJNDIName);, which will perform a remote JNDI loading operation. The specific code for the getRefent() function can be seen below, and is taken from the writeup at https://github.com/gobysec/Weblogic/blob/main/WebLogic_CVE-2023-21931_en_US.md:

package weblogic.jndi.internal;
public class ForeignOpaqueReference implements OpaqueReference, Serializable {
    private Hashtable jndiEnvironment;
    private String remoteJNDIName;
        ......
    public ForeignOpaqueReference(String remoteJNDIName, Hashtable env) {
        this.remoteJNDIName = remoteJNDIName;
        this.jndiEnvironment = env;
    }
    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);   // vulnerability point
        } finally {
            context.close();
        }
        return retVal;
    }
    ......
}

This implementation of OpaqueReference’s getReferent() method inside of ForeignOpaqueReference will be called by the WLNamingManager class’s getObjectInstance() method, as mentioned previously. Specifically the getObjectInstance() code will see that the passed in boundObject, which will be a ForeignOpaqueReference object, is an instance of the OpaqueReference interface, and will call boundObject = ((OpaqueReference)boundObject).getReferent(name, ctx);

This will end up leading to a remote JNDI loading operation using the location specified in the remoteJNDIName class variable of the ForeignOpaqueReference object the attacker passed in. Remote JNDI loading operations are particularly dangerous since they are essentially an application reaching out to a given target, usually a remote server in the case of remote JNDI loading, and saying “Hey, I’m interested in this particular class. Serve me up the class file for that object and I’ll instantiate a local copy on my server”. The problem with this is that you can define code in Java within a static block in a class definition that will be run whenever the class is created.

The Metasploit module at https://github.com/rapid7/metasploit-framework/pull/17946 takes advantage of this to trigger a JNDI connection to a LDAP server we control. The LDAP server will then respond with a remote reference response that points to a HTTP server that we control, where the malicious Java class file will be hosted. Oracle Weblogic will then make a HTTP request to retrieve the malicious Java class file, at which point our HTTP server will serve up the malicious class file and Oracle Weblogic will instantiate an instance of that class, granting us RCE as the oracle user.

Overall the risk of this vulnerability is fairly high since most of Oracle Weblogic runs as the oracle user, so this allows an unauthenticated attacker who has access to IIOP/T3 ports on a given target to gain full control over the server. It can be mitigated to some extent by not exposing IIOP/T3 ports to the public, however the risk will still remain that those on the internal network might be able to abuse this vulnerability to gain access to the server. Whilst public exploit code is available that makes exploitation easier, there are a number of details about this vulnerability that would take an attacker some time to reverse engineer.

Additionally, here are some other limitations that are important to take into account:

  • JDK 8u121 introduces the “trustURLCodebase” property which makes it so that we cannot load remote classes via RMI, and later this was expanded to also apply to LDAP connections such as the ones used in this vulnerability. The only way to get around this now is to take advantage of gadget chains within the application itself and essentially do a deserialization attack using gadgets from existing Java class files available in the class path.
  • For some reason in my tests the Java class name had to be exactly 11 characters long, otherwise things started to get wonky and would fail.
  • When sending the URL to visit as part of the LDAP response to the JDNI request, you have to redirect to the root, aka /, of a target web server. Requesting a page or a subdirectory won’t work. Anchor tags after the / are fine though.
  • You must compile the target class to send with Java 8 SDK. Compiling it with a later JDK will result in a class that uses a bytecode version later than 52.0, which may not be able to be loaded by the target depending on which Java version they have installed.

A final point which is of important note is that this is quite similar to CVE-2023-21931, the only difference is that CVE-2023-21931 targets the getObjectInstance() method of the WLNamingManager class using an object that is an instance of the LinkRef interface instead of the OpaqueReference interface, and uses different internal methods to perform the remote JNDI load.

CVSS V3 Severity and Metrics
Base Score:
7.5 High
Impact Score:
3.6
Exploitability Score:
3.9
Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Attack Vector (AV):
Network
Attack Complexity (AC):
Low
Privileges Required (PR):
None
User Interaction (UI):
None
Scope (S):
Unchanged
Confidentiality (C):
High
Integrity (I):
None
Availability (A):
None

General Information

Vendors

  • oracle

Products

  • weblogic server 12.2.1.3.0,
  • weblogic server 12.2.1.4.0,
  • weblogic server 14.1.1.0.0

Exploited in the Wild

Reported by:

Additional Info

Technical Analysis