Path: blob/master/lib/metasploit/framework/login_scanner/ssh.rb
23684 views
require 'net/ssh'1require 'metasploit/framework/login_scanner/base'2require 'metasploit/framework/ssh/platform'3require 'rex/socket/ssh_factory'45module Metasploit6module Framework7module LoginScanner89# This is the LoginScanner class for dealing with the Secure Shell protocol.10# It is responsible for taking a single target, and a list of credentials11# and attempting them. It then saves the results.12#13class SSH14include Metasploit::Framework::LoginScanner::Base15include Msf::Exploit::Remote::SSH16#17# CONSTANTS18#1920CAN_GET_SESSION = true21DEFAULT_PORT = 2222LIKELY_PORTS = [ DEFAULT_PORT ]23LIKELY_SERVICE_NAMES = [ 'ssh' ]24PRIVATE_TYPES = [ :password, :ssh_key ]25REALM_KEY = nil2627VERBOSITIES = [28:debug,29:info,30:warn,31:error,32:fatal33]34# @!attribute ssh_socket35# @return [Net::SSH::Connection::Session] The current SSH connection36attr_accessor :ssh_socket37# @!attribute verbosity38# The verbosity level for the SSH client.39#40# @return [Symbol] An element of {VERBOSITIES}.41attr_accessor :verbosity42# @!attribute skip_gather_proof43# @return [Boolean] Whether to skip calling gather_proof44attr_accessor :skip_gather_proof4546validates :verbosity,47presence: true,48inclusion: { in: VERBOSITIES }4950# (see {Base#attempt_login})51# @note The caller *must* close {#ssh_socket}52def attempt_login(credential)53self.ssh_socket = nil54opt_hash = ssh_client_defaults.merge({55:port => port,56:verbose => verbosity57})58case credential.private_type59when :password, nil60opt_hash.update(61:auth_methods => ['password','keyboard-interactive'],62:password => credential.private,63)64when :ssh_key65opt_hash.update(66:auth_methods => ['publickey'],67:key_data => credential.private,68)69end70opt_hash[:passphrase] = cred_details.password7172result_options = {73credential: credential74}75begin76::Timeout.timeout(connection_timeout) do77self.ssh_socket = Net::SSH.start(78host,79credential.public,80opt_hash81)82end83rescue OpenSSL::Cipher::CipherError, ::EOFError, Net::SSH::Disconnect, Rex::ConnectionError, ::Timeout::Error, Errno::ECONNRESET, Errno::EPIPE => e84result_options.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)85rescue Net::SSH::Exception => e86status = Metasploit::Model::Login::Status::INCORRECT87status = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT if e.message.split("\n").first == 'could not settle on kex algorithm'8889result_options.merge!(status: status, proof: e)90end9192unless result_options.has_key? :status93if ssh_socket94begin95proof = gather_proof unless skip_gather_proof96rescue StandardError => e97elog('Failed to gather SSH proof', error: e)98proof = nil99end100result_options.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: proof)101else102result_options.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: nil)103end104end105106result = ::Metasploit::Framework::LoginScanner::Result.new(result_options)107result.host = host108result.port = port109result.protocol = 'tcp'110result.service_name = 'ssh'111result112end113114private115116# This method attempts to gather proof that we successfully logged in.117# @return [String] The proof of a connection, May be empty.118def gather_proof119Metasploit::Framework::Ssh::Platform.get_platform_info(ssh_socket)120end121122def set_sane_defaults123self.connection_timeout = 30 if self.connection_timeout.nil?124self.port = DEFAULT_PORT if self.port.nil?125self.verbosity = :fatal if self.verbosity.nil?126end127128public129130def get_platform(proof)131Metasploit::Framework::Ssh::Platform.get_platform_from_info(proof)132end133end134end135end136end137138139