I have noticed that nmap.registry holds two parallel structures for credentials: "creds" and "credentials". The former is abstracted out through the creds library and the latter is used directly by just a few scripts.
Specifically, two scripts (http-brute, and http-form-brute) are populating structure credentials.http, while they also utilize the creds library so they are storing the credentials twice. In the entire script collection only one script (http-domino-enum-passwords) seems to consume the credentials.http structure.
I would like to solicit opinions whether the redundancy serves a particular purpose or whether it is just a leftover. In case of the latter, the attached patch converts the one script to use the creds library and retires the credentials.http structure.
The patch does not touch script backorifice-brute, which populates registry structure credentials.backorifice, although it would be very easy to do so. As far as I can tell none of the scripts consume credentials.backorifice. It looks like script backorifice-info was meant to but it was not implemented.
--- a/scripts/http-brute.nse
+++ b/scripts/http-brute.nse
@@ -16,8 +16,8 @@
-- nmap --script http-brute -p 80 <host>
--
-- This script uses the unpwdb and brute libraries to perform password
--- guessing. Any successful guesses are stored in the nmap registry, under
--- the nmap.registry.credentials.http key for other scripts to use.
+-- guessing. Any successful guesses are stored in the nmap registry, using
+-- the creds library, for other scripts to use.
--
-- @output
-- PORT STATE SERVICE REASON
@@ -90,13 +90,6 @@
-- but gave me a number of false positives last time I tried.
-- We decided to change it to ~= 4xx.
if ( response.status < 400 or response.status > 499 ) then
- if ( not( nmap.registry['credentials'] ) ) then
- nmap.registry['credentials'] = {}
- end
- if ( not( nmap.registry.credentials['http'] ) ) then
- nmap.registry.credentials['http'] = {}
- end
- table.insert( nmap.registry.credentials.http, { username = username, password = password } )
return true, creds.Account:new( username, password, creds.State.VALID)
end
return false, brute.Error:new( "Incorrect password" )
--- a/scripts/http-domino-enum-passwords.nse
+++ b/scripts/http-domino-enum-passwords.nse
@@ -1,3 +1,4 @@
+local creds = require "creds"
local http = require "http"
local io = require "io"
local nmap = require "nmap"
@@ -81,10 +82,11 @@
-- @args domino-enum-passwords.password Password for HTTP auth, if required
--
--- Version 0.2
+-- Version 0.4
-- Created 07/30/2010 - v0.1 - created by Patrik Karlsson <[email protected]>
-- Revised 07/31/2010 - v0.2 - add support for downloading ID files
-- Revised 11/25/2010 - v0.3 - added support for separating hash-type <[email protected]>
+-- Revised 11/25/2010 - v0.4 - switched to "creds" credential repository, <nnposter>
author = "Patrik Karlsson"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
@@ -219,42 +221,37 @@
local vhost= stdnse.get_script_args('domino-enum-passwords.hostname')
local user = stdnse.get_script_args('domino-enum-passwords.username')
local pass = stdnse.get_script_args('domino-enum-passwords.password')
- local creds, pos, pager
+ local pos, pager
local links, result, hashes,legacyHashes, id_files = {}, {}, {}, {},{}
local chunk_size = 30
local max_fetch = tonumber(stdnse.get_script_args('domino-enum-passwords.count')) or 10
local http_response
- if ( nmap.registry['credentials'] and nmap.registry['credentials']['http'] ) then
- creds = nmap.registry['credentials']['http']
- end
-
-- authentication required?
if ( requiresAuth( vhost or host, port, path ) ) then
- if ( not(user) and not(creds) ) then
- return " \n ERROR: No credentials supplied (see domino-enum-passwords.username and domino-enum-passwords.password)"
- end
-
-- A user was provided, attempt to authenticate
if ( user ) then
if (not(isValidCredential( vhost or host, port, path, user, pass )) ) then
return " \n ERROR: The provided credentials where invalid"
end
- elseif ( creds ) then
- for _, cred in pairs(creds) do
- if ( isValidCredential( vhost or host, port, path, cred.username, cred.password ) ) then
- user = cred.username
- pass = cred.password
+ else
+ local has_creds = false
+ local c = creds.Credentials:new(creds.ALL_DATA, host, port)
+ for cred in c:getCredentials(creds.State.VALID) do
+ has_creds = true
+ if (isValidCredential(vhost or host, port, path, cred.user, cred.pass)) then
+ user = cred.user
+ pass = cred.pass
break
end
end
+ if not pass then
+ local msg = has_creds and "No valid credentials were found" or "No credentials supplied"
+ return string.format(" \n ERROR: %s (see domino-enum-passwords.username and domino-enum-passwords.password)", msg)
+ end
end
end
- if ( not(user) and not(pass) ) then
- return " \n ERROR: No valid credentials were found (see domino-enum-passwords.username and domino-enum-passwords.password)"
- end
-
path = "/names.nsf/People?OpenView"
http_response = http.get( vhost or host, port, path, { auth = { username = user, password = pass }, no_cache = true })
pager = getPager( http_response.body )
--- a/scripts/http-form-brute.nse
+++ b/scripts/http-form-brute.nse
@@ -12,8 +12,8 @@
Performs brute force password auditing against http form-based authentication.
This script uses the unpwdb and brute libraries to perform password
-guessing. Any successful guesses are stored in the nmap registry, under
-the nmap.registry.credentials.http key for other scripts to use.
+guessing. Any successful guesses are stored in the nmap registry, using
+the creds library, for other scripts to use.
The script automatically attempts to discover the form method, action, and
field names to use in order to perform password guessing. (Use argument
@@ -234,9 +234,6 @@
if not success then
return false, brute.Error:new("Incorrect password")
end
- nmap.registry['credentials'] = nmap.registry['credentials'] or {}
- nmap.registry.credentials['http'] = nmap.registry.credentials['http'] or {}
- table.insert(nmap.registry.credentials.http, {username = username, password = password})
return true, creds.Account:new(username, password, creds.State.VALID)
end,