Attacker Value
High
(2 users assessed)
Exploitability
Low
(2 users assessed)
User Interaction
None
Privileges Required
None
Attack Vector
Network
6

CVE-2023-50164

Disclosure Date: December 07, 2023
Add MITRE ATT&CK tactics and techniques that apply to this CVE.

Description

An attacker can manipulate file upload params to enable paths traversal and under some circumstances this can lead to uploading a malicious file which can be used to perform Remote Code Execution.
Users are recommended to upgrade to versions Struts 2.5.33 or Struts 6.3.0.2 or greater to fix this issue.

Add Assessment

2
Ratings
Technical Analysis

Despite the buzz on this one, so far we haven’t been able to identify any real-world applications that are vulnerable and exploitable out of the box, though that doesn’t mean they don’t exist.

Per @sfewer-r7’s analysis of the bug, this is not trivially exploitable, and exploits may need to be target-specific if there are any real applications discovered to be vulnerable in common configurations. At least three different security firms are reporting exploitation in the wild, but it’s not clear that any of them have seen actual exploitable code paths get hit, or that the attack vectors are production applications rather than demo applications configured to be artificially exploitable (which is what the public PoCs currently target). Happy to be wrong if we’re wrong, but until then, “don’t panic” sounds like the order of the day. If there are follow-on vendor advisories patching this out of their specific product implementations, it’d probably be good to pay attention to those as they roll in.

Edit: Shadowserver actually said explicitly that none of the attempts they’d seen as of December 13 had been successful.

2
Ratings
  • Attacker Value
    High
  • Exploitability
    Low
Technical Analysis

Based on our Rapid7 Analysis, the attacker value of this vulnerability is High, as successful exploitation can result in remote code execution via arbitrary file uploads, such as uploading a web shell or similar. However I have rated the exploitability as Low as there are a number or prerequisites that must be met for a Struts based web application to be vulnerable. Currently we don’t have any concrete examples of production applications that are vulnerable to CVE-2023-50164. This may change as the vulnerability comes under more scrutiny and more Struts based applications are examined.

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

General Information

Vendors

  • apache

Products

  • struts

Additional Info

Technical Analysis

Overview

Apache Struts is a popular Java web application framework. On December 7, 2023 Apache published an advisory for CVE-2023-50164, a Struts parameter pollution vulnerability that potentially leads to arbitrary file uploads. An attacker with the ability to perform arbitrary file uploads is very likely to be able to leverage this and achieve remote code execution. According to the vendor, the following versions of Struts are affected:

  • Struts 2.0.0 – Struts 2.3.37 (End of Life)
  • Struts 2.5.0 – Struts 2.5.32
  • Struts 6.0.0 – Struts 6.3.0

Several technical analyses on the root cause of the vulnerability have already been done (here, here, and here). Notably, all current public analysis of the vulnerability demonstrates exploitation on a custom made demo web application.

There are currently no known production web applications that are exploitable, although this is likely to change as the vulnerability comes under more scrutiny from researchers, and given the popularity of the Struts framework in enterprise web applications. Several security firms have reported exploitation (here and here), but as of December 15, 2023, it is unclear if the activity being reported actually refers to successful exploitation (i.e., code execution) against one or more known vulnerable targets, or if this is merely highlighting exploit attempts with the existing public PoCs (all of which target a demo application) being sprayed opportunistically at indiscriminate targets.

Analysis

To explore this vulnerability and better understand the prerequisites that will make a target application vulnerable, we will step through exploitation of the demo web application which accompanies the public PoC from https://github.com/jakabakos/CVE-2023-50164-Apache-Struts-RCE.

After opening the demo web application in IntelliJ, and running it on a Jetty application server, we can reach the vulnerable target endpoint via a HTTP POST request to /upload/upload.action. First we must examine the custom logic that implements the upload action.

We can see several private member variables are defined, these are expected to be set automatically by the Struts interceptor ParametersInterceptor via OGNL statements, when processing the HTTP request. The content of these values will be extracted from the HTTP request via the Struts interceptor FileUploadInterceptor.

public class Upload extends ActionSupport {
    private File upload;
    private String uploadFileName;
    private String uploadContentType;

Next we can see the custom logic that executes when this action is performed. The file that was uploaded will be copied to another location via FileUtils.copyFile. Of note is the destination path is constructed via uploadFileName.

    // Custom upload logic
    public String execute() throws Exception {
        if (uploadFileName != null) {
            try {
                // Specify the directory where files will be uploaded
                String uploadDirectory = System.getProperty("user.dir") + "/uploads/";

                // Create the destination file
                File destFile = new File(uploadDirectory, uploadFileName);

                // Copy the uploaded file to the destination
                FileUtils.copyFile(upload, destFile);

                // Add message to reflect the exact upload path on the frontend
                addActionMessage("File uploaded successfully to " + destFile.getAbsolutePath());

                return SUCCESS;
            } catch (Exception e) {
                addActionError(e.getMessage());
                e.printStackTrace();
                return ERROR;
            }
        } else {
            return INPUT;
        }
     }

Finally we can see that several getter and setter methods exist, for both the upload and uploadFileName member variables.

