mirror of
https://github.com/nmap/nmap.git
synced 2025-12-20 06:29:02 +00:00
o [NSE] Added the Apache JServer Protocol (AJP) library and the scripts
ajp-methods, ajp-headers and ajp-auth. [Patrik Karlsson]
This commit is contained in:
72
scripts/ajp-auth.nse
Normal file
72
scripts/ajp-auth.nse
Normal file
@@ -0,0 +1,72 @@
|
||||
description = [[
|
||||
Retrieves the authentication scheme and realm of an AJP service that requires
|
||||
authentication.
|
||||
]]
|
||||
|
||||
---
|
||||
-- @usage
|
||||
-- nmap -p 8009 <ip> --script ajp-auth [--script-args ajp-auth.path=/login]
|
||||
--
|
||||
-- @output
|
||||
-- PORT STATE SERVICE
|
||||
-- 8009/tcp open ajp13
|
||||
-- | ajp-auth:
|
||||
-- |_ Digest opaque=GPui3SvCGBoHrRMMzSsgaYBV qop=auth nonce=1336063830612:935b5b389696b0f67b9193e19f47e037 realm=example.org
|
||||
--
|
||||
-- @args ajp-auth.path Define the request path
|
||||
--
|
||||
|
||||
author = "Patrik Karlsson"
|
||||
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
categories = {"default", "auth", "safe"}
|
||||
|
||||
local ajp = require('ajp')
|
||||
local http = require('http')
|
||||
local shortport = require('shortport')
|
||||
|
||||
portrule = shortport.port_or_service(8009, 'ajp13', 'tcp')
|
||||
|
||||
local arg_path = stdnse.get_script_args(SCRIPT_NAME .. ".path")
|
||||
|
||||
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||
|
||||
action = function(host, port)
|
||||
local helper = ajp.Helper:new(host, port)
|
||||
|
||||
if ( not(helper:connect()) ) then
|
||||
return fail("Failed to connect to AJP server")
|
||||
end
|
||||
|
||||
local status, answer = helper:get(arg_path or "/")
|
||||
|
||||
--- check for 401 response code
|
||||
if ( not(status) or answer.status ~= 401 ) then
|
||||
return
|
||||
end
|
||||
|
||||
local result = { name = answer["status-line"]:match("^(.*)\r?\n$") }
|
||||
|
||||
local www_authenticate = answer.headers["www-authenticate"]
|
||||
if not www_authenticate then
|
||||
table.insert( result, ("Server returned status %d but no WWW-Authenticate header."):format(answer.status) )
|
||||
return stdnse.format_output(true, result)
|
||||
end
|
||||
|
||||
local challenges = http.parse_www_authenticate(www_authenticate)
|
||||
if ( not(challenges) ) then
|
||||
table.insert( result, ("Server returned status %d but the WWW-Authenticate header could not be parsed."):format(answer.status) )
|
||||
table.insert( result, ("WWW-Authenticate: %s"):format(www_authenticate) )
|
||||
return stdnse.format_output(true, result)
|
||||
end
|
||||
|
||||
for _, challenge in ipairs(challenges) do
|
||||
local line = challenge.scheme
|
||||
if ( challenge.params ) then
|
||||
for name, value in pairs(challenge.params) do
|
||||
line = line .. (" %s=%s"):format(name, value)
|
||||
end
|
||||
end
|
||||
table.insert(result, line)
|
||||
end
|
||||
return stdnse.format_output(true, result)
|
||||
end
|
||||
46
scripts/ajp-headers.nse
Normal file
46
scripts/ajp-headers.nse
Normal file
@@ -0,0 +1,46 @@
|
||||
description = [[
|
||||
Performs a HEAD or GET request against either the root directory or any
|
||||
optional directory and returns the server response headers.
|
||||
]]
|
||||
|
||||
---
|
||||
-- @usage
|
||||
-- nmap -p 8009 <ip> --script ajp-headers
|
||||
--
|
||||
-- @output
|
||||
-- PORT STATE SERVICE
|
||||
-- 8009/tcp open ajp13
|
||||
-- | ajp-headers:
|
||||
-- | X-Powered-By: JSP/2.2
|
||||
-- | Set-Cookie: JSESSIONID=goTHax+8ktEcZsBldANHBAuf.undefined; Path=/helloworld
|
||||
-- | Content-Type: text/html;charset=ISO-8859-1
|
||||
-- |_ Content-Length: 149
|
||||
--
|
||||
-- @args ajp-headers.path The path to request, such as <code>/index.php</code>. Default <code>/</code>.
|
||||
|
||||
local ajp = require('ajp')
|
||||
local shortport = require('shortport')
|
||||
|
||||
portrule = shortport.port_or_service(8009, 'ajp13', 'tcp')
|
||||
|
||||
author = "Patrik Karlsson"
|
||||
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
categories = {"discovery", "safe"}
|
||||
|
||||
local arg_path = stdnse.get_script_args(SCRIPT_NAME .. '.path') or "/"
|
||||
|
||||
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||
|
||||
action = function(host, port)
|
||||
local method
|
||||
local helper = ajp.Helper:new(host, port)
|
||||
helper:connect()
|
||||
|
||||
local status, response = helper:get(arg_path)
|
||||
helper:close()
|
||||
|
||||
if ( not(status) ) then
|
||||
return fail("Failed to retrieve server headers")
|
||||
end
|
||||
return stdnse.format_output(true, response.rawheaders)
|
||||
end
|
||||
80
scripts/ajp-methods.nse
Normal file
80
scripts/ajp-methods.nse
Normal file
@@ -0,0 +1,80 @@
|
||||
description = [[
|
||||
Finds out what options are supported by the AJP 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 http://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 http://nmap.org/book/man-legal.html"
|
||||
categories = {"default", "safe"}
|
||||
|
||||
local ajp = require('ajp')
|
||||
local shortport = require('shortport')
|
||||
|
||||
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 contains(t, elem)
|
||||
for _, e in ipairs(t) do if e == elem then return true end end
|
||||
return false
|
||||
end
|
||||
|
||||
local function filter_out(t, filter)
|
||||
local result = {}
|
||||
for _, e in ipairs(t) do
|
||||
if ( not(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 fail("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 = stdnse.strsplit(",%s", response.headers['allow'])
|
||||
|
||||
local output = {}
|
||||
table.insert(output, ("Supported methods: %s"):format(stdnse.strjoin(" ", methods)))
|
||||
|
||||
local interesting = filter_out(methods, UNINTERESTING_METHODS)
|
||||
if ( #interesting > 0 ) then
|
||||
table.insert(output, "Potentially risky methods: " .. stdnse.strjoin(" ", interesting))
|
||||
table.insert(output, "See http://nmap.org/nsedoc/scripts/ajp-methods.html")
|
||||
end
|
||||
return stdnse.format_output(true, output)
|
||||
end
|
||||
@@ -5,6 +5,9 @@ Entry { filename = "afp-ls.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "afp-path-vuln.nse", categories = { "exploit", "intrusive", "vuln", } }
|
||||
Entry { filename = "afp-serverinfo.nse", categories = { "default", "discovery", "safe", } }
|
||||
Entry { filename = "afp-showmount.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "ajp-auth.nse", categories = { "auth", "default", "safe", } }
|
||||
Entry { filename = "ajp-headers.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "ajp-methods.nse", categories = { "default", "safe", } }
|
||||
Entry { filename = "amqp-info.nse", categories = { "default", "discovery", "safe", "version", } }
|
||||
Entry { filename = "asn-query.nse", categories = { "discovery", "external", "safe", } }
|
||||
Entry { filename = "auth-owners.nse", categories = { "default", "safe", } }
|
||||
|
||||
Reference in New Issue
Block a user