Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/metasploit/framework/login_scanner/ssh.rb
23684 views
1
require 'net/ssh'
2
require 'metasploit/framework/login_scanner/base'
3
require 'metasploit/framework/ssh/platform'
4
require 'rex/socket/ssh_factory'
5
6
module Metasploit
7
module Framework
8
module LoginScanner
9
10
# This is the LoginScanner class for dealing with the Secure Shell protocol.
11
# It is responsible for taking a single target, and a list of credentials
12
# and attempting them. It then saves the results.
13
#
14
class SSH
15
include Metasploit::Framework::LoginScanner::Base
16
include Msf::Exploit::Remote::SSH
17
#
18
# CONSTANTS
19
#
20
21
CAN_GET_SESSION = true
22
DEFAULT_PORT = 22
23
LIKELY_PORTS = [ DEFAULT_PORT ]
24
LIKELY_SERVICE_NAMES = [ 'ssh' ]
25
PRIVATE_TYPES = [ :password, :ssh_key ]
26
REALM_KEY = nil
27
28
VERBOSITIES = [
29
:debug,
30
:info,
31
:warn,
32
:error,
33
:fatal
34
]
35
# @!attribute ssh_socket
36
# @return [Net::SSH::Connection::Session] The current SSH connection
37
attr_accessor :ssh_socket
38
# @!attribute verbosity
39
# The verbosity level for the SSH client.
40
#
41
# @return [Symbol] An element of {VERBOSITIES}.
42
attr_accessor :verbosity
43
# @!attribute skip_gather_proof
44
# @return [Boolean] Whether to skip calling gather_proof
45
attr_accessor :skip_gather_proof
46
47
validates :verbosity,
48
presence: true,
49
inclusion: { in: VERBOSITIES }
50
51
# (see {Base#attempt_login})
52
# @note The caller *must* close {#ssh_socket}
53
def attempt_login(credential)
54
self.ssh_socket = nil
55
opt_hash = ssh_client_defaults.merge({
56
:port => port,
57
:verbose => verbosity
58
})
59
case credential.private_type
60
when :password, nil
61
opt_hash.update(
62
:auth_methods => ['password','keyboard-interactive'],
63
:password => credential.private,
64
)
65
when :ssh_key
66
opt_hash.update(
67
:auth_methods => ['publickey'],
68
:key_data => credential.private,
69
)
70
end
71
opt_hash[:passphrase] = cred_details.password
72
73
result_options = {
74
credential: credential
75
}
76
begin
77
::Timeout.timeout(connection_timeout) do
78
self.ssh_socket = Net::SSH.start(
79
host,
80
credential.public,
81
opt_hash
82
)
83
end
84
rescue OpenSSL::Cipher::CipherError, ::EOFError, Net::SSH::Disconnect, Rex::ConnectionError, ::Timeout::Error, Errno::ECONNRESET, Errno::EPIPE => e
85
result_options.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
86
rescue Net::SSH::Exception => e
87
status = Metasploit::Model::Login::Status::INCORRECT
88
status = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT if e.message.split("\n").first == 'could not settle on kex algorithm'
89
90
result_options.merge!(status: status, proof: e)
91
end
92
93
unless result_options.has_key? :status
94
if ssh_socket
95
begin
96
proof = gather_proof unless skip_gather_proof
97
rescue StandardError => e
98
elog('Failed to gather SSH proof', error: e)
99
proof = nil
100
end
101
result_options.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: proof)
102
else
103
result_options.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: nil)
104
end
105
end
106
107
result = ::Metasploit::Framework::LoginScanner::Result.new(result_options)
108
result.host = host
109
result.port = port
110
result.protocol = 'tcp'
111
result.service_name = 'ssh'
112
result
113
end
114
115
private
116
117
# This method attempts to gather proof that we successfully logged in.
118
# @return [String] The proof of a connection, May be empty.
119
def gather_proof
120
Metasploit::Framework::Ssh::Platform.get_platform_info(ssh_socket)
121
end
122
123
def set_sane_defaults
124
self.connection_timeout = 30 if self.connection_timeout.nil?
125
self.port = DEFAULT_PORT if self.port.nil?
126
self.verbosity = :fatal if self.verbosity.nil?
127
end
128
129
public
130
131
def get_platform(proof)
132
Metasploit::Framework::Ssh::Platform.get_platform_from_info(proof)
133
end
134
end
135
end
136
end
137
end
138
139