diff --git a/lib/metasploit/framework/login_scanner/snmp.rb b/lib/metasploit/framework/login_scanner/snmp.rb index a6ba854202..ee3ac8e93f 100644 --- a/lib/metasploit/framework/login_scanner/snmp.rb +++ b/lib/metasploit/framework/login_scanner/snmp.rb @@ -17,6 +17,35 @@ module Metasploit PRIVATE_TYPES = [ :password ] REALM_KEY = nil + # @!attribute retries + # @return [Fixnum] The number of retries + attr_accessor :retries + + validates :retries, + presence: true, + numericality: { + only_integer: true, + greater_than_or_equal_to: 0 + } + + # @!attribute version + # @return [String] The SNMP version to scan + attr_accessor :version + + validates :version, + presence: true, + inclusion: { in: ['1', '2c', 'all'] } + + # This method returns an array of versions to scan + # @return [Array] An array of versions + def versions + case version + when '1'; [:SNMPv1] + when '2c'; [:SNMPv2c] + when 'all'; [:SNMPv1,:SNMPv2c] + end + end + # This method attempts a single login with a single credential against the target # @param credential [Credential] The credential object to attmpt to login with # @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object @@ -29,14 +58,14 @@ module Metasploit service_name: 'snmp' } - [:SNMPv1, :SNMPv2c].each do |version| + versions.each do |version| snmp_client = ::SNMP::Manager.new( :Host => host, :Port => port, :Community => credential.public, :Version => version, :Timeout => connection_timeout, - :Retries => 2, + :Retries => retries, :Transport => ::SNMP::RexUDPTransport, :Socket => ::Rex::Socket::Udp.create('Context' => { 'Msf' => framework, 'MsfExploit' => framework_module }) ) diff --git a/modules/auxiliary/scanner/snmp/snmp_login.rb b/modules/auxiliary/scanner/snmp/snmp_login.rb index 223d5e7a75..17a4af375e 100644 --- a/modules/auxiliary/scanner/snmp/snmp_login.rb +++ b/modules/auxiliary/scanner/snmp/snmp_login.rb @@ -30,7 +30,10 @@ class Metasploit3 < Msf::Auxiliary [ Opt::RPORT(161), Opt::CHOST, + OptInt.new('CONNECTION_TIMEOUT', [true, 'The timeout value for each probe', 1]), + OptInt.new('RETRIES', [true, 'The number of retries per community string', 0]), OptInt.new('BATCHSIZE', [true, 'The number of hosts to probe in each set', 256]), + OptEnum.new('VERSION', [true, 'The SNMP version to scan', 'all', ['1','2c','all']]), OptString.new('PASSWORD', [ false, 'The password to test' ]), OptPath.new('PASS_FILE', [ false, "File containing communities, one per line", File.join(Msf::Config.data_directory, "wordlists", "snmp_default_pass.txt") @@ -61,9 +64,11 @@ class Metasploit3 < Msf::Auxiliary cred_details: collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 2, + connection_timeout: datastore['CONNECTION_TIMEOUT'], + retries: datastore['RETRIES'], + version: datastore['VERSION'], framework: framework, - framework_module: self, + framework_module: self ) scanner.scan! do |result|