    public File getUpload() {
        return upload;
    }

    public void setUpload(File upload) {
        this.upload = upload;
    }

    public String getUploadFileName() {
        return uploadFileName;
    }

    public void setUploadFileName(String uploadFileName) {
        this.uploadFileName = uploadFileName;
    }

By reading the documentation for the FileUploadInterceptor, we can see that an expected naming convention exists when uploading a file and mapping that file to an action’s member variables.

Interceptor that is based off of MultiPartRequestWrapper, which is automatically applied for any request that includes a file. It adds the following parameters, where <file name> is the name given to the file uploaded by the HTML form:

<file name>: File – the actual File
<file name>ContentType: String – the content type of the file
<file name>FileName: String – the actual name of the file uploaded (not the HTML name)

For example, uploading a file with a multi-part name of “foo”, can pass a file name through the parameter “fooFileName”. If a setter method called “setFooFileName” exists in the action, this setter method will be automatically called to set the file name. CVE-2023-50164 allows for this feature to be abused, bypassing file name sanitization, and allowing for an arbitrary file name path to be specified. If the custom application logic does something potentially dangerous, such as copy the uploaded file to a location based on the file name, this can be abused.

We can successfully exploit this demo web application with the following HTTP POST request.

POST /upload/upload.action HTTP/1.1
Host: 127.0.0.1:4444
User-Agent: Mozilla
Accept: */*
Connection: close
Content-Type: multipart/form-data; boundary=dujjbxrtqkhczyec
Content-Length: 256

--dujjbxrtqkhczyec
Content-Disposition: form-data; name="Upload"; filename="good.txt"
Content-Type: text/plain

Hello World
--dujjbxrtqkhczyec
Content-Disposition: form-data; name="uploadFileName"

..\..\..\..\..\..\evil.bin
--dujjbxrtqkhczyec--

Several things happen under the hood thanks to the Struts interceptors. First the FileUploadInterceptor will extract the uploaded file’s name and ensure it does not contain any path separators via org.apache.struts2.dispatcher.multipart.AbstractMultiPartRequest#getCanonicalName.

debug0.png

Then the FileUploadInterceptor will populate the actions parameters, held in the current ActionContext instance for this action. These parameters are later passed to the interceptor ParametersInterceptor for processing, allowing for the automatic setting of member variables within an action. As per the documentation for FileUploadInterceptor, parameters corresponding to the uploaded multipart form data fields <file name>, <file name>ContentType, and <file name>FileName are added.

debug1.png

Before the call to appendAll, we can observe that the actions parameters hold a single value, the malicious multi-part parameter named “uploadFileName” which contains a path with unsafe path traversal characters. It has not been subjected to any sanitation, as it is not intended as part of the file upload.

debug2.png

After the call to appendAll, we can see a new parameter with a key name of “UploadFileName” exists containing the upload’s expected file name. The two key values can exist at the same time as the first character in each is in a different case (lower/upper).

debug3.png

The ParametersInterceptor will now begin to process the action parameters, and it will call a setter method in the action, if a setter exists that matches the name of the parameter. Below we can see the action parameter named “UploadFileName” calls the actions setter setUploadFileName and passes the parameter “good.txt”, which is the expected file name that has been sanitized to ensure it does not contain any path specifiers.

debug4.png

Next the action parameter named “uploadFileName” is processed, we can see that the same setter setUploadFileName is called, even though the first character is a lowercase “u”. We can observe that the safe file name “good.txt” is replaced with the malicious file name “..\..\..\..\..\..\evil.bin”. This file name contains path specifiers that have not been sanitized, and allows for path traversal to an arbitrary location via double dot path notation.

debug5.png

Finally, once the underlying Struts interceptors have done their work, the action’s custom logic is executed and the uploaded file is unexpectedly copied to an arbitrary location.

We can see from stepping through the public PoC, that for a Struts based web application to be vulnerable to arbitrary file uploads via CVE-2023-50164, the following conditions must be met.

  • The Struts configuration must enable the interceptor FileUploadInterceptor. This is required, as the HTTP parameter pollution occurs via org.apache.struts2.dispatcher.HttpParameters#appendAll during org.apache.struts2.interceptor.FileUploadInterceptor#intercept.
  • A Struts action must implement custom logic that copies an uploaded file to a destination path, based on a file name which is provided via a setter routine. This is required as the HTTP parameter pollution allows for two OGNL statements to call the same setter routine twice, once with the expected file name that has been sanitized, and a second time with an unexpected file name that contains unsafe path traversal characters.

It is likely these conditions are going to be met in some real world production applications, due to how Struts is intended to be used, specifically how the FileUploadInterceptor is intended to auto wire the uploaded files parameters to an actions member variables via setters.

However, exploitation of this vulnerability will be target-specific based on the differing target action’s endpoints, the naming convention of the expected uploaded file name, and any other target-specific restrictions that may need to be overcome.

Remediation

Vendors who develop applications that use Apache Struts should upgrade to Struts 2.5.33, Struts 6.3.0.2, or greater to remediate CVE-2023-50164.