1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
local brute = require "brute"
local creds = require "creds"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local table = require "table"
description = [[
Performs brute force password auditing against the Lotus Domino Console.
]]
---
-- @usage
-- nmap --script domcon-brute -p 2050 <host>
--
-- @output
-- PORT STATE SERVICE REASON
-- 2050/tcp open unknown syn-ack
-- | domcon-brute:
-- | Accounts
-- |_ patrik karlsson:secret => Login correct
--
-- Summary
-- -------
-- x The Driver class contains the driver implementation used by the brute
-- library
--
--
-- Version 0.1
-- Created 07/12/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
--
author = "Patrik Karlsson"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
portrule = shortport.port_or_service(2050, "", "tcp", "open")
local not_admins = {}
SocketPool = {
new = function(self, max_sockets)
local o = {}
setmetatable(o, self)
self.__index = self
o.max_sockets = max_sockets
o.pool = {}
return o
end,
getSocket = function(self, host, port)
while(true) do
for i=1, #self.pool do
if ( not( self.pool[i].inuse ) ) then
self.pool[i].inuse = true
return self.pool[i].socket
end
end
if ( #self.pool < self.max_sockets ) then
local socket = nmap.new_socket()
local status = socket:connect( host, port )
if ( status ) then
socket:reconnect_ssl()
end
if ( status and socket ) then
table.insert( self.pool, {['socket'] = socket, ['inuse'] = false})
end
end
stdnse.sleep(1)
end
end,
releaseSocket = function( self, socket )
for i=1, #self.pool do
if( socket == self.pool[i].socket ) then
self.pool[i].inuse = false
break
end
end
end,
shutdown = function( self )
for i=1, #self.pool do
self.pool[i].socket:close()
end
end,
}
Driver =
{
new = function(self, host, port, options)
local o = {}
setmetatable(o, self)
self.__index = self
o.host = host
o.port = port
o.sockpool = options
return o
end,
connect = function( self )
self.socket = self.sockpool:getSocket( self.host, self.port )
if ( self.socket ) then
return true
else
return false
end
end,
--- Attempts to login to the Lotus Domino Console
--
-- @param username string containing the login username
-- @param password string containing the login password
-- @return status, true on success, false on failure
-- @return brute.Error object on failure
-- creds.Account object on success
login = function( self, username, password )
local data = ("#UI %s,%s\n"):format(username,password)
local status
if ( not_admins[username] ) then
return false, brute.Error:new( "Incorrect password" )
end
status, data = self.socket:send( data )
if ( not(status) ) then
local err = brute.Error:new( data )
err:setRetry(true)
return false, err
end
status, data = self.socket:receive_bytes(5)
if ( status and data:match("NOT_REG_ADMIN") ) then
not_admins[username] = true
elseif( status and data:match("VALID_USER") ) then
return true, creds.Account:new( username, password, creds.State.VALID)
end
return false, brute.Error:new( "Incorrect password" )
end,
disconnect = function( self )
self.sockpool:releaseSocket( self.socket )
end,
}
action = function(host, port)
local status, result
local pool = SocketPool:new(10)
local engine = brute.Engine:new(Driver, host, port, pool )
engine.options.script_name = SCRIPT_NAME
status, result = engine:start()
pool:shutdown()
return result
end
|