Lucene search

K
nmapPatrik KarlssonNMAP:DNS-IP6-ARPA-SCAN.NSE
HistoryApr 01, 2012 - 1:04 p.m.

dns-ip6-arpa-scan NSE Script

2012-04-0113:04:23
Patrik Karlsson
nmap.org
121

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%

Performs a quick reverse DNS lookup of an IPv6 network using a technique which analyzes DNS server response codes to dramatically reduce the number of queries needed to enumerate large networks.

The technique essentially works by adding an octet to a given IPv6 prefix and resolving it. If the added octet is correct, the server will return NOERROR, if not a NXDOMAIN result is received.

The technique is described in detail on Peter’s blog: <http://7bits.nl/blog/2012/03/26/finding-v6-hosts-by-efficiently-mapping-ip6-arpa&gt;

See also:

Script Arguments

prefix

the ip6 prefix to scan

mask

the ip6 mask to start scanning from

Example Usage

nmap --script dns-ip6-arpa-scan --script-args='prefix=2001:0DB8::/48'

Script Output

Pre-scan script results:
| dns-ip6-arpa-scan:
| ip                                 ptr
| 2001:0DB8:0:0:0:0:0:2              resolver1.example.com
|_2001:0DB8:0:0:0:0:0:3              resolver2.example.com

Requires


local coroutine = require "coroutine"
local dns = require "dns"
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 = [[
Performs a quick reverse DNS lookup of an IPv6 network using a technique
which analyzes DNS server response codes to dramatically reduce the number of queries needed to enumerate large networks.

The technique essentially works by adding an octet to a given IPv6 prefix
and resolving it. If the added octet is correct, the server will return
NOERROR, if not a NXDOMAIN result is received.

The technique is described in detail on Peter's blog:
http://7bits.nl/blog/2012/03/26/finding-v6-hosts-by-efficiently-mapping-ip6-arpa
]]

---
-- @usage
-- nmap --script dns-ip6-arpa-scan --script-args='prefix=2001:0DB8::/48'
--
-- @see dns-nsec3-enum.nse
-- @see dns-nsec-enum.nse
-- @see dns-brute.nse
-- @see dns-zone-transfer.nse
--
-- @output
-- Pre-scan script results:
-- | dns-ip6-arpa-scan:
-- | ip                                 ptr
-- | 2001:0DB8:0:0:0:0:0:2              resolver1.example.com
-- |_2001:0DB8:0:0:0:0:0:3              resolver2.example.com
--
-- @args prefix the ip6 prefix to scan
-- @args mask the ip6 mask to start scanning from

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


local arg_prefix = stdnse.get_script_args(SCRIPT_NAME .. ".prefix")
local arg_mask = stdnse.get_script_args(SCRIPT_NAME .. ".mask")

-- Return a prefix and mask based on script arguments. First checks for "/"
-- netmask syntax; then looks for a "mask" script argument if that fails. The
-- "/" syntax wins over "mask" if both are present.
local function get_prefix_mask(arg_prefix, arg_mask)
  if not arg_prefix then
    return
  end
  local prefix, mask = string.match(arg_prefix, "^(.*)/(.*)$")
  if not mask then
    prefix, mask = arg_prefix, arg_mask
  end
  return prefix, mask
end

prerule = function()
  local prefix, mask = get_prefix_mask(arg_prefix, arg_mask)
  return prefix and mask
end

local function query_prefix(query, result)
  local condvar = nmap.condvar(result)
  local status, res = dns.query(query, { dtype='PTR' })
  if ( not(status) and res == "No Answers") then
    table.insert(result, query)
  elseif ( status ) then
    local ip = query:sub(1, -10):gsub('%.',''):reverse():gsub('(....)', '%1:'):sub(1, -2)
    ip = ipOps.bin_to_ip(ipOps.ip_to_bin(ip))
    table.insert(result, { ptr = res, query = query, ip = ip } )
  end
  condvar "signal"
end

action = function()

  local prefix, mask = get_prefix_mask(arg_prefix, arg_mask)
  local query = dns.reverse(prefix)

  -- cut the query name down to the length of the prefix
  local len = (( mask / 8 ) * 4) + #(".ip6.arpa") - 1

  local found = { query:sub(-len) }
  local threads = {}

  local i = 20

  local result
  repeat
    result = {}
    for _, f in ipairs(found) do
      for q in ("0123456789abcdef"):gmatch("(%w)") do
        local co = stdnse.new_thread(query_prefix, q .. "." .. f, result)
        threads[co] = true
      end
    end

    local condvar = nmap.condvar(result)
    repeat
      for t in pairs(threads) do
        if ( coroutine.status(t) == "dead" ) then threads[t] = nil end
      end
      if ( next(threads) ) then
        condvar "wait"
      end
    until( next(threads) == nil )

    if ( 0 == #result ) then
      return
    end

    found = result
    i = i + 1
  until( 128 == i * 2 + mask )

  table.sort(result, function(a,b) return (a.ip < b.ip) end)
  local output = tab.new(2)
  tab.addrow(output, "ip", "ptr")

  for _, item in ipairs(result) do
    tab.addrow(output, item.ip, item.ptr)
  end

  return "\n" .. tab.dump(output)
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:DNS-IP6-ARPA-SCAN.NSE