local http = require "http" local table = require "table" local shortport = require "shortport" local stdnse = require "stdnse" local slaxml = require "slaxml" local nmap = require "nmap" description = [[ Retrieve hardwares details and configuration information utilizing HNAP, the "Home Network Administration Protocol". It is an HTTP-Simple Object Access Protocol (SOAP)-based protocol which allows for remote topology discovery, configuration, and management of devices (routers, cameras, PCs, NAS, etc.)]] --- -- @usage -- nmap --script hnap-info -p80,8080 -- -- @output -- PORT STATE SERVICE REASON -- 8080/tcp open http-proxy syn-ack -- | hnap-info: -- | Type: GatewayWithWiFi -- | Device: Ingraham -- | Vendor: Linksys -- | Description: Linksys E1200 -- | Model: E1200 -- | Firmware: 1.0.00 build 11 -- | Presentation URL: http://192.168.1.1/ -- | SOAPACTIONS: -- | http://purenetworks.com/HNAP1/IsDeviceReady -- | http://purenetworks.com/HNAP1/GetDeviceSettings -- | http://purenetworks.com/HNAP1/SetDeviceSettings -- | http://purenetworks.com/HNAP1/GetDeviceSettings2 -- | http://purenetworks.com/HNAP1/SetDeviceSettings2 -- -- -- @xmloutput -- GatewayWithWiFi -- Ingraham -- Linksys -- Linksys E1200 -- E1200 -- 1.0.00 build 11 -- http://192.168.1.1/ -- -- http://purenetworks.com/HNAP1/IsDeviceReady -- http://purenetworks.com/HNAP1/GetDeviceSettings -- http://purenetworks.com/HNAP1/SetDeviceSettings -- http://purenetworks.com/HNAP1/GetDeviceSettings2 -- http://purenetworks.com/HNAP1/SetDeviceSettings2 --
----------------------------------------------------------------------- author = "Gyanendra Mishra" license = "Same as Nmap--See https://nmap.org/book/man-legal.html" categories = { "safe", "discovery", "default", } portrule = shortport.http local ELEMENTS = {["Type"] = "Type", ["DeviceName"] = "Device", ["VendorName"] = "Vendor", ["ModelDescription"] = "Description", ["ModelName"] = "Model", ["FirmwareVersion"] = "Firmware", ["PresentationURL"] = "Presentation URL", ["string"] = "SOAPACTIONS", ["SubDeviceURLs"] = "Sub Device URLs"} function get_text_callback(store, name) if ELEMENTS[name] == nil then return end name = ELEMENTS[name] if name == 'SOAPACTIONS' or name == 'Sub Device URLs' or name == 'Type' then return function(content) store[name] = store[name] or {} table.insert(store[name], content) end else return function(content) store[name] = content end end end function action (host, port) -- Identify servers that answer 200 to invalid HTTP requests and exit as these would invalidate the tests local status_404, result_404, _ = http.identify_404(host,port) if ( status_404 and result_404 == 200 ) then stdnse.debug1("Exiting due to ambiguous response from web server on %s:%s. All URIs return status 200.", host.ip, port.number) return nil end local output = stdnse.output_table() local response = http.get(host, port, '/HNAP1') if response.status and response.status == 200 then local parser = slaxml.parser:new() parser._call = {startElement = function(name) parser._call.text = get_text_callback(output, name) end, closeElement = function(name) parser._call.text = function() return nil end end } parser:parseSAX(response.body, {stripWhitespace=true}) -- exit if the parser does not return output if not next(output) then return nil end -- set the port verson port.version.name = "hnap" port.version.name_confidence = 10 port.version.product = output["Description"] or nil port.version.version = output["Model"] or nil port.version.devicetype = output["Type"] and output["Type"][1] or nil port.version.cpe = port.version.cpe or {} if output["Vendor"] and output["Model"] then table.insert(port.version.cpe, "cpe:/h:".. output["Vendor"]:lower() .. ":" .. output["Model"]:lower()) end nmap.set_port_version(host, port, "hardmatched") return output end end