1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 13:11:28 +00:00

Implements XML structured output. Closes #604

This commit is contained in:
nnposter
2016-12-04 20:31:30 +00:00
parent 80de9e1875
commit b0b94049b7
2 changed files with 90 additions and 34 deletions

View File

@@ -40,8 +40,12 @@ o [NSE] Updated fingerprints for script http-default-accounts with 21 new
fingerprints. 5 fingerprints have been broadened to cover more variants. fingerprints. 5 fingerprints have been broadened to cover more variants.
[nnposter] [nnposter]
o [NSE][GH#577] Script http-default-accounts now can test systems that return o [NSE] Revised script http-default-accounts in several ways:
status 200 for non-existent pages. [nnposter] - [GH#577] It can now can test systems that return status 200 for
non-existent pages. [nnposter]
- [GH#604] Implemented XML output. Layout of the classic text output has also
changed, including reporting blank usernames or passwords as "<blank>",
instead of just empty strings. [nnposter]
o [NSE][GH#573] Updated http.lua to allow processing of HTTP responses with o [NSE][GH#573] Updated http.lua to allow processing of HTTP responses with
malformed header names. Such header lines are still captured in the rawheader malformed header names. Such header lines are still captured in the rawheader

View File

@@ -44,9 +44,33 @@ This script was based on http-enum.
-- nmap -p80 --script http-default-accounts host/ip -- nmap -p80 --script http-default-accounts host/ip
-- --
-- @output -- @output
-- PORT STATE SERVICE REASON -- PORT STATE SERVICE
-- 80/tcp open http syn-ack -- 80/tcp open http
-- |_http-default-accounts: [Cacti] credentials found -> admin:admin Path:/cacti/ -- | http-default-accounts:
-- | [Cacti] at /
-- | admin:admin
-- | [Nagios] at /nagios/
-- |_ nagiosadmin:CactiEZ
--
-- @xmloutput
-- <table key="Cacti">
-- <elem key="path">/</elem>
-- <table key="credentials">
-- <table>
-- <elem key="username">admin</elem>
-- <elem key="password">admin</elem>
-- </table>
-- </table>
-- </table>
-- <table key="Nagios">
-- <elem key="path">/nagios/</elem>
-- <table key="credentials">
-- <table>
-- <elem key="username">nagiosadmin</elem>
-- <elem key="password">CactiEZ</elem>
-- </table>
-- </table>
-- </table>
-- --
-- @args http-default-accounts.basepath Base path to append to requests. Default: "/" -- @args http-default-accounts.basepath Base path to append to requests. Default: "/"
-- @args http-default-accounts.fingerprintfile Fingerprint filename. Default: http-default-accounts-fingerprints.lua -- @args http-default-accounts.fingerprintfile Fingerprint filename. Default: http-default-accounts-fingerprints.lua
@@ -59,6 +83,12 @@ This script was based on http-enum.
-- * changed category from safe to intrusive -- * changed category from safe to intrusive
-- 2016-08-10 nnposter -- 2016-08-10 nnposter
-- * added sharing of probe requests across fingerprints -- * added sharing of probe requests across fingerprints
-- 2016-10-30 nnposter
-- * removed a limitation that prevented testing of systems returning
-- status 200 for non-existent pages.
-- 2016-12-01 nnposter
-- * implemented XML structured output
-- * changed classic output to report empty credentials as <blank>
--- ---
author = {"Paulino Calderon <calderon@websec.mx>", "nnposter"} author = {"Paulino Calderon <calderon@websec.mx>", "nnposter"}
@@ -212,15 +242,48 @@ local function format_basepath(basepath)
end end
--- ---
-- register_http_credentials(username, password) -- test_credentials(host, port, fingerprint, path)
-- Stores HTTP credentials in the registry. If the registry entry hasn't been -- Tests default credentials of a given fingerprint against a given path.
-- initiated, it will create it and store the credentials. -- Any successful credentials are registered in the Nmap credential repository.
-- @param login_username Username -- @param host table as received by the scripts action method
-- @param login_password Password -- @param port table as received by the scripts action method
-- @param fingerprint as defined in the fingerprint file
-- @param path againt which the the credentials will be tested
-- @return out table suitable for inclusion in the script structured output
-- (or nil if no credentials succeeded)
-- @return txtout table suitable for inclusion in the script textual output
--- ---
local function register_http_credentials(host, port, login_username, login_password) local function test_credentials (host, port, fingerprint, path)
local c = creds.Credentials:new( SCRIPT_NAME, host, port ) local credlst = {}
c:add(login_username, login_password, creds.State.VALID ) for _, login_combo in ipairs(fingerprint.login_combos) do
local user = login_combo.username
local pass = login_combo.password
stdnse.debug(2, "Trying login combo -> %s:%s", user, pass)
if fingerprint.login_check(host, port, path, user, pass) then
stdnse.debug(1, "[%s] valid default credentials found.", fingerprint.name)
local cred = stdnse.output_table()
cred.username = user
cred.password = pass
table.insert(credlst, cred)
end
end
if #credlst == 0 then return nil end
-- Some credentials found. Generate the fingerprint output report
local out = stdnse.output_table()
out.path = path
out.credentials = credlst
local txtout = {}
txtout.name = ("[%s] at %s"):format(fingerprint.name, path)
for _, cred in ipairs(credlst) do
table.insert(txtout,("%s:%s"):format(stdnse.string_or_blank(cred.username),
stdnse.string_or_blank(cred.password)))
end
-- Register the credentials
local credreg = creds.Credentials:new(SCRIPT_NAME, host, port)
for _, cred in ipairs(credlst) do
credreg:add(cred.username, cred.password, creds.State.VALID )
end
return out, txtout
end end
@@ -229,7 +292,8 @@ action = function(host, port)
local fingerprint_filename = stdnse.get_script_args("http-default-accounts.fingerprintfile") or "http-default-accounts-fingerprints.lua" local fingerprint_filename = stdnse.get_script_args("http-default-accounts.fingerprintfile") or "http-default-accounts-fingerprints.lua"
local category = stdnse.get_script_args("http-default-accounts.category") or false local category = stdnse.get_script_args("http-default-accounts.category") or false
local basepath = stdnse.get_script_args("http-default-accounts.basepath") or "/" local basepath = stdnse.get_script_args("http-default-accounts.basepath") or "/"
local output_lns = {} local output = stdnse.output_table()
local text_output = {}
-- Determine the target's response to "404" HTTP requests. -- Determine the target's response to "404" HTTP requests.
local status_404, result_404, known_404 = http.identify_404(host,port) local status_404, result_404, known_404 = http.identify_404(host,port)
@@ -278,7 +342,7 @@ action = function(host, port)
"HTTP request table is empty. This should not happen since we at least made one request.") "HTTP request table is empty. This should not happen since we at least made one request.")
end end
-- Iterate through responses to find a candidate for login routine -- Iterate through fingerprints to find a candidate for login routine
for _, fingerprint in ipairs(fingerprints) do for _, fingerprint in ipairs(fingerprints) do
local target_check = fingerprint.target_check or default_target_check local target_check = fingerprint.target_check or default_target_check
local credentials_found = false local credentials_found = false
@@ -286,29 +350,17 @@ action = function(host, port)
for _, probe in ipairs(fingerprint.paths) do for _, probe in ipairs(fingerprint.paths) do
local result = results[pathmap[probe.path]] local result = results[pathmap[probe.path]]
if result and not credentials_found then if result and not credentials_found then
local path = basepath .. probe['path'] local path = basepath .. probe.path
if target_check(host, port, path, result) then if target_check(host, port, path, result) then
for _, login_combo in ipairs(fingerprint.login_combos) do local out, txtout = test_credentials(host, port, fingerprint, path)
stdnse.debug(2, "Trying login combo -> %s:%s", login_combo["username"], login_combo["password"]) if out then
--Check default credentials output[fingerprint.name] = out
if( fingerprint.login_check(host, port, path, login_combo["username"], login_combo["password"]) ) then table.insert(text_output, txtout)
credentials_found = true
--Valid credentials found
stdnse.debug(1, "[%s] valid default credentials found.", fingerprint.name)
output_lns[#output_lns + 1] = string.format("[%s] credentials found -> %s:%s Path:%s",
fingerprint.name, login_combo["username"], login_combo["password"], path)
-- Add to http credentials table
register_http_credentials(host, port, login_combo["username"], login_combo["password"])
credentials_found = true
end
end end
end end
end end
end end
end end
return output, stdnse.format_output(true, text_output)
if #output_lns > 0 then
return stdnse.strjoin("\n", output_lns)
end
end end