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

Support RPCBIND 3 and 4, not only portmap 2. See #1469

This commit is contained in:
dmiller
2019-04-15 19:35:24 +00:00
parent ef132f2f24
commit 85ec647932
2 changed files with 109 additions and 47 deletions

View File

@@ -121,7 +121,7 @@ local mutex = nmap.mutex("rpc")
-- Supported protocol versions
RPC_version = {
["rpcbind"] = { min=2, max=2 },
["rpcbind"] = { min=2, max=4 },
["nfs"] = { min=1, max=3 },
["mountd"] = { min=1, max=3 },
}
@@ -577,6 +577,16 @@ Portmap =
CALLIT = 5,
},
[3] =
{
DUMP = 4,
},
[4] =
{
DUMP = 4,
},
},
State =
@@ -635,11 +645,13 @@ Portmap =
-- <code>
-- table[program_id][protocol]["port"] = <port number>
-- table[program_id][protocol]["version"] = <table of versions>
-- table[program_id][protocol]["addr"] = <IP address, for RPCv3 and higher>
-- </code>
--
-- Where
-- o program_id is the number associated with the program
-- o protocol is either "tcp" or "udp"
-- o protocol is one of "tcp", "udp", "tcp6", or "udp6", or another netid
-- reported by the system.
--
Dump = function(self, comm)
local status, data, packet, response, pos, header
@@ -701,16 +713,38 @@ Portmap =
break
end
program, version, protocol, port, pos = string.unpack(">I4 I4 I4 I4", data, pos)
program, version, pos = string.unpack(">I4 I4", data, pos)
local addr, owner
if comm.version > 2 then
local len
len, pos = string.unpack(">I4", data, pos)
pos, protocol = Util.unmarshall_vopaque(len, data, pos)
len, pos = string.unpack(">I4", data, pos)
pos, addr = Util.unmarshall_vopaque(len, data, pos)
len, pos = string.unpack(">I4", data, pos)
pos, owner = Util.unmarshall_vopaque(len, data, pos)
if protocol:match("^[tu][cd]p6?$") then
-- RFC 5665
local upper, lower
addr, upper, lower = addr:match("^(.-)%.(%d+)%.(%d+)$")
if addr then
port = tonumber(upper) * 0x100 + tonumber(lower)
end
end
else
protocol, port, pos = string.unpack(">I4 I4", data, pos)
if ( protocol == Portmap.PROTOCOLS.tcp ) then
protocol = "tcp"
elseif ( protocol == Portmap.PROTOCOLS.udp ) then
protocol = "udp"
end
end
program_table[program] = program_table[program] or {}
program_table[program][protocol] = program_table[program][protocol] or {}
program_table[program][protocol]["port"] = port
program_table[program][protocol]["addr"] = addr
program_table[program][protocol]["owner"] = owner
program_table[program][protocol]["version"] = program_table[program][protocol]["version"] or {}
table.insert( program_table[program][protocol]["version"], version )
-- parts of the code rely on versions being in order
@@ -2761,7 +2795,8 @@ Helper = {
RpcInfo = function( host, port )
local status, result
local portmap = Portmap:new()
local comm = Comm:new('rpcbind', 2)
local pversion = 4
local comm = Comm:new('rpcbind', pversion)
mutex "lock"
@@ -2775,6 +2810,7 @@ Helper = {
return true, nmap.registry[host.ip]['portmapper']
end
while pversion >= 2 do
status, result = comm:Connect(host, port)
if (not(status)) then
mutex "done"
@@ -2785,11 +2821,14 @@ Helper = {
status, result = portmap:Dump(comm)
comm:Disconnect()
mutex "done"
if (not(status)) then
if status then
break
end
stdnse.debug4("rpc.Helper.RpcInfo: %s", result)
pversion = pversion - 1
end
mutex "done"
return status, result
end,
@@ -2837,32 +2876,55 @@ Helper = {
return status, portmap_table
end
local info = {}
-- assume failure
status = false
for _, p in ipairs( RPC_PROTOCOLS ) do
local tmp = portmap_table[Util.ProgNameToNumber(program)]
if not tmp then
return false, "Program not supported by target"
end
if ( tmp and tmp[p] ) then
info = {}
local info = {}
local proginfo
local ipv6 = nmap.address_family() == "inet6"
::AF_FALLBACK::
for _, p in ipairs( RPC_PROTOCOLS ) do
if ipv6 then
proginfo = tmp[p .. "6"]
else
proginfo = tmp[p]
end
if proginfo then
info.port = {}
info.port.number = tmp[p].port
info.port.number = proginfo.port
info.port.protocol = p
break
end
end
if ipv6 and not proginfo then
-- Fall back to trying IPv4
ipv6 = false
goto AF_FALLBACK
end
if not proginfo then
return false, "No transport protocol supported"
end
-- choose the highest version available
if ( not(RPC_version[program]) ) then
info.version = tmp[p].version[#tmp[p].version]
info.version = proginfo.version[#proginfo.version]
status = true
else
for i=#tmp[p].version, 1, -1 do
if ( RPC_version[program].max >= tmp[p].version[i] ) then
for i=#proginfo.version, 1, -1 do
if ( RPC_version[program].max >= proginfo.version[i] ) then
if ( not(max_version) ) then
info.version = tmp[p].version[i]
info.version = proginfo.version[i]
status = true
break
else
if ( max_version >= tmp[p].version[i] ) then
info.version = tmp[p].version[i]
if ( max_version >= proginfo.version[i] ) then
info.version = proginfo.version[i]
status = true
break
end
@@ -2870,9 +2932,6 @@ Helper = {
end
end
end
break
end
end
return status, info
end,

View File

@@ -117,7 +117,10 @@ action = function(host, port)
end
end
table.insert( result, ("%-7d %-10s %5d/%s %s"):format(progid, table.concat(v2.version, ","), v2.port, proto, rpc.Util.ProgNumberToName(progid) or "") )
if v2.port then
-- TODO: report other transports that don't have a port; e.g. "local"
table.insert( result, ("%-7d %-10s %5d/%-4s %s"):format(progid, table.concat(v2.version, ","), v2.port, proto, rpc.Util.ProgNumberToName(progid) or "") )
end
end
end