Nmap Development mailing list archives
Another SCADA/ICS NMAP NSE script - Electro Industries / Guagetech 'Nexus' smart meter enumeration script
From: Bob Radvanovsky <rsradvan () unixworks net>
Date: Tue, 07 Dec 2010 15:19:47 -0600
This is one of several enumeration scripts that I have written for the SCADA/industrial control systems community. This checks/validates the web-based traffic for the Electro Industries / Guagetech 'Nexus' smart meter device. NOTE: This has been ONLY tested with a limited number of models from the 'Nexus' series, and I am still adding more models (such as the Shark 100S). All of these devices utilize an Ethernet connection to 'talk back' to a (probably) centralized controller. All devices are capable of running both Modbus TCP and DNP3. The Shark 100S and Shark 200S provide wireless (via WiFi) capabilities to poll these devices. All devices that have web server capabilities DO NOT utilize any "secured web servers" (port 443), ONLY UN-secured web servers (port 80). If I encounter any 'Nexus' devices that do provide/offer "secured web servers", that will be incorporated into the NSE enumeration script. Here is sample output from the modified NMAP NSE script (execute it as "nmap --script=./eig.nse <IP address> -PN -p80 -v"; use the "-PN" flag needs to be used on older TCP/IP device stacks, as NMAP has a tendency to lock up the TCP/IP stack). 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/eig.nse =============================================== description = "Confirms/verifies that target device is Electro Industries device." author = "Bob Radvanovsky <rsradvan at infracritical dot com>" license = "Refer to: http://nmap.org/book/man-legal.html for license." categories = {"safe", "discovery"} -- -- Filename: eig.nse -- -- Purpose: Checks for the following elements confirming said device: -- -- 1. PHASE I - HTML pattern matching & confirmation. -- a. STEP 1: EIG device confirmation. -- b. STEP 2: HTML device detailed information. -- -- 2. PHASE II - Documentation. -- -- ========================================================================== -- -- Version(s): N/A -- -- Usage: nmap --script=./eig.nse <IP> -PN -v -- -- Author(s): Bob Radvanovsky - Infracritical -- <rsradvan at infracritical dot com> -- -- Initwritten: September 2010 -- -- DATE---- INIT DESCRIPTION------------------------------------------------ -- 10.24.09 rsr Inital development - VERSION 001. -- 10.24.09 rsr Added script argument feature; argument called "VERBOSE". -- -- 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("http") require("url") require("strbuf") -- -- NOTE: Much of what is determined, may be found simply through interrogating -- the onboard web server; if the web server is DISABLED, or if the -- verification is performed through the EXTERNAL port, the results may -- vary, depending on how the firewall is configured. -- portrule = shortport.port_or_service({80},{"http"}) action = function(host, port) result = "CONFIRM DEVICE AS ELECTRO INDUSTRIES GAUGETECH" local a0, a1, a2, a3, a4, a5, device, buildinfo, eigweb a0 = http.get(host, port, "/"); eigdev = 0 if a0.status == 200 then if string.match(a0.body, "EIG Embedded Web Server") then eigweb = 1 end else eigweb = 0 if nmap.verbosity() > 1 then result = "File does not exist: index.htm" end end a1 = http.get(host, port, "/diag_firmware.htm"); eigdevice = 0 if a1.status == 200 then local s11 = ""; local s12 = ""; local s13 = ""; local s14 = "" local s15 = ""; local s16 = ""; local s17 = ""; local s18 = "" local s1a = ""; local s1b = ""; local s1c = ""; local s19 = "" local s1d = ""; local s1e = ""; local s1f = ""; local s10 = "" if string.match(a1.body, "Electro Industries/GaugeTech") or string.match(a1.body,"Shark Netcard") then eigdevice = 1 end else eigdevice = 0 if nmap.verbosity() > 1 then result = "File does not exist: diag_firmware.htm" end end if eigweb == 1 or eigdevice == 1 then if nmap.verbosity() > 1 then result = result .. "\n** PHASE 1: HTML verification" result = result .. "\n....Step 1: EIG device info : CONFIRMED" else result = result .. "\n** IF YOU REQUIRE MORE INFO, USE THE \"-v\" OPTION" end if string.match(a1.body,"Build info:") then if string.match(a1.body,"uild info: ") then s15 = stdnse.strsplit("uild info: ",a1.body) s16 = stdnse.strsplit("<BR>",s15[2]); s1c = s16[1]; buildinfo = s1c end if buildinfo == "Electro Industries/GaugeTech" then if string.match(a1.body,"time version: ") then s11 = stdnse.strsplit("time version: ", a1.body) s12 = stdnse.strsplit("<BR>",s11[2]); s1a = s12[1] end if string.match(a1.body,"oot version: ") then s13 = stdnse.strsplit("oot version: ",a1.body) s14 = stdnse.strsplit("<BR>",s13[2]); s1b = s14[1] end if string.match(a1.body,"oot ID: ") then s17 = stdnse.strsplit("oot ID: ",a1.body) s18 = stdnse.strsplit("<BR>",s17[2]); s1d = s18[1] end if string.match(a1.body,"time ID: ") then s19 = stdnse.strsplit("time ID: ",a1.body) s10 = stdnse.strsplit("<BR>",s19[2]); s1e = s10[1] end end if buildinfo == "Shark Netcard" then if string.match(a1.body,"Time version: ") then s11 = stdnse.strsplit("Time version: ", a1.body) s12 = stdnse.strsplit("<BR>",s11[2]); s1a = s12[1] end if string.match(a1.body,"oot version: ") then s13 = stdnse.strsplit("oot version: ",a1.body) s14 = stdnse.strsplit("<BR>",s13[2]); s1b = s14[1] end if string.match(a1.body,"oot ID: ") then s17 = stdnse.strsplit("oot ID: ",a1.body) s18 = stdnse.strsplit("<BR>",s17[2]); s1d = s18[1] end if string.match(a1.body,"time ID: ") then s19 = stdnse.strsplit("time ID: ",a1.body) s10 = stdnse.strsplit("<BR>",s19[2]); s1e = s10[1] end end if nmap.verbosity() > 1 then result = result .. "\n............Version S/W : " .. s1a result = result .. "\n............Boot Version S/W : " .. s1b result = result .. "\n....Step 2: HTML device detailed information" result = result .. "\n............Manufacturer name : " .. s1c result = result .. "\n............Boot ID model number : " .. s1d result = result .. "\n............Run ID model number : " .. s1e else result = result .. "\n............EIG device info : CONFIRMED" result = result .. "\n............Version S/W : " .. s1a end end else if nmap.verbosity() > 1 then result = "Fingerprint not found."; end end a2 = http.get(host, port, "/meter_information.htm") if a2.status == 200 then local s21 = ""; local s22 = ""; local s23 = "" local s24 = ""; local s25 = ""; local s26 = "" if string.match(a2.body, " Type") then s21 = stdnse.strsplit(" Type",a2.body) if string.match(s21[2],"Verdana") then s22 = stdnse.strsplit("Verdana",s21[2]) s23 = stdnse.strsplit(string.char(0x22,0x3e,0x20,0x0d,0x0a),s22[2]) -- s23 = stdnse.strsplit(string.char(0x0d,0x0a),s22[2]) if buildinfo == "Shark Netcard" then s24 = stdnse.strsplit(" ",s23[2]) device = "Shark" else s24 = stdnse.strsplit(" ",s23[2]) s25 = string.sub(s24[2],1,16) device = string.sub(s24[2],1,16) end end if nmap.verbosity() > 1 then result = result .. "\n............Device type : " .. s25 end end local s31 = ""; local s32 = ""; local s33 = "" local s34 = ""; local s35 = ""; local s36 = "" if string.match(a2.body, "Serial #") then s31 = stdnse.strsplit("Serial #",a2.body) if string.match(s31[2],"Verdana") then s32 = stdnse.strsplit("Verdana",s31[2]) s33 = stdnse.strsplit(string.char(0x22,0x3e,0x20,0x0d,0x0a),s32[2]) s34 = stdnse.strsplit(" ",s33[2]) s35 = string.sub(s34[2],1,8) end if nmap.verbosity() > 1 then result = result .. "\n............Serial number : " .. s35 end end local s41 = ""; local s42 = ""; local s43 = "" local s44 = ""; local s45 = ""; local s46 = "" if string.match(a2.body, "MAC") then s41 = stdnse.strsplit("Address",a2.body) if string.match(s41[2],"000000") then s42 = stdnse.strsplit("000000",s41[2]) -- s43 = stdnse.strsplit(string.char(0x22,0x3e,0x0d,0x0a),s42[2]) s43 = stdnse.strsplit(string.char(0x0d,0x0a),s42[2]) s44 = stdnse.strsplit(" ",s43[2]) s45 = string.sub(s44[2],1,17) end if nmap.verbosity() > 1 then result = result .. "\n............Network MAC Address : " .. s45 end end else if nmap.verbosity() > 1 then result = "File does not exist: meter_information.htm" end end a3 = http.get(host, port, "/diag_modbus_tcp_server.htm") if a3.status == 200 then local s51 = ""; local s52 = ""; local s5a = "" if string.match(a3.body,"Modbus TCP sockets: ") then s51 = stdnse.strsplit("Modbus TCP sockets: ", a3.body) s52 = stdnse.strsplit("<BR>",s51[2]); s5a = s52[1] if s5a == 0 then s5a = "DISABLED" else s5a = "ENABLED" end end if nmap.verbosity() > 1 then result = result .. "\n............Modbus TCP server : " .. s5a end end a4 = http.get(host, port, "/diag_dnp_lan_wan.htm") if a4.status == 200 then local s61 = ""; local s62 = ""; local s6a = "" if string.match(a4.body,"Mode: ") then s61 = stdnse.strsplit("Mode: ", a4.body) s62 = stdnse.strsplit("</font>",s61[2]); s6a = string.upper(s62[1]) end if nmap.verbosity() > 1 then result = result .. "\n............DNP TCP Server : " .. s6a end end result = result .. "\n** PHASE 2: Documentation" if string.match(device,"Nexus 1250") then result = result .. "\n....Step 1: Documentation exist? : YES" result = result .. "\n............ninja.infracritical.com/dox/gaugetech/nexus1250.pdf" else if string.match(device,"Nexus 1252") then result = result .. "\n....Step 1: Documentation exist? : YES" result = result .. "\n............ninja.infracritical.com/dox/gaugetech/nexus1252.pdf" else if string.match(device,"Nexus 1262") then result = result .. "\n....Step 1: Documentation exist? : YES" result = result .. "\n............ninja.infracritical.com/dox/gaugetech/nexus1262.pdf" else if string.match(device,"Nexus 1272") then result = result .. "\n....Step 1: Documentation exist? : YES" result = result .. "\n............ninja.infracritical.com/dox/gaugetech/nexus1272.pdf" else result = result .. "\n....Step 1: Documentation exist? : NO" end end end end return result end =============================================== Sample output from the NSE script. NOTE: The IP address, serial number, and MAC address for this sample output has been sanitized. [root@server nmap]# nmap --script=./eig.nse xxx.xxx.xxx.xxx -PN -p80 -v Starting Nmap 5.35DC1 ( http://nmap.org ) at 2010-12-07 14:55 CST NSE: Loaded 1 scripts for scanning. Initiating Parallel DNS resolution of 1 host. at 14:55 Completed Parallel DNS resolution of 1 host. at 14:55, 0.20s elapsed Initiating SYN Stealth Scan at 14:55 Scanning xxx.xxx.xxx.xxx [1 port] Discovered open port 80/tcp on xxx.xxx.xxx.xxx Completed SYN Stealth Scan at 14:55, 1.84s elapsed (1 total ports) NSE: Script scanning xxx.xxx.xxx.xxx. NSE: Starting runlevel 1 (of 1) scan. Initiating NSE at 14:55 Completed NSE at 14:55, 2.17s elapsed Nmap scan report for xxx.xxx.xxx.xxx Host is up (0.82s latency). PORT STATE SERVICE 80/tcp open http | eig: CONFIRM DEVICE AS ELECTRO INDUSTRIES GAUGETECH | ** PHASE 1: HTML verification | ....Step 1: EIG device info : CONFIRMED | ............Version S/W : 1.0 (Build 34) | ............Boot Version S/W : 1.0 (Build 50) | ....Step 2: HTML device detailed information | ............Manufacturer name : Electro Industries/GaugeTech | ............Boot ID model number : Boot 100 Base-T | ............Run ID model number : Run 100 Base-T | ............Device type : 0107 Nexus 1252 | ............Serial number : 00000000 | ............Network MAC Address : 00-00-00-00-00-00 | ............Modbus TCP server : ENABLED | ............DNP TCP Server : DISABLED | ** PHASE 2: Documentation | ....Step 1: Documentation exist? : YES |_............ninja.infracritical.com/dox/gaugetech/nexus1252.pdf Read data files from: /usr/local/share/nmap Nmap done: 1 IP address (1 host up) scanned in 4.48 seconds Raw packets sent: 2 (88B) | Rcvd: 1 (44B) _______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://seclists.org/nmap-dev/
Current thread:
- Another SCADA/ICS NMAP NSE script - Electro Industries / Guagetech 'Nexus' smart meter enumeration script Bob Radvanovsky (Dec 07)