mirror of
https://github.com/nmap/nmap.git
synced 2025-12-27 01:49:03 +00:00
Added command line support to the creds library
Changed getCredentials to allow a bitmask filter Changed getCredentials to return an iterator instead of a table Modified the brute library to support the changes [Patrik]
This commit is contained in:
@@ -256,13 +256,13 @@ Account =
|
||||
--
|
||||
-- @return string representation of object
|
||||
toString = function( self )
|
||||
local creds
|
||||
local c
|
||||
if ( #self.username > 0 ) then
|
||||
creds = ("%s:%s"):format( self.username, #self.password > 0 and self.password or "<empty>" )
|
||||
c = ("%s:%s"):format( self.username, #self.password > 0 and self.password or "<empty>" )
|
||||
else
|
||||
creds = ("%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
|
||||
return ( "%s => %s"):format(creds, self.state.msg )
|
||||
return ( "%s => %s"):format(c, creds.StateMsg[self.state] )
|
||||
end,
|
||||
|
||||
}
|
||||
@@ -460,16 +460,16 @@ Engine =
|
||||
return false
|
||||
end
|
||||
|
||||
local creds
|
||||
local c
|
||||
-- Do we have a username or not?
|
||||
if ( username and #username > 0 ) then
|
||||
creds = ("%s/%s"):format(username, #password > 0 and password or "<empty>")
|
||||
c = ("%s/%s"):format(username, #password > 0 and password or "<empty>")
|
||||
else
|
||||
creds = ("%s"):format(#password > 0 and password or "<empty>")
|
||||
c = ("%s"):format(#password > 0 and password or "<empty>")
|
||||
end
|
||||
|
||||
local msg = ( retries ~= self.options.max_retries ) and "Re-trying" or "Trying"
|
||||
stdnse.print_debug(2, "%s %s against %s:%d", msg, creds, self.host.ip, self.port.number )
|
||||
stdnse.print_debug(2, "%s %s against %s:%d", msg, c, self.host.ip, self.port.number )
|
||||
status, response = driver:login( username, password )
|
||||
|
||||
driver:disconnect()
|
||||
@@ -591,15 +591,15 @@ Engine =
|
||||
if ( not(f) ) then
|
||||
return false, ("Failed to open credfile (%s)"):format(credfile)
|
||||
end
|
||||
local creds = {}
|
||||
local c = {}
|
||||
for line in f:lines() do
|
||||
local trim = function(s) return s:match('^()%s*$') and '' or s:match('^%s*(.*%S)') end
|
||||
line = trim(line)
|
||||
local user, pass = line:match("^([^%/]*)%/(.*)$")
|
||||
table.insert(creds, { [user]=pass } )
|
||||
table.insert(c, { [user]=pass } )
|
||||
end
|
||||
|
||||
table.insert( self.iterators, Iterators.credential_iterator( creds ) )
|
||||
table.insert( self.iterators, Iterators.credential_iterator( c ) )
|
||||
elseif ( mode and mode == 'user' ) then
|
||||
table.insert( self.iterators, Iterators.user_pw_iterator( usernames, passwords ) )
|
||||
elseif( mode and mode == 'pass' ) then
|
||||
|
||||
152
nselib/creds.lua
152
nselib/creds.lua
@@ -24,8 +24,8 @@
|
||||
-- credentials:
|
||||
-- <code>
|
||||
-- local c = creds.Credentials:new(creds.ALL_DATA, host, port)
|
||||
-- for _, cred in pairs(c:getCredentials(creds.State.VALID)) do
|
||||
-- chowContentForUser(cred.user, cred.pass)
|
||||
-- for cred in c:getCredentials(creds.State.VALID) do
|
||||
-- showContentForUser(cred.user, cred.pass)
|
||||
-- end
|
||||
-- </code>
|
||||
--
|
||||
@@ -34,25 +34,39 @@
|
||||
-- @author "Patrik Karlsson <patrik@cqure.net>"
|
||||
-- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
|
||||
|
||||
-- Version 0.1
|
||||
-- Version 0.3
|
||||
-- Created 2011/02/06 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
|
||||
-- Revised 2011/27/06 - v0.2 - revised by Patrik Karlsson <patrik@cqure.net>
|
||||
-- added documentation
|
||||
-- added getCredentials function
|
||||
-- * added documentation
|
||||
-- * added getCredentials function
|
||||
--
|
||||
-- Revised 2011/05/07 - v0.3 - revised by Patrik Karlsson <patrik@cqure.net>
|
||||
-- * modified getCredentials to return an iterator
|
||||
-- * added support for adding credentials as
|
||||
-- script arguments
|
||||
--
|
||||
|
||||
module(... or "creds", package.seeall)
|
||||
|
||||
require('ipOps')
|
||||
require('bit')
|
||||
|
||||
-- Table containing the different account states
|
||||
State = {
|
||||
LOCKED = { msg = 'Account is locked' },
|
||||
VALID = { msg = 'Account is valid' },
|
||||
DISABLED = { msg = 'Account is disabled' },
|
||||
CHANGEPW = { msg = 'Password needs to be changed at next logon' },
|
||||
LOCKED = 1,
|
||||
VALID = 2,
|
||||
DISABLED = 4,
|
||||
CHANGEPW = 8,
|
||||
PARAM = 16,
|
||||
}
|
||||
|
||||
StateMsg = {
|
||||
[State.LOCKED] = 'Account is locked',
|
||||
[State.VALID] = 'Account is valid',
|
||||
[State.DISABLED] = 'Account is disabled',
|
||||
[State.CHANGEPW] = 'Password needs to be changed at next logon',
|
||||
}
|
||||
|
||||
|
||||
ALL_DATA = "all_script_data"
|
||||
|
||||
-- The RegStorage class
|
||||
@@ -103,37 +117,37 @@ RegStorage = {
|
||||
self.filter.state = state
|
||||
end,
|
||||
|
||||
--- Retrieves the table containing all credential records
|
||||
--- Returns a credential iterator matching the selected filters
|
||||
--
|
||||
-- @return table containing all credential records
|
||||
-- @return a credential iterator
|
||||
getAll = function( self )
|
||||
local tbl = nmap.registry.creds
|
||||
local new_tbl = {}
|
||||
local host, port = self.filter.host, self.filter.port
|
||||
local function get_next()
|
||||
local host, port = self.filter.host, self.filter.port
|
||||
|
||||
if ( not(tbl) ) then return end
|
||||
if ( not(nmap.registry.creds) ) then return end
|
||||
|
||||
for _, v in pairs(tbl) do
|
||||
local h = ( v.host.ip or v.host )
|
||||
if ( not(host) and not(port) ) then
|
||||
if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then
|
||||
table.insert(new_tbl, v)
|
||||
end
|
||||
elseif ( not(host) and ( port == v.port ) ) then
|
||||
if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then
|
||||
table.insert(new_tbl, v)
|
||||
end
|
||||
elseif ( ( host and ( h == host or h == host.ip ) ) and not(port) ) then
|
||||
if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then
|
||||
table.insert(new_tbl, v)
|
||||
end
|
||||
elseif ( ( host and ( h == host or h == host.ip ) ) and port.number == v.port ) then
|
||||
if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then
|
||||
table.insert(new_tbl, v)
|
||||
for _, v in pairs(nmap.registry.creds) do
|
||||
local h = ( v.host.ip or v.host )
|
||||
if ( not(host) and not(port) ) then
|
||||
if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then
|
||||
coroutine.yield(v)
|
||||
end
|
||||
elseif ( not(host) and ( port == v.port ) ) then
|
||||
if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then
|
||||
coroutine.yield(v)
|
||||
end
|
||||
elseif ( ( host and ( h == host or h == host.ip ) ) and not(port) ) then
|
||||
if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then
|
||||
coroutine.yield(v)
|
||||
end
|
||||
elseif ( ( host and ( h == host or h == host.ip ) ) and port.number == v.port ) then
|
||||
if ( not(self.filter.state) or ( v.state == bit.band(self.filter.state, v.state) ) ) then
|
||||
coroutine.yield(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return new_tbl
|
||||
return coroutine.wrap(get_next)
|
||||
end,
|
||||
|
||||
}
|
||||
@@ -160,9 +174,6 @@ Credentials = {
|
||||
|
||||
--- Add a discovered credential
|
||||
--
|
||||
-- @param host host table, name or ip
|
||||
-- @param port number containing the port of the service
|
||||
-- @param service the name of the service
|
||||
-- @param user the name of the user
|
||||
-- @param pass the password of the user
|
||||
-- @param state of the account
|
||||
@@ -180,24 +191,67 @@ Credentials = {
|
||||
end
|
||||
end,
|
||||
|
||||
--- Returns all accounts for a given state, or all states if no filter is set
|
||||
--- Returns a credential iterator
|
||||
--
|
||||
-- @param state table containing a value from the <Code>State</code> table
|
||||
-- @return table containing accounts matching the state, or all accounts if
|
||||
-- no state was given. Accounts have the following fields:
|
||||
-- @param state mask containing values from the <Code>State</code> table
|
||||
-- @return credential iterator, returning a credential each time it's
|
||||
-- called. Unless filtered by the state mask all credentials
|
||||
-- for the host, port match are iterated over.
|
||||
-- The credential table has the following fields:
|
||||
-- <code>host</code> - table as received by the action function
|
||||
-- <code>port</code> - number containing the port number
|
||||
-- <code>user</code> - string containing the user name
|
||||
-- <code>pass</code> - string containing the user password
|
||||
-- <code>state</code> - a state table @see <code>State</code>
|
||||
-- <code>state</code> - a state number @see <code>State</code>
|
||||
-- <code>service</code> - string containing the name of the service
|
||||
-- <code>scriptname</code> - string containing the name of the
|
||||
-- script that added the credential
|
||||
getCredentials = function(self, state)
|
||||
if ( state ) then
|
||||
self.storage:setFilter(self.host, { number=self.port, service = self.service }, state)
|
||||
local function next_credential()
|
||||
if ( state ) then
|
||||
self.storage:setFilter(self.host, { number=self.port, service = self.service }, state)
|
||||
end
|
||||
|
||||
for cred in self.storage:getAll() do
|
||||
if ( ( self.scriptname == ALL_DATA ) or
|
||||
( cred.scriptname == self.scriptname ) ) then
|
||||
coroutine.yield(cred)
|
||||
end
|
||||
end
|
||||
|
||||
if ( state and State.PARAM == bit.band(state, State.PARAM) ) then
|
||||
local creds_global = stdnse.get_script_args('creds.global')
|
||||
local creds_service= stdnse.get_script_args('creds.' .. self.service )
|
||||
local creds_params
|
||||
|
||||
if ( creds_service ) then creds_params = creds_service end
|
||||
if ( creds_global and creds_service ) then
|
||||
creds_params = creds_params .. ',' .. creds_global
|
||||
elseif ( creds_global ) then
|
||||
creds_params = creds_global
|
||||
end
|
||||
|
||||
if ( not(creds_params) ) then return end
|
||||
|
||||
for _, cred in ipairs(stdnse.strsplit(",", creds_params)) do
|
||||
-- if the credential contains a ':' we have a user + pass pair
|
||||
-- if not, we only have a user with an empty password
|
||||
local user, pass
|
||||
if ( cred:match(":") ) then
|
||||
user, pass = cred:match("^(.-):(.-)$")
|
||||
else
|
||||
user = cred:match("^(.*)$")
|
||||
end
|
||||
coroutine.yield( { host = self.host,
|
||||
port = self.port,
|
||||
user = user,
|
||||
pass = pass,
|
||||
state = State.PARAM,
|
||||
service = self.service } )
|
||||
end
|
||||
end
|
||||
end
|
||||
return self.storage:getAll()
|
||||
return coroutine.wrap( next_credential )
|
||||
end,
|
||||
|
||||
--- Returns a table of credentials
|
||||
@@ -206,14 +260,14 @@ Credentials = {
|
||||
getTable = function(self)
|
||||
local result = {}
|
||||
|
||||
for _, v in pairs(self.storage:getAll()) do
|
||||
for v in self.storage:getAll() do
|
||||
local h = ( v.host.ip or v.host )
|
||||
local svc = ("%s/%s"):format(v.port,v.service)
|
||||
local c
|
||||
if ( v.user and #v.user > 0 ) then
|
||||
c = ("%s:%s - %s"):format(v.user, v.pass, v.state.msg)
|
||||
c = ("%s:%s - %s"):format(v.user, v.pass, StateMsg[v.state])
|
||||
else
|
||||
c = ("%s - %s"):format(v.pass, v.state.msg)
|
||||
c = ("%s - %s"):format(v.pass, StateMsg[v.state])
|
||||
end
|
||||
local script = v.scriptname
|
||||
assert(type(h)=="string", "Could not determine a valid host")
|
||||
@@ -255,7 +309,7 @@ Credentials = {
|
||||
output = output[1]
|
||||
output.name = nil
|
||||
end
|
||||
return output
|
||||
return (#output > 0 ) and output
|
||||
end,
|
||||
|
||||
--- Get credentials with optional host and port filter
|
||||
|
||||
Reference in New Issue
Block a user