diff --git a/CHANGELOG b/CHANGELOG index 99c2cd653..1af61ef27 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ #Nmap Changelog ($Id$); -*-text-*- +o [GH#2468] Scripts dhcp-discover and broadcast-dhcp-discover now support + setting a client identifier. [nnposter] + o [GH#2331][GH#2471] Script oracle-tns-version was not reporting the version correctly for Oracle 19c or newer [linholmes] diff --git a/scripts/broadcast-dhcp-discover.nse b/scripts/broadcast-dhcp-discover.nse index 37bb82cca..2375c9a93 100644 --- a/scripts/broadcast-dhcp-discover.nse +++ b/scripts/broadcast-dhcp-discover.nse @@ -61,10 +61,21 @@ The script needs to be run as a privileged user, typically root. -- is used by default. Setting it to random will -- possibly cause the DHCP server to reserve a new IP address -- each time. +-- @args broadcast-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 broadcast-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 broadcast-dhcp-discover.timeout time in seconds to wait for a response -- (default: 10s) -- +-- Created 04/22/2022 - v0.3 - updated by nnposter +-- o Implemented script arguments "clientid" and "clientid-hex" to allow +-- passing a specific client identifier (option 61) +-- -- Created 01/14/2020 - v0.2 - updated by nnposter -- o Implemented script argument "mac" to force a specific MAC address -- @@ -112,10 +123,12 @@ end -- Listens for an incoming dhcp response -- -- @param iface string with the name of the interface to listen to +-- @param macaddr client hardware address +-- @param options DHCP options to include in the request -- @param timeout number of ms to wait for a response -- @param xid the DHCP transaction id -- @param result a table to which the result is written -local function dhcp_listener(sock, iface, macaddr, timeout, xid, result) +local function dhcp_listener(sock, iface, macaddr, options, timeout, xid, result) local condvar = nmap.condvar(result) local srcip = ipOps.ip_to_str("0.0.0.0") local dstip = ipOps.ip_to_str("255.255.255.255") @@ -125,7 +138,7 @@ local function dhcp_listener(sock, iface, macaddr, timeout, xid, result) dhcp.request_types.DHCPDISCOVER, srcip, macaddr, - nil, -- options + options, nil, -- request options {flags=0x8000}, -- override: broadcast nil, -- lease time @@ -197,6 +210,8 @@ action = function() local timeout = stdnse.parse_timespec(stdnse.get_script_args("broadcast-dhcp-discover.timeout")) timeout = (timeout or 10) * 1000 + local options = {} + local macaddr = (stdnse.get_script_args(SCRIPT_NAME .. ".mac") or "DE:AD:C0:DE:CA:FE"):lower() if macaddr:find("^ra?nd") then macaddr = rand.random_string(6) @@ -208,6 +223,26 @@ action = function() macaddr = stdnse.fromhex(macaddr) end + local clientid = stdnse.get_script_args(SCRIPT_NAME .. ".clientid") + if clientid then + clientid = "\x00" .. clientid -- hardware type 0 presumed + else + clientid = stdnse.get_script_args(SCRIPT_NAME .. ".clientid-hex") + if clientid then + clientid = clientid:gsub(":", "") + if not clientid:find("^%x+$") then + return stdnse.format_output(false, "Invalid hexadecimal client ID") + end + clientid = stdnse.fromhex(clientid) + end + end + if clientid then + if #clientid == 0 or #clientid > 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 interfaces -- first check if the user supplied an interface @@ -237,7 +272,7 @@ action = function() local sock, co sock = nmap.new_socket() sock:pcap_open(iface, 1500, false, "ip && udp dst port 68") - co = stdnse.new_thread( dhcp_listener, sock, iface, macaddr, timeout, xid, result ) + co = stdnse.new_thread( dhcp_listener, sock, iface, macaddr, options, timeout, xid, result ) threads[co] = true end diff --git a/scripts/dhcp-discover.nse b/scripts/dhcp-discover.nse index 856266368..d78ce7d7c 100644 --- a/scripts/dhcp-discover.nse +++ b/scripts/dhcp-discover.nse @@ -45,6 +45,13 @@ Some of the more useful fields: -- 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). -- @@ -74,6 +81,10 @@ Some of the more useful fields: -- -- +-- +-- 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 @@ -123,6 +134,7 @@ action = function(host, port) 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() @@ -152,11 +164,31 @@ action = function(host, port) macaddr_iter = function () return macaddr end end + local clientid = stdnse.get_script_args(SCRIPT_NAME .. ".clientid") + if clientid then + clientid = "\x00" .. clientid -- hardware type 0 presumed + else + clientid = stdnse.get_script_args(SCRIPT_NAME .. ".clientid-hex") + if clientid then + clientid = clientid:gsub(":", "") + if not clientid:find("^%x+$") then + return stdnse.format_output(false, "Invalid hexadecimal client ID") + end + clientid = stdnse.fromhex(clientid) + end + end + if clientid then + if #clientid == 0 or #clientid > 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, nil, nil, overrides) + 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