mirror of
https://github.com/nmap/nmap.git
synced 2025-12-27 18:09:01 +00:00
Final re-indent for scripts.
This commit is contained in:
@@ -101,14 +101,14 @@ portrule = shortport.port_or_service({80, 443}, {"http","https"}, "tcp", "open")
|
||||
-- @param port table as received by the action function
|
||||
-- @param path against which to check if authentication is required
|
||||
local function requiresAuth( host, port, path )
|
||||
local result = http.get(host, port, "/names.nsf")
|
||||
local result = http.get(host, port, "/names.nsf")
|
||||
|
||||
if ( result.status == 401 ) then
|
||||
return true
|
||||
elseif ( result.status == 200 and result.body and result.body:match("<input.-type=[\"]*password[\"]*") ) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
if ( result.status == 401 ) then
|
||||
return true
|
||||
elseif ( result.status == 200 and result.body and result.body:match("<input.-type=[\"]*password[\"]*") ) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Checks if the credentials are valid and allow access to <code>path</code>
|
||||
@@ -121,14 +121,14 @@ end
|
||||
-- @param pass the password used for authentication
|
||||
-- @return true on valid access, false on failure
|
||||
local function isValidCredential( host, port, path, user, pass )
|
||||
-- we need to supply the no_cache directive, or else the http library
|
||||
-- incorrectly tells us that the authentication was successfull
|
||||
local result = http.get( host, port, path, { auth = { username = user, password = pass }, no_cache = true })
|
||||
-- we need to supply the no_cache directive, or else the http library
|
||||
-- incorrectly tells us that the authentication was successfull
|
||||
local result = http.get( host, port, path, { auth = { username = user, password = pass }, no_cache = true })
|
||||
|
||||
if ( result.status == 401 ) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
if ( result.status == 401 ) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Retrieves all uniq links in a pages
|
||||
@@ -138,28 +138,28 @@ end
|
||||
-- @param links [optional] table containing previousy retrieved links
|
||||
-- @return links table containing retrieved links
|
||||
local function getLinks( body, filter, links )
|
||||
local tmp = {}
|
||||
local links = links or {}
|
||||
local filter = filter or ".*"
|
||||
local tmp = {}
|
||||
local links = links or {}
|
||||
local filter = filter or ".*"
|
||||
|
||||
if ( not(body) ) then return end
|
||||
for _, v in ipairs( links ) do
|
||||
tmp[v] = true
|
||||
end
|
||||
if ( not(body) ) then return end
|
||||
for _, v in ipairs( links ) do
|
||||
tmp[v] = true
|
||||
end
|
||||
|
||||
for link in body:gmatch("<a href=\"([^\"]+)\"") do
|
||||
-- use link as key in order to remove duplicates
|
||||
if ( link:match(filter)) then
|
||||
tmp[link] = true
|
||||
end
|
||||
end
|
||||
for link in body:gmatch("<a href=\"([^\"]+)\"") do
|
||||
-- use link as key in order to remove duplicates
|
||||
if ( link:match(filter)) then
|
||||
tmp[link] = true
|
||||
end
|
||||
end
|
||||
|
||||
links = {}
|
||||
for k, _ in pairs(tmp) do
|
||||
table.insert(links, k)
|
||||
end
|
||||
links = {}
|
||||
for k, _ in pairs(tmp) do
|
||||
table.insert(links, k)
|
||||
end
|
||||
|
||||
return links
|
||||
return links
|
||||
end
|
||||
|
||||
--- Retrieves the "next page" path from the returned document
|
||||
@@ -167,7 +167,7 @@ end
|
||||
-- @param body the html content of the recieved page
|
||||
-- @return link to next page
|
||||
local function getPager( body )
|
||||
return body:match("<form.+action=\"(.+%?ReadForm)&" )
|
||||
return body:match("<form.+action=\"(.+%?ReadForm)&" )
|
||||
end
|
||||
|
||||
--- Retrieves the username and passwords for a user
|
||||
@@ -177,19 +177,19 @@ end
|
||||
-- @return password the password hash for the user
|
||||
local function getUserDetails( body )
|
||||
|
||||
-- retrieve the details
|
||||
local full_name = body:match("<input name=\"FullName\".-value=\"(.-)\">")
|
||||
local http_passwd = body:match("<input name=\"HTTPPassword\".-value=\"(.-)\">")
|
||||
local dsp_http_passwd = body:match("<input name=\"dspHTTPPassword\".-value=\"(.-)\">")
|
||||
local id_file = body:match("<a href=\"(.-UserID)\">")
|
||||
-- retrieve the details
|
||||
local full_name = body:match("<input name=\"FullName\".-value=\"(.-)\">")
|
||||
local http_passwd = body:match("<input name=\"HTTPPassword\".-value=\"(.-)\">")
|
||||
local dsp_http_passwd = body:match("<input name=\"dspHTTPPassword\".-value=\"(.-)\">")
|
||||
local id_file = body:match("<a href=\"(.-UserID)\">")
|
||||
|
||||
-- Remove the parenthesis around the password
|
||||
http_passwd = http_passwd:sub(2,-2)
|
||||
-- In case we have more than one full name, return only the last
|
||||
full_name = stdnse.strsplit(";%s*", full_name)
|
||||
full_name = full_name[#full_name]
|
||||
-- Remove the parenthesis around the password
|
||||
http_passwd = http_passwd:sub(2,-2)
|
||||
-- In case we have more than one full name, return only the last
|
||||
full_name = stdnse.strsplit(";%s*", full_name)
|
||||
full_name = full_name[#full_name]
|
||||
|
||||
return { fullname = full_name, passwd = ( http_passwd or dsp_http_passwd ), idfile = id_file }
|
||||
return { fullname = full_name, passwd = ( http_passwd or dsp_http_passwd ), idfile = id_file }
|
||||
end
|
||||
|
||||
--- Saves the ID file to disk
|
||||
@@ -199,162 +199,162 @@ end
|
||||
-- @return status true on success, false on failure
|
||||
-- @return err string containing error message if status is false
|
||||
local function saveIDFile( filename, data )
|
||||
local f = io.open( filename, "w")
|
||||
if ( not(f) ) then
|
||||
return false, ("Failed to open file (%s)"):format(filename)
|
||||
end
|
||||
if ( not(f:write( data ) ) ) then
|
||||
return false, ("Failed to write file (%s)"):format(filename)
|
||||
end
|
||||
f:close()
|
||||
local f = io.open( filename, "w")
|
||||
if ( not(f) ) then
|
||||
return false, ("Failed to open file (%s)"):format(filename)
|
||||
end
|
||||
if ( not(f:write( data ) ) ) then
|
||||
return false, ("Failed to write file (%s)"):format(filename)
|
||||
end
|
||||
f:close()
|
||||
|
||||
return true
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
action = function(host, port)
|
||||
|
||||
local path = "/names.nsf"
|
||||
local download_path = stdnse.get_script_args('domino-enum-passwords.idpath')
|
||||
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 links, result, hashes,legacyHashes, id_files = {}, {}, {}, {},{}
|
||||
local chunk_size = 30
|
||||
local max_fetch = stdnse.get_script_args('domino-enum-passwords.count') and tonumber(stdnse.get_script_args('domino-enum-passwords.count')) or 10
|
||||
local http_response
|
||||
local path = "/names.nsf"
|
||||
local download_path = stdnse.get_script_args('domino-enum-passwords.idpath')
|
||||
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 links, result, hashes,legacyHashes, id_files = {}, {}, {}, {},{}
|
||||
local chunk_size = 30
|
||||
local max_fetch = stdnse.get_script_args('domino-enum-passwords.count') and 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
|
||||
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
|
||||
-- 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
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
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
|
||||
break
|
||||
end
|
||||
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
|
||||
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 )
|
||||
if ( not(pager) ) then
|
||||
if ( http_response.body and
|
||||
http_response.body:match(".*<input type=\"submit\".* value=\"Sign In\">.*" ) ) then
|
||||
return " \n ERROR: Failed to authenticate"
|
||||
else
|
||||
return " \n ERROR: Failed to process results"
|
||||
end
|
||||
end
|
||||
pos = 1
|
||||
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 )
|
||||
if ( not(pager) ) then
|
||||
if ( http_response.body and
|
||||
http_response.body:match(".*<input type=\"submit\".* value=\"Sign In\">.*" ) ) then
|
||||
return " \n ERROR: Failed to authenticate"
|
||||
else
|
||||
return " \n ERROR: Failed to process results"
|
||||
end
|
||||
end
|
||||
pos = 1
|
||||
|
||||
-- first collect all links
|
||||
while( true ) do
|
||||
path = pager .. "&Start=" .. pos
|
||||
http_response = http.get( vhost or host, port, path, { auth = { username = user, password = pass }, no_cache = true })
|
||||
-- first collect all links
|
||||
while( true ) do
|
||||
path = pager .. "&Start=" .. pos
|
||||
http_response = http.get( vhost or host, port, path, { auth = { username = user, password = pass }, no_cache = true })
|
||||
|
||||
if ( http_response.status == 200 ) then
|
||||
local size = #links
|
||||
links = getLinks( http_response.body, "%?OpenDocument", links )
|
||||
-- No additions were made
|
||||
if ( size == #links ) then
|
||||
break
|
||||
end
|
||||
end
|
||||
if ( http_response.status == 200 ) then
|
||||
local size = #links
|
||||
links = getLinks( http_response.body, "%?OpenDocument", links )
|
||||
-- No additions were made
|
||||
if ( size == #links ) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if ( max_fetch > 0 and max_fetch < #links ) then
|
||||
break
|
||||
end
|
||||
if ( max_fetch > 0 and max_fetch < #links ) then
|
||||
break
|
||||
end
|
||||
|
||||
pos = pos + chunk_size
|
||||
end
|
||||
pos = pos + chunk_size
|
||||
end
|
||||
|
||||
for _, link in ipairs(links) do
|
||||
stdnse.print_debug(2, "Fetching link: %s", link)
|
||||
http_response = http.get( vhost or host, port, link, { auth = { username = user, password = pass }, no_cache = true })
|
||||
local u_details = getUserDetails( http_response.body )
|
||||
for _, link in ipairs(links) do
|
||||
stdnse.print_debug(2, "Fetching link: %s", link)
|
||||
http_response = http.get( vhost or host, port, link, { auth = { username = user, password = pass }, no_cache = true })
|
||||
local u_details = getUserDetails( http_response.body )
|
||||
|
||||
if ( max_fetch > 0 and (#hashes+#legacyHashes)>= max_fetch ) then
|
||||
break
|
||||
end
|
||||
if ( max_fetch > 0 and (#hashes+#legacyHashes)>= max_fetch ) then
|
||||
break
|
||||
end
|
||||
|
||||
if ( u_details.fullname and u_details.passwd and #u_details.passwd > 0 ) then
|
||||
stdnse.print_debug(2, "Found Internet hash for: %s:%s", u_details.fullname, u_details.passwd)
|
||||
-- Old type are 32 bytes, new are 20
|
||||
if #u_details.passwd == 32 then
|
||||
table.insert( legacyHashes, ("%s:%s"):format(u_details.fullname, u_details.passwd))
|
||||
else
|
||||
table.insert( hashes, ("%s:(%s)"):format(u_details.fullname, u_details.passwd))
|
||||
end
|
||||
end
|
||||
if ( u_details.fullname and u_details.passwd and #u_details.passwd > 0 ) then
|
||||
stdnse.print_debug(2, "Found Internet hash for: %s:%s", u_details.fullname, u_details.passwd)
|
||||
-- Old type are 32 bytes, new are 20
|
||||
if #u_details.passwd == 32 then
|
||||
table.insert( legacyHashes, ("%s:%s"):format(u_details.fullname, u_details.passwd))
|
||||
else
|
||||
table.insert( hashes, ("%s:(%s)"):format(u_details.fullname, u_details.passwd))
|
||||
end
|
||||
end
|
||||
|
||||
if ( u_details.idfile ) then
|
||||
stdnse.print_debug(2, "Found ID file for user: %s", u_details.fullname)
|
||||
if ( download_path ) then
|
||||
stdnse.print_debug(2, "Downloading ID file for user: %s", u_details.full_name)
|
||||
http_response = http.get( vhost or host, port, u_details.idfile, { auth = { username = user, password = pass }, no_cache = true })
|
||||
if ( u_details.idfile ) then
|
||||
stdnse.print_debug(2, "Found ID file for user: %s", u_details.fullname)
|
||||
if ( download_path ) then
|
||||
stdnse.print_debug(2, "Downloading ID file for user: %s", u_details.full_name)
|
||||
http_response = http.get( vhost or host, port, u_details.idfile, { auth = { username = user, password = pass }, no_cache = true })
|
||||
|
||||
if ( http_response.status == 200 ) then
|
||||
local filename = download_path .. "/" .. stdnse.filename_escape(u_details.fullname .. ".id")
|
||||
local status, err = saveIDFile( filename, http_response.body )
|
||||
if ( status ) then
|
||||
table.insert( id_files, ("%s ID File has been downloaded (%s)"):format(u_details.fullname, filename) )
|
||||
else
|
||||
table.insert( id_files, ("%s ID File was not saved (error: %s)"):format(u_details.fullname, err ) )
|
||||
end
|
||||
else
|
||||
table.insert( id_files, ("%s ID File was not saved (error: unexpected response from server)"):format( u_details.fullname ) )
|
||||
end
|
||||
else
|
||||
table.insert( id_files, ("%s has ID File available for download"):format(u_details.fullname) )
|
||||
end
|
||||
end
|
||||
end
|
||||
if ( http_response.status == 200 ) then
|
||||
local filename = download_path .. "/" .. stdnse.filename_escape(u_details.fullname .. ".id")
|
||||
local status, err = saveIDFile( filename, http_response.body )
|
||||
if ( status ) then
|
||||
table.insert( id_files, ("%s ID File has been downloaded (%s)"):format(u_details.fullname, filename) )
|
||||
else
|
||||
table.insert( id_files, ("%s ID File was not saved (error: %s)"):format(u_details.fullname, err ) )
|
||||
end
|
||||
else
|
||||
table.insert( id_files, ("%s ID File was not saved (error: unexpected response from server)"):format( u_details.fullname ) )
|
||||
end
|
||||
else
|
||||
table.insert( id_files, ("%s has ID File available for download"):format(u_details.fullname) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if( #hashes + #legacyHashes > 0) then
|
||||
table.insert( result, { name = "Information", [1] = ("Information retrieved as: \"%s\""):format(user) } )
|
||||
end
|
||||
if( #hashes + #legacyHashes > 0) then
|
||||
table.insert( result, { name = "Information", [1] = ("Information retrieved as: \"%s\""):format(user) } )
|
||||
end
|
||||
|
||||
if ( #hashes ) then
|
||||
hashes.name = "Internet hashes (salted, jtr: --format=DOMINOSEC)"
|
||||
table.insert( result, hashes )
|
||||
end
|
||||
if (#legacyHashes ) then
|
||||
legacyHashes.name = "Internet hashes (unsalted, jtr: --format=lotus5)"
|
||||
table.insert( result, legacyHashes )
|
||||
end
|
||||
if ( #hashes ) then
|
||||
hashes.name = "Internet hashes (salted, jtr: --format=DOMINOSEC)"
|
||||
table.insert( result, hashes )
|
||||
end
|
||||
if (#legacyHashes ) then
|
||||
legacyHashes.name = "Internet hashes (unsalted, jtr: --format=lotus5)"
|
||||
table.insert( result, legacyHashes )
|
||||
end
|
||||
|
||||
if ( #id_files ) then
|
||||
id_files.name = "ID Files"
|
||||
table.insert( result, id_files )
|
||||
end
|
||||
if ( #id_files ) then
|
||||
id_files.name = "ID Files"
|
||||
table.insert( result, id_files )
|
||||
end
|
||||
|
||||
local result = stdnse.format_output(true, result)
|
||||
local result = stdnse.format_output(true, result)
|
||||
|
||||
if ( max_fetch > 0 ) then
|
||||
result = result .. (" \n Results limited to %d results (see domino-enum-passwords.count)"):format(max_fetch)
|
||||
end
|
||||
if ( max_fetch > 0 ) then
|
||||
result = result .. (" \n Results limited to %d results (see domino-enum-passwords.count)"):format(max_fetch)
|
||||
end
|
||||
|
||||
return result
|
||||
return result
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user