From 480380003c1798b6dca0ae75e2bb13bed929679b Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sun, 21 Mar 2010 18:42:47 +0000 Subject: [PATCH] Make verbose status printing standardized across login modules git-svn-id: file:///home/svn/framework3/trunk@8866 4d416f70-5f16-0410-b530-b9f4589650da --- lib/msf/core/auxiliary/auth_brute.rb | 18 ++++++++++++- .../auxiliary/scanner/mssql/mssql_login.rb | 10 +++----- .../auxiliary/scanner/mysql/mysql_login.rb | 23 +++++++---------- .../scanner/postgres/postgres_login.rb | 20 ++++++++------- modules/auxiliary/scanner/smb/smb_login.rb | 25 ++++++++++++++++++- modules/auxiliary/scanner/ssh/ssh_login.rb | 14 ++++++----- .../auxiliary/scanner/telnet/telnet_login.rb | 20 ++++++--------- 7 files changed, 80 insertions(+), 50 deletions(-) diff --git a/lib/msf/core/auxiliary/auth_brute.rb b/lib/msf/core/auxiliary/auth_brute.rb index e9da52673b..f326aa6712 100644 --- a/lib/msf/core/auxiliary/auth_brute.rb +++ b/lib/msf/core/auxiliary/auth_brute.rb @@ -17,7 +17,8 @@ def initialize(info = {}) OptPath.new('USER_FILE', [ false, "File containing usernames, one per line" ]), OptPath.new('PASS_FILE', [ false, "File containing passwords, one per line" ]), OptPath.new('USERPASS_FILE', [ false, "File containing users and passwords separated by space, one pair per line" ]), - OptInt.new('BRUTEFORCE_SPEED', [ true, "How fast to bruteforce, from 0 to 5", 5]) + OptInt.new('BRUTEFORCE_SPEED', [ true, "How fast to bruteforce, from 0 to 5", 5]), + OptBool.new('VERBOSE', [ true, "Whether to print output for all attempts", true]), ], Auxiliary::AuthBrute) @user = nil @@ -114,6 +115,21 @@ def userpass_sleep_interval select(nil,nil,nil,sleep_time) unless sleep_time == 0 end +def vprint_status(msg='') + return if not datastore['VERBOSE'] + print_status(msg) +end + +def vprint_error(msg='') + return if not datastore['VERBOSE'] + print_error(msg) +end + +def vprint_good(msg='') + return if not datastore['VERBOSE'] + print_good(msg) +end + protected # # These methods all close their files after reaching EOF so that modifications diff --git a/modules/auxiliary/scanner/mssql/mssql_login.rb b/modules/auxiliary/scanner/mssql/mssql_login.rb index 122f0ddf6d..1f8555156e 100644 --- a/modules/auxiliary/scanner/mssql/mssql_login.rb +++ b/modules/auxiliary/scanner/mssql/mssql_login.rb @@ -29,11 +29,6 @@ class Metasploit3 < Msf::Auxiliary 'Author' => 'MC', 'License' => MSF_LICENSE ) - - register_options( - [ - OptBool.new('VERBOSE', [ true, 'Verbose output', false]) - ], self.class) end def run_host(ip) @@ -56,7 +51,7 @@ class Metasploit3 < Msf::Auxiliary end def do_login(user='sa', pass='', this_cred='', verbose=false) - print_status("#{rhost}:#{rport} - MSSQL - Trying username:'#{user}' with password:'#{pass}' against #{rhost}:#{rport}") if verbose + vprint_status("#{rhost}:#{rport} - MSSQL - Trying username:'#{user}' with password:'#{pass}'") begin success = mssql_login(user, pass) @@ -74,7 +69,7 @@ class Metasploit3 < Msf::Auxiliary self.credentials_good[this_cred] = pass return :next_user else - print_error("#{rhost}:#{rport} failed to login as '#{user}'") if verbose + vprint_error("#{rhost}:#{rport} failed to login as '#{user}'") return end rescue ::Rex::ConnectionError @@ -82,3 +77,4 @@ class Metasploit3 < Msf::Auxiliary end end end + diff --git a/modules/auxiliary/scanner/mysql/mysql_login.rb b/modules/auxiliary/scanner/mysql/mysql_login.rb index 70795d6915..19f8724ca4 100644 --- a/modules/auxiliary/scanner/mysql/mysql_login.rb +++ b/modules/auxiliary/scanner/mysql/mysql_login.rb @@ -29,11 +29,6 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE, 'Version' => '$Revision$' )) - - register_options( - [ - OptBool.new('VERBOSE', [ true, 'Verbose output', false]) - ], self.class) end @@ -44,13 +39,13 @@ class Metasploit3 < Msf::Auxiliary this_cred = [user,ip,rport].join(":") next if self.credentials_tried[this_cred] == pass || self.credentials_good[this_cred] self.credentials_tried[this_cred] = pass - do_login(user, pass, this_cred, datastore['VERBOSE']) + do_login(user, pass, this_cred) } end end # Tmtm's rbmysql is only good for recent versions of mysql, according - # to http://www.tmtm.org/en/mysql/ruby/. We'll need to write our own + # to http://www.tmtm.org/en/mysql/ruby/. We'll need to write our own # auth checker for earlier versions. Shouldn't be too hard. # This code is essentially the same as the mysql_version module, just less # whitespace and returns false on errors. @@ -61,8 +56,8 @@ class Metasploit3 < Msf::Auxiliary disconnect(s) rescue ::Rex::ConnectionError, ::EOFError return false - rescue ::Exception - print_error("Error: #{$!}") + rescue ::Exception => e + vprint_error("#{rhost}:#{rport} error checking version #{e.class} #{e}") return false end offset = 0 @@ -78,7 +73,7 @@ class Metasploit3 < Msf::Auxiliary version = data[offset..-1].unpack('Z*')[0] report_service(:host => rhost, :port => rport, :name => "mysql", :info => version) short_version = version.split('-')[0] - print_status "#{rhost}:#{rport} - Found remote MySQL version #{short_version}." if datastore['VERBOSE'] + vprint_status "#{rhost}:#{rport} - Found remote MySQL version #{short_version}" int_version(short_version) >= int_version(target) end @@ -100,9 +95,9 @@ class Metasploit3 < Msf::Auxiliary end - def do_login(user='root', pass='', this_cred = '', verbose=false) + def do_login(user='root', pass='', this_cred = '') - print_status("Trying username:'#{user}' with password:'#{pass}' against #{rhost}:#{rport}") if verbose + vprint_status("#{rhost}:#{rport} Trying username:'#{user}' with password:'#{pass}'") begin mysql_login(user, pass) print_good("#{rhost}:#{rport} - SUCCESSFUL LOGIN '#{user}' : '#{pass}'") @@ -116,10 +111,10 @@ class Metasploit3 < Msf::Auxiliary ) self.credentials_good[this_cred] = pass rescue ::RbMysql::AccessDeniedError - print_status("#{rhost}:#{rport} failed to login as '#{user}' with password '#{pass}'") if verbose + vprint_status("#{rhost}:#{rport} failed to login as '#{user}' with password '#{pass}'") return :fail rescue ::RbMysql::Error => e - print_error("#{rhost}:#{rport} failed to login: #{e}") + vprint_error("#{rhost}:#{rport} failed to login: #{e.class} #{e}") return :error rescue ::Interrupt raise $! diff --git a/modules/auxiliary/scanner/postgres/postgres_login.rb b/modules/auxiliary/scanner/postgres/postgres_login.rb index da3300d3ae..3fe8f4203f 100644 --- a/modules/auxiliary/scanner/postgres/postgres_login.rb +++ b/modules/auxiliary/scanner/postgres/postgres_login.rb @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Auxiliary include Msf::Auxiliary::AuthBrute include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report - + # Creates an instance of this module. def initialize(info = {}) super(update_info(info, @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE, 'References' => [ - [ 'URL', 'www.postgresql.org' ] + [ 'URL', 'http://www.postgresql.org' ] ], 'Version' => '$Revision$' )) @@ -60,7 +60,7 @@ class Metasploit3 < Msf::Auxiliary self.credentials_tried[this_cred] = pass datastore['USERNAME'] = user datastore['PASSWORD'] = pass - do_login(user,pass,this_cred,datastore['DATABASE'],datastore['VERBOSE']) + do_login(user,pass,this_cred) } end @@ -69,7 +69,7 @@ class Metasploit3 < Msf::Auxiliary datastore['RHOST'] end - # Alias for RPORT + # Alias for RPORT def rport datastore['RPORT'] end @@ -77,10 +77,11 @@ class Metasploit3 < Msf::Auxiliary # Actually do all the login stuff. Note that "verbose" is really pretty # verbose, since postgres_login also makes use of the verbose value # to print diagnostics for other modules. - def do_login(user=nil,pass=nil,this_cred='',database=nil,verbose=false) + def do_login(user=nil,pass=nil,this_cred='') + database = datastore['DATABASE'] begin msg = "#{rhost}:#{rport} Postgres -" - print_status("#{msg} Trying username:'#{user}' with password:'#{pass}' against #{rhost}:#{rport} on database '#{database}'") if verbose + vprint_status("#{msg} Trying username:'#{user}' with password:'#{pass}' on database '#{database}'") # Here's where the actual connection happens. result = postgres_login( :db => database, @@ -94,7 +95,7 @@ class Metasploit3 < Msf::Auxiliary self.credentials_good[this_cred] = pass return :next_user # This is a success for user:pass! when :error_credentials - print_error("#{msg} Username/Password failed.") if verbose + vprint_error("#{msg} Username/Password failed.") return when :connected print_good("#{msg} Success: #{user}:#{pass} (Database '#{database}' succeeded.)") @@ -103,11 +104,11 @@ class Metasploit3 < Msf::Auxiliary postgres_logout return :next_user when :error - print_error("#{msg} Unknown error encountered, quitting.") if verbose + vprint_error("#{msg} Unknown error encountered, giving up on host") return :done end rescue Rex::ConnectionError - print_error "#{rhost}:#{rport} Connection Error: #{$!}" if datastore['VERBOSE'] + vprint_error "#{rhost}:#{rport} Connection Error: #{$!}" return :done end end @@ -137,3 +138,4 @@ class Metasploit3 < Msf::Auxiliary end end + diff --git a/modules/auxiliary/scanner/smb/smb_login.rb b/modules/auxiliary/scanner/smb/smb_login.rb index 98c4e68328..45ef1cd685 100644 --- a/modules/auxiliary/scanner/smb/smb_login.rb +++ b/modules/auxiliary/scanner/smb/smb_login.rb @@ -53,11 +53,16 @@ class Metasploit3 < Msf::Auxiliary end def run_host(ip) - print_status("Starting host #{ip}") + vprint_status("Starting SMB login attempt on #{ip}") if (datastore["SMBUser"] and not datastore["SMBUser"].empty?) # then just do this user/pass try_user_pass(datastore["SMBUser"], datastore["SMBPass"], [datastore["SMBUser"],ip,rport].join(":")) else + if accepts_bogus_logins? + print_error("This system accepts authentication with any credentials, brute force is ineffective.") + return + end + begin each_user_pass do |user, pass| userpass_sleep_interval unless self.credentials_tried.empty? @@ -71,6 +76,23 @@ class Metasploit3 < Msf::Auxiliary end end + def accepts_bogus_logins? + datastore["SMBUser"] = Rex::Text.rand_text_alpha(8) + datastore["SMBPass"] = Rex::Text.rand_text_alpha(8) + + # Connection problems are dealt with at a higher level + connect() + + begin + smb_login() + rescue ::Rex::Proto::SMB::Exceptions::LoginError => e + end + + disconnect + + simple.client.auth_user ? true : false + end + def try_user_pass(user, pass, this_cred) datastore["SMBUser"] = user datastore["SMBPass"] = pass @@ -85,6 +107,7 @@ class Metasploit3 < Msf::Auxiliary case e.error_reason when 'STATUS_LOGON_FAILURE' # Nothing interesting + vprint_status("#{rhost} - FAILED LOGIN (#{smb_peer_os}) #{user} : #{pass} (#{e.error_reason})") disconnect() return diff --git a/modules/auxiliary/scanner/ssh/ssh_login.rb b/modules/auxiliary/scanner/ssh/ssh_login.rb index a2703169c8..d10e99a5b8 100644 --- a/modules/auxiliary/scanner/ssh/ssh_login.rb +++ b/modules/auxiliary/scanner/ssh/ssh_login.rb @@ -41,14 +41,13 @@ class Metasploit3 < Msf::Auxiliary [ OptString.new('USERNAME', [ false, 'The username to authenticate as' ]), OptString.new('PASSWORD', [ false, 'The password for the specified username' ]), - OptBool.new('VERBOSE', [ true, 'Verbose output', false]), Opt::RPORT(22) ], self.class ) register_advanced_options( [ - OptBool.new('SSH_Debug', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]) + OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]) ] ) @@ -71,7 +70,7 @@ class Metasploit3 < Msf::Auxiliary :password => pass } - opt_hash.merge!(:verbose => :debug) if datastore['SSH_Debug'] + opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] begin self.ssh_socket = Net::SSH.start( @@ -137,6 +136,8 @@ class Metasploit3 < Msf::Auxiliary this_cred = [user,ip,rport].join(":") next if self.credentials_tried[this_cred] == pass || self.credentials_good[this_cred] self.credentials_tried[this_cred] = pass + + vprint_status("#{ip}:#{rport} - SSH - Trying: username: '#{user}' with password: '#{pass}'") ret,proof = do_login(ip,user,pass,rport) case ret when :success @@ -144,15 +145,16 @@ class Metasploit3 < Msf::Auxiliary self.credentials_good[this_cred] = pass do_report(ip,user,pass,rport,proof) when :connection_error - print_error "#{ip}:#{rport} - Could not connect" if datastore['VERBOSE'] + vprint_error "#{ip}:#{rport} - SSH - Could not connect" return when :connection_disconnect - print_error "#{ip}:#{rport} - Connection timed out" if datastore['VERBOSE'] + vprint_error "#{ip}:#{rport} - SSH - Connection timed out" return when :fail - print_error "#{ip}:#{rport} - SSH - Failed: '#{user}':'#{pass}'" if datastore['VERBOSE'] + vprint_error "#{ip}:#{rport} - SSH - Failed: '#{user}':'#{pass}'" end end end end + diff --git a/modules/auxiliary/scanner/telnet/telnet_login.rb b/modules/auxiliary/scanner/telnet/telnet_login.rb index c28f5ced7a..afe7110fac 100644 --- a/modules/auxiliary/scanner/telnet/telnet_login.rb +++ b/modules/auxiliary/scanner/telnet/telnet_login.rb @@ -46,11 +46,6 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE ) deregister_options('RHOST') - register_options( - [ - OptBool.new('VERBOSE', [ true, 'Verbose output', false]) - ], Msf::Exploit::Remote::Telnet - ) register_advanced_options( [ OptInt.new('TIMEOUT', [ true, 'Default timeout for telnet connections. The greatest value of TelnetTimeout, TelnetBannerTimeout, or this option will be used as an overall timeout.', 0]) @@ -91,16 +86,16 @@ class Metasploit3 < Msf::Auxiliary else self.credentials_tried[this_cred] = pass end - print_status "#{rhost}:#{rport} Telnet - Attempting: '#{user}':'#{pass}'" if datastore['VERBOSE'] + vprint_status "#{rhost}:#{rport} Telnet - Attempting: '#{user}':'#{pass}'" ret = do_login(user,pass) if ret == :no_pass_prompt - print_status "#{rhost}:#{rport} Telnet - Skipping '#{user}':'#{pass}' due to missing password prompt" if datastore['VERBOSE'] + vprint_status "#{rhost}:#{rport} Telnet - Skipping '#{user}':'#{pass}' due to missing password prompt" self.no_pass_prompt << this_cred elsif ret == :timeout - print_status "#{rhost}:#{rport} Telnet - Skipping '#{user}':'#{pass}' due to timeout" if datastore['VERBOSE'] + vprint_status "#{rhost}:#{rport} Telnet - Skipping '#{user}':'#{pass}' due to timeout" elsif ret == :busy - print_status "#{rhost}:#{rport} Telnet - Skipping '#{user}':'#{pass}' due to busy state" if datastore['VERBOSE'] + vprint_status "#{rhost}:#{rport} Telnet - Skipping '#{user}':'#{pass}' due to busy state" else start_telnet_session(rhost,rport,user,pass) if login_succeeded? end @@ -114,7 +109,7 @@ class Metasploit3 < Msf::Auxiliary begin - print_status("#{rhost}:#{rport} Banner: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}") if datastore['VERBOSE'] + vprint_status("#{rhost}:#{rport} Banner: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}") if busy_message? self.sock.close unless self.sock.closed? @@ -146,7 +141,7 @@ class Metasploit3 < Msf::Auxiliary recv_telnet(self.sock, 0.10) end - print_status("#{rhost}:#{rport} Prompt: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}") if datastore['VERBOSE'] + vprint_status("#{rhost}:#{rport} Prompt: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}") if password_prompt? send_pass(pass) @@ -157,7 +152,7 @@ class Metasploit3 < Msf::Auxiliary end - print_status("#{rhost}:#{rport} Result: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}") if datastore['VERBOSE'] + vprint_status("#{rhost}:#{rport} Result: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}") if login_succeeded? report_telnet(user,pass,@trace) @@ -218,3 +213,4 @@ class Metasploit3 < Msf::Auxiliary end end +