Patch Analysis: Examining a Missing Dot-Dot in Oracle WebLogic

September 17, 2019 | KP Choubey

Earlier this year, an Oracle WebLogic deserialization vulnerability was discovered and released as an 0day vulnerability. The bug was severe enough for Oracle to break their normal quarterly patch cadence and release an emergency update. Unfortunately, researchers quickly discovered the patch could be bypassed by attackers.

Patches that don’t completely resolve a security problem seem to be a bit of a trend, and Oracle is no exception. This blog covers a directory traversal bug that took more than one try to get fully corrected. Oracle initially patched this vulnerability as CVE-2019-2618 in April 2019, but later released a corrected patch in July. 

Vulnerability Details

Oracle WebLogic is an application server for building and deploying Java Enterprise Edition (EE) applications. The default installation of the WebLogic server contains various applications to maintain and configure domains and applications. One such application is bea_wls_deployment_internal.war, which contains a feature to upload files. A file can be uploaded by sending an authenticated request to the URI /bea_wls_deployment_internal/DeploymentService.

The application calls the handlePlanOrApplicationUpload() method if the value of the wl_request_type header of the request is “app_upload” or “plan_upload”. The handlePlanOrApplicationUpload() method validates the value of the wl_upload_application_name header and checks for two variants of directory traversal characters: ../ and /..:

Figure 1 - Directory Traversal Character Checks – With Comments Added

The path <ORACLE_HOME>\user_projects\domains\[DOMAIN NAME]\servers\AdminServer\upload\ is stored in variable uploadingDirName. The wl_upload_application_name request header value is used as subdirectory of this path. The method shown above appends the user-controlled value wl_upload_application_name to uploadingDirName and passes it via the saveDirectory argument of doUploadFile(). The doUploadFile() function should create a file in this location using the filename parameter of the request:

Figure 2 - The doUploadFile() Function

The wl_upload_application_name and filename fields were vulnerable to directory traversal. In April 2019, Oracle tried to patch the directory traversal as CVE-2019-2618. The patch for CVE-2019-2618 added checks for two more variants of directory traversal characters in the wl_upload_application_name field: \.. and ..\:

Figure 3 - Code Changes from CVE-2019-2618

For the filename field, CVE-2019-2618 added a check to doUploadFile() to ensure the final path where the file is saved contains the proper save directory as indicated by variable saveDir. The value of saveDir is <ORACLE_HOME>\user_projects\domains\[DOMAIN NAME]\servers\AdminServer\upload\[UPLOAD_APP], where the value of [UPLOAD_APP] is found in wl_upload_application_name. The patched doUploadFile() method throws an error if filename variable contains directory traversal characters and does not contain the string represented by saveDir:

Figure 4 - Exception Error for saveDir

This validation of the fileName field is mostly sufficient. As a side note, though, it would have been better if they had used startsWith instead of contains. The way the patch is written, the validation theoretically can be bypassed if anywhere within the final path there is a substring resembling the legitimate save path. There is no direct route to exploitation, though. The doUploadFile() function will not automatically create a directory structure if the one specified by saveTo doesn’t exist. So, for a bypass of the above patch to be relevant, an attacker would need some other technique that is powerful enough to enable creation of arbitrary directory structures within a sensitive location on the server, yet fails to offer a file upload capability of its own. On the whole, this is an unlikely scenario.

However, in regard to the wl_upload_application_name header field, the CVE-2019-2618 patch is inadequate and can be bypassed by setting the value wl_upload_application_name header to .. (dot-dot). This allows uploading to any subdirectory of the <ORACLE_HOME>\user_projects\domains\[DOMAIN NAME]\servers\AdminServer directory. Note the absence of the final path component, which should be “upload”. This is a sufficient condition to achieve code execution by writing a JSP file within the <ORACLE_HOME>\user_projects\domains\[DOMAIN NAME]\servers\AdminServer\tmp\ directory. An example of a POST request to write a file poc.jsp to a location within the <ORACLE_HOME>\user_projects\domains\[DOMAIN NAME]\servers\AdminServer\tmp directory is as follows:

Figure 5 - Demonstration the Directory Traversal

A file written to the \_WL_internal\bea_wls_internal subdirectory of the tmp directory can be accessed without authentication. For the aforementioned example, the attacker can execute JSP code by sending a request to the URI /bea_wls_internal/pos.jsp.

The patch for CVE-2019-2827 released in July fixed the directory traversal vulnerability correctly by validating the wl_upload_application_name header field for .. (dot-dot) directory traversal characters as follows:

Figure 6 - Code Changes for CVE-2019-2827


Variations of directory traversal bugs have existed for some time, but continue to affect multiple types of software. Developers should ensure they are filtering or sanitizing user input prior to using it in file operations. Over the years, attackers have used various encoding tricks to get around traversal defenses. For example, using URI encoding “%2e%2e%2f” translates to “../” and could evade some filters. Never underestimate the creativity of those looking to exploit your systems.

While this blog covers a failed patch from Oracle, multiple vendors have similar problems. Patch analysis is a great way to probe for things that may have been missed by the developers, and a great way to find related bugs is to examine the patched components. 

You can find me on Twitter @nktropy, and follow the team for the latest in exploit techniques and security patches.