Nmap Development mailing list archives

Another SCADA/ICS NMAP NSE script - Rockwell MicroLogix Series 1400 enumeration script


From: Bob Radvanovsky <rsradvan () unixworks net>
Date: Mon, 06 Dec 2010 21:28:38 -0600

This is one of several enumeration scripts that I have written for the SCADA/industrial control systems community.  
This checks/validates the SNMP traffic for the Allen-Bradley/Rockwell MicroLogix Series 1400 PLC controller. 

The same script is shown below; if you wish to download the script, the script may be accessed here: 
http://www.infracritical.com/enum-scripts/micrologix1400.nse

===============================================

description = "Confirms/verifies that target device is Rockwell MicroLogix."
author      = "Bob Radvanovsky <rsradvan at infracritical dot com>"
license     = "Refer to: http://nmap.org/book/man-legal.html for license."
categories  = {"default", "discovery", "safe"}
dependencies= {"snmp-brute"}

--
--  Filename:      micrologix1400.nse
--
--  Purpose:       Checks for the following elements confirming said device:
--
--  1.  PHASE I - SNMP verification.
--      a.  STEP 1:  Performs verification through 'snmpwalk'.
--      b.  STEP 2:  Acquires specific details from SNMP 'sysDescr.0'.
--
--  2.  PHASE II - Documentation.
--
--  ==========================================================================
--
--  Version(s):    4.0, 5.0
--
--  Usage:         nmap --script=./micrologix1400.nse <IP>
--                 (continued) --script-args='dox=1' -PN -sU -p161 -v
--
--  Author(s):     Bob Radvanovsky - Infracritical
--                 <rsradvan at infracritical dot com>
--
--  Initwritten:   September 2010
--
--  DATE----  INIT DESCRIPTION------------------------------------------------
--  10.05.09  rsr  Inital development - VERSION 001.
--  10.05.09  rsr  Included URL links for related reference documentation.
--
--  NOTE: Script is a derived work from Thomas Buchanan's "snmp-sysdescr.nse"
--        NSE script, and has been modified to work specifically on/for the
--        Allen-Bradley/Rockwell Automation MicroLogix Series 1400 devices.
--
--  NOTE: We try and verify, running tests on as many versions of this device
--        as possible.  If you encounter an "UNKNOWN", this may mean that you
--        have scanned a device version/variant that was not tested.
--
--        Since we are providing this script free-of-charge to everyone,
--        would help us - and the community - if you would report the variance
--        to us.  Submit your findings to "report () infracritical com".  Thanks!
--

require("nmap")
require("nsedebug")
require("datafiles")
require("stdnse")
require("shortport")
require("snmp")
require("http")
require("url")
require("strbuf")

portrule = shortport.portnumber({80,161}, "udp", {"open", "open|filtered"})

