1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-15 04:09:01 +00:00
Files
nmap/scripts/targets-ipv6-multicast-invalid-dst.nse
david d8ce681711 Simplify and document the invalid destination options header.
The packet construction had a bug that made it more effective in at
least one case for me. Weilin had supplied a 16-byte destination options
buffer, including some random bytes from a packet capture. But the
length of buffer was set incorrectly in the packet, making it look like
it was 8 bytes instead of 16. Therefore the expected ICMPv6 packet
started in the middle of the buffer, making it appear to have a
type/code of 254/24 instead of 128/0 as expected.

I tried setting the proper length, while keeping the invalid destination
option, but then stopped getting a Parameter Problem response. I also
tried setting a proper destination options buffer with no invalid
options, followed by ICMPv6 with type/code of 128/0, and again got no
response. It appears that I get a response only when both of these
conditions are satisfied: 1) an invalid destination option exists, and
2) the ICMPv6 type is unknown. This is against OS X.

The probe was being effective by accident, but now I've simplified it
and documented these strange conditions.

This breaks any hosts that might have ignored the invalid destination
option (which they shouldn't do) and replied to the echo request. But we
have targets-ipv6-multicast-echo for that.
2011-09-02 04:11:07 +00:00

154 lines
4.6 KiB
Lua

description = [[
Multicast invalid packet host discovery.
This script works by sending an ICMPv6 packet with an invalid extension header
to the all-nodes link-local multicast address, <code>ff02::1</code>. Some hosts
will respond to this probe with an ICMPv6 Parameter Problem packet. This script
can discover hosts reachable on an interface without needing to individually
ping each address.
]]
---
-- @usage
-- ./nmap -6 --script=targets-ipv6-multicast-invalid-dst.nse --script-args 'newtargets,interface=eth0' -sP
-- @args newtargets If true, add discovered targets to the scan queue.
-- @args targets-ipv6-multicast-invalid-dst.interface The interface to use for host discovery.
author = "David and Weilin"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"discovery"}
require 'nmap'
require 'target'
require 'packet'
local bit = require 'bit'
prerule = function()
return nmap.is_privileged() and
(stdnse.get_script_args(SCRIPT_NAME .. ".interface") or nmap.get_interface())
end
catch = function()
dnet:ethernet_close()
pcap:pcap_close()
end
try = nmap.new_try(catch)
local function get_ipv6_interface_info_by_name(if_name)
local ifaces = nmap.list_interfaces()
local iface
local if_nfo
for _,iface in pairs(ifaces) do
if if_name == iface.device and (#iface.address>15 or string.find(iface.address, "::")) then
if_nfo = iface
return if_nfo
end
end
return nil
end
local function get_identifier(ip6_addr)
return string.sub(ip6_addr, 9, 16)
end
--- Build an IPv6 invalid extension header.
-- @param nxt_hdr integer that stands for next header's type
local function build_invalid_extension_header(nxt_hdr)
-- RFC 2640, section 4.2 defines the TLV format of options headers.
-- It is important that the first byte have 10 in the most significant
-- bits; that instructs the receiver to send a Parameter Problem.
-- Option type 0x80 is unallocated; see
-- http://www.iana.org/assignments/ipv6-parameters/.
local ex_invalid_opt = string.char(0x80,0x01,0x00,0x00,0x00,0x00)
local ext_header =
string.char(nxt_hdr) .. --next header
string.char(0) .. -- length 8
ex_invalid_opt
return ext_header
end
action = function()
local if_name = stdnse.get_script_args(SCRIPT_NAME .. ".interface") or nmap.get_interface()
local if_nfo = get_ipv6_interface_info_by_name(if_name)
if not if_nfo then
stdnse.print_debug("Invalid interface: " .. if_name)
return false
end
local src_mac = if_nfo.mac
local src_ip6 = packet.ip6tobin(if_nfo.address)
local dst_mac = packet.mactobin("33:33:00:00:00:01")
local dst_ip6 = packet.ip6tobin("ff02::1")
local id_set = {}
----------------------------------------------------------------------------
--Multicast invalid destination exheader probe
local dnet = nmap.new_dnet()
local pcap = nmap.new_socket()
try(dnet:ethernet_open(if_name))
pcap:pcap_open(if_name, 128, false, "icmp6 and ip6[6:1] = 58 and ip6[40:1] = 4")
local probe = packet.Frame:new()
probe.mac_src = src_mac
probe.mac_dst = dst_mac
probe.ip6_src = src_ip6
probe.ip6_dst = dst_ip6
-- In addition to setting an invalid option in
-- build_invalid_extension_header, we set an unknown ICMPv6 type of
-- 254. (See http://www.iana.org/assignments/icmpv6-parameters for
-- allocations.) Mac OS X 10.6 appears to send a Parameter Problem
-- response only if both of these conditions are met. In this we differ
-- from the alive6 tool, which sends a proper echo request.
probe.icmpv6_type = 254
probe.icmpv6_code = 0
-- Add a non-empty payload too.
probe.icmpv6_payload = string.char(0x00, 0x00, 0x00, 0x00)
probe:build_icmpv6_header()
probe.exheader = build_invalid_extension_header(packet.IPPROTO_ICMPV6)
probe.ip6_nxt_hdr = packet.IPPROTO_DSTOPTS
probe:build_ipv6_packet()
probe:build_ether_frame()
try(dnet:ethernet_send(probe.frame_buf))
pcap:set_timeout(1000)
local pcap_timeout_count = 0
local nse_timeout = 5
local start_time = nmap:clock()
local cur_time = nmap:clock()
local found_targets = 0
repeat
local status, length, layer2, layer3 = pcap:pcap_receive()
cur_time = nmap:clock()
if not status then
pcap_timeout_count = pcap_timeout_count + 1
else
local reply = packet.Frame:new(layer2)
if reply.mac_dst == src_mac then
reply = packet.Packet:new(layer3)
local target_addr = reply.ip6_src
found_targets = found_targets + 1
local identifier = get_identifier(reply.ip6_src)
if not id_set[identifier] then
id_set[identifier] = true
local target_str = packet.toipv6(target_addr)
target.add(target_str)
end
end
end
until pcap_timeout_count >= 2 or cur_time - start_time >= nse_timeout
dnet:ethernet_close()
pcap:pcap_close()
return true
end