diff --git a/lib/metasploit/framework/login_scanner/snmp.rb b/lib/metasploit/framework/login_scanner/snmp.rb index a6ba854202..b13d1bb7ad 100644 --- a/lib/metasploit/framework/login_scanner/snmp.rb +++ b/lib/metasploit/framework/login_scanner/snmp.rb @@ -17,6 +17,40 @@ module Metasploit PRIVATE_TYPES = [ :password ] REALM_KEY = nil + # The number of retries per community string + # @return [Fixnum] + attr_accessor :retries + + # The SNMP version to scan + # @return [String] + attr_accessor :version + + validates :retries, + presence: true, + numericality: { + only_integer: true, + greater_than_or_equal_to: 0 + } + + validates :version, + presence: true, + inclusion: { + in: ['1', '2c', 'all'] + } + + # This method returns an array of versions to scan for + # @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 +63,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..0db2136f3b 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', 2]), + 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| diff --git a/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb b/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb index 0dc0c8851c..30ae6fa46c 100644 --- a/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb @@ -37,6 +37,8 @@ describe Metasploit::Framework::LoginScanner::SNMP do snmp_scanner.host = '127.0.0.1' snmp_scanner.port = 161 snmp_scanner.connection_timeout = 1 + snmp_scanner.retries = 0 + snmp_scanner.version = 'all' snmp_scanner.stop_on_success = true snmp_scanner.cred_details = detail_group end