From 0d47952611198ef6b1163f366dc03922d20b1475 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 09:42:04 +0200 Subject: Adding upstream version 7.94+git20230807.3be01efb1+dfsg. Signed-off-by: Daniel Baumann --- scripts/dhcp-discover.nse | 228 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 scripts/dhcp-discover.nse (limited to 'scripts/dhcp-discover.nse') diff --git a/scripts/dhcp-discover.nse b/scripts/dhcp-discover.nse new file mode 100644 index 0000000..d78ce7d --- /dev/null +++ b/scripts/dhcp-discover.nse @@ -0,0 +1,228 @@ +local dhcp = require "dhcp" +local rand = require "rand" +local nmap = require "nmap" +local outlib = require "outlib" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local ipOps = require "ipOps" + +description = [[ +Sends a DHCPINFORM request to a host on UDP port 67 to obtain all the local configuration parameters +without allocating a new address. + +DHCPINFORM is a DHCP request that returns useful information from a DHCP server, without allocating an IP +address. The request sends a list of which fields it wants to know (a handful by default, every field if +verbosity is turned on), and the server responds with the fields that were requested. It should be noted +that the server doesn't have to return every field, nor does it have to return them in the same order, +or honour the request at all. A Linksys WRT54g, for example, completely ignores the list of requested +fields and returns a few standard ones. This script displays every field it receives. + +With script arguments, the type of DHCP request can be changed, which can lead to interesting results. +Additionally, the MAC address can be randomized, which in should override the cache on the DHCP server and +assign a new IP address. Extra requests can also be sent to exhaust the IP address range more quickly. + +Some of the more useful fields: +* DHCP Server (the address of the server that responded) +* Subnet Mask +* Router +* DNS Servers +* Hostname +]] + +--- +-- @see broadcast-dhcp6-discover.nse +-- @see broadcast-dhcp-discover.nse +-- +-- @args dhcp-discover.dhcptype The type of DHCP request to make. By default, +-- DHCPINFORM is sent, but this argument can change it to DHCPOFFER, +-- DHCPREQUEST, DHCPDECLINE, DHCPACK, DHCPNAK, DHCPRELEASE or +-- DHCPINFORM. Not all types will evoke a response from all servers, +-- and many require different fields to contain specific values. +-- @args dhcp-discover.mac Set to native (default) or +-- random or a specific client MAC address in the DHCP +-- request. Keep in mind that you may not see the response if +-- a non-native address is used. Setting it to random will +-- possibly cause the DHCP server to reserve a new IP address each time. +-- @args dhcp-discover.clientid Client identifier to use in DHCP option 61. +-- The value is a string, while hardware type 0, appropriate for FQDNs, +-- is assumed. Example: clientid=kurtz is equivalent to specifying +-- clientid-hex=00:6b:75:72:74:7a (see below). +-- @args dhcp-discover.clientid-hex Client identifier to use in DHCP option 61. +-- The value is a hexadecimal string, where the first octet is +-- the hardware type. +-- @args dhcp-discover.requests Set to an integer to make up to that many +-- requests (and display the results). +-- +-- @usage +-- nmap -sU -p 67 --script=dhcp-discover +-- @output +-- Interesting ports on 192.168.1.1: +-- PORT STATE SERVICE +-- 67/udp open dhcps +-- | dhcp-discover: +-- | DHCP Message Type: DHCPACK +-- | Server Identifier: 192.168.1.1 +-- | IP Address Lease Time: 1 day, 0:00:00 +-- | Subnet Mask: 255.255.255.0 +-- | Router: 192.168.1.1 +-- |_ Domain Name Server: 208.81.7.10, 208.81.7.14 +-- +-- @xmloutput +-- DHCPACK +-- 192.168.1.1 +-- 1 day, 0:00:00 +-- 255.255.255.0 +-- 192.168.1.1 +-- +-- 208.81.7.10 +-- 208.81.7.14 +--
+-- + +-- +-- 2022-04-22 - Revised by nnposter +-- o Implemented script arguments "clientid" and "clientid-hex" to allow +-- passing a specific client identifier (option 61) +-- +-- 2020-01-14 - Revised by nnposter +-- o Added script argument "mac" to prescribe a specific MAC address +-- o Deprecated argument "randomize_mac" in favor of "mac=random" +-- +-- 2011-12-28 - Revised by Patrik Karlsson +-- o Removed DoS code and placed script into discovery and safe categories +-- +-- 2011-12-27 - Revised by Patrik Karlsson +-- o Changed script to use DHCPINFORM instead of DHCPDISCOVER +-- + + +author = "Ron Bowes" + +license = "Same as Nmap--See https://nmap.org/book/man-legal.html" + +categories = {"discovery", "safe"} + + +-- We want to run against a specific host if UDP/67 is open +function portrule(host, port) + if nmap.address_family() ~= 'inet' then + stdnse.debug1("is IPv4 compatible only.") + return false + end + + return shortport.portnumber(67, "udp")(host, port) +end + +action = function(host, port) + local dhcptype = (stdnse.get_script_args(SCRIPT_NAME .. ".dhcptype") or "DHCPINFORM"):upper() + local dhcptypeid = dhcp.request_types[dhcptype] + if not dhcptypeid then + return stdnse.format_output(false, "Invalid request type (use " + .. table.concat(dhcp.request_types_str, " / ") + .. ")") + end + + local reqcount = tonumber(stdnse.get_script_args(SCRIPT_NAME .. ".requests") or 1) + if not reqcount then + return stdnse.format_output(false, "Invalid request count") + end + + local iface, err = nmap.get_interface_info(host.interface) + if not (iface and iface.address) then + return stdnse.format_output(false, "Couldn't determine local IP for interface: " .. host.interface) + end + + local options = {} + local overrides = {} + + local macaddr = (stdnse.get_script_args(SCRIPT_NAME .. ".mac") or "native"):lower() + -- Support for legacy argument "randomize_mac" + local randomize = (stdnse.get_script_args(SCRIPT_NAME .. ".randomize_mac") or "false"):lower() + if randomize == "true" or randomize == "1" then + stdnse.debug1("Use %s.mac=random instead of %s.randomize_mac=%s", SCRIPT_NAME, SCRIPT_NAME, randomize) + macaddr = "random" + end + if macaddr ~= "native" then + -- Set the scanner as a relay agent + overrides.giaddr = string.unpack(" 255 then + return stdnse.format_output(false, "Client ID must be between 1 and 255 characters long") + end + table.insert(options, {number = 61, type = "string", value = clientid }) + end + + local results = {} + for i = 1, reqcount do + local macaddr = macaddr_iter() + stdnse.debug1("Client MAC address: %s", stdnse.tohex(macaddr, {separator = ":"})) + local status, result = dhcp.make_request(host.ip, dhcptypeid, iface.address, macaddr, options, nil, overrides) + if not status then + return stdnse.format_output(false, "Couldn't send DHCP request: " .. result) + end + table.insert(results, result) + end + + if #results == 0 then + return nil + end + + nmap.set_port_state(host, port, "open") + + local response = stdnse.output_table() + + -- Display the results + for i, result in ipairs(results) do + local result_table = stdnse.output_table() + + if dhcptype ~= "DHCPINFORM" then + result_table["IP Offered"] = result.yiaddr_str + end + for _, v in ipairs(result.options) do + if type(v.value) == 'table' then + outlib.list_sep(v.value) + end + result_table[ v.name ] = v.value + end + + if(#results == 1) then + response = result_table + else + response[string.format("Response %d of %d", i, #results)] = result_table + end + end + + return response +end -- cgit v1.2.3