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

Compare commits

...

23 Commits

Author SHA1 Message Date
nnposter
cf24dab1c9 Streamline the loop construct 2025-12-04 19:44:12 +00:00
nnposter
df4896eadb Remove unnecessary conditional 2025-12-04 19:39:52 +00:00
nnposter
472b586767 Refactor the script to address multiple issues
- Add support for HTTPS
  - Add support for IPv6
  - Add support for more than one path argument
  - Properly identify the Location header in the HTTP response
  - Properly identify the destination host in the Location header
  - Leverage normalized IP address comparison
  - Avoid processing the HTTP response body, possibly "endless"
  - Add the found IP address as a new scan target (optionally)
Close #3218, close #3191)
2025-12-02 23:55:01 +00:00
nnposter
306263da43 Explain the effect of arguments that are not script-specific. Close #3223, close #3221, fix #3211 2025-12-02 22:48:31 +00:00
nnposter
c0a01aa7e1 Keep a local function local 2025-12-02 04:49:44 +00:00
nnposter
46fe5228f4 Populate jobname and owner even without Apple-specific attributes 2025-11-28 03:48:38 +00:00
nnposter
6dc02c9bcd Remove duplicate code 2025-11-28 03:45:12 +00:00
nnposter
3d205335b9 Remove development leftover 2025-11-28 03:41:56 +00:00
nnposter
138c7b7467 Eliminate unnecessary repeated lookups 2025-11-28 03:40:56 +00:00
nnposter
5daccaed1d Remove unnecessary variable shadowing logically the same parameter 2025-11-25 03:03:26 +00:00
nnposter
790deb7daf Remove unused variable 2025-11-25 02:59:19 +00:00
nnposter
a04fc3389e Use the correct variable for error checking. Close #3232 2025-11-23 02:55:21 +00:00
nnposter
a74125aef5 Add missing cookie attributes 2025-11-01 23:34:30 +00:00
nnposter
f5a3251e97 Use the correct the port range, 512-1023, not 513-1024.
Detect if binding a socket to a given port failed and retry.
Close #3196
2025-11-01 22:52:49 +00:00
nnposter
8d7fa538e3 Properly detect if binding an RPC socket to a given port failed. Close #3194
Testing the return status of socket:bind() and socket:connect() is not enough.
For details, see #1939.
2025-11-01 22:34:51 +00:00
nnposter
8d06576dbb Remove deprecated category "Application". Close #3217 2025-10-28 22:57:18 +00:00
nnposter
d2d591ce0c Avoid a crash when the IP contains a colon but no hextets 2025-10-27 01:19:40 +00:00
nnposter
4f7c92fbac Include operand "ne" in the documentation 2025-10-26 19:54:18 +00:00
nnposter
d2fbcc6cd6 Perform effective socket error checking 2025-10-26 02:23:22 +00:00
nnposter
b4b921c913 Streamline the code by using math.min() 2025-10-26 02:14:47 +00:00
nnposter
81b0568452 Remove redundant code 2025-10-26 01:42:15 +00:00
nnposter
7a989ff957 Remove duplicate of previously defined skip_space() 2025-10-26 01:37:00 +00:00
nnposter
9289bbccee Skip over contiguous linear whitespace in a single step 2025-10-26 01:35:07 +00:00
11 changed files with 212 additions and 207 deletions

View File

