fix up some more specs
some spec cleanup and added basic specs to the HTTP LoginScannerbug/bundler_fix
parent
1a5abc49d1
commit
5e6f57f711
|
@ -1,5 +1,6 @@
|
|||
require 'rex/proto/http'
|
||||
require 'metasploit/framework/login_scanner'
|
||||
require 'metasploit/framework/login_scanner/base'
|
||||
require 'metasploit/framework/login_scanner/rex_socket'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
|
@ -8,75 +9,17 @@ module Metasploit
|
|||
# HTTP-specific login scananer.
|
||||
#
|
||||
class HTTP
|
||||
include ActiveModel::Validations
|
||||
include Metasploit::Framework::LoginScanner::Base
|
||||
include Metasploit::Framework::LoginScanner::RexSocket
|
||||
|
||||
# @!attribute connection_timeout
|
||||
# @return [Numeric] The timeout in seconds for a single connection
|
||||
attr_accessor :connection_timeout
|
||||
|
||||
# @!attribute cred_details
|
||||
# @return [Array] An array of {Credential} objects
|
||||
attr_accessor :cred_details
|
||||
|
||||
# @!attribute failures
|
||||
# @return [Array] Array of {Result} objects that failed
|
||||
attr_accessor :failures
|
||||
|
||||
# @!attribute host
|
||||
# @return [String] The IP address or hostname to connect to
|
||||
attr_accessor :host
|
||||
|
||||
# @!attribute port
|
||||
# @return [Fixnum] The port to connect to
|
||||
attr_accessor :port
|
||||
|
||||
# @!attribute ssl
|
||||
# @return [Boolean] Whether this client makes SSL connections
|
||||
attr_accessor :ssl
|
||||
|
||||
# @!attribute ssl_version
|
||||
# @return [Symbol] The version of SSL/TLS to use when connecting
|
||||
attr_accessor :ssl_version
|
||||
|
||||
# @!attribute stop_on_success
|
||||
# @return [Boolean] Whether the scanner should stop when it has
|
||||
# found one working {Credential}
|
||||
attr_accessor :stop_on_success
|
||||
|
||||
# @!attribute successes
|
||||
# @return [Array] Array of {Result} objects that succeded
|
||||
attr_accessor :successes
|
||||
|
||||
# @!attribute uri
|
||||
# @return [String] The path and query string on the server to
|
||||
# authenticate to.
|
||||
attr_accessor :uri
|
||||
|
||||
validates :connection_timeout, presence: true
|
||||
|
||||
validates :cred_details, presence: true
|
||||
|
||||
validates :host, presence: true
|
||||
|
||||
validates :port,
|
||||
presence: true,
|
||||
numericality: {
|
||||
only_integer: true,
|
||||
greater_than_or_equal_to: 1,
|
||||
less_than_or_equal_to: 0xffff
|
||||
}
|
||||
|
||||
validates :uri, presence: true, length: { minimum: 1 }
|
||||
|
||||
# @param attributes [Hash{Symbol => String,nil}]
|
||||
def initialize(attributes = {})
|
||||
attributes.each do |attribute, value|
|
||||
public_send("#{attribute}=", value)
|
||||
end
|
||||
self.successes = []
|
||||
self.failures = []
|
||||
end
|
||||
|
||||
# Attempt a single login with a single credential against the target.
|
||||
#
|
||||
# @param credential [Credential] The credential object to attempt to
|
||||
|
@ -126,39 +69,13 @@ module Metasploit
|
|||
Result.new(result_opts)
|
||||
end
|
||||
|
||||
# Run all the login attempts against the target.
|
||||
#
|
||||
# This method calls {#attempt_login} once for each credential in
|
||||
# {#cred_details}. Results are stored in {#successes} and {#failures}.
|
||||
# If a block is given, each result will be yielded as we go.
|
||||
#
|
||||
# @yieldparam result [Result] The frozen {Result} object associated
|
||||
# with each attempt
|
||||
# @yieldreturn [void]
|
||||
# @return [void]
|
||||
def scan!
|
||||
valid!
|
||||
cred_details.each do |credential|
|
||||
result = attempt_login(credential)
|
||||
result.freeze
|
||||
private
|
||||
|
||||
yield result if block_given?
|
||||
|
||||
if result.success?
|
||||
successes << result
|
||||
break if stop_on_success
|
||||
else
|
||||
failures << result
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @return [void]
|
||||
# @raise [Invalid] if this scanner's attributes are not valid
|
||||
def valid!
|
||||
unless valid?
|
||||
raise LoginScanner::Invalid.new(self)
|
||||
end
|
||||
# This method sets the sane defaults for things
|
||||
# like timeouts and TCP evasion options
|
||||
def set_sane_defaults
|
||||
self.max_send_size = 0 if self.max_send_size.nil?
|
||||
self.send_delay = 0 if self.send_delay.nil?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
require 'spec_helper'
|
||||
require 'metasploit/framework/login_scanner/http'
|
||||
|
||||
describe Metasploit::Framework::LoginScanner::HTTP do
|
||||
|
||||
subject(:http_scanner) { described_class.new }
|
||||
|
||||
it_behaves_like 'Metasploit::Framework::LoginScanner::Base'
|
||||
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
|
||||
|
||||
it { should respond_to :uri }
|
||||
|
||||
|
||||
end
|
|
@ -276,13 +276,14 @@ shared_examples_for 'Metasploit::Framework::LoginScanner::Base' do
|
|||
|
||||
it 'calls valid! before running' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:valid!).and_call_original
|
||||
my_scanner.should_receive(:valid!)
|
||||
my_scanner.should_receive(:attempt_login).at_least(:once).and_return success
|
||||
my_scanner.scan!
|
||||
end
|
||||
|
||||
it 'call attempt_login once for each cred_detail' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:valid!)
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_blank).and_return success
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_pub).and_return success
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_pri).and_return success
|
||||
|
@ -291,6 +292,7 @@ shared_examples_for 'Metasploit::Framework::LoginScanner::Base' do
|
|||
|
||||
it 'adds the failed results to the failures attribute' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:valid!)
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_blank).and_return failure_blank
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_pub).and_return success
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_pri).and_return failure
|
||||
|
@ -301,6 +303,7 @@ shared_examples_for 'Metasploit::Framework::LoginScanner::Base' do
|
|||
|
||||
it 'adds the success results to the successes attribute' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:valid!)
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_blank).and_return failure_blank
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_pub).and_return success
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_pri).and_return failure
|
||||
|
@ -319,6 +322,7 @@ shared_examples_for 'Metasploit::Framework::LoginScanner::Base' do
|
|||
|
||||
it 'stops after the first successful login' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:valid!)
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_blank).and_return failure_blank
|
||||
my_scanner.should_receive(:attempt_login).once.with(pub_pub).and_return success
|
||||
my_scanner.should_not_receive(:attempt_login).with(pub_pri)
|
||||
|
|
|
@ -8,51 +8,51 @@ shared_examples_for 'Metasploit::Framework::LoginScanner::RexSocket' do
|
|||
|
||||
context 'send_delay' do
|
||||
it 'is not valid for a non-number' do
|
||||
ftp_scanner.send_delay = "a"
|
||||
expect(ftp_scanner).to_not be_valid
|
||||
expect(ftp_scanner.errors[:send_delay]).to include "is not a number"
|
||||
login_scanner.send_delay = "a"
|
||||
expect(login_scanner).to_not be_valid
|
||||
expect(login_scanner.errors[:send_delay]).to include "is not a number"
|
||||
end
|
||||
|
||||
it 'is not valid for a floating point' do
|
||||
ftp_scanner.send_delay = 5.76
|
||||
expect(ftp_scanner).to_not be_valid
|
||||
expect(ftp_scanner.errors[:send_delay]).to include "must be an integer"
|
||||
login_scanner.send_delay = 5.76
|
||||
expect(login_scanner).to_not be_valid
|
||||
expect(login_scanner.errors[:send_delay]).to include "must be an integer"
|
||||
end
|
||||
|
||||
it 'is not valid for a negative number' do
|
||||
ftp_scanner.send_delay = -8
|
||||
expect(ftp_scanner).to_not be_valid
|
||||
expect(ftp_scanner.errors[:send_delay]).to include "must be greater than or equal to 0"
|
||||
login_scanner.send_delay = -8
|
||||
expect(login_scanner).to_not be_valid
|
||||
expect(login_scanner.errors[:send_delay]).to include "must be greater than or equal to 0"
|
||||
end
|
||||
|
||||
it 'is valid for a legitimate number' do
|
||||
ftp_scanner.send_delay = rand(1000) + 1
|
||||
expect(ftp_scanner.errors[:send_delay]).to be_empty
|
||||
login_scanner.send_delay = rand(1000) + 1
|
||||
expect(login_scanner.errors[:send_delay]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'max_send_size' do
|
||||
it 'is not valid for a non-number' do
|
||||
ftp_scanner.max_send_size = "a"
|
||||
expect(ftp_scanner).to_not be_valid
|
||||
expect(ftp_scanner.errors[:max_send_size]).to include "is not a number"
|
||||
login_scanner.max_send_size = "a"
|
||||
expect(login_scanner).to_not be_valid
|
||||
expect(login_scanner.errors[:max_send_size]).to include "is not a number"
|
||||
end
|
||||
|
||||
it 'is not valid for a floating point' do
|
||||
ftp_scanner.max_send_size = 5.76
|
||||
expect(ftp_scanner).to_not be_valid
|
||||
expect(ftp_scanner.errors[:max_send_size]).to include "must be an integer"
|
||||
login_scanner.max_send_size = 5.76
|
||||
expect(login_scanner).to_not be_valid
|
||||
expect(login_scanner.errors[:max_send_size]).to include "must be an integer"
|
||||
end
|
||||
|
||||
it 'is not valid for a negative number' do
|
||||
ftp_scanner.max_send_size = -8
|
||||
expect(ftp_scanner).to_not be_valid
|
||||
expect(ftp_scanner.errors[:max_send_size]).to include "must be greater than or equal to 0"
|
||||
login_scanner.max_send_size = -8
|
||||
expect(login_scanner).to_not be_valid
|
||||
expect(login_scanner.errors[:max_send_size]).to include "must be greater than or equal to 0"
|
||||
end
|
||||
|
||||
it 'is valid for a legitimate number' do
|
||||
ftp_scanner.max_send_size = rand(1000) + 1
|
||||
expect(ftp_scanner.errors[:max_send_size]).to be_empty
|
||||
login_scanner.max_send_size = rand(1000) + 1
|
||||
expect(login_scanner.errors[:max_send_size]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue