1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 21:21:31 +00:00
Files
nmap/scripts/ajp-brute.nse
dmiller f37ac44380 Move brute.Account to creds.Account
In addition to fitting better (brute library is the verb, creds library
is the noun), this will allow creds.lua to use creds.Account internally
where necessary (see subsequent commits)

Also change old references to string argument "OPEN" into
creds.State.VALID.
2014-09-23 05:23:13 +00:00

113 lines
2.8 KiB
Lua

local ajp = require "ajp"
local base64 = require "base64"
local brute = require "brute"
local creds = require "creds"
local http = require "http"
local shortport = require "shortport"
local stdnse = require "stdnse"
description = [[
Performs brute force passwords auditing against the Apache JServ protocol.
The Apache JServ Protocol is commonly used by web servers to communicate with
back-end Java application server containers.
]]
---
-- @usage
-- nmap -p 8009 <ip> --script ajp-brute
--
-- @output
-- PORT STATE SERVICE
-- 8009/tcp open ajp13
-- | ajp-brute:
-- | Accounts
-- | root:secret - Valid credentials
-- | Statistics
-- |_ Performed 1946 guesses in 23 seconds, average tps: 82
--
author = "Patrik Karlsson"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
portrule = shortport.port_or_service(8009, 'ajp13', 'tcp')
local arg_url = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/"
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
Driver = {
new = function(self, host, port, options)
local o = { host = host,
port = port,
options = options,
helper = ajp.Helper:new(host, port)
}
setmetatable(o, self)
self.__index = self
return o
end,
connect = function(self)
return self.helper:connect()
end,
disconnect = function(self)
return self.helper:close()
end,
login = function(self, user, pass)
local headers = {
["Authorization"] = ("Basic %s"):format(base64.enc(user .. ":" .. pass))
}
local status, response = self.helper:get(arg_url, headers)
if ( not(status) ) then
local err = brute.Error:new( response )
err:setRetry( true )
return false, err
elseif( response.status ~= 401 ) then
return true, creds.Account:new(user, pass, creds.State.VALID)
end
return false, brute.Error:new( "Incorrect password" )
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:get(arg_url)
if ( not(response.headers['www-authenticate']) ) then
return "\n URL does not require authentication"
end
local challenges = http.parse_www_authenticate(response.headers['www-authenticate'])
local options = { scheme = nil }
for _, challenge in ipairs(challenges or {}) do
if ( challenge and challenge.scheme and challenge.scheme:lower() == "basic") then
options.scheme = challenge.scheme:lower()
break
end
end
if ( not(options.scheme) ) then
return fail("Could not find a supported authentication scheme")
end
local engine = brute.Engine:new(Driver, host, port )
engine.options.script_name = SCRIPT_NAME
local status, result = engine:start()
if ( status ) then
return result
end
end