mirror of
https://github.com/nmap/nmap.git
synced 2025-12-07 21:21:31 +00:00
* fixed a bug that would result in unnecessary connects and disconnect for
discovered accounts * documented engine options * added new engine option (nostore) that instructs the library not to store the discovered credentials in the credential database
This commit is contained in:
@@ -183,7 +183,24 @@ require 'unpwdb'
|
|||||||
require 'datafiles'
|
require 'datafiles'
|
||||||
require 'creds'
|
require 'creds'
|
||||||
|
|
||||||
-- Options that can be set through --script-args
|
-- Engine options that can be set by scripts
|
||||||
|
-- Supported options are:
|
||||||
|
-- * firstonly - stop after finding the first correct password
|
||||||
|
-- (can be set using script-arg brute.firstonly)
|
||||||
|
-- * passonly - guess passwords only, don't supply a username
|
||||||
|
-- (can be set using script-arg brute.passonly)
|
||||||
|
-- * max_retries - the amount of retries to do before aborting
|
||||||
|
-- (can be set using script-arg brute.retries)
|
||||||
|
-- * delay - sets the delay between attempts
|
||||||
|
-- (can be set using script-arg brute.delay)
|
||||||
|
-- * mode - can be set to either cred, user or pass and controls
|
||||||
|
-- whether the engine should iterate over users, passwords
|
||||||
|
-- or fetch a list of credentials from a single file.
|
||||||
|
-- (can be set using script-arg brut.mode)
|
||||||
|
-- * title - changes the title of the result table where the
|
||||||
|
-- passwords are returned.
|
||||||
|
-- * nostore - don't store the results in the credential library
|
||||||
|
--
|
||||||
Options = {
|
Options = {
|
||||||
|
|
||||||
new = function(self)
|
new = function(self)
|
||||||
@@ -239,6 +256,11 @@ Options = {
|
|||||||
-- @param param string containing the parameter name
|
-- @param param string containing the parameter name
|
||||||
-- @param value string containing the parameter value
|
-- @param value string containing the parameter value
|
||||||
setOption = function( self, param, value ) self[param] = value end,
|
setOption = function( self, param, value ) self[param] = value end,
|
||||||
|
|
||||||
|
--- Set an alternate title for the result output (default: Accounts)
|
||||||
|
--
|
||||||
|
-- @param title string containing the title value
|
||||||
|
setTitle = function(self, title) self.title = title end,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +291,11 @@ Account =
|
|||||||
else
|
else
|
||||||
c = ("%s"):format( ( self.password and #self.password > 0 ) and self.password or "<empty>" )
|
c = ("%s"):format( ( self.password and #self.password > 0 ) and self.password or "<empty>" )
|
||||||
end
|
end
|
||||||
return ( "%s => %s"):format(c, creds.StateMsg[self.state] )
|
if ( creds.StateMsg[self.state] ) then
|
||||||
|
return ( "%s - %s"):format(c, creds.StateMsg[self.state] )
|
||||||
|
else
|
||||||
|
return ("%s"):format(c)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -437,7 +463,14 @@ Engine =
|
|||||||
|
|
||||||
local username, password
|
local username, password
|
||||||
if ( not(username) and not(password) ) then
|
if ( not(username) and not(password) ) then
|
||||||
username, password = next_credential()
|
repeat
|
||||||
|
username, password = next_credential()
|
||||||
|
if ( not(username) and not(password) ) then
|
||||||
|
driver:disconnect()
|
||||||
|
self.threads[coroutine.running()].terminate = true
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
until ( not(self.found_accounts) or not(self.found_accounts[username]) )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- make sure that all threads locked in connect stat terminate quickly
|
-- make sure that all threads locked in connect stat terminate quickly
|
||||||
@@ -445,20 +478,7 @@ Engine =
|
|||||||
driver:disconnect()
|
driver:disconnect()
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- We've reached the end of the iterator, signal the thread to terminate
|
|
||||||
if ( not(password) ) then
|
|
||||||
driver:disconnect()
|
|
||||||
self.threads[coroutine.running()].terminate = true
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- The username was already tested
|
|
||||||
if ( self.found_accounts and self.found_accounts[username] ) then
|
|
||||||
driver:disconnect()
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local c
|
local c
|
||||||
-- Do we have a username or not?
|
-- Do we have a username or not?
|
||||||
if ( username and #username > 0 ) then
|
if ( username and #username > 0 ) then
|
||||||
@@ -508,7 +528,12 @@ Engine =
|
|||||||
if ( status ) then
|
if ( status ) then
|
||||||
-- Prevent locked accounts from appearing several times
|
-- Prevent locked accounts from appearing several times
|
||||||
if ( not(self.found_accounts) or self.found_accounts[response.username] == nil ) then
|
if ( not(self.found_accounts) or self.found_accounts[response.username] == nil ) then
|
||||||
creds.Credentials:new( self.options.script_name, self.host, self.port ):add(response.username, response.password, response.state )
|
if ( not(self.options.nostore) ) then
|
||||||
|
creds.Credentials:new( self.options.script_name, self.host, self.port ):add(response.username, response.password, response.state )
|
||||||
|
else
|
||||||
|
self.credstore = self.credstore or {}
|
||||||
|
table.insert(self.credstore, response:toString() )
|
||||||
|
end
|
||||||
|
|
||||||
stdnse.print_debug("Discovered account: %s", response:toString())
|
stdnse.print_debug("Discovered account: %s", response:toString())
|
||||||
|
|
||||||
@@ -586,7 +611,10 @@ Engine =
|
|||||||
local function next_user() coroutine.yield( "" ) end
|
local function next_user() coroutine.yield( "" ) end
|
||||||
return coroutine.wrap(next_user)
|
return coroutine.wrap(next_user)
|
||||||
end
|
end
|
||||||
table.insert( self.iterators, Iterators.user_pw_iterator( single_user_iter(), passwords ) )
|
-- only add this iterator if no other iterator was specified
|
||||||
|
if ( #self.iterators == 0 ) then
|
||||||
|
table.insert( self.iterators, Iterators.user_pw_iterator( single_user_iter(), passwords ) )
|
||||||
|
end
|
||||||
elseif ( mode == 'creds' ) then
|
elseif ( mode == 'creds' ) then
|
||||||
local credfile = stdnse.get_script_args("brute.credfile")
|
local credfile = stdnse.get_script_args("brute.credfile")
|
||||||
if ( not(credfile) ) then
|
if ( not(credfile) ) then
|
||||||
@@ -622,12 +650,18 @@ Engine =
|
|||||||
-- wait for all threads to finnish running
|
-- wait for all threads to finnish running
|
||||||
while self:threadCount()>0 do condvar "wait" end
|
while self:threadCount()>0 do condvar "wait" end
|
||||||
|
|
||||||
local valid_accounts = creds.Credentials:new(self.options.script_name, self.host, self.port):getTable()
|
local valid_accounts
|
||||||
|
|
||||||
|
if ( not(self.options.nostore) ) then
|
||||||
|
valid_accounts = creds.Credentials:new(self.options.script_name, self.host, self.port):getTable()
|
||||||
|
else
|
||||||
|
valid_accounts = self.credstore
|
||||||
|
end
|
||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
-- Did we find any accounts, if so, do formatting
|
-- Did we find any accounts, if so, do formatting
|
||||||
if ( valid_accounts and #valid_accounts > 0 ) then
|
if ( valid_accounts and #valid_accounts > 0 ) then
|
||||||
valid_accounts.name = "Accounts"
|
valid_accounts.name = self.options.title or "Accounts"
|
||||||
table.insert( result, valid_accounts )
|
table.insert( result, valid_accounts )
|
||||||
else
|
else
|
||||||
table.insert( result, {"No valid accounts found", name="Accounts"} )
|
table.insert( result, {"No valid accounts found", name="Accounts"} )
|
||||||
|
|||||||
Reference in New Issue
Block a user