Jenkins, a popular open-source automation server, was discovered to be affected by a file read vulnerability, CVE-2024-23897. Jenkins employs a built-in Command-Line Interface (CLI) to facilitate interaction from script or shell environments and uses the args4j library to parse command arguments and options on the Jenkins controller during CLI command processing. The vulnerability exists in this library, allowing an unauthenticated user to read the first few lines of any files on the file system. Additionally, authenticated users can go even further by gaining the ability to read entire files.
Given its high severity we would like to emphasise the need for swift measures to secure Jenkins installations.
- Feature: expandAtFiles
- Description: This command parser feature automatically replaces an '@' character followed by a file path in an argument with the file’s content.
- Enabled By Default: Yes
- Affected Versions: Jenkins 2.441 and earlier, LTS 2.426.2 and earlier.
- Description: Attackers can read arbitrary files on the Jenkins controller file system using the default character encoding of the Jenkins controller process.
- Permissions Impact: Attackers with Overall/Read permission can read entire files while attackers without Overall/Read permissions can read the first few lines of files. The specific line count depends on available CLI commands.
- Over 45,000 unpatched Jenkins instances were identified by the non-profit security organisation ShadowServer.
- ShadowServer dashboard
Beyond file reads: RCE possibilities
Figure 1 shows some of the possibilities that can result from an “Arbitrary File Read” leading to remote code execution (RCE). More information about this can be found on the Jenkins advisory page.
Recent attacks
Our analysis found several attack instances originating from various regions, with the majority of the source IP addresses of the attacks originating from the Netherlands, as per Shadowserver data. Meanwhile, most of the targets were from South Africa, as shown in Figure 3.
Most of the observed attack events lead to the use of proof-of-concept (POC) scanners. We also came across instances where RCE exploits were actively being traded — specifically, we found entries related to the sale of the CVE-2024-23897 exploit that grants unauthenticated RCE capabilities (although there is a possibility that the exploit in question may be fraudulent or fabricated).
Vulnerability analysis
CVE-2024-23897 can be exploited via HTTP, WebSocket and over Secure Shell (SSH), with the first two having the highest chance of exploitation.
The HTTP endpoint requires making two POST requests by default. One of the requests will send an “upload” request containing the commands and its arguments while the second request is a “download” request to execute the commands and receive the output.
Upon receiving any of these requests, the following methods will be called in order:
The CliCrumbExecution method will validate the endpoint, while the FullDuplexHttpService method deals with request and response (note that PlainCLIProtocol is used to make the request). Finally, the cmdLineParser method, which uses the vulnerable args4j library, is used to parse arguments from the CLI Input.
The Jenkins PlainCLIProtocol
The Jenkins PlainCLIprotcol java class uses a specific binary format that consists of various opcodes and sequential frames.
Each opcode has a Boolean property clientSide indicating whether it is sent from the client to the server (true) or from the server to the client (false). These opcodes are used to define the different types of operations that can be exchanged between the client and server in the CLI protocol.
The Jenkins binary format
Jenkins has a specific binary format that is based off sequential frames. Figure 8 depicts the Jenkins binary format (as provided by Alex Williams):
The binary format for this protocol involves framing each message with an int length followed by a byte opcode, and then finally by the actual data.
The following is a breakdown of the binary format for a generic message:
Length Field (4 bytes): This represents the length of the message excluding the length field itself and the opcode. It is Encoded as a 32-bit signed integer in network byte order (big-endian).
Opcode Field (1 byte): This represents the operation code (opcode) for the message.
Data Field: This is the actual data specific to the opcode.
Vulnerable Code
The vulnerable code can be found in the Args4j library
Functionality in regular use
Normally, the “@” in Jenkins-cli is used to specify a file containing the bearer token or username:password from a file.
Using an authenticated command with Jenkins-cli will produce the following output:
Using the feature “@” to specify the password.txt file in -auth switch produces the following:
Vulnerability scenario
Passing “@” as an argument to available Jenkins-cli commands will result in the output shown in Figure 13.
As seen in the image, data is exposed in the error output, even though the “version” command does not take any arguments.
The extent of information disclosure is contingent on the command argument patterns. For instance, if the argument allows list inputs, it signifies a potential for more extensive data exposure:
$ java -jar jenkins-cli.jar -s http://172.17.0[.]1:8080/ -auth admin:pass reload-job @/etc/passwd
In our recent research, we've identified reload-job as an alternative to the commonly used connect-node command for reading multiple lines.
Other examples include delete-job, delete-node, disconnect-node, offline-node, and online-node.
Alternative attack vector: unauthenticated users
Command | Details |
---|---|
help | Adds jobs to view |
who-am-i | Reports credential and permissions |
restart | Restarts Jenkins |
shutdown | Immediately shuts down Jenkins server |
enable-job | Enables a job |
Table 1. Alternative attack vector for unauthenticated users
Alternative Attack Vectors: Authenticated users
Command | Details |
---|---|
add-job-to-view | Adds jobs to view. |
build | Builds a job, and optionally waits until its completion |
cancel-quiet-down | Cancels the effect of the quiet-down command. |
clear-queue | Clears the build queue |
connect-node | Reconnects to a node(s) |
console | Retrieves console output of a build. |
copy-job | Copies a job. |
create-credentials-by-xml | Creates credential via XML |
create-credentials-domain-by-xml | Create credentials domain via XML |
create-job | Creates a new job by reading stdin as a configuration XML file |
Table 2. Alternative attack vector for authenticated users
Attack request via Windows
In the context of this attack, where a request originates from a Windows machine to a Jenkins Linux server, the observed encoding is identified as windows-1252.
Attack Request via Linux
If the request is from a Linux machine to a Jenkins Linux server, the observed encoding is UTF-8 in the context of this attack.
Attack Request via WebSocket
WebSocket-based attack requests will have masking on the data, resulting in user input being invisible.
Conclusion
Jenkins patched CVE-2024-23897 in versions 2.442 and LTS 2.426.3 by disabling the problematic command parser feature. Users are strongly recommended to apply this update at the soonest possible time to avoid any potential security incidents.
Trend Micro Solutions
The following protections exist to detect and protect Trend customers against CVE-2024-23897:
Trend Vision One Endpoint Security, Trend Cloud One - Workload and Endpoint Security, Deep Security and Vulnerability Protection IPS Rules
- 1011966 - Jenkins Arbitrary File Read Vulnerability Over HTTP (CVE-2024-23897)
- 1011976 - Jenkins Arbitrary File Read Vulnerability Over WebSocket (CVE-2024-23897)
Trend Micro Cloud One - Network Security & TippingPoint Filters
- 43766: HTTP: Jenkins CI Server Arbitrary File Read Vulnerability
Trend Vision One Network Sensor and Trend Micro Deep Discovery Inspector (DDI) Rule
- 4997 - CVE-2024-23897 - Jenkins Authentication Bypass Exploit - HTTP (Request)