# SNMP Enumeraion (Port 161)

## Quick Intro <a href="#quick-intro" id="quick-intro"></a>

* The Simple Network Management Protocol (SNMP) is a protocol **used in TCP/IP networks to collect and manage information about networked devices.** SNMP operates in the application layer (layer 7 of the OSI model) and uses **UDP port 161** to listen for requests. The SNMP protocol is supported by many types of devices including routers, switches, servers, printers, Network Attached Storage (NAS), firewalls, WLAN controllers and more. In the following sections we will be looking at the main components of SNMP managed networks, how they communicate with each other and something called the Management Information Base (MIB). We will also look at how and why SNMP can cause security issues and, of course, how to enumerate the SNMP protocol.

**SNMP components**&#x20;

SNMP managed networks have 3 components:

1. Managed Device\
   A managed device (also referred to as a ‘node’) is a network device with the SNMP service enabled allowing unidirectional (read) or bidirectional (read/write) communication. Managed devices can be any networked device including servers, firewalls and routers.
2. Agent\
   The agent is the software running on the managed device which is responsible for handling the communication. The agent translates device-specific configuration parameters into an SNMP format for the Network Management System.
3. Network Management System (NMS)\
   The Network Management System is the software that is actually managing and monitoring networked devices. An SNMP managed network will always contain at least one NMS.

**SNMP commands**&#x20;

The SNMP protocol uses several commands which are sent from the NMS to the managed device’s agent and back. These commands can be categorized as read, write, trap and traversal commands.

* Read commands are sent by the NMS to nodes for monitoring purposes.
* Write commands are used to control the nodes in the network.
* The trap commands are used for unsolicited SNMP messages from a device’s agent to the NMS to inform the NMS about certain events such as errors.
* Traversal commands are used to check what information is retained on a managed device and to retrieve it.

**SNMP Management Information Base (MIB)**&#x20;

* The SNMP Management Information Base (MIB) is a database that contains information about the network device. When the Network Management System (NMS) sends a ‘get’ request for information about a managed device on the network, the agent service returns a structured table with data. This table is what is called the Management Information Base (MIB). MIB values are indexed using a series of numbers with dots. For example, MIB value 1.3.6.1.2.1.1.1 refers to the system description (sysDescr) and value 1.3.6.1.2.1.1.6 refers to the system location (sysLocation).

**SNMP Community strings**&#x20;

* The SNMP community string is like a username or password that allows access to the managed device. There are three different community strings that allow a user to set (1) read-only commands, (2) read and write commands and (3) traps. Most SNMPv1 and SNMPv2 devices ship from the factory with a default read-only community string set to **‘public’** and the read-write string set to ‘private’. As these default values are well-known and easy to guess, it is good security practice to replace all community strings with a value that is hard to guess. It is good practice to threat community strings as passwords. In SNMPv3, the community string was replaced by username and password authentication.

## SNMP MIB Trees <a href="#snmp-mib-trees" id="snmp-mib-trees"></a>

* 1.3.6.1.2.1.25.1.6.0 - System Processes
* 1.3.6.1.2.1.25.4.2.1.2 - Running Programs
* 1.3.6.1.2.1.25.4.2.1.4 - Processes Path
* 1.3.6.1.2.1.25.2.3.1.4 - Storage Units
* 1.3.6.1.2.1.25.6.3.1.2 - Software Name
* 1.3.6.1.4.1.77.1.2.25 - User Accounts
* 1.3.6.1.2.1.6.13.1.3 - TCP Local Ports

## SNMPwalk <a href="#snmpwalk" id="snmpwalk"></a>

SNMPwalk is a great tool to query MIB values to retrieve information about managed devices, but, as a minimum, **it requires a valid SNMP read-only community string.**

```
for community in public private manager; do snmpwalk -c $community -v1 $ip; done
# here it will take three comunity strings and check one by one

snmpwalk -c public -v1 $ip

snmpwalk -c public -v2c <target-ip>
# here -c stands for community string and 2c is most common version found on today's snmp devices
```

## SNMPcheck <a href="#snmpcheck" id="snmpcheck"></a>

Same as `snmpwalk` but give nice output

```
snmpcheck -t 192.168.1.X -c public
```

## Brute forcing community string <a href="#brute-forcing-community-string" id="brute-forcing-community-string"></a>

### OneSixtyOne

* Onesixtyone is a very fast tool to brute force SNMP community strings and take advantage of the connectionless protocol. Onesixtyone sends an SNMP request and (by default) waits 10 milliseconds for a response. If the community string sent by onesixtyone to the SNMP enabled device is invalid, then the request is dropped. However, if a valid community string is passed to an SNMP enabled device, the device responds with the information requested (the ‘system.sysDescr.0’ value).

```
onesixtyone -c dict.txt <ip>
```

## Wordlists

```
/usr/share/seclists/Discovery/SNMP/common-snmp-community-strings-onesixtyone.txt

/usr/share/metasploit-framework/data/wordlists/snmp_default_pass.txt
```

## NSE Script <a href="#nse-script" id="nse-script"></a>

```
ls -l /usr/share/nmap/scripts/snmp*
```

## SNMPv3 Enumeration <a href="#snmpv3-enumeration" id="snmpv3-enumeration"></a>

