diff --git a/lib/metasploit/framework/login_scanner/ssh.rb b/lib/metasploit/framework/login_scanner/ssh.rb index 74a7d5c49b..babf5174b3 100644 --- a/lib/metasploit/framework/login_scanner/ssh.rb +++ b/lib/metasploit/framework/login_scanner/ssh.rb @@ -7,15 +7,30 @@ 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 # @!attribute cred_details # @return [Array] An array of hashes containing the cred attr_accessor :cred_details # @!attribute host # @return [String] The IP address or hostname to connect to attr_accessor :host + # @!attribute msframework + # @return [Framework] The Framework instance to use for Session handling + attr_accessor :msframework + # @!attribute msfmodule + # @return [Module] The Metasploit module that instantiated this object + attr_accessor :msfmodule # @!attribute port # @return [Fixnum] The port to connect to attr_accessor :port + # @!attribute stop_on_success + # @return [Boolean] Whether the scanner should stop when it has found one working Credential + attr_accessor :stop_on_success + # @!attribute verbosity + # @return [Symbol] The verbosity level for the SSH client. + attr_accessor :verbosity validates :port, presence: true, @@ -25,6 +40,21 @@ module Metasploit less_than_or_equal_to: 65535 } + validates :connection_timeout, + presence: true, + numericality: { + only_integer: true, + greater_than_or_equal_to: 1 + } + + validates :verbosity, + presence: true, + inclusion: { in: [:debug, :info, :warn, :error, :fatal] } + + validates :stop_on_success, + presence: true, + inclusion: { in: [true, false] } + validates :host, presence: true validates :cred_details, presence: true diff --git a/spec/lib/metasploit/framework/login_scanner/ssh_spec.rb b/spec/lib/metasploit/framework/login_scanner/ssh_spec.rb index 937579da1c..89b21b057d 100644 --- a/spec/lib/metasploit/framework/login_scanner/ssh_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/ssh_spec.rb @@ -10,6 +10,10 @@ describe Metasploit::Framework::LoginScanner::SSH do it { should respond_to :port } it { should respond_to :host } it { should respond_to :cred_details } + it { should respond_to :connection_timeout } + it { should respond_to :verbosity } + it { should respond_to :stop_on_success } + it { should respond_to :valid! } context 'validations' do context 'port' do @@ -156,6 +160,113 @@ describe Metasploit::Framework::LoginScanner::SSH do end end + context 'connection_timeout' do + + it 'is not valid for not set' do + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:connection_timeout]).to include "is not a number" + end + + it 'is not valid for a non-number' do + ssh_scanner.connection_timeout = "a" + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:connection_timeout]).to include "is not a number" + end + + it 'is not valid for a floating point' do + ssh_scanner.connection_timeout = 5.76 + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:connection_timeout]).to include "must be an integer" + end + + it 'is not valid for a negative number' do + ssh_scanner.connection_timeout = -8 + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:connection_timeout]).to include "must be greater than or equal to 1" + end + + it 'is not valid for 0' do + ssh_scanner.connection_timeout = 0 + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:connection_timeout]).to include "must be greater than or equal to 1" + end + + it 'is valid for a legitimate number' do + ssh_scanner.port = rand(1000) + 1 + expect(ssh_scanner.errors[:connection_timeout]).to be_empty + end + end + + context 'verbosity' do + + it 'is valid with :debug' do + ssh_scanner.verbosity = :debug + expect(ssh_scanner.errors[:verbosity]).to be_empty + end + + it 'is valid with :info' do + ssh_scanner.verbosity = :info + expect(ssh_scanner.errors[:verbosity]).to be_empty + end + + it 'is valid with :warn' do + ssh_scanner.verbosity = :warn + expect(ssh_scanner.errors[:verbosity]).to be_empty + end + + it 'is valid with :error' do + ssh_scanner.verbosity = :error + expect(ssh_scanner.errors[:verbosity]).to be_empty + end + + it 'is valid with :fatal' do + ssh_scanner.verbosity = :fatal + expect(ssh_scanner.errors[:verbosity]).to be_empty + end + + it 'is invalid with a random symbol' do + ssh_scanner.verbosity = :foobar + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:verbosity]).to include 'is not included in the list' + end + + it 'is invalid with a string' do + ssh_scanner.verbosity = 'debug' + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:verbosity]).to include 'is not included in the list' + end + end + + context 'stop_on_success' do + + it 'is not valid for not set' do + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:stop_on_success]).to include 'is not included in the list' + end + + it 'is not valid for the string true' do + ssh_scanner.stop_on_success = 'true' + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:stop_on_success]).to include 'is not included in the list' + end + + it 'is not valid for the string false' do + ssh_scanner.stop_on_success = 'false' + expect(ssh_scanner).to_not be_valid + expect(ssh_scanner.errors[:stop_on_success]).to include 'is not included in the list' + end + + it 'is valid for true class' do + ssh_scanner.stop_on_success = true + expect(ssh_scanner.errors[:stop_on_success]).to be_empty + end + + it 'is valid for false class' do + ssh_scanner.stop_on_success = false + expect(ssh_scanner.errors[:stop_on_success]).to be_empty + end + end + context '#valid!' do it 'raises a Metasploit::Framework::LoginScanner::Invalid when validations fail' do expect{ssh_scanner.valid!}.to raise_error Metasploit::Framework::LoginScanner::Invalid