basic login attempt functionality

groundowkr now layed for trying
authentication attempts on the
SSH LoginScanner, with test coverage
bug/bundler_fix
David Maloney 2014-04-18 20:08:28 -05:00
parent 85349ccec4
commit 9a15a2be04
No known key found for this signature in database
GPG Key ID: DEDBA9DC3A913DB2
2 changed files with 106 additions and 0 deletions

View File

@ -8,6 +8,7 @@ module Metasploit
class SSH
include ActiveModel::Validations
# @!attribute connection_timeout
# @return [Fixnum] The timeout in seconds for a single SSH connection
attr_accessor :connection_timeout
@ -75,6 +76,7 @@ module Metasploit
end
def attempt_login(user, pass)
ssh_socket = nil
opt_hash = {
:auth_methods => ['password','keyboard-interactive'],
:msframework => msframework,
@ -104,6 +106,13 @@ module Metasploit
return [:fail,nil] # For whatever reason. Can't tell if passwords are on/off without timing responses.
end
if ssh_socket
proof = gather_proof
create_session(proof,user,pass)
[:success, proof]
else
[:fail, nil]
end
end
@ -121,6 +130,73 @@ module Metasploit
private
def create_session(proof,user,pass)
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
datastore_opts = {
'USERPASS_FILE' => nil,
'USER_FILE' => nil,
'PASS_FILE' => nil,
'USERNAME' => user,
'PASSWORD' => pass
}
session = Msf::Sessions::CommandShell.new(conn.lsock)
session.info = "SSH: #{user}:#{pass} (#{host}:#{port})"
# Set module details on the session if we have them
if msfmodule
session.set_from_exploit(msfmodule)
session.exploit_datastore.merge!(datastore_opts)
end
# Register the new session
if msframework
msframework.sessions.register(session)
end
# Set the session platform
case proof
when /Linux/
session.platform = "linux"
when /Darwin/
session.platform = "osx"
when /SunOS/
session.platform = "solaris"
when /BSD/
session.platform = "bsd"
when /HP-UX/
session.platform = "hpux"
when /AIX/
session.platform = "aix"
when /Win32|Windows/
session.platform = "windows"
when /Unknown command or computer name/
session.platform = "cisco-ios"
end
end
def gather_proof
proof = ''
begin
Timeout.timeout(5) do
proof = ssh_socket.exec!("id\n").to_s
if(proof =~ /id=/)
proof << ssh_socket.exec!("uname -a\n").to_s
else
# Cisco IOS
if proof =~ /Unknown command or computer name/
proof = ssh_socket.exec!("ver\n").to_s
else
proof << ssh_socket.exec!("help\n?\n\n\n").to_s
end
end
end
rescue ::Exception
end
proof
end
def host_address_must_be_valid
unless host.kind_of? String
errors.add(:host, "must be a string")

View File

@ -338,6 +338,36 @@ describe Metasploit::Framework::LoginScanner::SSH do
Net::SSH.should_receive(:start) { raise Net::SSH::Exception }
expect(ssh_scanner.attempt_login('root', 'toor')).to eq [:fail,nil]
end
it 'returns [:fail,nil] if no socket returned' do
Net::SSH.should_receive(:start).and_return nil
expect(ssh_scanner.attempt_login('root', 'toor')).to eq [:fail,nil]
end
end
context 'when it succeeds' do
it 'gathers proof of the connections' do
Net::SSH.should_receive(:start) {"fake_socket"}
my_scanner = ssh_scanner
my_scanner.should_receive(:gather_proof)
my_scanner.attempt_login('root', 'toor')
end
it 'creates a session from the connection' do
Net::SSH.should_receive(:start) {"fake_socket"}
my_scanner = ssh_scanner
my_scanner.should_receive(:gather_proof).and_return('root')
my_scanner.should_receive(:create_session).with('root', 'root', 'toor')
my_scanner.attempt_login('root', 'toor')
end
it 'returns a success code and proof' do
Net::SSH.should_receive(:start) {"fake_socket"}
my_scanner = ssh_scanner
my_scanner.should_receive(:gather_proof).and_return('root')
expect(my_scanner.attempt_login('root', 'toor')).to eq [:success, 'root']
end
end
end