From da5a25c097d3f536750376806a124276b86366ff Mon Sep 17 00:00:00 2001 From: kroosec Date: Fri, 3 Aug 2012 22:58:29 +0000 Subject: [PATCH] Added mrinfo.nse script which queries a target router for multicasting information. --- CHANGELOG | 3 + scripts/mrinfo.nse | 217 +++++++++++++++++++++++++++++++++++++++++++++ scripts/script.db | 1 + 3 files changed, 221 insertions(+) create mode 100644 scripts/mrinfo.nse diff --git a/CHANGELOG b/CHANGELOG index 2510ec05e..993a95bf9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ # Nmap Changelog ($Id$); -*-text-*- +o [NSE] Added mrinfo script whiches queries a target router for multicast + information. [Hani Benhabiles] + o [NSE] Added ssl-date script which gets server's time from SSL ServerHello reply server random part. [Aleksandar Nikolic] diff --git a/scripts/mrinfo.nse b/scripts/mrinfo.nse new file mode 100644 index 000000000..2d58371f1 --- /dev/null +++ b/scripts/mrinfo.nse @@ -0,0 +1,217 @@ +local nmap = require "nmap" +local packet = require "packet" +local ipOps = require "ipOps" +local bin = require "bin" +local stdnse = require "stdnse" +local target = require "target" +local table = require "table" + + +description = [[ +Queries a target router for multicast information. + +This works by sending a DVMRP Ask Neighbors 2 request to the target and +listening for the DVMRP Neighbors 2 response that contains local addresses and +the multicast neighbors on each one. + +]] + + +--- +-- @args mrinfo.timeout Time to wait for a response in seconds. +-- Defaults to 5 seconds. +-- +--@usage +-- nmap --script mrinfo +-- +--@output +-- Host script results: +-- | mrinfo: +-- | Version 12.4 +-- | Local address: 192.168.2.2 +-- | Neighbor: 192.168.2.4 +-- | Neighbor: 192.168.2.3 +-- | Local address: 192.168.13.1 +-- | Neighbor: 192.168.13.3 +-- |_ Use the newtargets script-arg to add the results as targets + + +author = "Hani Benhabiles" + +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" + +categories = {"discovery", "safe"} + + +hostrule = function(host) + if nmap.address_family() ~= 'inet' then + stdnse.print_verbose("%s is IPv4 only.", SCRIPT_NAME) + return false + end + return true +end + +-- Parses a DVMRP Ask Neighbor 2 raw data and returns +-- a structured response. +-- @param data raw data. +local mrinfoParse = function(data) + local index, interface, neighbor + local response = {} + + -- first byte should be IGMP type == 0x013 (DVMRP) + if data:byte(1) ~= 0x013 then return end + + -- DVMRP Code + index, response.code = bin.unpack(">C", data, 2) + -- Checksum + index, response.checksum = bin.unpack(">S", data, index) + -- Capabilities (Skip one reserved byte) + index, response.capabilities = bin.unpack(">C", data, index + 1) + -- Major and minor version + index, response.minver = bin.unpack(">C", data, index) + index, response.majver = bin.unpack(">C", data, index) + response.interfaces = {} + -- Iterate over target local addresses (interfaces) + while index < #data do + if data:byte(index) == 0x00 then break end + interface = {} + -- Local address + index, interface.address = bin.unpack("C", data, index) + -- Treshold + index, interface.treshold= bin.unpack(">C", data, index) + -- Flags + index, interface.flags = bin.unpack(">C", data, index) + -- Number of neighbors + index, interface.ncount = bin.unpack(">C", data, index) + + interface.neighbors = {} + -- Iterate over neighbors + for i = 1, interface.ncount do + index, neighbor = bin.unpack("C", 0x13) + -- Code: Ask Neighbor v2 + mrinfo_raw = mrinfo_raw.. bin.pack(">C", 0x05) + -- Checksum: Calculated later + mrinfo_raw = mrinfo_raw.. bin.pack(">S", 0x0000) + -- Reserved + mrinfo_raw = mrinfo_raw.. bin.pack(">S", 0x000a) + -- Version == Cisco IOS 12.4 + -- Minor version: 4 + mrinfo_raw = mrinfo_raw.. bin.pack(">C", 0x04) + -- Major version: 12 + mrinfo_raw = mrinfo_raw.. bin.pack(">C", 0x0c) + -- Calculate checksum + mrinfo_raw = mrinfo_raw:sub(1,2) .. bin.pack(">S", packet.in_cksum(mrinfo_raw)) .. mrinfo_raw:sub(5) + + return mrinfo_raw +end + +-- Function that sends a DVMRP query. +--@param mrinfo_raw Raw DVMRP packet. +--@param scrip Source IP of the packet. +--@param dstip Destination IP to send to. +local mrinfoQuery = function(mrinfo_raw, srcip, dstip) + + local ip_raw = bin.pack("H", "45c00040ed780000400218bc0a00c8750a00c86b") .. mrinfo_raw -- Less ugly way to do it ? + local mrinfo_packet = packet.Packet:new(ip_raw, ip_raw:len()) + mrinfo_packet:ip_set_bin_src(ipOps.ip_to_str(srcip)) + mrinfo_packet:ip_set_bin_dst(ipOps.ip_to_str(dstip)) + mrinfo_packet:ip_set_len(ip_raw:len()) + + local sock = nmap.new_dnet() + sock:ip_open() + sock:ip_send(mrinfo_packet.buf) + sock:ip_close() +end + + +action = function(host) + local timeout = tonumber(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) or 5 + local mrinfo_raw, dstip, srcip, interface + local results = {} + + timeout = timeout * 1000 + + dstip = host.ip + interface = nmap.get_interface_info(host.interface) + srcip = interface.address + + -- Thread that listens for responses + stdnse.new_thread(mrinfoListen, interface, host, timeout, results) + + -- Send request + stdnse.sleep(0.5) + mrinfo_raw = mrinfoRaw() + mrinfoQuery(mrinfo_raw, srcip, dstip) + local condvar = nmap.condvar(results) + condvar("wait") + + if #results > 0 then + local output, ifoutput = {} + local response = results[1] + table.insert(output, ("Version %s.%s"):format(response.majver, response.minver)) + for _, interface in pairs(response.interfaces) do + ifoutput = {} + ifoutput.name = "Local address: " .. interface.address + for _, neighbor in pairs(interface.neighbors) do + if target.ALLOW_NEW_TARGETS then target.add(neighbor) end + table.insert(ifoutput, "Neighbor: " .. neighbor) + end + table.insert(output, ifoutput) + end + if not target.ALLOW_NEW_TARGETS then + table.insert(output,"Use the newtargets script-arg to add the results as targets") + end + return stdnse.format_output(true, output) + end +end diff --git a/scripts/script.db b/scripts/script.db index 1ea61812c..409df9b5f 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -242,6 +242,7 @@ Entry { filename = "modbus-discover.nse", categories = { "discovery", "intrusive Entry { filename = "mongodb-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "mongodb-info.nse", categories = { "default", "discovery", "safe", } } +Entry { filename = "mrinfo.nse", categories = { "discovery", "safe", } } Entry { filename = "ms-sql-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "ms-sql-config.nse", categories = { "discovery", "safe", } } Entry { filename = "ms-sql-dac.nse", categories = { "discovery", "safe", } }