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-b9f4589650daunstable
parent
1f957891fb
commit
dbdab1f282
|
@ -57,6 +57,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
[
|
[
|
||||||
OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
|
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.', '']),
|
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
|
end
|
||||||
|
|
||||||
|
def key_dir
|
||||||
|
datastore['KEY_DIR']
|
||||||
|
end
|
||||||
|
|
||||||
def rport
|
def rport
|
||||||
datastore['RPORT']
|
datastore['RPORT']
|
||||||
end
|
end
|
||||||
|
@ -74,8 +79,14 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
def read_keyfile(file)
|
def read_keyfile(file)
|
||||||
if file == :keyfile_b64
|
if file == :keyfile_b64
|
||||||
keyfile = datastore['SSH_KEYFILE_B64'].unpack("m*").first
|
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
|
else
|
||||||
keyfile = File.open(file) {|f| f.read(f.stat.size)}
|
keyfile = File.open(file, "rb") {|f| f.read(f.stat.size)}
|
||||||
end
|
end
|
||||||
keys = []
|
keys = []
|
||||||
this_key = []
|
this_key = []
|
||||||
|
@ -135,10 +146,20 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
keys = read_keyfile(:keyfile_b64)
|
keys = read_keyfile(:keyfile_b64)
|
||||||
cleartext_keys = pull_cleartext_keys(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 (read from datastore)."
|
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
|
else
|
||||||
return :missing_keyfile
|
return :missing_keyfile
|
||||||
end
|
end
|
||||||
key_data = cleartext_keys
|
# key_data = cleartext_keys
|
||||||
|
cleartext_keys.each_with_index do |key_data,key_idx|
|
||||||
|
|
||||||
opt_hash = {
|
opt_hash = {
|
||||||
:auth_methods => ['publickey'],
|
:auth_methods => ['publickey'],
|
||||||
|
@ -161,9 +182,19 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
return :connection_error
|
return :connection_error
|
||||||
rescue Net::SSH::Disconnect, ::EOFError
|
rescue Net::SSH::Disconnect, ::EOFError
|
||||||
return :connection_disconnect
|
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.
|
return [:fail,nil] # For whatever reason.
|
||||||
end
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
if self.ssh_socket
|
if self.ssh_socket
|
||||||
self.good_key = self.ssh_socket.auth_info[:pubkey_id]
|
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
|
# Clean up the stored data - need to stash the keyfile into
|
||||||
# a datastore for later reuse.
|
# a datastore for later reuse.
|
||||||
if datastore['KEY_FILE'] and !datastore['KEY_FILE'].empty?
|
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['SSH_KEYFILE_B64'] = [keyfile].pack("m*").gsub("\n","")
|
||||||
sess.exploit_datastore['KEY_FILE'] = nil
|
sess.exploit_datastore['KEY_FILE'] = nil
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue