Security Verification and Offensive-Defensive Practice

Vulnerability Analysis | Apache StreamPark authenticated system users can trigger Remote Code Execution (CVE-2023-49898)

Apache StreamPark is an open-source stream processing platform that provides a powerful set of tools and frameworks for processing real-time data streams. It is built on the Apache Flink stream processing engine and offers a range of libraries and APIs, enabling developers to easily build, deploy, and manage stream data processing applications.

In December 2023, the official new version (2.1.2) was released to fix the CVE-2023-49898 Apache StreamPark remote code execution vulnerability. Authenticated system users can trigger remote command execution, allowing attackers to exploit this vulnerability to obtain server privileges. It is recommended to patch this vulnerability as soon as possible.


▌Vulnerability Details

In Apache StreamPark, there is a project management feature module that integrates Maven compilation capabilities; however, this feature does not validate the Maven compilation parameters.

Additionally, Apache StreamPark allows users to customize Maven configurations. An attacker can insert malicious code into the Maven Settings File Path configuration to achieve remote command execution.

The successful exploitation of this vulnerability requires the user to log into the StreamPark system and possess system-level privileges. Therefore, the risk level of this vulnerability is relatively low.

▌Vulnerability Reproduction

1. Environment Setup

  • Download the docker-compose.yaml and .env files for Apache StreamPark:

  • wget https://raw.githubusercontent.com/apache/incubator-streampark/dev/deploy/docker/docker-compose.yaml
    wget https://raw.githubusercontent.com/apache/incubator-streampark/dev/deploy/docker/.env

  • Modify the Apache StreamPark version number in docker-compose.yaml to release-2.1.1.

  • Use docker-compose up -d to start the container. After waiting for a few minutes, access http://localhost:10000 to see the StreamPark login page, indicating that the environment has successfully started.


2. Log in and Configure Malicious Maven Settings.xml Path

Log in to the system using StreamPark's default username "admin" and password "streampark".

Configure the malicious Maven Settings.xml path in Setting Center -> System Setting -> Maven Settings File Path:

/usr/share/java/maven-3/conf/settings.xml & touch /tmp/success

At this point, the browser will call the /flink/setting/update interface to modify the Maven Settings File Path configuration.

3. Triggering the Vulnerability

Under StreamPark -> Project Management, there is a default "streampark-quickstart" project. Click "Update Project" on the right. Modify the project branch to any existing branch and submit. Please note that the container must be able to access the repository and retrieve the branch information.

Then, build the project to trigger the vulnerability and execute remote commands.

By capturing the network packets, we can see that the browser calls the /flink/project/build interface to start building the project:

Checking the build logs reveals that malicious code has been embedded into the Maven compilation parameters:

Entering the container confirms that "touch /tmp/success" has been successfully executed:

▌Vulnerability Analysis

First, switch the branch to release-2.1.1. The exploitation process of this vulnerability can be divided into the following two steps:

  1. Configure the Maven Settings.xml path, inserting malicious code after the Maven Settings.xml file path.

  2. Build the project, triggering the vulnerability to execute remote commands.

1. Configure Maven Settings.xml Path

Through packet capture analysis, we found that when modifying the Maven Settings File Path, the browser calls the /flink/setting/update interface, which in turn calls the update() method of settingService:

The update() method writes the value of Maven Settings File Path into the database and global configuration.

2. Build Project, Trigger Vulnerability to Execute Remote Commands

When we click to start building the project, the browser calls the /flink/project/build interface. This interface performs the build by calling the projectService.build method:

Locating the implementation of the projectService.build method, we find that this method executes the build command via an asynchronous task:

This triggers the projectBuildTask.doRun() method to start executing the build task:

The projectBuildTask.doRun() method first clones the project, and upon a successful clone, calls projectBuild(project) to compile and build:

Clearly, the server executes system commands via CommandUtils.execute, and the argument passed is the return result of project.getMavenArgs().

The getMavenArgs() method does not filter or validate the MAVEN_SETTINGS_PATH retrieved from InternalConfigHolder when splicing cmdBuffer. Therefore, if a malicious system command is embedded after the configured maven settings.xml file path, the Maven parameters containing the malicious system command will be directly passed into the CommandUtils.execute method for execution.

▌Lexie Security Verification Rules

On December 28, the attack simulation for this vulnerability was added to the Lexie Security Metrics and Validation Platform. You can search for the keywords "Apache StreamPark" or "CVE-2023-49898" on the platform to obtain the relevant attack simulation verification tasks. This allows you to verify whether your security defense system can effectively counter this vulnerability, with the platform ensuring your validation process is safe and harmless in an industry-unique manner.

References:

https://github.com/apache/incubator-streampark https://streampark.apache.org/zh-CN/docs/user-guide/docker-deployment/