Last Wednesday, on January 24, 2024, the Jenkins team issued a security advisory disclosing a critical vulnerability, CVE-2024-23897, affecting the Jenkins CI/CD tool. This advisory set off alarm bells among the infosec community because the potential impact is huge: Jenkins is widely deployed, with tens of thousands of public-facing installs, and the Jenkins advisory was clear that this vulnerability could lead to remote code execution. Jenkins is a common target for attackers, and, as of this writing, there are four prior Jenkins-related vulnerabilities in CISA’s catalog of Known Exploited Vulnerabilities.
Our advice for users of Jenkins is don’t panic… unless you need to. This is a textbook example of a vulnerability whose true impact can only be accurately assessed within the context of your environment. The typical Jenkins install will not be exploitable by unauthenticated attackers. However, there are a few factors that could significantly increase the potential for damage, elevating this to a truly critical vulnerability. We’ll discuss these factors in this post, as well as how the NodeZero platform can be used to provide an accurate assessment of risk.
CVE-2023-23897 resides in the Jenkins CLI, an alternative way for users to interact with Jenkins without going through web interface. The CLI is enabled by default. Vulnerable Jenkins servers misinterpret command line arguments supplied by users to the CLI. Specifically, CLI arguments preprended by
@ are incorrectly interpreted as files that need to be opened to read in arguments, and in some cases the lines in these files are echo’d back as part of error messages to the CLI user. A detailed technical explanation is available here from Yaniz Nizry of Sonarsource, who discovered the vulnerability.
An unauthenticated attacker with no permissions (i.e. the default Jenkins install) can leak the first couple of lines of arbitrary text files on a vulnerable Jenkins server. For instance, here’s an example of retrieving the first few lines of the
C:\windows\win.ini file using the CLI
An authenticated attacker can retrieve entire text files, using the
connect-node CLI command:
Dangerous Configuration Options
There are two dangerous Jenkins configuration options that allow unauthenticated attackers to effectively act like authenticated attackers. The “Allow users to sign up” option allows anyone with access to the Jenkins instance to self-register an account. And the “Allow anonymous read access” option gives everyone the Overall/Read permission.
For instance here’s an example of an unauthenticated attacker reading the
/etc/passwd file off a Jenkins server that has been enabled with the “Allow anonymous read access” option:
Reading Binary Files
Binary files can also be read but the Jenkins server will try to convert them into text, using the default character encoding set defined for the Jenkins server. Binary characters outside the character encoding set will be returned in mangled/unusable form back to the CLI user. According to the Jenkins advisory, if Jenkins is running on Linux, where the default character encoding set is UTF-8, an average of half the characters in binary files will end up being mangled. However, if Jenkins is running on Windows, where the default character encoding set is Windows 1252, a much smaller percentage (5/256) of the characters would be mangled on average. Therefore it may be possible for an attacker targeting a Jenkins server running on Windows to re-construct secrets contained in binary files. This is significant because the
hudson.util.Secret file is a small binary file that contains an encrypted key used to encrypt other secrets.
Here’s an example of trying to read the
hudson.util.Secret file on Linux:
Remote Code Execution and Credential Dumping
Given the above, how likely is it that an attacker can use this vulnerability to achieve remote code execution or dump credentials stored within Jenkins? We put together the following risk matrix:
|Jenkins Server Running on Linux
|Jenkins Server Running on Windows
|Attacker has no permissions
|Attacker has Overall/Read permissions
|Risk: Very High
How NodeZero Assesses CVE-2024-23897
One of the core functions of the NodeZero platform is exploiting vulnerabilities to help practitioners understand the true risk of these vulnerabilities and to plan remediation accordingly.
To assess this particular vulnerability, NodeZero performs the following steps:
- Determines if the Jenkins server is vulnerable using the
X-Jenkinsversion header present in HTTP responses.
- Benignly exploits the vulnerability by attempting to read the
C:\windows\win.inifile from the server
- This is done using multiple Jenkins CLI commands to determine if an unauthenticated attacker has no permissions (can only partially read files) or Overall/Read permissions (can fully read files)
- This helps determine if the Jenkins server is running on Linux or Windows
- NodeZero also accounts for Jenkins servers running behind reverse proxies, which may or may not be exploitable.
- Checks if user self signup is enabled.
By default, NodeZero assigns this particular vulnerability a base score of 8.1 (High). This is the score we’d expect for typical Jenkins installs that haven’t been patched for this vulnerability but are using default configuration options and are running on Linux. The proof that NodeZero captures for the vulnerability shows the partial contents of the
If NodeZero finds that any of the following conditions are true, it elevates the score to 9.5 (Critical):
- Unauthenticated attacker has Overall/Read permissions
- User self signup is enabled
- The Jenkins server is running on Windows
For instance, on this Jenkins server, self signup is enabled, and anonymous users are configured with Overall/Read permissions, enabling unauthenticated attackers to read the full content of text files:
Here’s a Jenkins server running on Windows where only partial file read is possible, but there’s a chance attackers may still be able to recover secrets stored in binary files, leading to further compromise:
Finally, it’s not always possible to exploit this vulnerability, particularly if the Jenkins server is running behind a reverse proxy. NodeZero will mark vulnerabilities for which exploits have failed with a failure reason and downgrade the severity of the vulnerability accordingly.
Updating to at least Jenkins versions 2.442 and 2.426.3 (long-term support version) will address this vulnerability. It is also possible to mitigate by disabling the Jenkins CLI, as described here.
We recommend patching immediately if NodeZero identifies conditions that elevate this to a critical severity. Note that if you’re running Jenkins on the Internet, the dangerous configuration options of anonymous read access and self signup should never be enabled. NodeZero will surface these misconfigurations as additional weaknesses.
Even if NodeZero doesn’t identify CVE-2024-23897 as a critical vulnerability, it still merits patching. It is entirely possible for attackers to acquire credentials for valid users through attacks such as password spray, and then exploit CVE-2024-23897 as an authenticated user to read arbitrary files.