diff --git a/scripts/openlookup-info.nse b/scripts/openlookup-info.nse new file mode 100644 index 000000000..61b1ac06b --- /dev/null +++ b/scripts/openlookup-info.nse @@ -0,0 +1,258 @@ +description = [[ +Connects to openlookup sync service and extracts information from the handshake. +]] + +--- +-- @usage +-- nmap -p 5850 --script openlookup-info +-- +-- @output +-- 5850/tcp open openlookup +-- | openlookup-info: +-- | sync port: 5850 +-- | name: Paradise, Arizona +-- | your address: 127.0.0.1:50162 +-- | timestamp: 1305977167.52 (2011-05-21 11:26:07 UTC) +-- | version: 2.7 +-- |_ http port: 5851 + +author = "Toni Ruottu" +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" +categories = {"default", "discovery", "safe", "version"} + +require("comm") +require("stdnse") +require("shortport") + +portrule = shortport.port_or_service(5850, "openlookup") + +-- Netstring helpers +-- http://cr.yp.to/proto/netstrings.txt + +-- parses a Netstring element +local function parsechunk(data) + local parts = stdnse.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 = stdnse.strjoin(":", 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 FORMAT = "!%Y-%m-%d %H:%M:%S UTC" + local time = parsefloat(data) + if not time then + return + end + local human = os.date(FORMAT, time) + return time .. " (" .. human .. ")" +end + +local function formatkey(key) + local parts = stdnse.strsplit("_", key) + return stdnse.strjoin(" ", parts) +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 + +local function format(rawkey, nson) + local key = formatkey(rawkey) + local value = formatvalue(rawkey, nson) + return key .. ": " .. value +end + +function formatoptions(header) + local msg = parsedict(header) + if not msg then + return + end + local rawmeth = msg["method"] + if not rawmeth then + stdnse.print_debug(2, "header missing method field") + return + end + local method = parsestring(rawmeth) + if not method then + return + end + if method ~= "hello" then + stdnse.print_debug(1, "expecting hello, got " .. method .. " instead") + return + end + local rawopts = msg["options"] + if not rawopts then + return {} + end + local options = parsedict(rawopts) + if not options then + return + end + local formatted = {} + for key, nson in pairs(options) do + local tmp = format(key, nson) + if tmp then + table.insert(formatted, tmp) + end + end + return formatted +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, "hardmatched") + if #options < 1 then + return + end + local response = {} + table.insert(response, options) + return stdnse.format_output(true, response) +end + diff --git a/scripts/script.db b/scripts/script.db index c7730406f..173b3d6dd 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -125,7 +125,7 @@ Entry { filename = "ldap-novell-getpass.nse", categories = { "discovery", "safe" Entry { filename = "ldap-rootdse.nse", categories = { "discovery", "safe", } } Entry { filename = "ldap-search.nse", categories = { "discovery", "safe", } } Entry { filename = "lexmark-config.nse", categories = { "discovery", "safe", } } -Entry { filename = "lltd-discovery.nse", categories = { "discovery", "safe", } } +Entry { filename = "lltd-discovery.nse", categories = { "broadcast", "discovery", "safe", } } Entry { filename = "modbus-discover.nse", categories = { "discovery", "intrusive", } } Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "mongodb-info.nse", categories = { "default", "discovery", "safe", } } @@ -161,6 +161,7 @@ Entry { filename = "ntp-info.nse", categories = { "default", "discovery", "safe" Entry { filename = "ntp-monlist.nse", categories = { "discovery", "intrusive", } } Entry { filename = "omp2-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "omp2-enum-targets.nse", categories = { "discovery", "safe", } } +Entry { filename = "openlookup-info.nse", categories = { "default", "discovery", "safe", "version", } } Entry { filename = "oracle-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "oracle-enum-users.nse", categories = { "auth", "intrusive", } } Entry { filename = "oracle-sid-brute.nse", categories = { "brute", "intrusive", } }