use base mixin in scanners
refactor the LoginScanner classes to use the new Base mixin. Still some more cleanup to be donebug/bundler_fix
parent
7978587428
commit
90882f803b
|
@ -8,147 +8,152 @@ module Metasploit
|
||||||
# the LoginScanner classes. All of the LoginScanners
|
# the LoginScanner classes. All of the LoginScanners
|
||||||
# should include this module to establish base behaviour
|
# should include this module to establish base behaviour
|
||||||
module Base
|
module Base
|
||||||
|
extend ActiveSupport::Concern
|
||||||
include ActiveModel::Validations
|
include ActiveModel::Validations
|
||||||
|
|
||||||
# @!attribute connection_timeout
|
included do
|
||||||
# @return [Fixnum] The timeout in seconds for a single SSH connection
|
# @!attribute connection_timeout
|
||||||
attr_accessor :connection_timeout
|
# @return [Fixnum] The timeout in seconds for a single SSH connection
|
||||||
# @!attribute cred_details
|
attr_accessor :connection_timeout
|
||||||
# @return [Array] An array of Credential objects
|
# @!attribute cred_details
|
||||||
attr_accessor :cred_details
|
# @return [Array] An array of Credential objects
|
||||||
# @!attribute successes
|
attr_accessor :cred_details
|
||||||
# @return [Array] Array of of result objects that failed
|
# @!attribute successes
|
||||||
attr_accessor :failures
|
# @return [Array] Array of of result objects that failed
|
||||||
# @!attribute host
|
attr_accessor :failures
|
||||||
# @return [String] The IP address or hostname to connect to
|
# @!attribute host
|
||||||
attr_accessor :host
|
# @return [String] The IP address or hostname to connect to
|
||||||
# @!attribute port
|
attr_accessor :host
|
||||||
# @return [Fixnum] The port to connect to
|
# @!attribute port
|
||||||
attr_accessor :port
|
# @return [Fixnum] The port to connect to
|
||||||
# @!attribute proxies
|
attr_accessor :port
|
||||||
# @return [String] The proxy directive to use for the socket
|
# @!attribute proxies
|
||||||
attr_accessor :proxies
|
# @return [String] The proxy directive to use for the socket
|
||||||
# @!attribute ssh_socket
|
attr_accessor :proxies
|
||||||
# @return [Net::SSH::Connection::Session] The current SSH connection
|
# @!attribute ssh_socket
|
||||||
attr_accessor :ssh_socket
|
# @return [Net::SSH::Connection::Session] The current SSH connection
|
||||||
# @!attribute stop_on_success
|
attr_accessor :ssh_socket
|
||||||
# @return [Boolean] Whether the scanner should stop when it has found one working Credential
|
# @!attribute stop_on_success
|
||||||
attr_accessor :stop_on_success
|
# @return [Boolean] Whether the scanner should stop when it has found one working Credential
|
||||||
# @!attribute successes
|
attr_accessor :stop_on_success
|
||||||
# @return [Array] Array of results that successfully logged in
|
# @!attribute successes
|
||||||
attr_accessor :successes
|
# @return [Array] Array of results that successfully logged in
|
||||||
|
attr_accessor :successes
|
||||||
|
|
||||||
validates :connection_timeout,
|
validates :connection_timeout,
|
||||||
presence: true,
|
presence: true,
|
||||||
numericality: {
|
numericality: {
|
||||||
only_integer: true,
|
only_integer: true,
|
||||||
greater_than_or_equal_to: 1
|
greater_than_or_equal_to: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
validates :cred_details, presence: true
|
validates :cred_details, presence: true
|
||||||
|
|
||||||
validates :host, presence: true
|
validates :host, presence: true
|
||||||
|
|
||||||
validates :port,
|
validates :port,
|
||||||
presence: true,
|
presence: true,
|
||||||
numericality: {
|
numericality: {
|
||||||
only_integer: true,
|
only_integer: true,
|
||||||
greater_than_or_equal_to: 1,
|
greater_than_or_equal_to: 1,
|
||||||
less_than_or_equal_to: 65535
|
less_than_or_equal_to: 65535
|
||||||
}
|
}
|
||||||
|
|
||||||
validates :stop_on_success,
|
validates :stop_on_success,
|
||||||
inclusion: { in: [true, false] }
|
inclusion: { in: [true, false] }
|
||||||
|
|
||||||
validate :host_address_must_be_valid
|
validate :host_address_must_be_valid
|
||||||
|
|
||||||
validate :validate_cred_details
|
validate :validate_cred_details
|
||||||
|
|
||||||
# @param attributes [Hash{Symbol => String,nil}]
|
# @param attributes [Hash{Symbol => String,nil}]
|
||||||
def initialize(attributes={})
|
def initialize(attributes={})
|
||||||
attributes.each do |attribute, value|
|
attributes.each do |attribute, value|
|
||||||
public_send("#{attribute}=", value)
|
public_send("#{attribute}=", value)
|
||||||
|
end
|
||||||
|
self.successes= []
|
||||||
|
self.failures=[]
|
||||||
end
|
end
|
||||||
self.successes= []
|
|
||||||
self.failures=[]
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method runs all the login attempts against the target.
|
# This method runs all the login attempts against the target.
|
||||||
# It calls {attempt_login} once for each credential.
|
# It calls {attempt_login} once for each credential.
|
||||||
# Results are stored in {successes} and {failures}
|
# Results are stored in {successes} and {failures}
|
||||||
# @return [void] There is no valid return value for this method
|
# @return [void] There is no valid return value for this method
|
||||||
# @yield [result]
|
# @yield [result]
|
||||||
# @yieldparam result [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object for the attempt
|
# @yieldparam result [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object for the attempt
|
||||||
# @yieldreturn [void]
|
# @yieldreturn [void]
|
||||||
def scan!
|
def scan!
|
||||||
valid!
|
valid!
|
||||||
cred_details.each do |credential|
|
cred_details.each do |credential|
|
||||||
result = attempt_login(credential)
|
result = attempt_login(credential)
|
||||||
result.freeze
|
result.freeze
|
||||||
|
|
||||||
yield result if block_given?
|
yield result if block_given?
|
||||||
|
|
||||||
if result.success?
|
if result.success?
|
||||||
successes << result
|
successes << result
|
||||||
break if stop_on_success
|
break if stop_on_success
|
||||||
|
else
|
||||||
|
failures << result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# @raise [Metasploit::Framework::LoginScanner::Invalid] if the attributes are not valid on the scanner
|
||||||
|
def valid!
|
||||||
|
unless valid?
|
||||||
|
raise Metasploit::Framework::LoginScanner::Invalid.new(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# This method validates that the host address is both
|
||||||
|
# of a valid type and is resolveable.
|
||||||
|
# @return [void]
|
||||||
|
def host_address_must_be_valid
|
||||||
|
unless host.kind_of? String
|
||||||
|
errors.add(:host, "must be a string")
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
resolved_host = ::Rex::Socket.getaddress(host, true)
|
||||||
|
if host =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
||||||
|
unless host =~ Rex::Socket::MATCH_IPV4
|
||||||
|
errors.add(:host, "could not be resolved")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
host = resolved_host
|
||||||
|
rescue
|
||||||
|
errors.add(:host, "could not be resolved")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# This method validates that the credentials supplied
|
||||||
|
# are all valid.
|
||||||
|
# @return [void]
|
||||||
|
def validate_cred_details
|
||||||
|
if cred_details.kind_of? Array
|
||||||
|
cred_details.each do |detail|
|
||||||
|
unless detail.kind_of? Metasploit::Framework::LoginScanner::Credential
|
||||||
|
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
||||||
|
next
|
||||||
|
end
|
||||||
|
unless detail.valid?
|
||||||
|
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
failures << result
|
errors.add(:cred_details, "must be an array")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# @raise [Metasploit::Framework::LoginScanner::Invalid] if the attributes are not valid on the scanner
|
|
||||||
def valid!
|
|
||||||
unless valid?
|
|
||||||
raise Metasploit::Framework::LoginScanner::Invalid.new(self)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# This method validates that the host address is both
|
|
||||||
# of a valid type and is resolveable.
|
|
||||||
# @return [void]
|
|
||||||
def host_address_must_be_valid
|
|
||||||
unless host.kind_of? String
|
|
||||||
errors.add(:host, "must be a string")
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
resolved_host = ::Rex::Socket.getaddress(host, true)
|
|
||||||
if host =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
|
||||||
unless host =~ Rex::Socket::MATCH_IPV4
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
host = resolved_host
|
|
||||||
rescue
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method validates that the credentials supplied
|
|
||||||
# are all valid.
|
|
||||||
# @return [void]
|
|
||||||
def validate_cred_details
|
|
||||||
if cred_details.kind_of? Array
|
|
||||||
cred_details.each do |detail|
|
|
||||||
unless detail.kind_of? Metasploit::Framework::LoginScanner::Credential
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
next
|
|
||||||
end
|
|
||||||
unless detail.valid?
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
errors.add(:cred_details, "must be an array")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'metasploit/framework/ftp/client'
|
require 'metasploit/framework/ftp/client'
|
||||||
require 'metasploit/framework/login_scanner'
|
require 'metasploit/framework/login_scanner/base'
|
||||||
|
|
||||||
module Metasploit
|
module Metasploit
|
||||||
module Framework
|
module Framework
|
||||||
|
@ -9,33 +9,15 @@ module Metasploit
|
||||||
# It is responsible for taking a single target, and a list of credentials
|
# It is responsible for taking a single target, and a list of credentials
|
||||||
# and attempting them. It then saves the results.
|
# and attempting them. It then saves the results.
|
||||||
class FTP
|
class FTP
|
||||||
include ActiveModel::Validations
|
include Metasploit::Framework::LoginScanner::Base
|
||||||
include Metasploit::Framework::Ftp::Client
|
include Metasploit::Framework::Ftp::Client
|
||||||
|
|
||||||
# @!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 Credential objects
|
|
||||||
attr_accessor :cred_details
|
|
||||||
# @!attribute successes
|
|
||||||
# @return [Array] Array of of result objects that failed
|
|
||||||
attr_accessor :failures
|
|
||||||
# @!attribute ftp_timeout
|
# @!attribute ftp_timeout
|
||||||
# @return [Fixnum] The timeout in seconds to wait for a response to an FTP command
|
# @return [Fixnum] The timeout in seconds to wait for a response to an FTP command
|
||||||
attr_accessor :ftp_timeout
|
attr_accessor :ftp_timeout
|
||||||
# @!attribute host
|
|
||||||
# @return [String] The IP address or hostname to connect to
|
|
||||||
attr_accessor :host
|
|
||||||
# @!attribute max_send_size
|
# @!attribute max_send_size
|
||||||
# @return [Fixnum] The max size of the data to encapsulate in a single packet
|
# @return [Fixnum] The max size of the data to encapsulate in a single packet
|
||||||
attr_accessor :max_send_size
|
attr_accessor :max_send_size
|
||||||
# @!attribute port
|
|
||||||
# @return [Fixnum] The port to connect to
|
|
||||||
attr_accessor :port
|
|
||||||
# @!attribute proxies
|
|
||||||
# @return [String] The proxy directive to use for the socket
|
|
||||||
attr_accessor :proxies
|
|
||||||
# @!attribute send_delay
|
# @!attribute send_delay
|
||||||
# @return [Fixnum] The delay between sending packets
|
# @return [Fixnum] The delay between sending packets
|
||||||
attr_accessor :send_delay
|
attr_accessor :send_delay
|
||||||
|
@ -45,22 +27,6 @@ module Metasploit
|
||||||
# @!attribute ssl_version
|
# @!attribute ssl_version
|
||||||
# @return [String] The version of SSL to implement
|
# @return [String] The version of SSL to implement
|
||||||
attr_accessor :ssl_version
|
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 results that successfully logged in
|
|
||||||
attr_accessor :successes
|
|
||||||
|
|
||||||
|
|
||||||
validates :connection_timeout,
|
|
||||||
presence: true,
|
|
||||||
numericality: {
|
|
||||||
only_integer: true,
|
|
||||||
greater_than_or_equal_to: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
validates :cred_details, presence: true
|
|
||||||
|
|
||||||
validates :ftp_timeout,
|
validates :ftp_timeout,
|
||||||
presence: true,
|
presence: true,
|
||||||
|
@ -69,8 +35,6 @@ module Metasploit
|
||||||
greater_than_or_equal_to: 1
|
greater_than_or_equal_to: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
validates :host, presence: true
|
|
||||||
|
|
||||||
validates :max_send_size,
|
validates :max_send_size,
|
||||||
presence: true,
|
presence: true,
|
||||||
numericality: {
|
numericality: {
|
||||||
|
@ -78,14 +42,6 @@ module Metasploit
|
||||||
greater_than_or_equal_to: 0
|
greater_than_or_equal_to: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
validates :port,
|
|
||||||
presence: true,
|
|
||||||
numericality: {
|
|
||||||
only_integer: true,
|
|
||||||
greater_than_or_equal_to: 1,
|
|
||||||
less_than_or_equal_to: 65535
|
|
||||||
}
|
|
||||||
|
|
||||||
validates :send_delay,
|
validates :send_delay,
|
||||||
presence: true,
|
presence: true,
|
||||||
numericality: {
|
numericality: {
|
||||||
|
@ -93,13 +49,6 @@ module Metasploit
|
||||||
greater_than_or_equal_to: 0
|
greater_than_or_equal_to: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
validates :stop_on_success,
|
|
||||||
inclusion: { in: [true, false] }
|
|
||||||
|
|
||||||
|
|
||||||
validate :host_address_must_be_valid
|
|
||||||
|
|
||||||
validate :validate_cred_details
|
|
||||||
|
|
||||||
# @param attributes [Hash{Symbol => String,nil}]
|
# @param attributes [Hash{Symbol => String,nil}]
|
||||||
def initialize(attributes={})
|
def initialize(attributes={})
|
||||||
|
@ -140,60 +89,8 @@ module Metasploit
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method runs all the login attempts against the target.
|
|
||||||
# It calls {attempt_login} once for each credential.
|
|
||||||
# Results are stored in {successes} and {failures}
|
|
||||||
# @return [void] There is no valid return value for this method
|
|
||||||
# @yield [result]
|
|
||||||
# @yieldparam result [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object for the attempt
|
|
||||||
# @yieldreturn [void]
|
|
||||||
def scan!
|
|
||||||
valid!
|
|
||||||
cred_details.each do |credential|
|
|
||||||
result = attempt_login(credential)
|
|
||||||
result.freeze
|
|
||||||
|
|
||||||
yield result if block_given?
|
|
||||||
|
|
||||||
if result.success?
|
|
||||||
successes << result
|
|
||||||
break if stop_on_success
|
|
||||||
else
|
|
||||||
failures << result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @raise [Metasploit::Framework::LoginScanner::Invalid] if the attributes are not valid on the scanner
|
|
||||||
def valid!
|
|
||||||
unless valid?
|
|
||||||
raise Metasploit::Framework::LoginScanner::Invalid.new(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
# This method validates that the host address is both
|
|
||||||
# of a valid type and is resolveable.
|
|
||||||
# @return [void]
|
|
||||||
def host_address_must_be_valid
|
|
||||||
unless host.kind_of? String
|
|
||||||
errors.add(:host, "must be a string")
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
resolved_host = ::Rex::Socket.getaddress(host, true)
|
|
||||||
if host =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
|
||||||
unless host =~ Rex::Socket::MATCH_IPV4
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
host = resolved_host
|
|
||||||
rescue
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def chost
|
def chost
|
||||||
'0.0.0.0'
|
'0.0.0.0'
|
||||||
end
|
end
|
||||||
|
@ -210,27 +107,6 @@ module Metasploit
|
||||||
port
|
port
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method validates that the credentials supplied
|
|
||||||
# are all valid.
|
|
||||||
# @return [void]
|
|
||||||
def validate_cred_details
|
|
||||||
if cred_details.kind_of? Array
|
|
||||||
cred_details.each do |detail|
|
|
||||||
unless detail.kind_of? Metasploit::Framework::LoginScanner::Credential
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
next
|
|
||||||
end
|
|
||||||
unless detail.valid?
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
errors.add(:cred_details, "must be an array")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'snmp'
|
require 'snmp'
|
||||||
require 'metasploit/framework/login_scanner'
|
require 'metasploit/framework/login_scanner/base'
|
||||||
|
|
||||||
module Metasploit
|
module Metasploit
|
||||||
module Framework
|
module Framework
|
||||||
|
@ -9,69 +9,7 @@ module Metasploit
|
||||||
# It is responsible for taking a single target, and a list of credentials
|
# It is responsible for taking a single target, and a list of credentials
|
||||||
# and attempting them. It then saves the results.
|
# and attempting them. It then saves the results.
|
||||||
class SNMP
|
class SNMP
|
||||||
include ActiveModel::Validations
|
include Metasploit::Framework::LoginScanner::Base
|
||||||
|
|
||||||
# @!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 Credential objects
|
|
||||||
attr_accessor :cred_details
|
|
||||||
# @!attribute successes
|
|
||||||
# @return [Array] Array of 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 proxies
|
|
||||||
# @return [String] The proxy directive to use for the socket
|
|
||||||
attr_accessor :proxies
|
|
||||||
# @!attribute ssh_socket
|
|
||||||
# @return [Net::SSH::Connection::Session] The current SSH connection
|
|
||||||
|
|
||||||
attr_accessor :stop_on_success
|
|
||||||
# @!attribute successes
|
|
||||||
# @return [Array] Array of results that successfully logged in
|
|
||||||
attr_accessor :successes
|
|
||||||
|
|
||||||
|
|
||||||
validates :connection_timeout,
|
|
||||||
presence: true,
|
|
||||||
numericality: {
|
|
||||||
only_integer: true,
|
|
||||||
greater_than_or_equal_to: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
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: 65535
|
|
||||||
}
|
|
||||||
|
|
||||||
validates :stop_on_success,
|
|
||||||
inclusion: { in: [true, false] }
|
|
||||||
|
|
||||||
validate :host_address_must_be_valid
|
|
||||||
|
|
||||||
validate :validate_cred_details
|
|
||||||
|
|
||||||
# @param attributes [Hash{Symbol => String,nil}]
|
|
||||||
def initialize(attributes={})
|
|
||||||
attributes.each do |attribute, value|
|
|
||||||
public_send("#{attribute}=", value)
|
|
||||||
end
|
|
||||||
self.successes= []
|
|
||||||
self.failures=[]
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method attempts a single login with a single credential against the target
|
# This method attempts a single login with a single credential against the target
|
||||||
# @param credential [Credential] The credential object to attmpt to login with
|
# @param credential [Credential] The credential object to attmpt to login with
|
||||||
|
@ -113,59 +51,8 @@ module Metasploit
|
||||||
::Metasploit::Framework::LoginScanner::Result.new(result_options)
|
::Metasploit::Framework::LoginScanner::Result.new(result_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method runs all the login attempts against the target.
|
|
||||||
# It calls {attempt_login} once for each credential.
|
|
||||||
# Results are stored in {successes} and {failures}
|
|
||||||
# @return [void] There is no valid return value for this method
|
|
||||||
# @yield [result]
|
|
||||||
# @yieldparam result [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object for the attempt
|
|
||||||
# @yieldreturn [void]
|
|
||||||
def scan!
|
|
||||||
valid!
|
|
||||||
cred_details.each do |credential|
|
|
||||||
result = attempt_login(credential)
|
|
||||||
result.freeze
|
|
||||||
|
|
||||||
yield result if block_given?
|
|
||||||
|
|
||||||
if result.success?
|
|
||||||
successes << result
|
|
||||||
break if stop_on_success
|
|
||||||
else
|
|
||||||
failures << result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @raise [Metasploit::Framework::LoginScanner::Invalid] if the attributes are not valid on the scanner
|
|
||||||
def valid!
|
|
||||||
unless valid?
|
|
||||||
raise Metasploit::Framework::LoginScanner::Invalid.new(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# This method validates that the host address is both
|
|
||||||
# of a valid type and is resolveable.
|
|
||||||
# @return [void]
|
|
||||||
def host_address_must_be_valid
|
|
||||||
unless host.kind_of? String
|
|
||||||
errors.add(:host, "must be a string")
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
resolved_host = ::Rex::Socket.getaddress(host, true)
|
|
||||||
if host =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
|
||||||
unless host =~ Rex::Socket::MATCH_IPV4
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
host = resolved_host
|
|
||||||
rescue
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method takes an snmp client and tests whether
|
# This method takes an snmp client and tests whether
|
||||||
# it has read access to the remote system. It checks
|
# it has read access to the remote system. It checks
|
||||||
# the sysDescr oid to use as proof
|
# the sysDescr oid to use as proof
|
||||||
|
@ -201,28 +88,6 @@ module Metasploit
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# This method validates that the credentials supplied
|
|
||||||
# are all valid.
|
|
||||||
# @return [void]
|
|
||||||
def validate_cred_details
|
|
||||||
if cred_details.kind_of? Array
|
|
||||||
cred_details.each do |detail|
|
|
||||||
unless detail.kind_of? Metasploit::Framework::LoginScanner::Credential
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
next
|
|
||||||
end
|
|
||||||
unless detail.valid?
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
errors.add(:cred_details, "must be an array")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'net/ssh'
|
require 'net/ssh'
|
||||||
require 'metasploit/framework/login_scanner'
|
require 'metasploit/framework/login_scanner/base'
|
||||||
|
|
||||||
module Metasploit
|
module Metasploit
|
||||||
module Framework
|
module Framework
|
||||||
|
@ -9,7 +9,7 @@ module Metasploit
|
||||||
# It is responsible for taking a single target, and a list of credentials
|
# It is responsible for taking a single target, and a list of credentials
|
||||||
# and attempting them. It then saves the results.
|
# and attempting them. It then saves the results.
|
||||||
class SSH
|
class SSH
|
||||||
include ActiveModel::Validations
|
include Metasploit::Framework::LoginScanner::Base
|
||||||
|
|
||||||
#
|
#
|
||||||
# CONSTANTS
|
# CONSTANTS
|
||||||
|
@ -23,78 +23,16 @@ module Metasploit
|
||||||
:fatal
|
:fatal
|
||||||
]
|
]
|
||||||
|
|
||||||
# @!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 Credential objects
|
|
||||||
attr_accessor :cred_details
|
|
||||||
# @!attribute successes
|
|
||||||
# @return [Array] Array of 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 proxies
|
|
||||||
# @return [String] The proxy directive to use for the socket
|
|
||||||
attr_accessor :proxies
|
|
||||||
# @!attribute ssh_socket
|
|
||||||
# @return [Net::SSH::Connection::Session] The current SSH connection
|
|
||||||
attr_accessor :ssh_socket
|
|
||||||
# @!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 results that successfully logged in
|
|
||||||
attr_accessor :successes
|
|
||||||
# @!attribute verbosity
|
# @!attribute verbosity
|
||||||
# The verbosity level for the SSH client.
|
# The verbosity level for the SSH client.
|
||||||
#
|
#
|
||||||
# @return [Symbol] An element of {VERBOSITIES}.
|
# @return [Symbol] An element of {VERBOSITIES}.
|
||||||
attr_accessor :verbosity
|
attr_accessor :verbosity
|
||||||
|
|
||||||
validates :connection_timeout,
|
|
||||||
presence: true,
|
|
||||||
numericality: {
|
|
||||||
only_integer: true,
|
|
||||||
greater_than_or_equal_to: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
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: 65535
|
|
||||||
}
|
|
||||||
|
|
||||||
validates :stop_on_success,
|
|
||||||
inclusion: { in: [true, false] }
|
|
||||||
|
|
||||||
validates :verbosity,
|
validates :verbosity,
|
||||||
presence: true,
|
presence: true,
|
||||||
inclusion: { in: VERBOSITIES }
|
inclusion: { in: VERBOSITIES }
|
||||||
|
|
||||||
validate :host_address_must_be_valid
|
|
||||||
|
|
||||||
validate :validate_cred_details
|
|
||||||
|
|
||||||
# @param attributes [Hash{Symbol => String,nil}]
|
|
||||||
def initialize(attributes={})
|
|
||||||
attributes.each do |attribute, value|
|
|
||||||
public_send("#{attribute}=", value)
|
|
||||||
end
|
|
||||||
self.successes= []
|
|
||||||
self.failures=[]
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method attempts a single login with a single credential against the target
|
# This method attempts a single login with a single credential against the target
|
||||||
# @param credential [Credential] The credential object to attmpt to login with
|
# @param credential [Credential] The credential object to attmpt to login with
|
||||||
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
||||||
|
@ -142,37 +80,6 @@ module Metasploit
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method runs all the login attempts against the target.
|
|
||||||
# It calls {attempt_login} once for each credential.
|
|
||||||
# Results are stored in {successes} and {failures}
|
|
||||||
# @return [void] There is no valid return value for this method
|
|
||||||
# @yield [result]
|
|
||||||
# @yieldparam result [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object for the attempt
|
|
||||||
# @yieldreturn [void]
|
|
||||||
def scan!
|
|
||||||
valid!
|
|
||||||
cred_details.each do |credential|
|
|
||||||
result = attempt_login(credential)
|
|
||||||
result.freeze
|
|
||||||
|
|
||||||
yield result if block_given?
|
|
||||||
|
|
||||||
if result.success?
|
|
||||||
successes << result
|
|
||||||
break if stop_on_success
|
|
||||||
else
|
|
||||||
failures << result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @raise [Metasploit::Framework::LoginScanner::Invalid] if the attributes are not valid on the scanner
|
|
||||||
def valid!
|
|
||||||
unless valid?
|
|
||||||
raise Metasploit::Framework::LoginScanner::Invalid.new(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# This method attempts to gather proof that we successfuly logged in.
|
# This method attempts to gather proof that we successfuly logged in.
|
||||||
|
@ -198,47 +105,6 @@ module Metasploit
|
||||||
proof
|
proof
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method validates that the host address is both
|
|
||||||
# of a valid type and is resolveable.
|
|
||||||
# @return [void]
|
|
||||||
def host_address_must_be_valid
|
|
||||||
unless host.kind_of? String
|
|
||||||
errors.add(:host, "must be a string")
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
resolved_host = ::Rex::Socket.getaddress(host, true)
|
|
||||||
if host =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
|
||||||
unless host =~ Rex::Socket::MATCH_IPV4
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
host = resolved_host
|
|
||||||
rescue
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method validates that the credentials supplied
|
|
||||||
# are all valid.
|
|
||||||
# @return [void]
|
|
||||||
def validate_cred_details
|
|
||||||
if cred_details.kind_of? Array
|
|
||||||
cred_details.each do |detail|
|
|
||||||
unless detail.kind_of? Metasploit::Framework::LoginScanner::Credential
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
next
|
|
||||||
end
|
|
||||||
unless detail.valid?
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
errors.add(:cred_details, "must be an array")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'net/ssh'
|
require 'net/ssh'
|
||||||
require 'metasploit/framework/login_scanner'
|
require 'metasploit/framework/login_scanner/base'
|
||||||
|
|
||||||
module Metasploit
|
module Metasploit
|
||||||
module Framework
|
module Framework
|
||||||
|
@ -10,7 +10,7 @@ module Metasploit
|
||||||
# and attempting them. It then saves the results. In this case it is expecting
|
# and attempting them. It then saves the results. In this case it is expecting
|
||||||
# SSH private keys for the private credential.
|
# SSH private keys for the private credential.
|
||||||
class SSHKey
|
class SSHKey
|
||||||
include ActiveModel::Validations
|
include Metasploit::Framework::LoginScanner::Base
|
||||||
|
|
||||||
#
|
#
|
||||||
# CONSTANTS
|
# CONSTANTS
|
||||||
|
@ -24,77 +24,16 @@ module Metasploit
|
||||||
:fatal
|
:fatal
|
||||||
]
|
]
|
||||||
|
|
||||||
# @!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 Credential objects
|
|
||||||
attr_accessor :cred_details
|
|
||||||
# @!attribute successes
|
|
||||||
# @return [Array] Array of 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 proxies
|
|
||||||
# @return [String] The proxy directive to use for the socket
|
|
||||||
attr_accessor :proxies
|
|
||||||
# @!attribute ssh_socket
|
|
||||||
# @return [Net::SSH::Connection::Session] The current SSH connection
|
|
||||||
attr_accessor :ssh_socket
|
|
||||||
# @!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 results that successfully logged in
|
|
||||||
attr_accessor :successes
|
|
||||||
# @!attribute verbosity
|
# @!attribute verbosity
|
||||||
# The verbosity level for the SSH client.
|
# The verbosity level for the SSH client.
|
||||||
#
|
#
|
||||||
# @return [Symbol] An element of {VERBOSITIES}.
|
# @return [Symbol] An element of {VERBOSITIES}.
|
||||||
attr_accessor :verbosity
|
attr_accessor :verbosity
|
||||||
|
|
||||||
validates :connection_timeout,
|
|
||||||
presence: true,
|
|
||||||
numericality: {
|
|
||||||
only_integer: true,
|
|
||||||
greater_than_or_equal_to: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
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: 65535
|
|
||||||
}
|
|
||||||
|
|
||||||
validates :stop_on_success,
|
|
||||||
inclusion: { in: [true, false] }
|
|
||||||
|
|
||||||
validates :verbosity,
|
validates :verbosity,
|
||||||
presence: true,
|
presence: true,
|
||||||
inclusion: { in: VERBOSITIES }
|
inclusion: { in: VERBOSITIES }
|
||||||
|
|
||||||
validate :host_address_must_be_valid
|
|
||||||
|
|
||||||
validate :validate_cred_details
|
|
||||||
|
|
||||||
# @param attributes [Hash{Symbol => String,nil}]
|
|
||||||
def initialize(attributes={})
|
|
||||||
attributes.each do |attribute, value|
|
|
||||||
public_send("#{attribute}=", value)
|
|
||||||
end
|
|
||||||
self.successes= []
|
|
||||||
self.failures=[]
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method attempts a single login with a single credential against the target
|
# This method attempts a single login with a single credential against the target
|
||||||
# @param credential [Credential] The credential object to attmpt to login with
|
# @param credential [Credential] The credential object to attmpt to login with
|
||||||
|
@ -143,37 +82,6 @@ module Metasploit
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method runs all the login attempts against the target.
|
|
||||||
# It calls {attempt_login} once for each credential.
|
|
||||||
# Results are stored in {successes} and {failures}
|
|
||||||
# @return [void] There is no valid return value for this method
|
|
||||||
# @yield [result]
|
|
||||||
# @yieldparam result [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object for the attempt
|
|
||||||
# @yieldreturn [void]
|
|
||||||
def scan!
|
|
||||||
valid!
|
|
||||||
cred_details.each do |credential|
|
|
||||||
result = attempt_login(credential)
|
|
||||||
result.freeze
|
|
||||||
|
|
||||||
yield result if block_given?
|
|
||||||
|
|
||||||
if result.success?
|
|
||||||
successes << result
|
|
||||||
break if stop_on_success
|
|
||||||
else
|
|
||||||
failures << result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @raise [Metasploit::Framework::LoginScanner::Invalid] if the attributes are not valid on the scanner
|
|
||||||
def valid!
|
|
||||||
unless valid?
|
|
||||||
raise Metasploit::Framework::LoginScanner::Invalid.new(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# This method attempts to gather proof that we successfuly logged in.
|
# This method attempts to gather proof that we successfuly logged in.
|
||||||
|
@ -199,47 +107,6 @@ module Metasploit
|
||||||
proof
|
proof
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method validates that the host address is both
|
|
||||||
# of a valid type and is resolveable.
|
|
||||||
# @return [void]
|
|
||||||
def host_address_must_be_valid
|
|
||||||
unless host.kind_of? String
|
|
||||||
errors.add(:host, "must be a string")
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
resolved_host = ::Rex::Socket.getaddress(host, true)
|
|
||||||
if host =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
|
||||||
unless host =~ Rex::Socket::MATCH_IPV4
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
host = resolved_host
|
|
||||||
rescue
|
|
||||||
errors.add(:host, "could not be resolved")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method validates that the credentials supplied
|
|
||||||
# are all valid.
|
|
||||||
# @return [void]
|
|
||||||
def validate_cred_details
|
|
||||||
if cred_details.kind_of? Array
|
|
||||||
cred_details.each do |detail|
|
|
||||||
unless detail.kind_of? Metasploit::Framework::LoginScanner::Credential
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
next
|
|
||||||
end
|
|
||||||
unless detail.valid?
|
|
||||||
errors.add(:cred_details, "has invalid element #{detail.inspect}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
errors.add(:cred_details, "must be an array")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue