Lucene search

K
nmapPatrik KarlssonNMAP:BROADCAST-RIPNG-DISCOVER.NSE
HistoryJan 14, 2012 - 6:44 p.m.

broadcast-ripng-discover NSE Script

2012-01-1418:44:07
Patrik Karlsson
nmap.org
40

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Discovers hosts and routing information from devices running RIPng on the LAN by sending a broadcast RIPng Request command and collecting any responses.

Script Arguments

broadcast-ripng-discover.timeout

sets the connection timeout (default: 5s)

Example Usage

nmap --script broadcast-ripng-discover

Script Output

| broadcast-ripng-discover:
|   fe80::a00:27ff:fe9a:880c
|     route                       metric  next hop
|     fe80:470:0:0:0:0:0:0/64     1
|     fe80:471:0:0:0:0:0:0/64     1
|_    fe80:472:0:0:0:0:0:0/64     1

Requires


local ipOps = require "ipOps"
local nmap = require "nmap"
local stdnse = require "stdnse"
local string = require "string"
local tab = require "tab"
local table = require "table"

description = [[
Discovers hosts and routing information from devices running RIPng on the
LAN by sending a broadcast RIPng Request command and collecting any responses.
]]

---
-- @usage
-- nmap --script broadcast-ripng-discover
--
-- @output
-- | broadcast-ripng-discover:
-- |   fe80::a00:27ff:fe9a:880c
-- |     route                       metric  next hop
-- |     fe80:470:0:0:0:0:0:0/64     1
-- |     fe80:471:0:0:0:0:0:0/64     1
-- |_    fe80:472:0:0:0:0:0:0/64     1
--
-- @args broadcast-ripng-discover.timeout sets the connection timeout
--       (default: 5s)

author = "Patrik Karlsson"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"broadcast", "safe"}


prerule = function() return ( nmap.address_family() == "inet6" ) end

RIPng = {

  -- Supported RIPng commands
  Command = {
    Request = 1,
    Response = 2,
  },

  -- Route table entry
  RTE = {

    -- Creates a new Route Table Entry
    -- @param prefix string containing the ipv6 route prefix
    -- @param tag number containing the route tag
    -- @param prefix_len number containing the length in bits of the
    --        significant part of the prefix
    -- @param metric number containing the current metric for the
    --        destination
    new = function(self, prefix, tag, prefix_len, metric)
      local o = {
        prefix = prefix,
        tag = tag,
        prefix_len = prefix_len,
        metric = metric
      }
      setmetatable(o, self)
      self.__index = self
      return o
    end,

    -- Parses a byte string and creates an instance of RTE
    -- @param data string of bytes
    -- @return rte instance of RTE
    parse = function(data)
      local rte = RIPng.RTE:new()
      local pos, ip

      ip, rte.tag, rte.prefix_len, rte.metric, pos = string.unpack(">c16 I2 BB", data)
      rte.prefix = ipOps.str_to_ip(ip, 'inet6')
      return rte
    end,

    -- Converts a RTE instance to string
    -- @return string of bytes to send to the server
    __tostring = function(self)
      local ipstr = ipOps.ip_to_str(self.prefix)
      assert(16 == #ipstr, "Invalid IPv6 address encountered")
      return ipstr .. string.pack(">I2 BB", self.tag, self.prefix_len, self.metric)
    end,


  },

  -- The Request class contains functions to build a RIPv2 Request
  Request = {

    -- Creates a new Request instance
    --
    -- @param command number containing the RIPv2 Command to use
    -- @return o instance of request
    new = function(self, entries)
      local o = {
        command = 1,
        version = 1,
        entries = entries,
      }
      setmetatable(o, self)
      self.__index = self
      return o
    end,

    -- Converts the whole request to a string
    __tostring = function(self)
      local RESERVED = 0
      local str = {string.pack(">BB I2", self.command, self.version, RESERVED)}
      for _, rte in ipairs(self.entries) do
        str[#str+1] = tostring(rte)
      end
      return table.concat(str)
    end,

  },

  -- A RIPng Response
  Response = {

    -- Creates a new Response instance
    -- @return o new instance of Response
    new = function(self)
      local o = {  }
      setmetatable(o, self)
      self.__index = self
      return o
    end,

    -- Creates a new Response instance based on a string of bytes
    -- @return resp new instance of Response
    parse = function(data)
      local resp = RIPng.Response:new()
      local pos, _

      resp.command, resp.version, _, pos = string.unpack(">BB I2", data)
      resp.entries = {}
      while( pos < #data ) do
        local e = RIPng.RTE.parse(data:sub(pos))
        table.insert(resp.entries, e)
        pos = pos + 20
      end

      return resp
    end,
  }
}

local function fail(err) return stdnse.format_output(false, err) end

-- Parses a RIPng response
-- @return ret string containing the routing table
local function parse_response(resp)
  local next_hop
  local result = tab.new(3)
  tab.addrow(result, "route", "metric", "next hop")
  for _, rte in pairs(resp.entries or {}) do
    -- next hop information is specified in a separate RTE according to
    -- RFC 2080 section 2.1.1
    if ( 0xFF == rte.metric ) then
      next_hop = rte.prefix
    else
      tab.addrow(result, ("%s/%d"):format(rte.prefix, rte.prefix_len), rte.metric, next_hop or "")
    end
  end
  return tab.dump(result)
end

action = function()

  local req = RIPng.Request:new( { RIPng.RTE:new("0::", 0, 0, 16) } )
  local host, port = "FF02::9", { number = 521, protocol = "udp" }
  local iface = nmap.get_interface()
  local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME..".timeout"))
  timeout = (timeout or 5) * 1000

  local sock = nmap.new_socket("udp")
  sock:bind(nil, 521)
  sock:set_timeout(timeout)

  local status = sock:sendto(host, port, tostring(req))

  -- do we need to add the interface name to the address?
  if ( not(status) ) then
    if ( not(iface) ) then
      return fail("Couldn't determine what interface to use, try supplying it with -e")
    end
    status = sock:sendto(host .. "%" .. iface, port, tostring(req))
  end

  if ( not(status) ) then
    return fail("Failed to send request to server")
  end

  local responses = {}
  while(true) do
    local status, data = sock:receive()
    if ( not(status) ) then
      break
    else
      local status, _, _, rhost = sock:get_info()
      if ( not(status) ) then
        rhost = "unknown"
      end
      responses[rhost] = RIPng.Response.parse(data)
    end
  end

  local result = {}
  for ip, resp in pairs(responses) do
    stdnse.debug1(ip, resp)
    table.insert(result, { name = ip, parse_response(resp) } )
  end
  return stdnse.format_output(true, result)
end

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Related for NMAP:BROADCAST-RIPNG-DISCOVER.NSE