See #2133. Needs more testing, but solves the immediate problem of dying in the face of MaxAuthTries.

git-svn-id: file:///home/svn/framework3/trunk@9599 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Tod Beardsley 2010-06-23 22:58:56 +00:00
parent 1f957891fb
commit dbdab1f282
1 changed files with 36 additions and 5 deletions

View File

@ -57,6 +57,7 @@ class Metasploit3 < Msf::Auxiliary
[
OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
OptString.new('SSH_KEYFILE_B64', [false, 'Raw data of an unencrypted SSH public key. This should be used by programmatic interfaces to this module only.', '']),
OptPath.new('KEY_DIR', [false, 'Directory of several cleartext private keys. Filenames must not begin with a dot, or end in ".pub" in order to be read.'])
]
)
@ -67,6 +68,10 @@ class Metasploit3 < Msf::Auxiliary
end
def key_dir
datastore['KEY_DIR']
end
def rport
datastore['RPORT']
end
@ -74,8 +79,14 @@ class Metasploit3 < Msf::Auxiliary
def read_keyfile(file)
if file == :keyfile_b64
keyfile = datastore['SSH_KEYFILE_B64'].unpack("m*").first
elsif file.kind_of? Array
keyfile = ''
file.each do |dir_entry|
next unless File.readable? dir_entry
keyfile << File.open(dir_entry, "rb") {|f| f.read(f.stat.size)}
end
else
keyfile = File.open(file) {|f| f.read(f.stat.size)}
keyfile = File.open(file, "rb") {|f| f.read(f.stat.size)}
end
keys = []
this_key = []
@ -135,10 +146,20 @@ class Metasploit3 < Msf::Auxiliary
keys = read_keyfile(:keyfile_b64)
cleartext_keys = pull_cleartext_keys(keys)
print_status "#{ip}:#{rport} - SSH - Trying #{cleartext_keys.size} cleartext key#{(cleartext_keys.size > 1) ? "s" : ""} per user (read from datastore)."
elsif datastore['KEY_DIR']
return :missing_keyfile unless(File.directory?(key_dir) && File.readable?(key_dir))
unless @key_files
@key_files = Dir.entries(key_dir).reject {|f| f =~ /^\x2e/ || f =~ /\x2epub$/}.sort
end
these_keys = @key_files.map {|f| File.join(key_dir,f)}
keys = read_keyfile(these_keys)
cleartext_keys = pull_cleartext_keys(keys)
print_status "#{ip}:#{rport} - SSH - Trying #{cleartext_keys.size} cleartext key#{(cleartext_keys.size > 1) ? "s" : ""} per user."
else
return :missing_keyfile
end
key_data = cleartext_keys
# key_data = cleartext_keys
cleartext_keys.each_with_index do |key_data,key_idx|
opt_hash = {
:auth_methods => ['publickey'],
@ -159,11 +180,21 @@ class Metasploit3 < Msf::Auxiliary
)
rescue Rex::ConnectionError
return :connection_error
rescue Net::SSH::Disconnect, ::EOFError
rescue Net::SSH::Disconnect, ::EOFError
return :connection_disconnect
rescue Net::SSH::Exception
rescue Net::SSH::AuthenticationFailed
# Try, try, again
if @key_files
vprint_error "#{ip}:#{rport} - SSH - Failed authentication, trying key #{@key_files[key_idx+1]}... #{Time.now}"
else
vprint_error "#{ip}:#{rport} - SSH - Failed authentication, trying key #{key_idx+1}... #{Time.now}"
end
next
rescue Net::SSH::Exception => e
return [:fail,nil] # For whatever reason.
end
break
end
if self.ssh_socket
self.good_key = self.ssh_socket.auth_info[:pubkey_id]
@ -187,7 +218,7 @@ class Metasploit3 < Msf::Auxiliary
# Clean up the stored data - need to stash the keyfile into
# a datastore for later reuse.
if datastore['KEY_FILE'] and !datastore['KEY_FILE'].empty?
keyfile = File.open(datastore['KEY_FILE']) {|f| f.read(f.stat.size)}
keyfile = File.open(datastore['KEY_FILE'], "rb") {|f| f.read(f.stat.size)}
sess.exploit_datastore['SSH_KEYFILE_B64'] = [keyfile].pack("m*").gsub("\n","")
sess.exploit_datastore['KEY_FILE'] = nil
end