mirror of
https://github.com/nmap/nmap.git
synced 2026-01-06 14:39:03 +00:00
o [NSE] Added the library xmpp.lua and the script xmpp-brute that performs
brute force password auditing against XMPP (Jabber) servers. [Patrik]
This commit is contained in:
13
CHANGELOG
13
CHANGELOG
@@ -1,12 +1,19 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE] Added the library xmpp.lua and the script xmpp-brute that performs
|
||||
brute force password auditing against XMPP (Jabber) servers. [Patrik]
|
||||
|
||||
o [NSE] Fixed a bug in the ssh2-enum-algos script that would prevent it from
|
||||
displaying any output unless run in debug mode. [Patrik]
|
||||
|
||||
o [NSE] Fixed the nsedebug print_hex() function so it does not print an
|
||||
empty line if there are no remaining characters, and improved its NSEDoc.
|
||||
[Chris Woodbury].
|
||||
|
||||
o [NSE] Added the scripts http-axis2-dir-traversal and http-litespeed-sourcecode-download
|
||||
that exploits a directory traversal and null byte poisoning vulnerabilities in
|
||||
Apache Axis2 and LiteSpeed Web Server respectively. [Paulino]
|
||||
o [NSE] Added the scripts http-axis2-dir-traversal and
|
||||
http-litespeed-sourcecode-download that exploits a directory traversal and
|
||||
null byte poisoning vulnerabilities in Apache Axis2 and LiteSpeed Web Server
|
||||
respectively. [Paulino]
|
||||
|
||||
o [Ncat] Ncat now no longer blocks while an ssl handshake is taking place or
|
||||
waiting to complete. [Shinnok]
|
||||
|
||||
415
nselib/xmpp.lua
Normal file
415
nselib/xmpp.lua
Normal file
@@ -0,0 +1,415 @@
|
||||
--- A XMPP (Jabber) library, implementing a minimal subset of the protocol
|
||||
-- enough to do authentication brute-force.
|
||||
--
|
||||
-- The XML parsing of tags isn't optimal but there's no other easy way
|
||||
-- (nulls or line-feeds) to match the end of a message. The parse_tag
|
||||
-- method in the XML class was borrowed from the initial xmpp.nse
|
||||
-- script written by Vasiliy Kulikov.
|
||||
--
|
||||
-- The library consist of the following classes:
|
||||
-- * <code>XML<code> - containing a minimal XML parser written by
|
||||
-- Vasiliy Kulikov.
|
||||
-- * <code>TagProcessor</code> - Contains processing code for common tags
|
||||
-- * <code>XMPP</code> - containing the low-level functions used to
|
||||
-- communicate with the Jabber server.
|
||||
-- * <code>Helper</code> - containing the main interface for script
|
||||
-- writers
|
||||
--
|
||||
-- The following sample illustrates how to use the library to authenticate
|
||||
-- to a XMPP sever:
|
||||
-- <code>
|
||||
-- local helper = xmpp.Helper:new(host, port, options)
|
||||
-- local status, err = helper:connect()
|
||||
-- status, err = helper:login(user, pass, "DIGEST-MD5")
|
||||
-- </code>
|
||||
--
|
||||
-- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
|
||||
-- @author Patrik Karlsson <patrik@cqure.net>
|
||||
--
|
||||
-- Version 0.2
|
||||
-- Created 07/19/2011 - v0.1 - Created by Patrik Karlsson
|
||||
-- Revised 07/22/2011 - v0.2 - Added TagProcessors and two new auth mechs:
|
||||
-- CRAM-MD5 and LOGIN <patrik@cqure.net>
|
||||
|
||||
module(... or "xmpp", package.seeall)
|
||||
|
||||
require 'base64'
|
||||
require 'sasl'
|
||||
|
||||
XML = {
|
||||
|
||||
-- This is a trivial XML processor written by Vasiliy Kulikov. It doesn't
|
||||
-- fully support XML, but it should be sufficient for the basic XMPP
|
||||
-- stream handshake. If you see stanzas with uncommon symbols, feel
|
||||
-- free to enhance these regexps.
|
||||
parse_tag = function(s)
|
||||
local _, _, contents, empty, name = string.find(s, "([^<]*)\<(/?)([?:%w-]+)")
|
||||
local attrs = {}
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
for k, v in string.gmatch(s, "%s([%w:]+)='([^']+)'") do
|
||||
attrs[k] = v
|
||||
end
|
||||
for k, v in string.gmatch(s, "%s([%w:]+)=\"([^\"]+)\"") do
|
||||
attrs[k] = v
|
||||
end
|
||||
|
||||
local finish = (empty ~= "") or (s:sub(#s-1) == '/>')
|
||||
|
||||
return { name = name,
|
||||
attrs = attrs,
|
||||
start = (empty == ""),
|
||||
contents = contents,
|
||||
finish = finish }
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
TagProcessor = {
|
||||
|
||||
["failure"] = function(socket, tag)
|
||||
return TagProcessor["success"](socket,tag)
|
||||
end,
|
||||
|
||||
["success"] = function(socket, tag)
|
||||
if ( tag.finish ) then return true end
|
||||
local newtag
|
||||
repeat
|
||||
local status, data = socket:receive_buf(">", true)
|
||||
if ( not(status) ) then
|
||||
return false, ("ERROR: Failed to process %s tag"):format(tag.name)
|
||||
end
|
||||
newtag = XML.parse_tag(data)
|
||||
until( newtag.finish and newtag.name == tag.name )
|
||||
if ( newtag.name == tag.name ) then return true, tag end
|
||||
return false, ("ERROR: Failed to process %s tag"):format(tag.name)
|
||||
end,
|
||||
|
||||
["challenge"] = function(socket, tag)
|
||||
local status, data = socket:receive_buf(">", true)
|
||||
if ( not(status) ) then return false, "ERROR: Failed to read challenge tag" end
|
||||
local tag = XML.parse_tag(data)
|
||||
|
||||
if ( not(status) or tag.name ~= "challenge" ) then
|
||||
return false, "ERROR: Failed to process challenge"
|
||||
end
|
||||
return status, (tag.contents and base64.dec(tag.contents))
|
||||
end,
|
||||
|
||||
|
||||
}
|
||||
|
||||
XMPP = {
|
||||
|
||||
--- Creates a new instance of the XMPP class
|
||||
--
|
||||
-- @param host table as receieved by the action function
|
||||
-- @param port table as receieved by the action function
|
||||
-- @param options table containing options, currently supported
|
||||
-- <code>timeout</code> - sets the socket timeout
|
||||
-- <code>servername</code> - sets the server name to use in
|
||||
-- communication with the server.
|
||||
new = function(self, host, port, options)
|
||||
local o = { host = host,
|
||||
port = port,
|
||||
options = options or {},
|
||||
auth = { mechs = {} } }
|
||||
o.options.timeout = o.options.timeout and o.options.timeout or 10
|
||||
o.servername = host.targetname or o.options.servername
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end,
|
||||
|
||||
--- Sends data to XMPP server
|
||||
-- @param data string containing data to send to server
|
||||
-- @return status true on success false on failure
|
||||
-- @return err string containing error message
|
||||
send = function(self, data)
|
||||
|
||||
-- this ain't pretty, but we try to "flush" what's left of the receive
|
||||
-- buffer, prior to send. This way we account for not reading to the
|
||||
-- end of one message resulting in the next read reading from our
|
||||
-- previous message.
|
||||
self.socket:set_timeout(1)
|
||||
repeat
|
||||
local status = self.socket:receive_buf("\0")
|
||||
until(not(status))
|
||||
self.socket:set_timeout(self.options.timeout * 1000)
|
||||
|
||||
return self.socket:send(data)
|
||||
end,
|
||||
|
||||
--- Receives a XML tag from the server
|
||||
--
|
||||
-- @param tag [optional] if unset, receives the next available tag
|
||||
-- if set, reads until the given tag has been found
|
||||
-- @param close [optional] if set, matches a closing tag
|
||||
receive_tag = function(self, tag, close)
|
||||
local result
|
||||
repeat
|
||||
local status, data = self.socket:receive_buf(">", true)
|
||||
if ( not(status) ) then return false, data end
|
||||
result = XML.parse_tag(data)
|
||||
until( ( not(tag) and (close == nil or result.finish == close ) ) or
|
||||
( tag == result.name and ( close == nil or result.finish == close ) ) )
|
||||
return true, result
|
||||
end,
|
||||
|
||||
--- Connects to the XMPP server
|
||||
-- @return status true on success, false on failure
|
||||
-- @return err string containing an error message if status is false
|
||||
connect = function(self)
|
||||
assert(self.servername,
|
||||
"Cannot connect to XMPP server without valid server name")
|
||||
|
||||
-- we may be reconnecting using SSL
|
||||
if ( not(self.socket) ) then
|
||||
self.socket = nmap.new_socket()
|
||||
self.socket:set_timeout(self.options.timeout * 1000)
|
||||
local status, err = self.socket:connect(self.host, self.port)
|
||||
if ( not(status) ) then
|
||||
return false, err
|
||||
end
|
||||
end
|
||||
local data = ("<?xml version='1.0' ?><stream:stream to='%s' xmlns='jabber:client'" ..
|
||||
" xmlns:stream='http://etherx.jabber.org/streams'" ..
|
||||
" version='1.0'>"):format(self.servername)
|
||||
|
||||
local status, err = self:send(data)
|
||||
if ( not(status) ) then return false, "ERROR: Failed to connect to server" end
|
||||
|
||||
local version, start_tls
|
||||
repeat
|
||||
local status, tag = self:receive_tag()
|
||||
if ( not(status) ) then return false, "ERROR: Failed to connect to server" end
|
||||
|
||||
if ( tag.name == "stream:stream" ) then
|
||||
version = tag.attrs and tag.attrs.version
|
||||
elseif ( tag.name == "starttls" and tag.start ) then
|
||||
status, tag = self:receive_tag()
|
||||
if ( not(status) ) then
|
||||
return false, "ERROR: Failed to connect to server"
|
||||
end
|
||||
if ( tag.name ~= "starttls" ) then
|
||||
start_tls = tag.name
|
||||
else
|
||||
start_tls = "optional"
|
||||
end
|
||||
elseif ( tag.name == "mechanism" and tag.finish ) then
|
||||
self.auth.mechs[tag.contents] = true
|
||||
end
|
||||
until(tag.name == "stream:features" and tag.finish)
|
||||
|
||||
if ( version ~= "1.0" ) then
|
||||
return false, "ERROR: Only version 1.0 is supported"
|
||||
end
|
||||
|
||||
if ( start_tls == "required" ) then
|
||||
status, err = self:send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>")
|
||||
if ( not(status) ) then return false, "ERROR: Failed to initiate STARTTLS" end
|
||||
local status, tag = self:receive_tag()
|
||||
if ( not(status) ) then return false, "ERROR: Failed to recevice from server" end
|
||||
if ( tag.name == "proceed" ) then
|
||||
status, err = self.socket:reconnect_ssl()
|
||||
return self:connect()
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
|
||||
--- Logs in to the XMPP server
|
||||
--
|
||||
-- @param username string
|
||||
-- @param password string
|
||||
-- @param mech string containing a supported authentication mechanism
|
||||
-- @return status true on success, false on failure
|
||||
-- @return err string containing error message if status is false
|
||||
login = function(self, username, password, mech)
|
||||
assert(mech == "PLAIN" or
|
||||
mech == "DIGEST-MD5" or
|
||||
mech == "CRAM-MD5" or
|
||||
mech == "LOGIN",
|
||||
"Unsupported authentication mechanism")
|
||||
|
||||
local auth = ("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' " ..
|
||||
"mechanism='%s'/>"):format(mech)
|
||||
|
||||
-- we currently don't do anything with the realm
|
||||
local realm
|
||||
|
||||
-- we need to cut the @domain.tld from the username
|
||||
if ( username:match("@") ) then
|
||||
username, realm = username:match("^(.*)@(.*)$")
|
||||
end
|
||||
|
||||
local status, result
|
||||
|
||||
if ( mech == "PLAIN" ) then
|
||||
local mech_params = { username, password }
|
||||
local auth_data = sasl.Helper:new(mech):encode(unpack(mech_params))
|
||||
auth = ("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' " ..
|
||||
"mechanism='%s'>%s</auth>"):format(mech, base64.enc(auth_data))
|
||||
|
||||
status, result = self.socket:send(auth)
|
||||
if ( not(status) ) then return false, "ERROR: Failed to send SASL PLAIN authentication" end
|
||||
|
||||
status, result = self:receive_tag()
|
||||
if ( not(status) ) then return false, "ERROR: Failed to receive login response" end
|
||||
|
||||
if ( result.name == "failure" ) then
|
||||
status = TagProcessor[result.name](self.socket, result)
|
||||
end
|
||||
else
|
||||
local status, err = self.socket:send(auth)
|
||||
if(not(status)) then return false, "ERROR: Failed to initiate SASL login" end
|
||||
|
||||
local chall
|
||||
status, result = self:receive_tag()
|
||||
if ( not(status) ) then return false, "ERROR: Failed to retrieve challenge" end
|
||||
status, chall = TagProcessor[result.name](self.socket, result)
|
||||
|
||||
if ( mech == "LOGIN" ) then
|
||||
if ( chall ~= "User Name" ) then
|
||||
return false, ("ERROR: Login expected 'User Name' received: %s"):format(chall)
|
||||
end
|
||||
self.socket:send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" ..
|
||||
base64.enc(username) ..
|
||||
"</response>")
|
||||
|
||||
status, result = self:receive_tag()
|
||||
if ( not(status) or result.name ~= "challenge") then
|
||||
return false, "ERROR: Receiving tag from server"
|
||||
end
|
||||
status, chall = TagProcessor[result.name](self.socket, result)
|
||||
|
||||
if ( chall ~= "Password" ) then
|
||||
return false, ("ERROR: Login expected 'Password' received: %s"):format(chall)
|
||||
end
|
||||
|
||||
self.socket:send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" ..
|
||||
base64.enc(password) ..
|
||||
"</response>")
|
||||
|
||||
status, result = self:receive_tag()
|
||||
if ( not(status) ) then return false, "ERROR: Failed to receive login challenge" end
|
||||
if ( result.name == "failure" ) then
|
||||
status = TagProcessor[result.name](self.socket, result)
|
||||
return false, "Login failed"
|
||||
end
|
||||
else
|
||||
local mech_params = { username, password, chall, "xmpp", "xmpp/" .. self.servername }
|
||||
local auth_data = sasl.Helper:new(mech):encode(unpack(mech_params))
|
||||
auth_data = "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" ..
|
||||
base64.enc(auth_data) .. "</response>"
|
||||
|
||||
status, err = self.socket:send(auth_data)
|
||||
|
||||
-- read to the end tag regardless of what it is
|
||||
-- it should be one of either: success, challenge or error
|
||||
repeat
|
||||
status, result = self:receive_tag()
|
||||
if ( not(status) ) then return false, "ERROR: Failed to receive login challenge" end
|
||||
|
||||
if ( result.name == "failure" ) then
|
||||
status = TagProcessor[result.name](self.socket, result)
|
||||
return false, "Login failed"
|
||||
elseif ( result.name == "success" ) then
|
||||
status = TagProcessor[result.name](self.socket, result)
|
||||
if ( not(status) ) then return false, "Failed to process success message" end
|
||||
return true, "Login success"
|
||||
elseif ( result.name ~= "challenge" ) then
|
||||
return false, "ERROR: Failed to receive login challenge"
|
||||
end
|
||||
until( result.name == "challenge" and result.finish )
|
||||
|
||||
if ( result.name == "challenge" and mech == "DIGEST-MD5" ) then
|
||||
status, result = self.socket:send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>")
|
||||
if ( not(status) ) then return false, "ERROR: Failed to send DIGEST-MD5 request" end
|
||||
status, result = self:receive_tag()
|
||||
if ( not(status) ) then return false, "ERROR: Failed to receive DIGEST-MD5 response" end
|
||||
end
|
||||
end
|
||||
end
|
||||
if ( result.name == "success" ) then
|
||||
return true, "Login success"
|
||||
end
|
||||
|
||||
return false, "Login failed"
|
||||
end,
|
||||
|
||||
--- Retrieves the available authentication mechanisms
|
||||
-- @return table containing all available authentication mechanisms
|
||||
getAuthMechs = function(self) return self.auth.mechs end,
|
||||
|
||||
--- Disconnects the socket from the server
|
||||
-- @return status true on success, false on failure
|
||||
disconnect = function(self)
|
||||
local status, err = self.socket:close()
|
||||
self.socket = nil
|
||||
return status, err
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
|
||||
Helper = {
|
||||
|
||||
--- Creates a new Helper instance
|
||||
-- @param host table as receieved by the action function
|
||||
-- @param port table as receieved by the action function
|
||||
-- @param options table containing options, currently supported
|
||||
-- <code>timeout</code> - sets the socket timeout
|
||||
-- <code>servername</code> - sets the server name to use in
|
||||
-- communication with the server.
|
||||
new = function(self, host, port, options)
|
||||
local o = { host = host,
|
||||
port = port,
|
||||
options = options or {},
|
||||
xmpp = XMPP:new(host, port, options),
|
||||
state = "" }
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end,
|
||||
|
||||
--- Connects to the XMPP server and starts the initial communication
|
||||
-- @return status true on success, false on failure
|
||||
-- @return err string containing an error message is status is false
|
||||
connect = function(self)
|
||||
if ( not(self.host.targetname) and
|
||||
not(self.options.servername) ) then
|
||||
return false, "ERROR: Cannot connect to XMPP server without valid server name"
|
||||
end
|
||||
self.state = "CONNECTED"
|
||||
return self.xmpp:connect()
|
||||
end,
|
||||
|
||||
--- Login to the XMPP server
|
||||
--
|
||||
-- @param username string
|
||||
-- @param password string
|
||||
-- @param mech string containing a supported authentication mechanism
|
||||
-- (@see <code>getAuthMechs</code>)
|
||||
login = function(self, username, password, mech)
|
||||
return self.xmpp:login(username, password, mech)
|
||||
end,
|
||||
|
||||
--- Retrieves the available authentication mechanisms
|
||||
-- @return table containing all available authentication mechanisms
|
||||
getAuthMechs = function(self)
|
||||
if ( self.state == "CONNECTED" ) then
|
||||
return self.xmpp:getAuthMechs()
|
||||
end
|
||||
return
|
||||
end,
|
||||
|
||||
--- Closes the connection to the server
|
||||
close = function(self)
|
||||
self.xmpp:disconnect()
|
||||
self.state = "DISCONNECTED"
|
||||
end,
|
||||
|
||||
}
|
||||
@@ -227,4 +227,5 @@ Entry { filename = "wdb-version.nse", categories = { "default", "discovery", "ve
|
||||
Entry { filename = "whois.nse", categories = { "discovery", "external", "safe", } }
|
||||
Entry { filename = "wsdd-discover.nse", categories = { "default", "discovery", "safe", } }
|
||||
Entry { filename = "x11-access.nse", categories = { "auth", "default", "safe", } }
|
||||
Entry { filename = "xmpp-brute.nse", categories = { "brute", "intrusive", } }
|
||||
Entry { filename = "xmpp.nse", categories = { "default", "discovery", "safe", } }
|
||||
|
||||
134
scripts/xmpp-brute.nse
Normal file
134
scripts/xmpp-brute.nse
Normal file
@@ -0,0 +1,134 @@
|
||||
description = [[
|
||||
Performs brute force password auditing against XMPP (jabber) servers.
|
||||
]]
|
||||
|
||||
---
|
||||
-- @usage
|
||||
-- nmap -p 5222 --script xmpp-brute <host>
|
||||
--
|
||||
-- @output
|
||||
-- PORT STATE SERVICE
|
||||
-- 5222/tcp open xmpp-client
|
||||
-- | xmpp-brute:
|
||||
-- | Accounts
|
||||
-- | CampbellJ:arthur321 - Account is valid
|
||||
-- | CampbellA:joan123 - Account is valid
|
||||
-- | WalkerA:auggie123 - Account is valid
|
||||
-- | Statistics
|
||||
-- |_ Performed 6237 guesses in 5 seconds, average tps: 1247
|
||||
--
|
||||
-- @args xmpp-brute.auth authentication mechanism to use LOGIN, PLAIN, CRAM-MD5
|
||||
-- or DIGEST-MD5
|
||||
-- @args xmpp-brute.servername needed when host name cannot be automatically
|
||||
-- determined (eg. when running against an IP, instead of hostname)
|
||||
--
|
||||
-- Version 0.1
|
||||
-- Created 07/21/2011 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
|
||||
|
||||
require 'brute'
|
||||
require 'shortport'
|
||||
require 'xmpp'
|
||||
|
||||
author = "Patrik Karlsson"
|
||||
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
categories = {"brute", "intrusive"}
|
||||
|
||||
portrule = shortport.port_or_service(5222, {"jabber", "xmpp-client"})
|
||||
|
||||
local mech
|
||||
|
||||
ConnectionPool = {}
|
||||
|
||||
Driver =
|
||||
{
|
||||
|
||||
-- Creates a new driver instance
|
||||
-- @param host table as received by the action method
|
||||
-- @param port table as received by the action method
|
||||
-- @param pool an instance of the ConnectionPool
|
||||
new = function(self, host, port, options )
|
||||
local o = { host = host, port = port, options = options }
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end,
|
||||
|
||||
-- Connects to the server (retrieves a connection from the pool)
|
||||
connect = function( self )
|
||||
self.helper = ConnectionPool[coroutine.running()]
|
||||
if ( not(self.helper) ) then
|
||||
self.helper = xmpp.Helper:new( self.host, self.port, self.options )
|
||||
local status, err = self.helper:connect()
|
||||
if ( not(status) ) then return false, err end
|
||||
ConnectionPool[coroutine.running()] = self.helper
|
||||
end
|
||||
return true
|
||||
end,
|
||||
|
||||
-- Attempts to login to the server
|
||||
-- @param username string containing the username
|
||||
-- @param password string containing the password
|
||||
-- @return status true on success, false on failure
|
||||
-- @return brute.Error on failure and brute.Account on success
|
||||
login = function( self, username, password )
|
||||
local status, err = self.helper:login( username, password, mech )
|
||||
if ( status ) then
|
||||
self.helper:close()
|
||||
self.helper:connect()
|
||||
return true, brute.Account:new(username, password, creds.State.VALID)
|
||||
end
|
||||
if ( err:match("^ERROR: Failed to .* data$") ) then
|
||||
self.helper:close()
|
||||
self.helper:connect()
|
||||
local err = brute.Error:new( err )
|
||||
-- This might be temporary, set the retry flag
|
||||
err:setRetry( true )
|
||||
return false, err
|
||||
end
|
||||
return false, brute.Error:new( "Incorrect password" )
|
||||
end,
|
||||
|
||||
-- Disconnects from the server (release the connection object back to
|
||||
-- the pool)
|
||||
disconnect = function( self )
|
||||
return true
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
|
||||
action = function(host, port)
|
||||
|
||||
local options = { servername = stdnse.get_script_args("xmpp-brute.servername") }
|
||||
local helper = xmpp.Helper:new(host, port, options)
|
||||
local status, err = helper:connect()
|
||||
if ( not(status) ) then
|
||||
return "\n ERROR: Failed to connect to XMPP server"
|
||||
end
|
||||
|
||||
local mechs = helper:getAuthMechs()
|
||||
if ( not(mechs) ) then
|
||||
return "\n ERROR: Failed to retreive authentication mechs from XMPP server"
|
||||
end
|
||||
|
||||
local mech_prio = stdnse.get_script_args("xmpp-brute.auth")
|
||||
mech_prio = ( mech_prio and { mech_prio } ) or { "PLAIN", "LOGIN", "CRAM-MD5", "DIGEST-MD5"}
|
||||
|
||||
for _, mp in ipairs(mech_prio) do
|
||||
for m, _ in pairs(mechs) do
|
||||
if ( mp == m ) then mech = m; break end
|
||||
end
|
||||
if ( mech ) then break end
|
||||
end
|
||||
|
||||
if ( not(mech) ) then
|
||||
return "\n ERROR: Failed to find suitable authentication mechanism"
|
||||
end
|
||||
|
||||
local engine = brute.Engine:new(Driver, host, port, options)
|
||||
engine.options.script_name = SCRIPT_NAME
|
||||
status, result = engine:start()
|
||||
|
||||
return result
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user