1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
local ipOps = require "ipOps"
local coroutine = require "coroutine"
local nmap = require "nmap"
local stdnse = require "stdnse"
local tab = require "tab"
local table = require "table"
local tableaux = require "tableaux"
local target = require "target"
local multicast = require "multicast"
description = [[
Attempts to discover available IPv6 hosts on the LAN by sending an MLD
(multicast listener discovery) query to the link-local multicast address
(ff02::1) and listening for any responses. The query's maximum response delay
set to 1 to provoke hosts to respond immediately rather than waiting for other
responses from their multicast group.
]]
---
-- @usage
-- nmap -6 --script=targets-ipv6-multicast-mld.nse --script-args 'newtargets,interface=eth0'
--
-- @output
-- Pre-scan script results:
-- | targets-ipv6-multicast-mld:
-- | IP: fe80::5a55:abcd:ef01:2345 MAC: 58:55:ab:cd:ef:01 IFACE: en0
-- | IP: fe80::9284:0123:4567:89ab MAC: 90:84:01:23:45:67 IFACE: en0
-- |
-- |_ Use --script-args=newtargets to add the results as targets
--
-- @args targets-ipv6-multicast-mld.timeout timeout to wait for
-- responses (default: 10s)
-- @args targets-ipv6-multicast-mld.interface Interface to send on (default:
-- the interface specified with -e or every available Ethernet interface
-- with an IPv6 address.)
--
-- @xmloutput
-- <table>
-- <table>
-- <elem key="address">fe80::5a55:abcd:ef01:2345</elem>
-- <elem key="mac">58:55:ab:cd:ef:01</elem>
-- <elem key="iface">en0</elem>
-- </table>
-- <table>
-- <elem key="address">fe80::9284:0123:4567:89ab</elem>
-- <elem key="mac">90:84:01:23:45:67</elem>
-- <elem key="iface">en0</elem>
-- </table>
-- </table>
author = {"niteesh", "alegen"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery","broadcast"}
local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. '.timeout'))
prerule = function()
if ( not(nmap.is_privileged()) ) then
stdnse.verbose1("not running for lack of privileges.")
return false
end
return true
end
local function get_interfaces()
local interface_name = stdnse.get_script_args(SCRIPT_NAME .. ".interface")
or nmap.get_interface()
-- interfaces list (decide which interfaces to broadcast on)
local interfaces = {}
for _, if_table in pairs(nmap.list_interfaces()) do
if (interface_name == nil or if_table.device == interface_name) -- check for correct interface
and ipOps.ip_in_range(if_table.address, "fe80::/10") -- link local address
and if_table.link == "ethernet" then -- not the loopback interface
table.insert(interfaces, if_table)
end
end
return interfaces
end
local function single_interface_broadcast(if_nfo, results)
stdnse.debug2("Starting " .. SCRIPT_NAME .. " on " .. if_nfo.device)
local condvar = nmap.condvar(results)
local reports = multicast.mld_query(if_nfo, arg_timeout or 10)
for _, r in pairs(reports) do
local l2reply = r[2]
local l3reply = r[3]
local target_str = l3reply.ip_src
if not results[target_str] then
if target.ALLOW_NEW_TARGETS then
target.add(target_str)
end
results[target_str] = { address = target_str, mac = stdnse.format_mac(l2reply.mac_src), iface = if_nfo.device }
end
end
condvar("signal")
end
local function format_output(results)
local output = tab.new()
local xmlout = {}
local ips = tableaux.keys(results)
table.sort(ips)
for i, ip in ipairs(ips) do
local record = results[ip]
xmlout[i] = record
tab.addrow(output, " IP: " .. record.address, "MAC: " .. record.mac, "IFACE: " .. record.iface)
end
if ( #output > 0 ) then
output = {"", tab.dump(output) }
if not target.ALLOW_NEW_TARGETS then
table.insert(output, " Use --script-args=newtargets to add the results as targets")
end
return xmlout, table.concat(output, "\n")
end
end
action = function()
local threads = {}
local results = {}
local condvar = nmap.condvar(results)
for _, if_nfo in ipairs(get_interfaces()) do
-- create a thread for each interface
local co = stdnse.new_thread(single_interface_broadcast, if_nfo, results)
threads[co] = true
end
repeat
for thread in pairs(threads) do
if coroutine.status(thread) == "dead" then threads[thread] = nil end
end
if ( next(threads) ) then
condvar "wait"
end
until next(threads) == nil
return format_output(results)
end
|