diff --git a/CHANGELOG b/CHANGELOG
index 66068bf64..dbb80885c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,10 @@
# Nmap Changelog ($Id$); -*-text-*-
+o [NSE] Added prerule support to snmp-interfaces and the ability to
+ add the host's interface addresses to the scanning queue. The new
+ script arguments used for this functionality are "host" (required)
+ and "port" (optional). [Kris]
+
o [NSE] Added the resolveall prerule script which takes a table of
target names as a "hosts" argument and adds all of the resolved
addresses (IPv4 or IPv6, depending on Nmap's -6 option) for all of
diff --git a/scripts/snmp-interfaces.nse b/scripts/snmp-interfaces.nse
index 4c2c62471..d8463a252 100644
--- a/scripts/snmp-interfaces.nse
+++ b/scripts/snmp-interfaces.nse
@@ -1,8 +1,21 @@
description = [[
Attempts to enumerate network interfaces through SNMP.
+
+This script can also be run during Nmap's pre-scanning phase and can
+attempt to add the SNMP server's interface addresses to the target
+list. The script argument snmp-interfaces.host is
+required to know what host to probe. To specify a port for the SNMP
+server other than 161, use snmp-interfaces.port. When
+run in this way, the script's output tells how many new targets were
+successfully added.
]]
---
+-- @args snmp-interfaces.host Specifies the SNMP server to probe when
+-- running in the "pre-scanning phase".
+-- @args snmp-interfaces.port The optional port number corresponding
+-- to the host script argument. Defaults to 161.
+--
-- @output
-- | snmp-interfaces:
-- | eth0
@@ -12,7 +25,7 @@ Attempts to enumerate network interfaces through SNMP.
-- |_ Traffic stats: 6.45 Mb sent, 15.01 Mb received
--
-author = "Thomas Buchanan"
+author = "Thomas Buchanan, Kris Katterjohn"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
dependencies = {"snmp-brute"}
@@ -21,11 +34,14 @@ dependencies = {"snmp-brute"}
-- Created 03/03/2010 - v0.1 - created by Thomas Buchanan
-- Revised 03/05/2010 - v0.2 - Reworked output slighty, moved iana_types to script scope. Suggested by David Fifield
-- Revised 04/11/2010 - v0.2 - moved snmp_walk to snmp library
+-- Revised 08/10/2010 - v0.3 - prerule; add interface addresses to Nmap's target list (Kris Katterjohn)
require "shortport"
require "snmp"
require "datafiles"
+require "target"
+prerule = function() return true end
portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"})
-- List of IANA-assigned network interface types
@@ -292,6 +308,23 @@ function process_ips( if_tbl, ip_tbl )
return if_tbl
end
+--- Creates a table of IP addresses from the table of network interfaces
+--
+-- @param tbl table containing network interfaces
+-- @return table containing only IP addresses
+function list_addrs( tbl )
+ local new_tbl = {}
+
+ for _, index in ipairs( tbl.index_list ) do
+ local interface = tbl[index]
+ if interface.ip_addr then
+ table.insert( new_tbl, interface.ip_addr )
+ end
+ end
+
+ return new_tbl
+end
+
--- Process the table of network interfaces for reporting
--
-- @param tbl table containing network interfaces
@@ -353,9 +386,38 @@ action = function(host, port)
local interfaces = {}
local ips = {}
local status
+ local srvhost, srvport
+
+ if SCRIPT_TYPE == "prerule" then
+ for _, k in ipairs({"snmp-interfaces.host", "host"}) do
+ if nmap.registry.args[k] then
+ srvhost = nmap.registry.args[k]
+ end
+ end
+
+ if not srvhost then
+ stdnse.print_debug(3,
+ "Skipping '%s' %s, 'snmp-interfaces.host' argument is missing.",
+ SCRIPT_NAME, SCRIPT_TYPE)
+ return
+ end
+
+ for _, k in ipairs({"snmp-interfaces.port", "port"}) do
+ if nmap.registry.args[k] then
+ srvport = tonumber(nmap.registry.args[k])
+ end
+ end
+
+ if not srvport then
+ srvport = 161
+ end
+ else
+ srvhost = host.ip
+ srvport = port.number
+ end
socket:set_timeout(5000)
- try(socket:connect(host, port))
+ try(socket:connect(srvhost, srvport, "udp"))
-- retreive network interface information from IF-MIB
status, interfaces = snmp.snmpWalk( socket, if_oid )
@@ -371,7 +433,7 @@ action = function(host, port)
interfaces = process_interfaces( interfaces )
-- retreive IP address information from IP-MIB
- try(socket:connect(host, port))
+ try(socket:connect(srvhost, srvport, "udp"))
status, ips = snmp.snmpWalk( socket, ip_oid )
-- associate that IP address information with the correct interface
@@ -379,9 +441,31 @@ action = function(host, port)
interfaces = process_ips( interfaces, ips )
end
- nmap.set_port_state(host, port, "open")
-
- interfaces = build_results( interfaces )
-
- return stdnse.format_output( true, interfaces )
+ local output = stdnse.format_output( true, build_results(interfaces) )
+
+ if SCRIPT_TYPE == "prerule" and target.ALLOW_NEW_TARGETS then
+ local sum = 0
+
+ ips = list_addrs(interfaces)
+
+ -- Could add all of the addresses at once, but count
+ -- successful additions instead for script output
+ for _, i in ipairs(ips) do
+ local st, err = target.add(i)
+ if st then
+ sum = sum + 1
+ else
+ stdnse.print_debug("Couldn't add target " .. i .. ": " .. err)
+ end
+ end
+
+ if sum ~= 0 then
+ output = output .. "\nSuccessfully added " .. tostring(sum) .. " new targets"
+ end
+ elseif SCRIPT_TYPE == "portrule" then
+ nmap.set_port_state(host, port, "open")
+ end
+
+ return output
end
+