{% hint style="info" %}
<https://raw.githubusercontent.com/raesene/TestingScripts/master/snmpv3enum.rb>
{% endhint %}

```
snmpv3enum.rb && ./snmpv3enum.rb
```

* snmpv3enum.rb

```
#!/usr/bin/env ruby
  # == Synopsis  
  #   
  # This class just wraps snmpwalk and iterates over a series of IP addresses and usernames
  # Designed to brute-force a snmpv3 username
  # for it to work on ubuntu you need to have the snmp programs and MIBs installed
  # sudo apt-get install snmp snmp-mibs-downloader
  # sudo download-mibs
  # == Author
  #   Rory McCune
  #
  # == Options
  #   -h, --help          	Displays help message
  #   -v, --version       	Display the version, then exit
  #   -s, --snmpwalk		The location of snmpwalk if not specified assumed to be on the path 
  #   -i, --ipaddress		IP address to scan
  #   -u, --usernames		File name with usernames to try in it, specified one per line
  #   -f, --ipaddressfile		File name with ip addresses to try in it, specified one per line
  #   -r, --report		Report file name
  #
  # == Usage 
  #  snmpv3enum.rb -i <ip_address> -u <username_file>
  #  




class Snmpv3Enum
  VERSION = '0.1'

def initialize(arguments)

  require 'optparse'
  require 'ostruct'
  require 'logger'
  
  
  if arguments.length > 0
    arguments_flag = :true
  end

  @snmp_log = Logger.new('snmpv3enum.log')
  @snmp_log.level = Logger::DEBUG

  @options = OpenStruct.new

  @options.snmpwalk = %x[which snmpwalk].chomp
  @options.ip_address = Array.new
  @options.usernames = 'usernames'
  @options.report = 'snmp-report'

  opts = OptionParser.new do |opts|
    opts.banner = 'SNMPV3 Username enumerator'

    opts.on("-i", "--ipaddress [IPADDRESS]", "IP address to scan") do |address|
      @options.ip_address << address
    end

    opts.on("-u", "--usernames USERNAMES", "File with usernames to scan") do |name|
      @options.usernames = name
    end

    opts.on("-s", "--snmpwalk [SNMPWALK]", "Location of the snmpwalk binary") do |snmp|
      @options.snmpwalk = snmp
    end

    opts.on("-f", "--ip_address_file [IPADDRESSFILE]","File with IP addresses to scan") do |ipfile|
      ip_file = File.open(ipfile,'r').readlines
      ip_file.each do |ip|
        ip.chomp!
        @options.ip_address << ip
      end 
    end

    opts.on("-r", "--report [REPORT]","Report File") do |report|
      @options.report = report
    end
  
    opts.on("-h", "--help", "-?", "--?", "Get Help") do |help|
      puts opts
      exit
    end
      
    opts.on("-v", "--version", "get Version") do |ver|
      puts "SNMPV3 User name enumerator Version #{VERSION}"
      exit
    end
  end

  opts.parse!(arguments)

  unless arguments_flag
    puts "didn't get any arguments"
    puts opts
    exit
  end


  if @options.snmpwalk == ''
    @snmp_log.fatal("Couldn't find snmpwalk")
    abort "Couldn't find snmpwalk on Ubuntu try sudo apt-get install snmp"
  end

  unless @usernames = File.open(@options.usernames,'r').readlines
    @snmp_log.fatal("Couldn't open the usernames file")
    abort "Couldn't open the usernames file"
  end

  @usernames.each {|name| name.chomp!}

  @report = File.new(@options.report, "a+")

  @ip_addresses = @options.ip_address

  @snmpwalk = @options.snmpwalk
  @snmp_log.debug("snmpwalk set to" + @snmpwalk)

end

def scan
  @report.puts "SNMP SCAN V3 run at #{Time.now.to_s}"
  @report.puts "-------------------------------------"

  #Iterate over each ip address to be tested
  @ip_addresses.each do |ip|
    @snmp_log.debug("run for IP address of #{ip} started")
    @report.puts ''
    @report.puts "Results for : #{ip}"

    #This is an initial check to see if the host responds at all
    up_responses = %x[#{@snmpwalk} -v 3 -l noAuthNoPriv #{ip} RFC1213-MIB::sysUpTime.0 2>&1]
    if up_responses =~ /Timeout/
      @report.puts "No snmp server found on host"
      @snmp_log.warn("No SNMP server found on host : #{ip}")
      next
    end
    #Now for this host iterate over each of the names to try
    @usernames.each do |name|
      @snmp_log.debug("Run for name of #{name} with IP of #{ip} started")
      result = ''
      #This is the main request to snmpwalk
      response = %x[#{@snmpwalk} -v 3 -l noAuthNoPriv -u #{name} #{ip} RFC1213-MIB::sysUpTime.0 2>&1]
      if response =~ /Unknown user name/
        result = 'Unknown User'
      elsif response =~ /authorizationError/
        result = 'Known User'
        puts "valid username : #{name} on host : #{ip}"
      else
        result = 'unknown response.  See debug log for details'
      end
      @report.puts "Username : #{name} had response of #{result}"
      @snmp_log.debug("#{ip.to_s},#{name}, #{response}")
    end
  end
end



end

if __FILE__ == $0
  analysis = Snmpv3Enum.new(ARGV)
  analysis.scan
end
```
