NSE LIB

Back to library
Official safe Broadcast

broadcast-sonicwall-discover

Discovers Sonicwall firewalls which are directly attached (not routed) using the same method as the manufacturers own 'SetupTool'. An interface needs to be configured, as the script broadcasts a UDP packet.

Ports

Any

Protocols

n/a

Attribution

Nmap Project

Usage

Copy the command and adjust the target or script arguments as needed.

nmap -e eth0 --script broadcast-sonicwall-discover
Script Source Toggle

The full script source is stored with this entry and is hidden by default to keep the page easier to scan.

local ipOps = require "ipOps"
local nmap = require "nmap"
local packet = require "packet"
local stdnse = require "stdnse"
local string = require "string"
local target = require "target"

description = [[
Discovers Sonicwall firewalls which are directly attached (not routed) using
the same method as the manufacturers own 'SetupTool'. An interface needs to be
configured, as the script broadcasts a UDP packet.

The script needs to be run as a privileged user, typically root.

References:
* https://support.software.dell.com/kb/sw3677)
]]

---
-- @usage
-- nmap -e eth0 --script broadcast-sonicwall-discover
--
-- @output
-- | broadcast-sonicwall-discover:
-- |   192.168.5.1
-- |     MAC/Serial: 0006B1001122
-- |     Subnetmask: 255.255.255.0
-- |     Firmware: 3.9.1.2
-- |_    ROM: 14.0.1.1
--
-- @args broadcast-sonicwall-discover.timeout time in seconds to wait for a response
--       (default: 1s)

author = "Raphael Hoegger"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"broadcast", "safe"}


prerule = function()
  if not nmap.is_privileged() then
    stdnse.verbose1("Not running for lack of privileges.")
    return false
  end
  if nmap.address_family() ~= "inet" then
    stdnse.verbose1("Script is IPv4-only")
    return false
  end
  return true
end

action = function(host, port)
  -- preliminary checks
  local interface
  local collect_interface = function (if_table)
    if not interface and if_table.up == "up" and
      if_table.address and if_table.address:match("^%d+%.%d+%.%d+%.%d+$") then
      interface = if_table.device
    end
  end
  stdnse.get_script_interfaces(collect_interface)

  if not interface then
    stdnse.verbose1("No network interface was supplied, aborting.")
    return false
  end
  local sock, co
  sock = nmap.new_socket()

  local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout"))
  timeout = (timeout or 1) * 1000

  -- listen for a response
  sock:set_timeout(timeout)
  sock:pcap_open(interface, 1500, false, "ip && udp && port 26214 && greater 57")
  send_discover()

  local start_time = nmap.clock_ms()
  local results = stdnse.output_table()
  while( nmap.clock_ms() - start_time < timeout ) do
    local status, plen, _, layer3 = sock:pcap_receive()
    -- stop once we picked up our response
    if ( status ) then
      sock:close()
      local p = packet.Packet:new( layer3, #layer3)

      if ( p and p.udp_dport ) then
        -- parsing the result
        local IP = string.sub(layer3:sub(41), 0,4)
        IP = ipOps.str_to_ip(IP)
        local Netmask = string.sub(layer3:sub(45), 0,4)
        Netmask = ipOps.str_to_ip(Netmask)
        local Serial = string.sub(layer3:sub(49), 0,6)
        Serial = stdnse.tohex(Serial)
        local Romversion = string.sub(layer3:sub(55), 0,2)
        local ROMM = stdnse.tohex(Romversion, {separator=".", group=1})
        ROMM = string.gsub(ROMM, "[0-9a-f]", function(n) return tonumber(n, 16) end)
        local Firmwareversion = string.sub(layer3:sub(57), 0,2)
        local FIRMM = stdnse.tohex(Firmwareversion, {separator=".", group=1})
        FIRMM = string.gsub(FIRMM, "[0-9a-f]", function(n) return tonumber(n, 16) end)

        -- add nodes
        if target.ALLOW_NEW_TARGETS then
          target.add(IP)
        end

        local output = stdnse.output_table()
        output['MAC/Serial'] = Serial
        output['Subnetmask'] = Netmask
        output['Firmware'] = FIRMM
        output['ROM Version'] = ROMM
        results[IP] = output
      end
    end
    sock:close()
  end
  if #results > 0 then
    return results
  end
end

function send_discover()
  local host="255.255.255.255"
  local port="26214"
  local socket = nmap.new_socket("udp")

  local status = socket:sendto(host, port, "ackfin ping\00")
  if not status then return end
  socket:close()

  return true
end

Overview

Discovers Sonicwall firewalls which are directly attached (not routed) using the same method as the manufacturers own ‘SetupTool’. An interface needs to be configured, as the script broadcasts a UDP packet. The script needs to be run as a privileged user, typically root.