CVE-2020-14882

9.8%
9.8 / 10
CRITICAL

Vulnerability in the Oracle WebLogic Server product of Oracle Fusion Middleware (component: Console). Supported versions that are affected are 10.3.6.0.0, 12.1.3.0.0, 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 HTTP to compromise Oracle WebLogic Server. Successful attacks of this vulnerability can result in takeover of Oracle WebLogic Server. CVSS 3.1 Base Score 9.8 (Confidentiality, Integrity and Availability impacts). CVSS Vector: (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H).

Published: 2020-10-21

Community Advisory

Oracle Weblogic unauthorized bypass RCE via only one GET request

  • CVSS: 9.8/10 (CRITICAL)
  • Protocol: HTTP
  • Affects all versions

This is a translated summary of Jang @testanull's writeup (in Vietnamese), analyzing Oracle Weblogic 12.2.1.3.

Focus on the class files modified in the patch (October patch has number 3191038, diff with July patch 31535411):

  • HandleFactory.class
  • MBeanUtilsInitSingleFileServlet.class

The Sink

This patch of HandleFactory checks the handleClass type, allowing only instances of com.bea.console.handles.Handle.

According to the flow of the HandleFactory.getHandle() method, the input data is a String, and after processing it will reach Class.forName (className) to load this class. Next will look for a constructor with 1 argument of type String to create a new instance from there.

It is possible to trigger entrypoint with the following HTTP GET request (but this piece still needs to be authenticated first):

 http://<target>/console/console.portal?_nfpb=true&_pageLabel=HomePage1&handle=java.lang.String("ahihi")

Setting the breakpoint at HandleFactory.getHandle(), the values of handleConstructor args are all controlled from the input data.

To take advantage of this entrypoint, it is necessary to find a class that contains a public Constructor with 1 argument of type String.

The Source

With HandleFactory.getHandle() as the sink of this bug, then it is reasonable to assume the remaining patched class MBeanUtilsInitSingleFileServlet is the source of the bug.

The patched class has an additional field IllegalUrl as follows:

private static final String[] IllegalUrl = new String[]{";", "%252E%252E", "%2E%2E", "..", "%3C", "%3E", "<", ">"};

Note that the code of this servlet handle merely checks for existence on the url string .., and if not, will reject this request.

An additional authentication step is required in order to reach MBeanUtilsInitSingleFileServlet.service().

This url can trigger MBeanUtilsInitSingleFileServlet without any authentication:

/console/css/changemgmt.portal

Mapping to /css/ is unrestricted, and AsyncInitServlet can be the servlet handle, not FileServlet as is the case for .css extension.

As declared by static resource declaration of web.xml:

  • Url pattern /common/* is handled by JSPCServlet (handles requests to jsp files)
  • The /framework/* pattern urls are handled by FileServlet
  • There is no declaration of which servlet will handle urls patterns /images/* and /css/*

So when a request with the url /console/css/aaasdasdasd.portal, AppManagerServlet will handle this request.

By traversing /css/* to bypass authentication and *.portal to trigger, MBeanUtilsInitSingleFileServlet.service() is able to reach MBeanUtilsInitSingleFileServlet.service() without authentication. However, the request still cannot reach HandleFactory.getHandle() because the url pattern cannot match. So use a double encoded .. to trigger a bug.

Using a double encoded url can both bypass the original normalized url handler, and still get the servlet handler to work properly afterwards.

Trigger RCE

Use com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext() to trigger the RCE with outbound.

Also possible to find a new chain: no outbound required, RCE in one hit. Edit the GadgetInspector tool to serve the trace code. This chain after receiving argument from the constructor will call ShellSession.exec(), and chain execution with MVEL.executeExpression().

Thus, it is possible to execute an arbitrary MVEL expression.

View writeups (3)

Improve Advisory

Proof-of-Concept Exploits

View list (30)

Add PoC

Official References

View list