summaryrefslogtreecommitdiffstats
path: root/scripts/ajp-methods.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/ajp-methods.nse')
-rw-r--r--scripts/ajp-methods.nse81
1 files changed, 81 insertions, 0 deletions
diff --git a/scripts/ajp-methods.nse b/scripts/ajp-methods.nse
new file mode 100644
index 0000000..f8d62c7
--- /dev/null
+++ b/scripts/ajp-methods.nse
@@ -0,0 +1,81 @@
+local ajp = require "ajp"
+local shortport = require "shortport"
+local stdnse = require "stdnse"
+local stringaux = require "stringaux"
+local table = require "table"
+local tableaux = require "tableaux"
+
+description = [[
+Discovers which options are supported by the AJP (Apache JServ
+Protocol) server by sending an OPTIONS request and lists potentially
+risky methods.
+
+In this script, "potentially risky" methods are anything except GET,
+HEAD, POST, and OPTIONS. If the script reports potentially risky
+methods, they may not all be security risks, but you should check to
+make sure. This page lists the dangers of some common methods:
+
+http://www.owasp.org/index.php/Testing_for_HTTP_Methods_and_XST_%28OWASP-CM-008%29
+]]
+
+---
+-- @usage
+-- nmap -p 8009 <ip> --script ajp-methods
+--
+-- @output
+-- PORT STATE SERVICE
+-- 8009/tcp open ajp13
+-- | ajp-methods:
+-- | Supported methods: GET HEAD POST PUT DELETE TRACE OPTIONS
+-- | Potentially risky methods: PUT DELETE TRACE
+-- |_ See https://nmap.org/nsedoc/scripts/ajp-methods.html
+--
+-- @args ajp-methods.path the path to check or <code>/<code> if none was given
+--
+
+author = "Patrik Karlsson"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"default", "safe"}
+
+
+portrule = shortport.port_or_service(8009, 'ajp13', 'tcp')
+
+local arg_url = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/"
+local UNINTERESTING_METHODS = { "GET", "HEAD", "POST", "OPTIONS" }
+
+local function filter_out(t, filter)
+ local result = {}
+ for _, e in ipairs(t) do
+ if ( not(tableaux.contains(filter, e)) ) then
+ result[#result + 1] = e
+ end
+ end
+ return result
+end
+
+action = function(host, port)
+
+ local helper = ajp.Helper:new(host, port)
+ if ( not(helper:connect()) ) then
+ return stdnse.format_output(false, "Failed to connect to server")
+ end
+
+ local status, response = helper:options(arg_url)
+ helper:close()
+ if ( not(status) or response.status ~= 200 or
+ not(response.headers) or not(response.headers['allow']) ) then
+ return "Failed to get a valid response for the OPTION request"
+ end
+
+ local methods = stringaux.strsplit(",%s", response.headers['allow'])
+
+ local output = {}
+ table.insert(output, ("Supported methods: %s"):format(table.concat(methods, " ")))
+
+ local interesting = filter_out(methods, UNINTERESTING_METHODS)
+ if ( #interesting > 0 ) then
+ table.insert(output, "Potentially risky methods: " .. table.concat(interesting, " "))
+ table.insert(output, "See https://nmap.org/nsedoc/scripts/ajp-methods.html")
+ end
+ return stdnse.format_output(true, output)
+end