mirror of
https://github.com/nmap/nmap.git
synced 2025-12-12 10:49:02 +00:00
New NSE script: fcrdns
Performs Forward-confirmed reverse DNS lookup of the target, a.k.a. Full-circle reverse DNS, double-reverse DNS, or iprev.
This commit is contained in:
151
scripts/fcrdns.nse
Normal file
151
scripts/fcrdns.nse
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
local dns = require "dns"
|
||||||
|
local ipOps = require "ipOps"
|
||||||
|
local nmap = require "nmap"
|
||||||
|
local stdnse = require "stdnse"
|
||||||
|
local string = require "string"
|
||||||
|
local table = require "table"
|
||||||
|
|
||||||
|
description = [[
|
||||||
|
Performs a Forward-confirmed Reverse DNS lookup and reports anomalous results.
|
||||||
|
|
||||||
|
References:
|
||||||
|
* https://en.wikipedia.org/wiki/Forward-confirmed_reverse_DNS
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @output
|
||||||
|
-- Host script results:
|
||||||
|
-- |_fcrdns: FAIL (12.19.29.17, 12.19.20.14, 23.10.13.25)
|
||||||
|
--
|
||||||
|
-- Host script results:
|
||||||
|
-- |_fcrdns: PASS (37.58.100.86-static.reverse.softlayer.com)
|
||||||
|
--
|
||||||
|
-- Host script results:
|
||||||
|
-- | fcrdns:
|
||||||
|
-- | <none>:
|
||||||
|
-- | status: fail
|
||||||
|
-- |_ reason: No PTR record
|
||||||
|
--
|
||||||
|
-- Host script results:
|
||||||
|
-- | fcrdns:
|
||||||
|
-- | mail.example.com:
|
||||||
|
-- | status: fail
|
||||||
|
-- | reason: FCRDNS mismatch
|
||||||
|
-- | addresses:
|
||||||
|
-- | 12.19.29.17
|
||||||
|
-- | mail.contoso.net:
|
||||||
|
-- | status: fail
|
||||||
|
-- | reason: FCRDNS mismatch
|
||||||
|
-- | addresses:
|
||||||
|
-- | 12.19.20.14
|
||||||
|
-- |_ 23.10.13.25
|
||||||
|
--
|
||||||
|
--@xmloutput
|
||||||
|
-- <table key="mail.example.com">
|
||||||
|
-- <elem key="status">fail</elem>
|
||||||
|
-- <elem key="reason">FCRDNS mismatch</elem>
|
||||||
|
-- <table key="addresses">
|
||||||
|
-- <elem>12.19.29.17</elem>
|
||||||
|
-- </table>
|
||||||
|
-- </table>
|
||||||
|
-- <table key="mail.contoso.net">
|
||||||
|
-- <elem key="status">fail</elem>
|
||||||
|
-- <elem key="reason">FCRDNS mismatch</elem>
|
||||||
|
-- <table key="addresses">
|
||||||
|
-- <elem>12.19.20.14</elem>
|
||||||
|
-- <elem>23.10.13.25</elem>
|
||||||
|
-- </table>
|
||||||
|
-- </table>
|
||||||
|
|
||||||
|
author = "Daniel Miller"
|
||||||
|
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
|
||||||
|
-- not default, because user may choose -n and expect no DNS
|
||||||
|
categories = {"discovery", "safe"}
|
||||||
|
|
||||||
|
|
||||||
|
hostrule = function(host)
|
||||||
|
-- Every host with an IP address can be checked
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function keys(t)
|
||||||
|
local ret = {}
|
||||||
|
for k, _ in pairs(t) do
|
||||||
|
ret[#ret+1] = k
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
if stdnse.debug == nil then
|
||||||
|
-- Backwards compatibility.
|
||||||
|
-- TODO: remove this after next release
|
||||||
|
stdnse.debug = stdnse.print_debug
|
||||||
|
end
|
||||||
|
|
||||||
|
action = function(host)
|
||||||
|
-- Do reverse-DNS lookup of the IP
|
||||||
|
-- Can't just use host.name because some IPs have multiple PTR records
|
||||||
|
local status, rdns = dns.query(dns.reverse(host.ip), {dtype="PTR", retAll=true})
|
||||||
|
if not status then
|
||||||
|
stdnse.debug("PTR request for %s failed: %s", host.ip, rdns)
|
||||||
|
local ret = stdnse.output_table()
|
||||||
|
ret.status = "fail"
|
||||||
|
ret.reason = "No PTR record"
|
||||||
|
return {["<none>"]=ret}, "FAIL (No PTR record)"
|
||||||
|
end
|
||||||
|
|
||||||
|
local str_out = nil
|
||||||
|
-- Now do forward lookup of the name(s) we got
|
||||||
|
local names = stdnse.output_table()
|
||||||
|
local fcrdns
|
||||||
|
local fail_addrs = {}
|
||||||
|
local forward_type = nmap.address_family() == "inet" and "A" or "AAAA"
|
||||||
|
local no_record_err = string.format("No %s record", forward_type)
|
||||||
|
table.sort(rdns)
|
||||||
|
for _, n in ipairs(rdns) do
|
||||||
|
local name = stdnse.output_table()
|
||||||
|
-- assume failure, we can override when/if we succeed
|
||||||
|
name.status = "fail"
|
||||||
|
name.reason = "FCRDNS mismatch"
|
||||||
|
names[n] = name
|
||||||
|
|
||||||
|
status, fcrdns = dns.query(n, {dtype=forward_type, retAll=true})
|
||||||
|
if not status then
|
||||||
|
stdnse.debug("%s request for %s failed: %s", forward_type, n, fcrdns)
|
||||||
|
name.reason = no_record_err
|
||||||
|
else
|
||||||
|
for _, ip in ipairs(fcrdns) do
|
||||||
|
if ipOps.compare_ip( ip, "eq", host.ip) then
|
||||||
|
name.status = "pass"
|
||||||
|
name.reason = nil
|
||||||
|
str_out = string.format("PASS (%s)", n)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
name.addresses = fcrdns
|
||||||
|
if name.status == "fail" then
|
||||||
|
-- keep a list of unique addresses for short output
|
||||||
|
for _, a in ipairs(name.addresses) do
|
||||||
|
fail_addrs[a] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if nmap.verbosity() > 0 then
|
||||||
|
-- use default structured output for verbosity
|
||||||
|
str_out = nil
|
||||||
|
elseif str_out == nil then
|
||||||
|
-- we failed, and need to format a short output string
|
||||||
|
fail_addrs = keys(fail_addrs)
|
||||||
|
if #fail_addrs > 0 then
|
||||||
|
table.sort(fail_addrs)
|
||||||
|
str_out = string.format("FAIL (%s)", table.concat(fail_addrs, ", "))
|
||||||
|
else
|
||||||
|
str_out = string.format("FAIL (%s)", no_record_err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return names, str_out
|
||||||
|
end
|
||||||
@@ -105,6 +105,7 @@ Entry { filename = "eap-info.nse", categories = { "broadcast", "safe", } }
|
|||||||
Entry { filename = "enip-info.nse", categories = { "discovery", "version", } }
|
Entry { filename = "enip-info.nse", categories = { "discovery", "version", } }
|
||||||
Entry { filename = "epmd-info.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "epmd-info.nse", categories = { "default", "discovery", "safe", } }
|
||||||
Entry { filename = "eppc-enum-processes.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "eppc-enum-processes.nse", categories = { "discovery", "safe", } }
|
||||||
|
Entry { filename = "fcrdns.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "finger.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "finger.nse", categories = { "default", "discovery", "safe", } }
|
||||||
Entry { filename = "firewalk.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "firewalk.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "firewall-bypass.nse", categories = { "intrusive", "vuln", } }
|
Entry { filename = "firewall-bypass.nse", categories = { "intrusive", "vuln", } }
|
||||||
|
|||||||
Reference in New Issue
Block a user