@@ -1,5 +1,16 @@
#Nmap Changelog ($Id$); -*-text-*-
o [GH#3191][GH#3218] Script http-internal-ip-disclosure has been enhanced,
including added support for IPv6 and HTTPS and more accurate processing
of target responses. [nnposter]
o [GH#3194] RPC-based scripts were sporadically failing due to privileged
port conflicts. [nnposter]
o [GH#3196] Script rlogin-brute was sporadically failing due to using
an off-by-one range for privileged ports and not handling potential
port conflicts. [nnposter]
Nmap 7.98 [2025-08-21]
o [SECURITY] Rebuilt the Windows self-installer with NSIS 3.11, addressing

View File

@@ -2480,9 +2480,20 @@ escapes a quote. A backslash is only used to escape quotation marks in this
special case; in all other cases a backslash is interpreted literally. Values
may also be tables enclosed in <literal>{}</literal>, just as in Lua. A table
may contain simple string values or more name-value pairs, including nested
tables. Many scripts qualify their arguments with the script name, as in <literal>xmpp-info.server_name</literal>. You may use that full qualified version to affect just the specified script, or you may pass the unqualified version (<literal>server_name</literal> in this case) to affect all scripts using that argument name. A script will first check for its fully qualified argument name (the name specified in its documentation) before it accepts an unqualified argument name. A complex example of script arguments is
<option>--script-args 'user=foo,pass=",{}=bar",whois={whodb=nofollow+ripe},xmpp-info.server_name=localhost'</option>. The online NSE Documentation Portal at <ulink url="https://nmap.org/nsedoc/"/>
lists the arguments that each script accepts.
tables. A complex example of script arguments is
<option>--script-args 'user=foo,pass=",{}=bar",whois={whodb=nofollow+ripe},xmpp-info.server_name=localhost'</option>.
Many scripts qualify their arguments with the script name, as in
<literal>xmpp-info.server_name</literal>. A script will first check for its
fully qualified argument name (the name specified in its documentation) before
it accepts an unqualified argument name (<literal>server_name</literal> in this
case). Some arguments are not specific to one script. They typically effect
behavior of a library and therefore potentially all the scripts that use the
library. (One such example is <literal>http.useragent</literal>, which sets
the default HTTP User-Agent header for every web request, regardless which
script sends it.) It is not possible for the exact same argument to be given
different values for diferent scripts. The online NSE Documentation Portal at
<ulink url="https://nmap.org/nsedoc/"/> lists the arguments that each script
accepts.
</para>
</listitem>
</varlistentry>

View File

@@ -276,7 +276,6 @@ local function get_quoted_string(s, offset, crlf)
-- continuation." So there are really two definitions of quoted-string,
-- depending on whether it's in a header field or not. This function does
-- not allow CRLF.
c = s:sub(i, i)
if c ~= "\t" and c:match("^[\0\001-\031\127]$") then
error(string.format("Unexpected control character in quoted-string: 0x%02X.", c:byte(1)))
end
@@ -292,10 +291,9 @@ local function skip_lws(s, pos)
local _, e
while true do
while string.match(s, "^[ \t]", pos) do
pos = pos + 1
end
_, e = string.find(s, "^\r?\n[ \t]", pos)
_, pos = string.find(s, "^[ \t]*", pos)
pos = pos + 1
_, e = string.find(s, "^\r?\n[ \t]+", pos)
if not e then
return pos
end
@@ -360,7 +358,19 @@ local function validate_options(options)
stdnse.debug1("http: options.cookies[i].max-age should be a string")
bad = true
end
elseif not (cookie_key == 'httponly' or cookie_key == 'secure') then
elseif(cookie_key == 'domain') then
if(type(cookie_value) ~= 'string') then
stdnse.debug1("http: options.cookies[i].domain should be a string")
bad = true
end
elseif(cookie_key == 'samesite') then
if(type(cookie_value) ~= 'string') then
stdnse.debug1("http: options.cookies[i].samesite should be a string")
bad = true
end
elseif not (cookie_key == 'httponly'
or cookie_key == 'secure'
or cookie_key == 'partitioned') then
stdnse.debug1("http: Unknown field in cookie table: %s", cookie_key)
-- Ignore unrecognized attributes (per RFC 6265, Section 5.2)
end
@@ -2024,27 +2034,24 @@ function pipeline_go(host, port, all_requests)
stdnse.debug3("HTTP pipeline: connlimit=%d, batchlimit=%d", connlimit, batchlimit)
while #responses < #all_requests do
local status, err
-- reconnect if necessary
if connsent >= connlimit or resp.truncated or not socket:get_info() then
socket:close()
stdnse.debug3("HTTP pipeline: reconnecting")
socket:set_timeout(pipeline_comm_opts.request_timeout)
socket:connect(host, port, bopt)
if not socket then
return nil
status, err = socket:connect(host, port, bopt)
if not status then
stdnse.debug3("HTTP pipeline: cannot reconnect: %s", err)
return responses
end
partial = ""
connsent = 0
end
if connlimit > connsent + #all_requests - #responses then
connlimit = connsent + #all_requests - #responses
end
-- decrease the connection limit to match what we still need to send
connlimit = math.min(connlimit, connsent + #all_requests - #responses)
-- determine the current batch size
local batchsize = connlimit - connsent
if batchsize > batchlimit then
batchsize = batchlimit
end
local batchsize = math.min(connlimit - connsent, batchlimit)
stdnse.debug3("HTTP pipeline: batch=%d, conn=%d/%d, resp=%d/%d", batchsize, connsent, connlimit, #responses, #all_requests)
-- build and send a batch of requests
@@ -2055,7 +2062,11 @@ function pipeline_go(host, port, all_requests)
req.options.header = force_header(req.options.header, "Connection", connmode)
table.insert(requests, build_request(host, port, req.method, req.path, req.options))
end
socket:send(table.concat(requests))
status, err = socket:send(table.concat(requests))
if not status then
stdnse.debug3("HTTP pipeline: cannot send: %s", err)
return responses
end
-- receive batch responses
for i = 1, batchsize do
@@ -2082,19 +2093,9 @@ function pipeline_go(host, port, all_requests)
return responses
end
-- Parsing of specific headers. skip_space and the read_* functions return the
-- Parsing of specific headers. The read_* functions return the
-- byte index following whatever they have just read, or nil on error.
-- Skip whitespace (that has already been folded from LWS). See RFC 2616,
-- section 2.2, definition of LWS.
local function skip_space(s, pos)
local _
_, pos = string.find(s, "^[ \t]*", pos)
return pos + 1
end
-- See RFC 2616, section 2.2.
local function read_token(s, pos)
local _, token

View File

@@ -216,9 +216,9 @@ end
-- @param left String representing an IPv4 or IPv6 address. Shortened
-- notation is permitted.
-- @param op A comparison operator which may be one of the following strings:
-- <code>"eq"</code>, <code>"ge"</code>, <code>"le"</code>,
-- <code>"gt"</code> or <code>"lt"</code> (respectively ==, >=, <=,
-- >, <).
-- <code>"eq"</code>, <code>"ne"</code>, <code>"ge"</code>,
-- <code>"le"</code>, <code>"gt"</code> or <code>"lt"</code>
-- (respectively ==, ~=, >=, <=, >, <).
-- @param right String representing an IPv4 or IPv6 address. Shortened
-- notation is permitted.
-- @usage
@@ -381,6 +381,9 @@ expand_ip = function( ip, family )
for hdt in string.gmatch( ip, "[%.z%x]+" ) do
hexadectets[#hexadectets+1] = hdt
end
if #hexadectets == 0 then
return nil, ( err4:gsub( "IPv4", "IPv6" ) )
end
-- deal with IPv4in6 (last hexadectet only)
local t = {}

View File

@@ -83,35 +83,30 @@ IPP = {
attrib.value = {}
table.insert(attrib.value, { tag = attrib.tag, val = val })
repeat
while pos + 3 < #data do
local tag, name_len, val
if ( #data < pos + 3 ) then
tag, name_len, pos = string.unpack(">BI2", data, pos)
if name_len > 0 then
-- done; start of a new attribute
pos = pos - 3
break
end
tag, name_len, pos = string.unpack(">BI2", data, pos)
if ( name_len == 0 ) then
val, pos = string.unpack(">s2", data, pos)
table.insert(attrib.value, { tag = tag, val = val })
else
pos = pos - 3
end
until( name_len ~= 0 )
val, pos = string.unpack(">s2", data, pos)
table.insert(attrib.value, { tag = tag, val = val })
end
-- do minimal decoding
for i=1, #attrib.value do
if ( attrib.value[i].tag == IPP.Attribute.IPP_TAG_INTEGER ) then
attrib.value[i].val = string.unpack(">I4", attrib.value[i].val)
elseif ( attrib.value[i].tag == IPP.Attribute.IPP_TAG_ENUM ) then
attrib.value[i].val = string.unpack(">I4", attrib.value[i].val)
for _, av in ipairs(attrib.value) do
if av.tag == IPP.Attribute.IPP_TAG_INTEGER then
av.val = string.unpack(">I4", av.val)
elseif av.tag == IPP.Attribute.IPP_TAG_ENUM then
av.val = string.unpack(">I4", av.val)
end
end
if ( 1 == #attrib.value ) then
attrib.value = attrib.value[1].val
end
--print(attrib.name, attrib.value, stdnse.tohex(val))
return pos, attrib
end,
@@ -152,26 +147,14 @@ IPP = {
-- @param tag number containing the attribute tag
getAttribute = function(self, name, tag)
for _, attrib in ipairs(self.attribs) do
if ( attrib.name == name ) then
if ( not(tag) ) then
return attrib
elseif ( tag and attrib.tag == tag ) then
return attrib
end
if attrib.name == name and (not tag or attrib.tag == tag) then
return attrib
end
end
end,
getAttributeValue = function(self, name, tag)
for _, attrib in ipairs(self.attribs) do
if ( attrib.name == name ) then
if ( not(tag) ) then
return attrib.value
elseif ( tag and attrib.tag == tag ) then
return attrib.value
end
end
end
return (self:getAttribute(name, tag) or {}).value
end,
__tostring = function(self)
@@ -332,7 +315,7 @@ Helper = {
request:addAttributeGroup(ag)
local status, response = HTTP.Request( self.host, self.port, tostring(request) )
if ( not(response) ) then
if not status then
return status, response
end
@@ -350,9 +333,7 @@ Helper = {
local printer = {}
for k, v in pairs(attrib) do
if ( ag:getAttributeValue(k) ) then
printer[v] = ag:getAttributeValue(k)
end
printer[v] = ag:getAttributeValue(k)
end
table.insert(printers, printer)
end
@@ -360,7 +341,7 @@ Helper = {
end,
getQueueInfo = function(self, uri)
local uri = uri or ("ipp://%s/"):format(self.host.ip)
uri = uri or ("ipp://%s/"):format(self.host.ip)
local attribs = {
IPP.Attribute:new(IPP.Attribute.IPP_TAG_CHARSET, "attributes-charset", "utf-8" ),
@@ -375,7 +356,7 @@ Helper = {
{ tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-name" },
{ tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-state" },
{ tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "printer-uri" },
-- { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-originating-user-name" },
{ tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-originating-user-name" },
-- { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-printer-state-message" },
-- { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-printer-uri" },
{ tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "time-at-creation" } } ),
@@ -387,23 +368,25 @@ Helper = {
request:addAttributeGroup(ag)
local status, response = HTTP.Request( self.host, self.port, tostring(request) )
if ( not(response) ) then
if not status then
return status, response
end
local results = {}
for _, ag in ipairs(response:getAttributeGroups(IPP.Attribute.IPP_TAG_JOB)) do
local uri = ag:getAttributeValue("printer-uri")
local printer = uri:match(".*/(.*)$") or "Unknown"
local printer = ag:getAttributeValue("printer-uri"):match(".*/(.*)$") or "Unknown"
-- some jobs have multiple state attributes, so far the ENUM ones have been correct
local state = ag:getAttributeValue("job-state", IPP.Attribute.IPP_TAG_ENUM) or ag:getAttributeValue("job-state")
-- some jobs have multiple id tag, so far the INTEGER type have shown the correct ID
local id = ag:getAttributeValue("job-id", IPP.Attribute.IPP_TAG_INTEGER) or ag:getAttributeValue("job-id")
local attr = ag:getAttribute("time-at-creation")
local tm = ag:getAttributeValue("time-at-creation")
local size = ag:getAttributeValue("job-k-octets") .. "k"
local jobname = ag:getAttributeValue("com.apple.print.JobInfo.PMJobName") or "Unknown"
local owner = ag:getAttributeValue("com.apple.print.JobInfo.PMJobOwner") or "Unknown"
local jobname = ag:getAttributeValue("com.apple.print.JobInfo.PMJobName")
or ag:getAttributeValue("job-name")
or "Unknown"
local owner = ag:getAttributeValue("com.apple.print.JobInfo.PMJobOwner")
or ag:getAttributeValue("job-originating-user-name")
or "Unknown"
results[printer] = results[printer] or {}
table.insert(results[printer], {

View File

@@ -154,67 +154,54 @@ Comm = {
-- @return status boolean true on success, false on failure
-- @return string containing error message (if status is false)
Connect = function(self, host, port, timeout)
local status, err, socket
status, err = self:ChkProgram()
if (not(status)) then
timeout = timeout or stdnse.get_timeout(host, 10000)
local status, err = self:ChkProgram()
if not status then
return status, err
end
status, err = self:ChkVersion()
if (not(status)) then
if not status then
return status, err
end
timeout = timeout or stdnse.get_timeout(host, 10000)
local new_socket = function(...)
local socket = nmap.new_socket(...)
socket:set_timeout(timeout)
return socket
end
if ( port.protocol == "tcp" ) then
if nmap.is_privileged() then
-- Try to bind to a reserved port
for i = 1, 10, 1 do
local resvport = math.random(512, 1023)
socket = new_socket()
status, err = socket:bind(nil, resvport)
local socket = nmap.new_socket(port.protocol)
if nmap.is_privileged() then
-- Let's make several attempts to bind to an unused well-known port
for _ = 1, 10 do
local srcport = math.random(512, 1023)
status, err = socket:bind(nil, srcport)
if status then
socket:set_timeout(timeout)
status, err = socket:connect(host, port)
if status then
status, err = socket:connect(host, port)
if status or err == "TIMEOUT" then break end
socket:close()
-- socket:connect() succeeds even if mksock_bind_addr() fails.
-- It just assigns an ephemeral port instead of our choice,
-- so we need to check the actual source port afterwards.
local lport
status, err, lport = socket:get_info()
if status then
if lport == srcport then
break
end
status = false
err = "Address already in use"
end
end
end
else
socket = new_socket()
status, err = socket:connect(host, port)
socket:close()
end
else
if nmap.is_privileged() then
-- Try to bind to a reserved port
for i = 1, 10, 1 do
local resvport = math.random(512, 1023)
socket = new_socket("udp")
status, err = socket:bind(nil, resvport)
if status then
status, err = socket:connect(host, port)
if status or err == "TIMEOUT" then break end
socket:close()
end
end
else
socket = new_socket("udp")
status, err = socket:connect(host, port)
end
-- No privileges to force a specific source port
status, err = socket:connect(host, port)
end
if (not(status)) then
return status, string.format("%s connect error: %s",
self.program, err)
else
self.socket = socket
self.host = host
self.ip = host.ip
self.port = port.number
self.proto = port.protocol
return status, nil
if not status then
return status, ("%s connect error: %s"):format(self.program, err)
end
self.socket = socket
self.host = host
self.ip = host.ip
self.port = port.number
self.proto = port.protocol
return status, nil
end,
--- Disconnects from the remote program

View File

@@ -74,7 +74,7 @@ local ELEMENTS = {["Type"] = "Type",
["string"] = "SOAPACTIONS",
["SubDeviceURLs"] = "Sub Device URLs"}
function get_text_callback(store, name)
local function get_text_callback(store, name)
if ELEMENTS[name] == nil then return end
name = ELEMENTS[name]
if name == 'SOAPACTIONS' or name == 'Sub Device URLs' or name == 'Type' then

View File

@@ -1,21 +1,30 @@
local comm = require "comm"
local ipOps = require "ipOps"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local ipOps = require "ipOps"
local target = require "target"
local url = require "url"
description = [[
Determines if the web server leaks its internal IP address when sending an HTTP/1.0 request without a Host header.
Determines if the web server leaks its internal IP address when sending
an HTTP/1.0 request without a Host header.
Some misconfigured web servers leak their internal IP address in the response
headers when returning a redirect response. This is a known issue for some
versions of Microsoft IIS, but affects other web servers as well.
If script argument <code>newtargets</code> is set, the script will
add the found IP address as a new target into the scan queue. (See
the documentation for NSE library <code>target</code> for details.)
]]
---
-- @usage nmap --script http-internal-ip-disclosure <target>
-- @usage nmap --script http-internal-ip-disclosure --script-args http-internal-ip-disclosure.path=/path <target>
-- @usage nmap --script http-internal-ip-disclosure --script-args http-internal-ip-disclosure.path=/mypath <target>
--
-- @args http-internal-ip-disclosure.path Path to URI. Default: /
-- @args http-internal-ip-disclosure.path Path (or a table of paths) to probe
-- Default: /
--
-- @output
-- 80/tcp open http syn-ack
@@ -27,61 +36,59 @@ versions of Microsoft IIS, but affects other web servers as well.
--
-- @see ssl-cert-intaddr.nse
author = "Josh Amishav-Zlatin"
author = {"Josh Amishav-Zlatin", "nnposter"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = { "vuln", "discovery", "safe" }
portrule = shortport.http
local function generateHttpV1_0Req(host, port, path)
local redirectIP, privateIP
local socket = nmap.new_socket()
socket:connect(host, port)
local cmd = "GET " .. path .. " HTTP/1.0\r\n\r\n"
socket:send(cmd)
while true do
local status, lines = socket:receive_lines(1)
if not status then
break
end
-- Check if the response contains a location header
if lines:match("Location") then
local locTarget = lines:match("Location: [%a%p%d]+")
-- Check if the redirect location contains an IP address
redirectIP = locTarget:match("[%d%.]+")
if redirectIP then
privateIP = ipOps.isPrivate(redirectIP)
end
stdnse.debug1("Location: %s", locTarget )
stdnse.debug1("Internal IP: %s", redirectIP )
end
end
socket:close()
-- Only report if the internal IP leaked is different then the target IP
if privateIP and redirectIP ~= host.ip then
return redirectIP
end
end
action = function(host, port)
local output = stdnse.output_table()
local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/"
local IP = generateHttpV1_0Req(host, port, path)
-- Check /images which is often vulnerable on some unpatched IIS servers
if not IP and path ~= "/images" then
path = "/images"
IP = generateHttpV1_0Req(host, port, path)
local patharg = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/"
if type(patharg) ~= "table" then
patharg = {patharg}
end
local paths = stdnse.output_table()
for _, path in ipairs(patharg) do
paths[path] = 1
end
paths["/images"] = 1
if IP then
output["Internal IP Leaked"] = IP
return output
local socket
local bopt = nil
local try = nmap.new_try(function () socket:close() end)
for path in pairs(paths) do
local req = "GET " .. path .. " HTTP/1.0\r\n\r\n"
local resp
if not bopt then
socket, resp, bopt = comm.tryssl(host, port, req)
if not socket then return end
else
try(socket:connect(host, port, bopt))
try(socket:send(req))
resp = ""
end
local findhead = function (s)
return s:find("\r?\n\r?\n")
end
if not findhead(resp) then
resp = resp .. try(socket:receive_buf(findhead, true))
end
socket:close()
local loc = resp:lower():match("\nlocation:[ \t]+(%S+)")
local lochost = url.parse(loc or "").host
if lochost and lochost ~= "" then
-- remove any IPv6 enclosure
lochost = lochost:gsub("^%[(.*)%]$", "%1")
if ipOps.isPrivate(lochost) and ipOps.compare_ip(lochost, "ne", host.ip) then
if target.ALLOW_NEW_TARGETS then
target.add(lochost)
end
local output = stdnse.output_table()
output["Internal IP Leaked"] = lochost
return output
end
end
end
end

View File

@@ -51,34 +51,36 @@ Driver = {
end,
-- connects to the rlogin service
-- it sets the source port to a random value between 513 and 1024
-- it sets the source port to a random value between 512 and 1023
connect = function(self)
local status
local status, err
self.socket = brute.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"
-- Let's make several attempts to bind to an unused well-known port
for _ = 1, 10 do
local srcport = math.random(512, 1023)
status, err = self.socket:bind(nil, srcport)
if status then
self.socket:set_timeout(self.timeout)
status, err = self.socket:connect(self.host, self.port)
if status then
-- socket:connect() succeeds even if mksock_bind_addr() fails.
-- It just assigns an ephemeral port instead of our choice,
-- so we need to check the actual source port afterwards.
local lport
status, err, lport = self.socket:get_info()
if status then
if lport == srcport then
return status
end
status = false
err = "Address already in use"
end
end
end
else
self.socket:close()
end
if ( not(status) ) then
stdnse.debug3("ERROR: failed to connect to server")
if not status then
stdnse.debug2("Unable to bind to a well-known port (%s)", err)
end
return status
end,

View File

@@ -6,6 +6,6 @@ Exec=su-to-zenmap.sh %F
Terminal=false
Icon=zenmap
Type=Application
Categories=Application;Network;Security;
Categories=Network;Security;
Comment=A cross-platform GUI for the Nmap Security Scanner.
Keywords=network;scan;scanner;IP;security;

View File

@@ -6,6 +6,6 @@ Exec=zenmap %F
Terminal=false
Icon=zenmap
Type=Application
Categories=Application;Network;Security;
Categories=Network;Security;
Comment=A cross-platform GUI for the Nmap Security Scanner.
Keywords=network;scan;scanner;IP;security;