mirror of
https://github.com/nmap/nmap.git
synced 2025-12-10 09:49:05 +00:00
o [NSE] Added the script broadcast-dhcp-discover that sends a DHCP discover
message to the broadcast address and collects and reports the network information received from the DHCP server. [Patrik]
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added the script broadcast-dhcp-discover that sends a DHCP discover
|
||||||
|
message to the broadcast address and collects and reports the network
|
||||||
|
information received from the DHCP server. [Patrik]
|
||||||
|
|
||||||
o [NSE] Added the script smtp-brute that performs brute force password
|
o [NSE] Added the script smtp-brute that performs brute force password
|
||||||
auditing against SMTP servers. [Patrik]
|
auditing against SMTP servers. [Patrik]
|
||||||
|
|
||||||
|
|||||||
@@ -402,7 +402,31 @@ local function dhcp_send(interface, host, packet, transaction_id)
|
|||||||
return true, data
|
return true, data
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dhcp_build(request_type, ip_address, mac_address, request_options, overrides, lease_time, transaction_id)
|
--- Builds a DHCP packet
|
||||||
|
--
|
||||||
|
--@param request_type The type of request as an integer (use the <code>request_types</code> table at the
|
||||||
|
-- top of this file).
|
||||||
|
--@param ip_address Your ip address (as a dotted-decimal string). This tells the DHCP server where to
|
||||||
|
-- send the response. Setting it to "255.255.255.255" or "0.0.0.0" is generally acceptable (if not,
|
||||||
|
-- host.ip_src can work).
|
||||||
|
--@param mac_address Your mac address (as a string up to 16 bytes) where the server will send the response. Like
|
||||||
|
-- <code>ip_address</code>, setting to the broadcast address (FF:FF:FF:FF:FF:FF) is
|
||||||
|
-- common (host.mac_addr_src works).
|
||||||
|
--@param request_options [optional] The options to request from the server, as an array of integers. For the
|
||||||
|
-- acceptable options, see the <code>actions</code> table above or have a look at rfc2132.
|
||||||
|
-- Some DHCP servers (such as my Linksys WRT54g) will ignore this list and send whichever
|
||||||
|
-- information it wants. Default: all options marked as 'default' in the <code>actions</code>
|
||||||
|
-- table above are requested (the typical interesting ones) if no verbosity is given.
|
||||||
|
-- If any level of verbosity is on, get all types.
|
||||||
|
--@param overrides [optional] A table of overrides. If a field in the table matches a field in the DHCP
|
||||||
|
-- packet (see rfc2131 section 2 for a list of possible fields), the value in the table
|
||||||
|
-- will be sent instead of the default value.
|
||||||
|
--@param lease_time [optional] The lease time used when requestint an IP. Default: 1 second.
|
||||||
|
--@param transaction_id The identity of the transaction.
|
||||||
|
--
|
||||||
|
--@return status (true or false)
|
||||||
|
--@return The parsed response, as a table.
|
||||||
|
function dhcp_build(request_type, ip_address, mac_address, request_options, overrides, lease_time, transaction_id)
|
||||||
local packet = ''
|
local packet = ''
|
||||||
|
|
||||||
-- Set up the default overrides
|
-- Set up the default overrides
|
||||||
@@ -455,7 +479,7 @@ end
|
|||||||
--
|
--
|
||||||
--@param data The DHCP packet data. Any padding at the end of the packet will be ignored (by default,
|
--@param data The DHCP packet data. Any padding at the end of the packet will be ignored (by default,
|
||||||
-- DHCP packets are padded with \x00 bytes).
|
-- DHCP packets are padded with \x00 bytes).
|
||||||
local function dhcp_parse(data, transaction_id)
|
function dhcp_parse(data, transaction_id)
|
||||||
local pos = 1
|
local pos = 1
|
||||||
local result = {}
|
local result = {}
|
||||||
|
|
||||||
|
|||||||
197
scripts/broadcast-dhcp-discover.nse
Normal file
197
scripts/broadcast-dhcp-discover.nse
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
description = [[
|
||||||
|
Sends a DHCP request to the broadcast address (255.255.255.255) and reports
|
||||||
|
the results. The script uses a static MAC address (DE:AD:CO:DE:CA:FE) while
|
||||||
|
doing so in order to prevent scope exhaustion.
|
||||||
|
|
||||||
|
The script reads the response using pcap by opening a listening pcap socket
|
||||||
|
on all available ethernet interfaces that are reported up. If no response
|
||||||
|
has been received before the timeout has been reached (default 10 seconds)
|
||||||
|
the script will abort execution.
|
||||||
|
|
||||||
|
The script needs to be run as a privileged user, typically root.
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- sudo nmap --script broadcast-dhcp-discover
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- | broadcast-dhcp-discover:
|
||||||
|
-- | IP Offered: 192.168.1.114
|
||||||
|
-- | DHCP Message Type: DHCPOFFER
|
||||||
|
-- | 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: 192.168.1.1
|
||||||
|
-- |_ Domain Name: localdomain
|
||||||
|
--
|
||||||
|
-- @args broadcast-dhcp-discover.timeout time in seconds to wait for a response
|
||||||
|
-- (default: 10s)
|
||||||
|
--
|
||||||
|
|
||||||
|
-- Version 0.1
|
||||||
|
-- Created 07/14/2011 - v0.1 - created by Patrik Karlsson
|
||||||
|
|
||||||
|
author = "Patrik Karlsson"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"broadcast", "safe"}
|
||||||
|
|
||||||
|
prerule = function() return not( nmap.address_family() == "inet6") end
|
||||||
|
|
||||||
|
require 'dhcp'
|
||||||
|
require 'ipOps'
|
||||||
|
require 'packet'
|
||||||
|
|
||||||
|
-- Creates a random MAC address
|
||||||
|
--
|
||||||
|
-- @return mac_addr string containing a random MAC
|
||||||
|
local function randomizeMAC()
|
||||||
|
mac_addr = ""
|
||||||
|
for j=1, 6 do
|
||||||
|
mac_addr = mac_addr .. string.char(math.random(1, 255))
|
||||||
|
end
|
||||||
|
return mac_addr
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Gets a list of available interfaces based on link and up filters
|
||||||
|
--
|
||||||
|
-- @param link string containing the link type to filter
|
||||||
|
-- @param up string containing the interface status to filter
|
||||||
|
-- @return result table containing the matching interfaces
|
||||||
|
local function getInterfaces(link, up)
|
||||||
|
if( not(nmap.list_interfaces) ) then return end
|
||||||
|
local interfaces, err = nmap.list_interfaces()
|
||||||
|
local result
|
||||||
|
if ( not(err) ) then
|
||||||
|
for _, iface in ipairs(interfaces) do
|
||||||
|
if ( iface.link == link and iface.up == up ) then
|
||||||
|
result = result or {}
|
||||||
|
result[iface.device] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Listens for an incoming dhcp response
|
||||||
|
--
|
||||||
|
-- @param iface string with the name of the interface to listen to
|
||||||
|
-- @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(iface, timeout, xid, result)
|
||||||
|
local sock = nmap.new_socket()
|
||||||
|
local condvar = nmap.condvar(result)
|
||||||
|
|
||||||
|
sock:set_timeout(100)
|
||||||
|
sock:pcap_open(iface, 1500, false, "ip && udp && port 68")
|
||||||
|
|
||||||
|
local start_time = nmap.clock_ms()
|
||||||
|
while( nmap.clock_ms() - start_time < timeout ) do
|
||||||
|
local status, _, _, data = sock:pcap_receive()
|
||||||
|
-- abort, once another thread has picked up our response
|
||||||
|
if ( #result > 0 ) then
|
||||||
|
sock:close()
|
||||||
|
condvar "signal"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( status ) then
|
||||||
|
local p = packet.Packet:new( data, #data )
|
||||||
|
if ( p and p.udp_dport ) then
|
||||||
|
local data = data:sub(p.udp_offset + 9)
|
||||||
|
local status, response = dhcp.dhcp_parse(data, xid)
|
||||||
|
if ( status ) then
|
||||||
|
table.insert( result, response )
|
||||||
|
sock:close()
|
||||||
|
condvar "signal"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sock:close()
|
||||||
|
condvar "signal"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
action = function()
|
||||||
|
|
||||||
|
if not nmap.is_privileged() then
|
||||||
|
return ("\n ERROR: %s needs to be run as a privileged user (root)."):format(SCRIPT_NAME)
|
||||||
|
end
|
||||||
|
|
||||||
|
local host, port = "255.255.255.255", 67
|
||||||
|
local timeout = stdnse.get_script_args("broadcast-dhcp-discover.timeout")
|
||||||
|
timeout = tonumber(timeout) or 10
|
||||||
|
|
||||||
|
-- convert from seconds to ms
|
||||||
|
timeout = timeout * 1000
|
||||||
|
|
||||||
|
-- randomizing the MAC could exhaust dhcp servers with small scopes
|
||||||
|
-- if ran multiple times, so we should probably refrain from doing
|
||||||
|
-- this?
|
||||||
|
local mac = string.char(0xDE,0xAD,0xC0,0xDE,0xCA,0xFE)--randomizeMAC()
|
||||||
|
|
||||||
|
local interfaces
|
||||||
|
|
||||||
|
-- first check if the user supplied an interface
|
||||||
|
if ( nmap.get_interface() ) then
|
||||||
|
interfaces = { [nmap.get_interface()] = true }
|
||||||
|
else
|
||||||
|
-- As the response will be sent to the "offered" ip address we need
|
||||||
|
-- to use pcap to pick it up. However, we don't know what interface
|
||||||
|
-- our packet went out on, so lets get a list of all interfaces and
|
||||||
|
-- run pcap on all of them, if they're a) up and b) ethernet.
|
||||||
|
interfaces = getInterfaces("ethernet", "up")
|
||||||
|
end
|
||||||
|
|
||||||
|
if( not(interfaces) ) then return "\n ERROR: Failed to retrieve interfaces (try setting one explicitly using -e)" end
|
||||||
|
|
||||||
|
local transaction_id = bin.pack("<I", math.random(0, 0x7FFFFFFF))
|
||||||
|
local request_type = dhcp.request_types["DHCPDISCOVER"]
|
||||||
|
local ip_address = bin.pack(">I", ipOps.todword("0.0.0.0"))
|
||||||
|
|
||||||
|
-- we nead to set the flags to broadcast
|
||||||
|
local request_options, overrides, lease_time = nil, { flags = 0x8000 }, nil
|
||||||
|
local status, packet = dhcp.dhcp_build(request_type, ip_address, mac, request_options, overrides, lease_time, transaction_id)
|
||||||
|
if (not(status)) then return "\n ERROR: Failed to build packet" end
|
||||||
|
|
||||||
|
local socket = nmap.new_socket("udp")
|
||||||
|
socket:bind(nil, 68)
|
||||||
|
socket:sendto( host, port, packet )
|
||||||
|
socket:close()
|
||||||
|
|
||||||
|
local threads = {}
|
||||||
|
local result = {}
|
||||||
|
local condvar = nmap.condvar(result)
|
||||||
|
|
||||||
|
-- start a listening thread for each interface
|
||||||
|
for iface, _ in pairs(interfaces) do
|
||||||
|
local co = stdnse.new_thread( dhcp_listener, iface, timeout, transaction_id, result )
|
||||||
|
threads[co] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- wait until all threads are done
|
||||||
|
repeat
|
||||||
|
condvar "wait"
|
||||||
|
for thread in pairs(threads) do
|
||||||
|
if coroutine.status(thread) == "dead" then threads[thread] = nil end
|
||||||
|
end
|
||||||
|
until next(threads) == nil
|
||||||
|
|
||||||
|
local response = {}
|
||||||
|
-- Display the results
|
||||||
|
for i, r in ipairs(result) do
|
||||||
|
table.insert(response, string.format("IP Offered: %s", r.yiaddr_str))
|
||||||
|
for _, v in ipairs(r.options) do
|
||||||
|
if(type(v['value']) == 'table') then
|
||||||
|
table.insert(response, string.format("%s: %s", v['name'], stdnse.strjoin(", ", v['value'])))
|
||||||
|
else
|
||||||
|
table.insert(response, string.format("%s: %s\n", v['name'], v['value']))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return stdnse.format_output(true, response)
|
||||||
|
end
|
||||||
@@ -11,6 +11,7 @@ Entry { filename = "backorifice-info.nse", categories = { "default", "discovery"
|
|||||||
Entry { filename = "banner.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "banner.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "broadcast-avahi-dos.nse", categories = { "broadcast", "dos", "intrusive", "vuln", } }
|
Entry { filename = "broadcast-avahi-dos.nse", categories = { "broadcast", "dos", "intrusive", "vuln", } }
|
||||||
Entry { filename = "broadcast-db2-discover.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-db2-discover.nse", categories = { "broadcast", "safe", } }
|
||||||
|
Entry { filename = "broadcast-dhcp-discover.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-dns-service-discovery.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-dns-service-discovery.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-dropbox-listener.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-dropbox-listener.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-ms-sql-discover.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-ms-sql-discover.nse", categories = { "broadcast", "safe", } }
|
||||||
|
|||||||
Reference in New Issue
Block a user