1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +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

@@ -44,9 +44,33 @@ This script was based on http-enum.
-- nmap -p80 --script http-default-accounts host/ip
--
-- @output
-- PORT STATE SERVICE REASON
-- 80/tcp open http syn-ack
-- |_http-default-accounts: [Cacti] credentials found -> admin:admin Path:/cacti/
-- PORT STATE SERVICE
-- 80/tcp open http
-- | 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.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
-- 2016-08-10 nnposter
-- * 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"}
@@ -212,15 +242,48 @@ local function format_basepath(basepath)
end
---
-- register_http_credentials(username, password)
-- Stores HTTP credentials in the registry. If the registry entry hasn't been
-- initiated, it will create it and store the credentials.
-- @param login_username Username
-- @param login_password Password
-- test_credentials(host, port, fingerprint, path)
-- Tests default credentials of a given fingerprint against a given path.
-- Any successful credentials are registered in the Nmap credential repository.
-- @param host table as received by the scripts action method
-- @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 c = creds.Credentials:new( SCRIPT_NAME, host, port )
c:add(login_username, login_password, creds.State.VALID )
local function test_credentials (host, port, fingerprint, path)
local credlst = {}
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
@@ -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 category = stdnse.get_script_args("http-default-accounts.category") or false
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.
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.")
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
local target_check = fingerprint.target_check or default_target_check
local credentials_found = false
@@ -286,29 +350,17 @@ action = function(host, port)
for _, probe in ipairs(fingerprint.paths) do
local result = results[pathmap[probe.path]]
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
for _, login_combo in ipairs(fingerprint.login_combos) do
stdnse.debug(2, "Trying login combo -> %s:%s", login_combo["username"], login_combo["password"])
--Check default credentials
if( fingerprint.login_check(host, port, path, login_combo["username"], login_combo["password"]) ) then
--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
local out, txtout = test_credentials(host, port, fingerprint, path)
if out then
output[fingerprint.name] = out
table.insert(text_output, txtout)
credentials_found = true
end
end
end
end
end
if #output_lns > 0 then
return stdnse.strjoin("\n", output_lns)
end
return output, stdnse.format_output(true, text_output)
end