action = function(host, port)

  -- create the socket used for our connection
  local socket = nmap.new_socket()
        
  -- set a reasonable timeout value
  socket:set_timeout(5000)
        
  -- do some exception handling / cleanup
  local catch = function()
    socket:close()
  end
        
  -- connect to the potential SNMP system
  local try = nmap.new_try(catch)
  try(socket:connect(host.ip, port.number, "udp"))
        
  -- If you want to perform a test verifiication/validation of another OID,
  -- here are some values (as shown below):
  -- get value: 1.3.6.1.2.1.1.1 (SNMPv2-MIB::sysDescr.0)
  -- get value: 1.3.6.1.2.1.1.2 (SNMPv2-MIB::sysObjectID.0)
  -- get value: 1.3.6.1.2.1.1.3 (SNMPv2-MIB::sysUpTime.0)
  -- get value: 1.3.6.1.2.1.1.4 (SNMPv2-MIB::sysContact.0)
  -- get value: 1.3.6.1.2.1.1.5 (SNMPv2-MIB::sysName.0)
  -- get value: 1.3.6.1.2.1.1.6 (SNMPv2-MIB::sysLocation.0)
  -- get value: 1.3.6.1.2.1.1.7 (SNMPv2-MIB::sysServices.0)
  local payload; local options = {}; options.reqId = 28428 -- unnecessary?
  payload = snmp.encode(snmp.buildPacket(snmp.buildGetRequest(options, "1.3.6.1.2.1.1.1.0")))
  try(socket:send(payload))
  local status, response
        
  -- read in any response we might get
  status, response = socket:receive_bytes(1)
  if (not status) or (response == "TIMEOUT") then return; end
        
  -- since we got something back, the port is definitely open
  nmap.set_port_state(host, port, "open")

  local confirm = tostring(snmp.fetchFirst(response))
  -- print(confirm)
  result = "CONFIRM DEVICE AS ALLEN-BRADLEY/ROCKWELL MICROLOGIX"

  local split = stdnse.strsplit(" ",confirm)
  local split2 = stdnse.strsplit("-",split[1])

  if (string.match(split2[1], "Allen") and string.match(split2[2], "Bradley")) or string.match(confirm, "Rockwell") then
    if string.match(confirm, "MicroLogix1400") then
      if nmap.verbosity() > 1 then
        result = result .. "\n** PHASE 1: SNMP verification"
        result = result .. "\n....Step 1: MicroLogix device info : CONFIRMED"
      else
        result = result .. "\n** IF YOU REQUIRE MORE INFO, USE THE \"-v\" OPTION"
      end
    end
    local split = stdnse.strsplit(" ",confirm)
    if string.match(split2[1], "Allen") then
      name = string.sub(split[1],1,15)
    end
    if string.match(confirm, "Rockwell") then
      name1 = string.sub(split[1],1,15)
      name2 = string.sub(split[2],1,15)
      name = name1 .. " " .. name2
    end
    modelnum = string.sub(split[2],1,14)
    version = string.sub(split[3],3,6)
    fullversion = string.sub(split[3],1,6)
    modeltype = string.sub(split[4],1,10) .. " " .. string.sub(split[4],11,14)
    series = string.sub(split[6],1,1)
    revision = string.sub(split[8],1,4)
    if nmap.verbosity() > 1 then
      result = result .. "\n............Version S/W            : " .. fullversion
    else
      result = result .. "\n............MicroLogix device info : CONFIRMED"
      result = result .. "\n............Version S/W            : " .. version
    end
    if nmap.verbosity() > 1 then
      result = result .. "\n....Step 2: SNMP device detailed information"
      result = result .. "\n............Manufacturer name      : " .. name
      result = result .. "\n............Model number           : " .. modelnum
      result = result .. "\n............Type/model type        : " .. modeltype
      result = result .. "\n............Series type            : " .. series
      result = result .. "\n............Revision number        : " .. revision
      result = result .. "\n** PHASE 2: Documentation"
      result = result .. "\n....Step 1: Documentation exist?   : YES"
      result = result .. "\n"
      result = result .. "\n............ninja.infracritical.com/dox/1766-in001_-en-p.pdf"
      result = result .. "\n............ninja.infracritical.com/dox/1766-um002_-en-p.pdf"
    end
  else
    if nmap.verbosity() > 1 then result = "Fingerprint not found."; end
  end
  if nmap.verbosity() > 1 then result = result .. "\n"; end
  return result
end

===============================================

Same output was conducted on four (4) Internet-connected PLC devices "in the wild", and will look similar to something 
shown below. NOTE: "xxx.xxx.xxx.xxx" represents a sanitized IP address of the device taken from "in the wild" (thank 
you SHODAN).

[root@server nmap]# nmap --script=./micrologix1400.nse xxx.xxx.xxx.xxx -PN -sU -p161 -vv

Starting Nmap 5.35DC1 ( http://nmap.org ) at 2010-12-06 21:08 CST
NSE: Loaded 1 scripts for scanning.
Initiating Parallel DNS resolution of 1 host. at 21:08
Completed Parallel DNS resolution of 1 host. at 21:08, 0.15s elapsed
Initiating UDP Scan at 21:08
Scanning xxx.domain.com (xxx.xxx.xxx.xxx) [1 port]
Discovered open port 161/udp on xxx.xxx.xxx.xxx
Completed UDP Scan at 21:08, 2.01s elapsed (1 total ports)
NSE: Script scanning xxx.xxx.xxx.xxx.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 21:08
Completed NSE at 21:08, 0.14s elapsed
Nmap scan report for xxx.domain.com (xxx.xxx.xxx.xxx)
Host is up (1.8s latency).
Scanned at 2010-12-06 21:08:34 CST for 2s
PORT    STATE SERVICE
161/udp open  snmp
| micrologix1400: CONFIRM DEVICE AS ALLEN-BRADLEY/ROCKWELL MICROLOGIX
| ** PHASE 1: SNMP verification
| ....Step 1: MicroLogix device info : CONFIRMED
| ............Version S/W            : A/5.00
| ....Step 2: SNMP device detailed information
| ............Manufacturer name      : Allen-Bradley
| ............Model number           : 1766-L32AWAA
| ............Type/model type        : MicroLogix 1400
| ............Series type            : A
| ............Revision number        : 5.0
| ** PHASE 2: Documentation
| ....Step 1: Documentation exist?   : YES
| ............ninja.infracritical.com/dox/1766-in001_-en-p.pdf
|_............ninja.infracritical.com/dox/1766-um002_-en-p.pdf

Read data files from: /usr/local/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 2.58 seconds
           Raw packets sent: 2 (176B) | Rcvd: 2 (160B)
_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://seclists.org/nmap-dev/


Current thread: