1
0
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:
patrik
2012-05-07 18:49:22 +00:00
parent cec2dd7816
commit d02dafb630
6 changed files with 634 additions and 0 deletions

72
scripts/ajp-auth.nse Normal file
View 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
View 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
View 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

View File

@@ -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", } }