mirror of
https://github.com/nmap/nmap.git
synced 2025-12-08 05:31:31 +00:00
Added the script http-waf-fingerprint which tries to detect the presence of a web application firewall and its type and version.
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE] Added the script http-waf-fingerprint which tries to detect the presence of
|
||||
a web application firewall and its type and version. [Hani Benhabiles]
|
||||
|
||||
o [NSE] More Windows 7 and Windows 2008 fixes for the smb library and smb-ls
|
||||
scripts. [Patrik Karlsson]
|
||||
|
||||
|
||||
605
scripts/http-waf-fingerprint.nse
Normal file
605
scripts/http-waf-fingerprint.nse
Normal file
@@ -0,0 +1,605 @@
|
||||
local http = require "http"
|
||||
local stdnse = require "stdnse"
|
||||
local shortport = require "shortport"
|
||||
local string = require "string"
|
||||
local url = require "url"
|
||||
|
||||
description = [[
|
||||
Tries to detect the presence of web application firewall and its type and version.
|
||||
|
||||
This works by sending a number of requests and looking in the responses for known behavior and fingerprints
|
||||
such as Server header, cookies and headers values.
|
||||
]]
|
||||
|
||||
---
|
||||
-- @args http-waf-fingerprint.root The base path. Defaults to <code>/</code>.
|
||||
--
|
||||
-- @usage
|
||||
-- nmap --script=http-waf-fingerprint <targets>
|
||||
--
|
||||
--@output
|
||||
--PORT STATE SERVICE REASON
|
||||
--80/tcp open http syn-ack
|
||||
--| http-waf-fingerprint:
|
||||
--| Detected firewalls
|
||||
--|_ BinarySec version 3.2.2
|
||||
|
||||
author = "Hani Benhabiles"
|
||||
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
categories = {"discovery", "intrusive"}
|
||||
|
||||
--
|
||||
-- Version 0.1:
|
||||
-- - Initial version based on work done with wafw00f.
|
||||
-- - Removed many false positives.
|
||||
-- - Added fingeprints for WAFs such as Incapsula WAF, Cloudflare, USP-SES ,Cisco ACE XML Gateway and ModSecurity.
|
||||
-- - Added fingerprints and version detection for Webknight and BinarySec, Citrix Netscaler and ModSecurity
|
||||
--
|
||||
--
|
||||
-- TODO: Fingerprints for other WAFs
|
||||
-- Add intensive mode (WAF specific requests)
|
||||
--
|
||||
|
||||
portrule = shortport.service("http")
|
||||
|
||||
-- Each WAF has a table with name, version and detected keys
|
||||
-- as well as a match function.
|
||||
-- HTTP Responses are passed to match function which will alter detected
|
||||
-- and version values after analyzing responses if adequate fingerprints
|
||||
-- are found.
|
||||
|
||||
local bigip
|
||||
bigip = {
|
||||
name = "F5 BigIP",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
|
||||
if response.header['x-cnection'] then
|
||||
stdnse.print_debug("%s BigIP detected through X-Cnection header.", SCRIPT_NAME)
|
||||
bigip.detected = true
|
||||
return
|
||||
end
|
||||
|
||||
if response.header.server == 'BigIP' then --
|
||||
stdnse.print_debug("%s BigIP detected through Server header.", SCRIPT_NAME)
|
||||
bigip.detected = true
|
||||
return
|
||||
end
|
||||
|
||||
for _, cookie in pairs(response.cookies) do --
|
||||
if string.find(cookie.name, "BIGipServer") then
|
||||
stdnse.print_debug("%s BigIP detected through cookies.", SCRIPT_NAME)
|
||||
bigip.detected = true
|
||||
return
|
||||
end
|
||||
-- Application Security Manager module
|
||||
if string.match(cookie.name, 'TS%w+') and string.len(cookie.name) <= 8 then
|
||||
stdnse.print_debug("%s F5 ASM detected through cookies.", SCRIPT_NAME)
|
||||
bigip.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local webknight
|
||||
webknight = {
|
||||
name = "Webknight",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for name, response in pairs(responses) do
|
||||
if response.header.server and string.find(response.header.server, 'WebKnight/') then --
|
||||
stdnse.print_debug("%s WebKnight detected through Server Header.", SCRIPT_NAME)
|
||||
webknight.version = string.sub(response.header.server, 11)
|
||||
webknight.detected = true
|
||||
return
|
||||
end
|
||||
if response.status == 999 then
|
||||
if not webknight.detected then stdnse.print_debug("%s WebKnight detected through 999 response status code.", SCRIPT_NAME) end
|
||||
webknight.detected = true
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local isaserver
|
||||
isaserver = {
|
||||
name = "ISA Server",
|
||||
detected = false,
|
||||
version = nil,
|
||||
-- TODO Check if version detection is possible
|
||||
-- based on the response reason
|
||||
reason = {"Forbidden %( The server denied the specified Uniform Resource Locator %(URL%). Contact the server administrator. %)",
|
||||
"Forbidden %( The ISA Server denied the specified Uniform Resource Locator %(URL%)"
|
||||
},
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
for _, reason in pairs(isaserver.reason) do --
|
||||
if http.response_contains(response, reason, true) then -- TODO Replace with something more performant
|
||||
stdnse.print_debug("%s ISA Server detected through response reason.", SCRIPT_NAME)
|
||||
isaserver.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local airlock
|
||||
airlock = {
|
||||
name = "Airlock",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
for _, cookie in pairs(response.cookies) do --
|
||||
-- TODO Check if version detection is possible
|
||||
-- based on the difference in cookies name
|
||||
if cookie.name == "AL_LB" and string.sub(cookie.value, 1, 4) == '$xc/' then
|
||||
stdnse.print_debug("%s Airlock detected through AL_LB cookies.", SCRIPT_NAME)
|
||||
airlock.detected = true
|
||||
return
|
||||
end
|
||||
if cookie.name == "AL_SESS" and (string.sub(cookie.value, 1, 5) == 'AAABL'
|
||||
or string.sub(cookie.value, 1, 5) == 'LgEAA' )then
|
||||
stdnse.print_debug("%s Airlock detected through AL_SESS cookies.", SCRIPT_NAME)
|
||||
airlock.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local barracuda
|
||||
barracuda = {
|
||||
name = "Barracuda",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
for _, cookie in pairs(response.cookies) do
|
||||
if cookie.name == "barra_counter_session" then
|
||||
stdnse.print_debug("%s Barracuda detected through cookies.", SCRIPT_NAME)
|
||||
barracuda.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local denyall
|
||||
denyall = {
|
||||
name = "Denyall",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
for _, cookie in pairs(response.cookies) do
|
||||
-- TODO Check accuracy
|
||||
if cookie.name == "sessioncookie" then
|
||||
stdnse.print_debug("%s Denyall detected through cookies.", SCRIPT_NAME)
|
||||
denyall.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local f5trafficshield
|
||||
f5trafficshield = {
|
||||
name = "F5 Traffic Shield",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
-- TODO Check for version detection possibility
|
||||
-- based on the cookie name / server header presence
|
||||
if response.header.server == "F5-TrafficShield" then
|
||||
stdnse.print_debug("%s F5 Traffic Shield detected through Server header.", SCRIPT_NAME)
|
||||
f5trafficshield.detected = true
|
||||
return
|
||||
end
|
||||
|
||||
for _, cookie in pairs(response.cookies) do
|
||||
if cookie.name == "ASINFO" then
|
||||
stdnse.print_debug("%s F5 Traffic Shield detected through cookies.", SCRIPT_NAME)
|
||||
f5trafficshield.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local teros
|
||||
teros = {
|
||||
name = "Teros / Citrix Application Firewall Enterprise", -- CAF EX, according to citrix documentation
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
for _, cookie in pairs(response.cookies) do
|
||||
if cookie.name == "st8id" or cookie.name == "st8_wat" or cookie.name == "st8_wlf" then
|
||||
stdnse.print_debug("%s Teros / CAF detected through cookies.", SCRIPT_NAME)
|
||||
teros.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local binarysec
|
||||
binarysec = {
|
||||
name = "BinarySec",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
if response.header.server and string.find(response.header.server, 'BinarySEC/') then --
|
||||
stdnse.print_debug("%s BinarySec detected through Server Header.", SCRIPT_NAME)
|
||||
binarysec.version = string.sub(response.header.server, 11)
|
||||
binarysec.detected = true
|
||||
return
|
||||
end
|
||||
if response.header['x-binarysec-via'] or response.header['x-binarysec-nocache']then
|
||||
if not binarysec.detected then stdnse.print_debug("%s BinarySec detected through header.", SCRIPT_NAME) end
|
||||
binarysec.detected = true
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local profense
|
||||
profense = {
|
||||
name = "Profense",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
if response.header.server == 'Profense' then
|
||||
stdnse.print_debug("%s Profense detected through Server header.", SCRIPT_NAME)
|
||||
profense.detected = true
|
||||
return
|
||||
end
|
||||
for _, cookie in pairs(response.cookies) do
|
||||
if cookie.name == "PLBSID" then
|
||||
stdnse.print_debug("%s Profense detected through cookies.", SCRIPT_NAME)
|
||||
profense.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local netscaler
|
||||
netscaler = {
|
||||
name = "Citrix Netscaler",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
|
||||
-- TODO Check for other version detection possibilities
|
||||
-- based on fingerprint difference
|
||||
if response.header.via and string.find(response.header.via, 'NS-CACHE') then --
|
||||
stdnse.print_debug("%s Citrix Netscaler detected through Via Header.", SCRIPT_NAME)
|
||||
netscaler.version = string.sub(response.header.via, 10, 12)
|
||||
netscaler.detected = true
|
||||
return
|
||||
end
|
||||
|
||||
if response.header.cneonction == "close" or response.header.nncoection == "close" then
|
||||
if not netscaler.detected then stdnse.print_debug("%s Netscaler detected through Cneoction/nnCoection header.", SCRIPT_NAME) end
|
||||
netscaler.detected = true
|
||||
end
|
||||
|
||||
-- TODO Does X-CLIENT-IP apply to Citrix Application Firewall too ?
|
||||
if response.header['x-client-ip'] then
|
||||
if not netscaler.detected then stdnse.print_debug("%s Netscaler detected through X-CLIENT-IP header.", SCRIPT_NAME) end
|
||||
netscaler.detected = true
|
||||
end
|
||||
|
||||
for _, cookie in pairs(response.cookies) do
|
||||
if cookie.name == "ns_af" or cookie.name == "citrix_ns_id" or
|
||||
string.find(cookie.name, "NSC_") then
|
||||
if not netscaler.detected then stdnse.print_debug("%s Netscaler detected through cookies.", SCRIPT_NAME) end
|
||||
netscaler.detected = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local dotdefender
|
||||
dotdefender = {
|
||||
name = "dotDefender",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
if response.header['X-dotdefender-denied'] == "1" then
|
||||
stdnse.print_debug("%s dotDefender detected through X-dotDefender-denied header.", SCRIPT_NAME)
|
||||
dotdefender.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local ibmdatapower
|
||||
ibmdatapower = {
|
||||
name = "IBM DataPower",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
if response.header['x-backside-transport'] then
|
||||
stdnse.print_debug("%s IBM DataPower detected through X-Backside-Transport header.", SCRIPT_NAME)
|
||||
ibmdatapower.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local cloudflare
|
||||
cloudflare = {
|
||||
name = "Cloudflare",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
if response.header.server == 'cloudflare-nginx' then
|
||||
stdnse.print_debug("%s Cloudflare detected through Server header.", SCRIPT_NAME)
|
||||
cloudflare.detected = true
|
||||
return
|
||||
end
|
||||
for _, cookie in pairs(response.cookies) do
|
||||
if cookie.name == "__cfduid" then
|
||||
stdnse.print_debug("%s Cloudflare detected through cookies.", SCRIPT_NAME)
|
||||
cloudflare.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local incapsula
|
||||
incapsula = {
|
||||
name = "Incapsula WAF",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
for _, cookie in pairs(response.cookies) do
|
||||
if string.find(cookie.name, 'incap_ses') or string.find(cookie.name, 'visid_incap') then
|
||||
stdnse.print_debug("%s Incapsula WAF detected through cookies.", SCRIPT_NAME)
|
||||
incapsula.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local uspses
|
||||
uspses = {
|
||||
name = "USP Secure Entry Server",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
if response.header.server == 'Secure Entry Server' then
|
||||
stdnse.print_debug("%s USP-SES detected through Server header.", SCRIPT_NAME)
|
||||
uspses.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local ciscoacexml
|
||||
ciscoacexml = {
|
||||
name = "Cisco ACE XML Gateway",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
if response.header.server == 'ACE XML Gateway' then
|
||||
stdnse.print_debug("%s Cisco ACE XML Gateway detected through Server header.", SCRIPT_NAME)
|
||||
ciscoacexml.detected = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
local modsecurity
|
||||
modsecurity = {
|
||||
-- Credit to Brendan Coles
|
||||
name = "ModSecurity",
|
||||
detected = false,
|
||||
version = nil,
|
||||
|
||||
match = function(responses)
|
||||
for _, response in pairs(responses) do
|
||||
if response.header.server and string.find(response.header.server, 'mod_security/') then
|
||||
stdnse.print_debug("%s Modsecurity detected through Server Header.", SCRIPT_NAME)
|
||||
local pos = string.find(response.header.server, 'mod_security/')
|
||||
modsecurity.version = string.sub(response.header.server, pos + 13, pos + 18)
|
||||
modsecurity.detected = true
|
||||
return
|
||||
end
|
||||
|
||||
if response.header.server and string.find(response.header.server, 'Mod_Security') then
|
||||
stdnse.print_debug("%s Modsecurity detected through Server Header.", SCRIPT_NAME)
|
||||
modsecurity.version = string.sub(response.header.server, 13, -9)
|
||||
modsecurity.detected = true
|
||||
return
|
||||
end
|
||||
|
||||
-- The default SecServerSignature value is "NOYB" <= TODO For older versions, so we could
|
||||
-- probably do some version detection out of it.
|
||||
if response.header.server == 'NOYB' then
|
||||
stdnse.print_debug("%s modsecurity detected through Server header.", SCRIPT_NAME)
|
||||
modsecurity.detected = true
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
local wafs = {
|
||||
-- WAFs that are commented out don't have reliable fingerprints
|
||||
-- with no false positives yet.
|
||||
|
||||
bigip = bigip,
|
||||
webknight = webknight,
|
||||
isaserver = isaserver,
|
||||
airlock = airlock,
|
||||
barracuda = barracuda,
|
||||
denyall = denyall,
|
||||
f5trafficshield = f5trafficshield,
|
||||
teros = teros,
|
||||
binarysec = binarysec,
|
||||
profense = profense,
|
||||
netscaler = netscaler,
|
||||
dotdefender = dotdefender,
|
||||
ibmdatapower = ibmdatapower,
|
||||
cloudflare = cloudflare,
|
||||
incapsula = incapsula,
|
||||
uspses = uspses,
|
||||
ciscoacexml = ciscoacexml,
|
||||
modsecurity = modsecurity,
|
||||
-- netcontinuum = netcontinuum,
|
||||
-- secureiis = secureiis,
|
||||
-- urlscan = urlscan,
|
||||
-- beeware = beeware,
|
||||
-- hyperguard = hyperguard,
|
||||
-- websecurity = websecurity,
|
||||
-- imperva = imperva,
|
||||
-- ibmwas = ibmwas,
|
||||
-- naxsi = naxsi,
|
||||
-- nevisProxy = nevisProxy,
|
||||
-- genericwaf = genericwaf,
|
||||
}
|
||||
|
||||
|
||||
local send_requests = function(host, port, root)
|
||||
local requests, all, responses = {}, {}, {}
|
||||
|
||||
local dirtraversal = "../../../etc/passwd"
|
||||
local cleanhtml = "<hellot>hello"
|
||||
local xssstring = "<script>alert(1)</script>"
|
||||
local cmdexe = "cmd.exe"
|
||||
|
||||
-- Normal index
|
||||
all = http.pipeline_add(root, nil, all, "GET")
|
||||
table.insert(requests,"normal")
|
||||
|
||||
-- Normal inexisting
|
||||
all = http.pipeline_add(root .. "asofKlj", nil, all, "GET")
|
||||
table.insert(requests,"inexisting")
|
||||
|
||||
-- Invalid Method
|
||||
all = http.pipeline_add(root, nil, all, "ASDE")
|
||||
table.insert(requests,"invalidmethod")
|
||||
|
||||
-- Directory traversal
|
||||
all = http.pipeline_add(root .. "?parameter=" .. dirtraversal, nil, all, "GET")
|
||||
table.insert(requests,"invalidmethod")
|
||||
|
||||
-- Invalid Host
|
||||
all = http.pipeline_add(root , {header= {Host = "somerandomsite.com"}}, all, "GET")
|
||||
table.insert(requests,"invalidhost")
|
||||
|
||||
--Clean HTML encoded
|
||||
all = http.pipeline_add(root .. "?parameter=" .. cleanhtml , nil, all, "GET")
|
||||
table.insert(requests,"cleanhtml")
|
||||
|
||||
--Clean HTML
|
||||
all = http.pipeline_add(root .. "?parameter=" .. url.escape(cleanhtml), nil, all, "GET")
|
||||
table.insert(requests,"cleanhtmlencoded")
|
||||
|
||||
-- XSS
|
||||
all = http.pipeline_add(root .. "?parameter=" .. xssstring, nil, all, "GET")
|
||||
table.insert(requests,"xss")
|
||||
|
||||
-- XSS encoded
|
||||
all = http.pipeline_add(root .. "?parameter=" .. url.escape(xssstring), nil, all, "GET")
|
||||
table.insert(requests,"xssencoded")
|
||||
|
||||
-- cmdexe
|
||||
all = http.pipeline_add(root .. "?parameter=" .. cmdexe, nil, all, "GET")
|
||||
table.insert(requests,"cmdexe")
|
||||
|
||||
|
||||
-- send all requests
|
||||
local pipeline_responses = http.pipeline_go(host, port, all)
|
||||
if not pipeline_responses then
|
||||
stdnse.print_debug("%s No response from pipelined requests", SCRIPT_NAME)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Associate responses with requests names
|
||||
for i, response in pairs(pipeline_responses) do
|
||||
responses[requests[i]] = response
|
||||
end
|
||||
|
||||
return responses
|
||||
end
|
||||
|
||||
action = function(host, port)
|
||||
local root = stdnse.get_script_args(SCRIPT_NAME .. '.root') or "/"
|
||||
local result = {"Detected firewalls", {}}
|
||||
|
||||
-- We send requests
|
||||
local responses = send_requests(host, port, root)
|
||||
if not responses then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- We iterate over wafs table passing the responses list to each function to analyze
|
||||
-- the presence of any fingerprints.
|
||||
for _, waf in pairs(wafs) do
|
||||
waf.match(responses)
|
||||
if waf.detected then
|
||||
if waf.version then
|
||||
table.insert(result[2], waf.name .. " version " .. waf.version)
|
||||
else
|
||||
table.insert(result[2], waf.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
if #result[2] > 0 then
|
||||
return stdnse.format_output(true, result)
|
||||
end
|
||||
end
|
||||
@@ -183,6 +183,7 @@ Entry { filename = "http-vuln-cve2011-3192.nse", categories = { "safe", "vuln",
|
||||
Entry { filename = "http-vuln-cve2011-3368.nse", categories = { "intrusive", "vuln", } }
|
||||
Entry { filename = "http-vuln-cve2012-1823.nse", categories = { "exploit", "intrusive", "vuln", } }
|
||||
Entry { filename = "http-waf-detect.nse", categories = { "discovery", "intrusive", } }
|
||||
Entry { filename = "http-waf-fingerprint.nse", categories = { "discovery", "intrusive", } }
|
||||
Entry { filename = "http-wordpress-brute.nse", categories = { "brute", "intrusive", } }
|
||||
Entry { filename = "http-wordpress-enum.nse", categories = { "auth", "intrusive", "vuln", } }
|
||||
Entry { filename = "http-wordpress-plugins.nse", categories = { "discovery", "intrusive", } }
|
||||
|
||||
Reference in New Issue
Block a user