summaryrefslogtreecommitdiffstats
path: root/scripts/openlookup-info.nse
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--scripts/openlookup-info.nse246
1 files changed, 246 insertions, 0 deletions
diff --git a/scripts/openlookup-info.nse b/scripts/openlookup-info.nse
new file mode 100644
index 0000000..0d24959
--- /dev/null
+++ b/scripts/openlookup-info.nse
@@ -0,0 +1,246 @@
+local comm = require "comm"
+local datetime = require "datetime"
+local nmap = require "nmap"
+local shortport = require "shortport"
+local stdnse = require "stdnse"
+local string = require "string"
+local stringaux = require "stringaux"
+local table = require "table"
+
+description = [[
+Parses and displays the banner information of an OpenLookup (network key-value store) server.
+]]
+
+---
+-- @usage
+-- nmap -p 5850 --script openlookup-info <target>
+--
+-- @output
+-- 5850/tcp open openlookup
+-- | openlookup-info:
+-- | sync port: 5850
+-- | name: Paradise, Arizona
+-- | your address: 127.0.0.1:50162
+-- | timestamp: 2011-05-21T11:26:07
+-- | version: 2.7
+-- |_ http port: 5851
+--
+-- @xmloutput
+-- <elem key="sync port">5850</elem>
+-- <elem key="name">Paradise, Arizona</elem>
+-- <elem key="your address">127.0.0.1:50162</elem>
+-- <elem key="timestamp">2011-05-21T11:26:07</elem>
+-- <elem key="version">2.7</elem>
+-- <elem key="http port">5851</elem>
+
+author = "Toni Ruottu"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"default", "discovery", "safe", "version"}
+
+
+portrule = shortport.version_port_or_service(5850, "openlookup")
+
+-- Netstring helpers
+-- http://cr.yp.to/proto/netstrings.txt
+
+-- parses a Netstring element
+local function parsechunk(data)
+ local parts = stringaux.strsplit(":", data)
+ if #parts < 2 then
+ return nil, data
+ end
+ local head = table.remove(parts, 1)
+ local size = tonumber(head)
+ if not size then
+ return nil, data
+ end
+ local body = table.concat(parts, ":")
+ if #body < size then
+ return nil, data
+ end
+ local chunk = string.sub(body, 1, size)
+ local skip = #chunk + string.len(",")
+ local rest = string.sub(body, skip + 1)
+ return chunk, rest
+end
+
+-- NSON helpers
+-- http://code.google.com/p/messkit/source/browse/trunk/messkit/nson.py
+
+-- parses an NSON int
+local function parseint(data)
+ if string.sub(data, 1, 1) ~= "i" then
+ return
+ end
+ local text = string.sub(data, 2)
+ local number = tonumber(text)
+ return number
+end
+
+-- parses an NSON float
+local function parsefloat(data)
+ if string.sub(data, 1, 1) ~= "f" then
+ return
+ end
+ local text = string.sub(data, 2)
+ local number = tonumber(text)
+ return number
+end
+
+-- parses an NSON string
+local function parsestring(data)
+ if string.sub(data, 1, 1) ~= "s" then
+ return
+ end
+ return string.sub(data, 2)
+end
+
+-- parses an NSON int, float, or string
+local function parsesimple(data)
+ local i = parseint(data)
+ local f = parsefloat(data)
+ local s = parsestring(data)
+ return i or f or s
+end
+
+-- parses an NSON dictionary
+local function parsedict(data)
+ if #data < 1 then
+ return
+ end
+ if string.sub(data, 1, 1) ~= "d" then
+ return
+ end
+ local rest = string.sub(data, 2)
+ local dict = {}
+ while #rest > 0 do
+ local chunk, key, value
+ chunk, rest = parsechunk(rest)
+ if not chunk then
+ return
+ end
+ key = parsestring(chunk)
+ value, rest = parsechunk(rest)
+ if not value then
+ return
+ end
+ dict[key] = value
+ end
+ return dict
+end
+
+-- parses an NSON array
+local function parsearray(data)
+ if #data < 1 then
+ return
+ end
+ if string.sub(data, 1, 1) ~= "a" then
+ return
+ end
+ local rest = string.sub(data, 2)
+ local array = {}
+ while #rest > 0 do
+ local value
+ value, rest = parsechunk(rest)
+ if not value then
+ return
+ end
+ table.insert(array, value)
+ end
+ return array
+end
+
+-- OpenLookup specific stuff
+
+local function formataddress(data)
+ local parts = parsearray(data)
+ if not parts then
+ return
+ end
+ if #parts < 2 then
+ return
+ end
+ local ip = parsestring(parts[1])
+ if not ip then
+ return
+ end
+ local port = parseint(parts[2])
+ if not port then
+ return
+ end
+ return ip .. ":" .. port
+end
+
+local function formattime(data)
+ local time = parsefloat(data)
+ if not time then
+ return
+ end
+ return datetime.format_timestamp(time)
+end
+
+local function formatvalue(key, nson)
+ local value
+ if key == "your_address" then
+ value = formataddress(nson)
+ elseif key == "timestamp" then
+ value = formattime(nson)
+ else
+ value = parsesimple(nson)
+ end
+ if not value then
+ value = "<" .. #nson .. "B of data>"
+ end
+ return value
+end
+
+function formatoptions(header)
+ local msg = parsedict(header)
+ if not msg then
+ return
+ end
+ local rawmeth = msg["method"]
+ if not rawmeth then
+ stdnse.debug2("header missing method field")
+ return
+ end
+ local method = parsestring(rawmeth)
+ if not method then
+ return
+ end
+ if method ~= "hello" then
+ stdnse.debug1("expecting hello, got " .. method .. " instead")
+ return
+ end
+ local rawopts = msg["options"]
+ if not rawopts then
+ return {}
+ end
+ return parsedict(rawopts)
+end
+
+action = function(host, port)
+ local status, banner = comm.get_banner(host, port)
+ if not status then
+ return
+ end
+ local header, _ = parsechunk(banner)
+ if not header then
+ return
+ end
+ local options = formatoptions(header)
+ if not options then
+ return
+ end
+ port.version.name = "openlookup"
+ local version = options["version"]
+ if version then
+ port.version.version = version
+ end
+ nmap.set_port_version(host, port)
+ if #options < 1 then
+ return
+ end
+ return options
+end
+