From 4c525b584de0cc8f21a195c534ca446adaede2bc Mon Sep 17 00:00:00 2001 From: patrik Date: Tue, 29 Nov 2011 00:48:59 +0000 Subject: [PATCH] o [NSE] Added the script reverse-index that creates creates a reverse index showing which hosts run a particular service rather than the services for each host. [Patrik] --- CHANGELOG | 4 + scripts/reverse-index.nse | 153 ++++++++++++++++++++++++++++++++++++++ scripts/script.db | 1 + 3 files changed, 158 insertions(+) create mode 100644 scripts/reverse-index.nse diff --git a/CHANGELOG b/CHANGELOG index 83e3bb415..132823d9b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ # Nmap Changelog ($Id$); -*-text-*- +o [NSE] Added the script reverse-index that creates creates a reverse index + showing which hosts run a particular service rather than the services for + each host. [Patrik] + o [NSE] Added whitelist capabilities to the unusual-port script to be able to handle legitimate services on dynamic ports and discrepancies between names of services. [Patrik] diff --git a/scripts/reverse-index.nse b/scripts/reverse-index.nse new file mode 100644 index 000000000..24beed829 --- /dev/null +++ b/scripts/reverse-index.nse @@ -0,0 +1,153 @@ +description = [[ +This script creates a reverse index showing which hosts run a particular +service rather than just listing the services on each host. +]] + +--- +-- @usage +-- nmap --script reverse-index +-- +-- @output +-- Post-scan script results: +-- | reverse-index: +-- | 22/tcp: 192.168.0.60 +-- | 23/tcp: 192.168.0.100 +-- | 80/tcp: 192.168.0.70 +-- | 445/tcp: 192.168.0.1 +-- | 53/udp: 192.168.0.105, 192.168.0.70, 192.168.0.60, 192.168.0.1 +-- |_ 5353/udp: 192.168.0.105, 192.168.0.70, 192.168.0.60, 192.168.0.1 +-- +-- @args reverse-index.mode the output display mode, can be either horizontal +-- or vertical (default: horizontal) +-- + +-- Version 0.1 +-- Created 11/22/2011 - v0.1 - created by Patrik Karlsson +author = "Patrik Karlsson" +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" +categories = { "safe" } + +-- the postrule displays the reverse-index once all hosts are scanned +postrule = function() return true end + +-- the hostrule iterates over open ports for the host and pushes them into the registry +hostrule = function() return true end + +hostaction = function(host) + nmap.registry[SCRIPT_NAME] = nmap.registry[SCRIPT_NAME] or {} + for _, s in ipairs({"open", "open|filtered"}) do + for _, p in ipairs({"tcp","udp"}) do + local host, port = host, nil + local db = nmap.registry[SCRIPT_NAME] + while( true ) do + port = nmap.get_ports(host, port, p, s) + if ( not(port) ) then break end + db[p] = db[p] or {} + db[p][port.number] = db[p][port.number] or {} + table.insert(db[p][port.number], { ip = host.ip, port = port, proto = p, state = s } ) + end + end + end +end + +-- +-- Shows an index similar to the following one +-- Post-scan script results: +-- | reverse-index: +-- | tcp/22 +-- | 192.168.0.60 +-- | tcp/23 +-- | 192.168.0.100 +-- | tcp/80 +-- | 192.168.0.70 +-- | tcp/445 +-- | 192.168.0.1 +-- | udp/5353 +-- | 192.168.0.105 +-- | 192.168.0.1 +-- | 192.168.0.60 +-- |_ 192.168.0.70 +local function createVerticalResults(db) + local results = {} + for proto, ports in pairs(db) do + for port, entries in pairs(ports) do + local result_entries = {} + for _, entry in ipairs(entries) do + table.insert(result_entries, entry.ip) + end + table.sort(result_entries) + result_entries.name = ("%d/%s"):format(port, proto) + table.insert(results, result_entries) + table.sort(results, + function(a,b) + local a_port, a_proto = a.name:match("^(%d+)\/(%w*)") + local b_port, b_proto = b.name:match("^(%d+)\/(%w*)") + if ( a_proto == b_proto ) then + return ( tonumber(a_port) ) < ( tonumber(b_port) ) + else + return a_proto < b_proto + end + end + ) + end + end + return results +end + +-- +-- Shows an index similar to the following one +-- | reverse-index: +-- | tcp/22: 192.168.0.60 +-- | tcp/23: 192.168.0.100 +-- | tcp/80: 192.168.0.70 +-- | tcp/445: 192.168.0.1 +-- | udp/53: 192.168.0.105, 192.168.0.70, 192.168.0.60, 192.168.0.1 +-- |_ udp/5353: 192.168.0.105, 192.168.0.70, 192.168.0.60, 192.168.0.1 +local function createHorizontalResults(db) + local results = {} + + for proto, ports in pairs(db) do + for port, entries in pairs(ports) do + local result_entries = {} + for _, entry in ipairs(entries) do + table.insert(result_entries, entry.ip) + end + local ips = stdnse.strjoin(", ", result_entries) + local str = ("%d/%s: %s"):format(port, proto, ips) + table.insert(results, str) + table.sort(results, + function(a,b) + local a_port, a_proto = a:match("^(%d+)\/(%w*):") + local b_port, b_proto = b:match("^(%d+)\/(%w*):") + if ( a_proto == b_proto ) then + return ( tonumber(a_port) ) < ( tonumber(b_port) ) + else + return a_proto < b_proto + end + end + ) + end + end + return results +end + +postaction = function() + local db = nmap.registry[SCRIPT_NAME] + local results + local mode = stdnse.get_script_args("reverse-index.mode") or "horizontal" + + if ( mode == 'horizontal' ) then + results = createHorizontalResults(db) + else + results = createVerticalResults(db) + end + return stdnse.format_output(true, results) +end + +local Actions = { + hostrule = hostaction, + postrule = postaction +} + +-- execute the action function corresponding to the current rule +action = function(...) return Actions[SCRIPT_TYPE](...) end diff --git a/scripts/script.db b/scripts/script.db index ba819a53d..4f7f77a13 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -207,6 +207,7 @@ Entry { filename = "quake3-info.nse", categories = { "default", "discovery", "sa Entry { filename = "quake3-master-getservers.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "realvnc-auth-bypass.nse", categories = { "auth", "default", "safe", } } Entry { filename = "resolveall.nse", categories = { "discovery", "safe", } } +Entry { filename = "reverse-index.nse", categories = { "safe", } } Entry { filename = "rexec-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "rlogin-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "rmi-dumpregistry.nse", categories = { "default", "discovery", "safe", } }