mirror of
https://github.com/nmap/nmap.git
synced 2026-01-05 22:19:03 +00:00
o [NSE] Changed the dhcp-discover script to use the DHCPINFORM request to query
dhcp servers instead of DHCPDISCOVER. Cleaned up some code in the DHCP library. [Patrik]
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE] Changed the dhcp-discover script to use the DHCPINFORM request to query
|
||||
dhcp servers instead of DHCPDISCOVER. Cleaned up some code in the DHCP
|
||||
library. [Patrik]
|
||||
|
||||
o [NSE] Added script dns-blacklist that performs DNSBL checks of given or
|
||||
scanned IP addresses against multiple DNSBL services. [Patrik]
|
||||
|
||||
|
||||
@@ -359,44 +359,33 @@ local function dhcp_send(interface, host, packet, transaction_id)
|
||||
local result
|
||||
local results = {}
|
||||
|
||||
|
||||
local bind_socket = nmap.new_socket("udp")
|
||||
bind_socket:bind(nil, 68)
|
||||
bind_socket:set_timeout(5000)
|
||||
stdnse.print_debug(1, "dhcp: Starting listener")
|
||||
|
||||
-- Create the UDP socket (TODO: enable SO_BROADCAST if we need to)
|
||||
socket = nmap.new_socket()
|
||||
status, err = socket:connect(host, 67, "udp")
|
||||
socket = nmap.new_socket("udp")
|
||||
socket:bind(nil, 68)
|
||||
socket:set_timeout(5000)
|
||||
-- status, err = socket:connect(host, 67, "udp")
|
||||
if(status == false) then
|
||||
return false, "Couldn't create socket: " .. err
|
||||
end
|
||||
stdnse.print_debug(1, "dhcp: Created UDP socket")
|
||||
|
||||
-- Send out the packet
|
||||
socket:send(packet)
|
||||
socket:sendto(host, { number=67, protocol="udp" }, packet)
|
||||
|
||||
-- Read the response
|
||||
local status, data = bind_socket:receive()
|
||||
local status, data = socket:receive()
|
||||
if ( not(status) ) then
|
||||
return false, data
|
||||
end
|
||||
|
||||
-- This pulls back 4 bytes in the packet that correspond to the transaction id. This should be randomly
|
||||
-- generated and different for every instance of a script (to prevent collisions)
|
||||
while status and data:sub(5, 8) ~= transaction_id do
|
||||
local status, data = bind_socket:receive()
|
||||
end
|
||||
if(status == false) then
|
||||
stdnse.print_debug(1, "dhcp: Error calling bind_socket:receive(): %s", err)
|
||||
return false, "Error calling bind_socket:receive(): " .. err
|
||||
while status and data:sub(5, 8) ~= transaction_id do
|
||||
local status, data = socket:receive()
|
||||
end
|
||||
|
||||
-- If no data was captured (ie, a timeout), return an error
|
||||
if(data == nil) then
|
||||
stdnse.print_debug(1, "dhcp: Error calling pcap_receive(): TIMEOUT")
|
||||
return false, "TIMEOUT"
|
||||
end
|
||||
|
||||
|
||||
-- Close our sockets
|
||||
socket:close()
|
||||
bind_socket:close()
|
||||
|
||||
-- Finally, return the data
|
||||
return true, data
|
||||
@@ -625,7 +614,7 @@ function make_request(target, interface, request_type, ip_address, mac_address,
|
||||
local status, response = dhcp_send(interface, target, packet, transaction_id)
|
||||
if(not(status)) then
|
||||
stdnse.print_debug(1, "dhcp: Couldn't send packet: " .. response)
|
||||
return false, "Couldn't send packet: " .. response
|
||||
return false, "Couldn't send/receive packet: " .. response
|
||||
end
|
||||
|
||||
-- Parse the response
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
description = [[
|
||||
Sends a DHCPDISCOVER request to a host on UDP port 67. The response
|
||||
comes back to UDP port 68, and
|
||||
is read using pcap (due to the inability for a script to choose its source port at the moment).
|
||||
Sends a DHCPINFORM request to a host on UDP port 67 to obtain all the local configuration parameters
|
||||
without allocating a new address.
|
||||
|
||||
DHCPDISCOVER is a DHCP request that returns useful information from a DHCP server. 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.
|
||||
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 should override the cache on the DHCP server and
|
||||
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.
|
||||
|
||||
DHCPINFORM is another type of DHCP request that requests the same information, but doesn't reserve
|
||||
an address. Unfortunately, because many home routers simply ignore DHCPINFORM requests, we opted
|
||||
to use DHCPDISCOVER instead.
|
||||
|
||||
Some of the more useful fields:
|
||||
* DHCP Server (the address of the server that responded)
|
||||
* Subnet Mask
|
||||
@@ -76,19 +71,7 @@ function portrule(host, port)
|
||||
return shortport.portnumber(67, "udp")(host, port)
|
||||
end
|
||||
|
||||
-- We will want to run as a prerule any time
|
||||
--prerule = function()
|
||||
-- return true
|
||||
--end
|
||||
|
||||
local function go(host, port)
|
||||
-- Set up a fake host for prerule
|
||||
if(not(host)) then
|
||||
host = {}
|
||||
host.mac_addr_src = string.char(0xFF) .. string.char(0xFF) .. string.char(0xFF) .. string.char(0xFF) .. string.char(0xFF) .. string.char(0xFF)
|
||||
host.ip = "255.255.255.255"
|
||||
host.interface = "eth0" -- TODO: I'd like to have a better way of doing this
|
||||
end
|
||||
|
||||
-- Create fake requests if the user asked to. These are fired and forgotten, we ignore the responses.
|
||||
if(nmap.registry.args.fake_requests) then
|
||||
@@ -122,7 +105,7 @@ local function go(host, port)
|
||||
local results = {}
|
||||
for i = 1, requests, 1 do
|
||||
-- Decide which type of request to make
|
||||
local request_type = dhcp.request_types[nmap.registry.args.dhcptype or "DHCPDISCOVER"]
|
||||
local request_type = dhcp.request_types[nmap.registry.args.dhcptype or "DHCPINFORM"]
|
||||
if(request_type == nil) then
|
||||
return false, "Valid request types: " .. stdnse.strjoin(", ", dhcp.request_types_str)
|
||||
end
|
||||
@@ -136,12 +119,16 @@ local function go(host, port)
|
||||
mac_addr = mac_addr .. string.char(math.random(1, 255))
|
||||
end
|
||||
end
|
||||
|
||||
-- Receive the result
|
||||
local status, result = dhcp.make_request(host.ip, host.interface, request_type, "0.0.0.0", mac_addr)
|
||||
if(status == false) then
|
||||
|
||||
local iface, err = nmap.get_interface_info(host.interface)
|
||||
if ( not(iface) or not(iface.address) ) then
|
||||
return false, "Couldn't determine local ip for interface: " .. host.interface
|
||||
end
|
||||
|
||||
local status, result = dhcp.make_request(host.ip, host.interface, request_type, iface.address, mac_addr)
|
||||
if( not(status) ) then
|
||||
stdnse.print_debug(1, "dhcp-discover: Couldn't send DHCP request: %s", result)
|
||||
return false, "Couldn't send DHCP request: " .. result
|
||||
return false, result
|
||||
end
|
||||
|
||||
table.insert(results, result)
|
||||
@@ -174,7 +161,10 @@ action = function(host, port)
|
||||
for i, result in ipairs(results) do
|
||||
local result_table = {}
|
||||
|
||||
table.insert(result_table, string.format("IP Offered: %s", result.yiaddr_str))
|
||||
if ( nmap.registry.args.dhcptype and
|
||||
"DHCPINFORM" ~= nmap.registry.args.dhcptype ) then
|
||||
table.insert(result_table, string.format("IP Offered: %s", result.yiaddr_str))
|
||||
end
|
||||
for _, v in ipairs(result.options) do
|
||||
if(type(v['value']) == 'table') then
|
||||
table.insert(result_table, string.format("%s: %s", v['name'], stdnse.strjoin(", ", v['value'])))
|
||||
|
||||
Reference in New Issue
Block a user