diff --git a/CHANGELOG b/CHANGELOG index 21f0d562d..8a16d27a4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,6 +9,13 @@ o Added a UDP SIPOptions probe corresponding to the TCP one thanks to o Added a UDP payload and service detection probe for Citrix MetaFrame, which typically runs on 1604/udp. [Thomas Buchanan] +o Added new NSE scripts: + + o ntp-info asks for configuration variables from the NTP service, + which may include such interesting information as the operating + system, server build date, and upstream time server IP address. + [Richard Sammet] + Nmap 5.10BETA1 [2009-11-23] o Added 14 new NSE scripts for a grand total of 72! You can learn diff --git a/scripts/ntp-info.nse b/scripts/ntp-info.nse new file mode 100644 index 000000000..1bbac5678 --- /dev/null +++ b/scripts/ntp-info.nse @@ -0,0 +1,83 @@ +description = [[ +Gets variables from an NTP server by sending a "read variables" (opcode 2) +control message. + +See RFC 1035 and the Network Time Protocol Version 4 Reference and +Implementation Guide +(http://www.eecis.udel.edu/~mills/database/reports/ntp4/ntp4.pdf) for +documentation of the protocol. +]] + +--- +-- @output +-- PORT STATE SERVICE VERSION +-- 123/udp open ntp NTP v4 +-- | ntp-info: +-- | version: ntpd 4.2.4p4@1.1520-o Wed May 13 21:06:31 UTC 2009 (1) +-- | processor: x86_64 +-- | system: Linux/2.6.24-24-server +-- | stratum: 2 +-- |_ refid: 195.145.119.188 + + +author = "Richard Sammet" +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" +categories = {"default", "discovery", "safe"} + + +require "bin" +require "stdnse" +require "comm" +require "shortport" + +portrule = shortport.port_or_service(123, "ntp", {"udp", "tcp"}) + +-- Transform an array into a table where the array's values all map to true. +local function make_set(a) + local i, v, result + result = {} + for i, v in ipairs(a) do + result[v] = true + end + return result +end + +-- Only these fields from the response are displayed with default verbosity. +local DEFAULT_FIELDS = make_set({"version", "processor", "system", "refid", "stratum"}) + +action = function(host, port) + local status + local bufrlres + local output = {} + + -- This is a ntp v2 mode6 (control) rl (readlist/READVAR(2)) request. See + -- appendix B of RFC 1305. + local rlreq = string.char(0x16, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00) + + status, bufrlres = comm.exchange(host, port, rlreq, {proto=port.protocol}) + + if status then + local _, data, k, q, v + + -- Skip the first 10 bytes of the header, then get the data which is + -- preceded by a 2-byte length. + _, p, data = bin.unpack("A10>P", bufrlres) + + -- This parsing is not quite right with respect to quoted strings. + -- Backslash escapes should be interpreted inside strings and commas should + -- be allowed inside them. + for k, q, v in string.gmatch(data, "%s*(%w+)=(\"?)([^,\"]*)%2,?") do + if DEFAULT_FIELDS[k] then + table.insert(output, string.format("%s: %s", k, v)) + end + end + end + + if(#output > 0) then + nmap.set_port_state(host, port, "open") + return stdnse.format_output(true, output) + else + return nil + end +end diff --git a/scripts/script.db b/scripts/script.db index e01cb7a37..7fec156cc 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -32,6 +32,7 @@ Entry { filename = "ms-sql-info.nse", categories = { "default", "discovery", "in Entry { filename = "mysql-info.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "nbstat.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "nfs-showmount.nse", categories = { "discovery", "safe", } } +Entry { filename = "ntp-info.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "p2p-conficker.nse", categories = { "default", "safe", } } Entry { filename = "pjl-ready-message.nse", categories = { "intrusive", } } Entry { filename = "pop3-brute.nse", categories = { "auth", "intrusive", } }