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

Compare commits

...

3 Commits

Author SHA1 Message Date
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
4 changed files with 81 additions and 73 deletions

View File

@@ -1,5 +1,12 @@
#Nmap Changelog ($Id$); -*-text-*-
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

@@ -358,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

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

@@ -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,