mirror of
https://github.com/nmap/nmap.git
synced 2026-01-04 13:49:03 +00:00
AUTH_UNIX support for rpc.lua.
http://seclists.org/nmap-dev/2012/q2/54 This patch is from Daniel Miller. He writes: I've just finished enhancing the nfs-ls, nfs-statfs, and nfs-showmount scripts so that they can run based on version detection information, for cases where the portmapper is firewalled. For nfs-ls and nfs-statfs, this required making a hostrule to check that both a mountd service and a nfs service were detected. In the process, I ended up adding the AUTH_UNIX flavor to rpc.lua, since the RFC states that AUTH_NULL can only be used for the NULL procedure (and my Linux nfs-kernel-server was enforcing that). Other minor changes: * If running privileged, attempt to bind to a reserved port. Many NFS servers refuse to talk to source ports >1024, as a "security measure" * handle an odd case in nfs-ls where READDIRPLUS does not return file attributes. Chose to use all ?'s, but in the future maybe a direct GETATTR call? * remove reference to nfs.dirlist argument from nfs-ls doc, since it is unused
This commit is contained in:
@@ -4,6 +4,7 @@ local stdnse = require "stdnse"
|
||||
local string = require "string"
|
||||
local tab = require "tab"
|
||||
local table = require "table"
|
||||
local nmap = require "nmap"
|
||||
|
||||
description = [[
|
||||
Attempts to get useful information about files from NFS exports.
|
||||
@@ -55,8 +56,7 @@ These access permissions are shown only with NFSv3:
|
||||
-- |_ lrwxrwxrwx 1000 1002 8 2010-06-10 08:34 symlink
|
||||
--
|
||||
-- @args nfs-ls.maxfiles If set, limits the amount of files returned by
|
||||
-- the script when using the <code>nfs-ls.dirlist</code> argument.
|
||||
-- If set to 0
|
||||
-- the script. If set to 0
|
||||
-- or less, all files are shown. The default value is 10.
|
||||
-- @args nfs-ls.human If set to <code>1</code> or <code>true</code>,
|
||||
-- shows file sizes in a human readable format with suffixes like
|
||||
@@ -88,19 +88,57 @@ categories = {"discovery", "safe"}
|
||||
|
||||
portrule = shortport.port_or_service(111, "rpcbind", {"tcp", "udp"} )
|
||||
|
||||
local mountport = nil
|
||||
local nfsport = nil
|
||||
hostrule = function(host)
|
||||
for _,proto in ipairs({"tcp","udp"}) do
|
||||
local port = nmap.get_ports(host, nil, proto, "open")
|
||||
while port do
|
||||
if port.version then
|
||||
if port.service == "mountd" then
|
||||
mountport = port
|
||||
elseif port.service == "nfs" then
|
||||
nfsport = port
|
||||
end
|
||||
end
|
||||
if mountport and nfsport then break end
|
||||
port = nmap.get_ports(host, port, proto, "open")
|
||||
end
|
||||
if mountport and nfsport then break end
|
||||
end
|
||||
if nfsport == nil then return false end
|
||||
if nfsport.version.rpc_highver == 4 and nfsport.version.rpc_lowver <= 3 then
|
||||
nfsport.version.rpc_goodver = 3
|
||||
else
|
||||
nfsport.version.rpc_goodver = nfsport.version.rpc_highver
|
||||
end
|
||||
return (mountport and nfsport)
|
||||
end
|
||||
|
||||
local procedures = { }
|
||||
|
||||
local function table_attributes(nfs, mount, attr)
|
||||
local file = {}
|
||||
|
||||
file.type = rpc.Util.FtypeToChar(attr.mode)
|
||||
file.mode = rpc.Util.FpermToString(attr.mode)
|
||||
file.uid = tostring(attr.uid)
|
||||
file.gid = tostring(attr.gid)
|
||||
if nfs.human then
|
||||
file.size = rpc.Util.SizeToHuman(attr.size)
|
||||
if attr.mode then
|
||||
file.type = rpc.Util.FtypeToChar(attr.mode)
|
||||
file.mode = rpc.Util.FpermToString(attr.mode)
|
||||
file.uid = tostring(attr.uid)
|
||||
file.gid = tostring(attr.gid)
|
||||
if nfs.human then
|
||||
file.size = rpc.Util.SizeToHuman(attr.size)
|
||||
else
|
||||
file.size = tostring(attr.size)
|
||||
end
|
||||
file.time = rpc.Util.TimeToString(attr[nfs.time].seconds)
|
||||
else
|
||||
file.size = tostring(attr.size)
|
||||
file.type = '?'
|
||||
file.mode = '?????????'
|
||||
file.uid = '?'
|
||||
file.gid = '?'
|
||||
file.size = '?'
|
||||
file.time = '?'
|
||||
end
|
||||
file.time = rpc.Util.TimeToString(attr[nfs.time].seconds)
|
||||
file.filename = mount
|
||||
|
||||
return file
|
||||
@@ -145,12 +183,12 @@ local function nfs_ls(nfs, mount, results, access)
|
||||
local nfsobj = rpc.NFS:new()
|
||||
local mnt_comm, nfs_comm, fhandle
|
||||
|
||||
mnt_comm, fhandle = rpc.Helper.MountPath(nfs.host, nfs.port, mount)
|
||||
mnt_comm, fhandle = procedures.MountPath(nfs.host, mount)
|
||||
if mnt_comm == nil then
|
||||
return false, fhandle
|
||||
end
|
||||
|
||||
local nfs_comm, status = rpc.Helper.NfsOpen(nfs.host, nfs.port)
|
||||
local nfs_comm, status = procedures.NfsOpen(nfs.host)
|
||||
if nfs_comm == nil then
|
||||
rpc.Helper.UnmountPath(mnt_comm, mount)
|
||||
return false, status
|
||||
@@ -243,12 +281,11 @@ local function report(nfs, table)
|
||||
return tab.dump(outtab)
|
||||
end
|
||||
|
||||
action = function(host, port)
|
||||
local mainaction = function(host)
|
||||
local o, results, mounts, status = {}, {}, {}
|
||||
local nfs_info =
|
||||
{
|
||||
host = host,
|
||||
port = port,
|
||||
--recurs = tonumber(nmap.registry.args['nfs-ls.recurs']) or 1,
|
||||
}
|
||||
|
||||
@@ -275,9 +312,13 @@ action = function(host, port)
|
||||
table.insert(o, args)
|
||||
end
|
||||
|
||||
status, mounts = rpc.Helper.ShowMounts(nfs_info.host, nfs_info.port)
|
||||
status, mounts = procedures.ShowMounts(nfs_info.host)
|
||||
if not status or mounts == nil then
|
||||
return stdnse.format_output(false, mounts)
|
||||
if mounts then
|
||||
return stdnse.format_output(false, mounts)
|
||||
else
|
||||
return stdnse.format_output(false, "Mount error")
|
||||
end
|
||||
end
|
||||
|
||||
for _, v in ipairs(mounts) do
|
||||
@@ -298,3 +339,85 @@ action = function(host, port)
|
||||
|
||||
return stdnse.format_output(true, o)
|
||||
end
|
||||
|
||||
hostaction = function(host)
|
||||
procedures = {
|
||||
ShowMounts = function(ahost)
|
||||
local mnt_comm, status, result, mounts
|
||||
local mnt = rpc.Mount:new()
|
||||
mnt_comm = rpc.Comm:new('mountd', mountport.version.rpc_highver)
|
||||
status, result = mnt_comm:Connect(ahost, mountport)
|
||||
if ( not(status) ) then
|
||||
stdnse.print_debug(4, "ShowMounts: %s", result)
|
||||
return false, result
|
||||
end
|
||||
status, mounts = mnt:Export(mnt_comm)
|
||||
mnt_comm:Disconnect()
|
||||
if ( not(status) ) then
|
||||
stdnse.print_debug(4, "ShowMounts: %s", mounts)
|
||||
end
|
||||
return status, mounts
|
||||
end,
|
||||
|
||||
MountPath = function(ahost, path)
|
||||
local fhandle, status, err
|
||||
local mountd, mnt_comm
|
||||
local mnt = rpc.Mount:new()
|
||||
|
||||
mnt_comm = rpc.Comm:new("mountd", mountport.version.rpc_highver)
|
||||
|
||||
status, err = mnt_comm:Connect(host, mountport)
|
||||
if not status then
|
||||
stdnse.print_debug(4, "MountPath: %s", err)
|
||||
return nil, err
|
||||
end
|
||||
|
||||
status, fhandle = mnt:Mount(mnt_comm, path)
|
||||
if not status then
|
||||
mnt_comm:Disconnect()
|
||||
stdnse.print_debug(4, "MountPath: %s", fhandle)
|
||||
return nil, fhandle
|
||||
end
|
||||
|
||||
return mnt_comm, fhandle
|
||||
end,
|
||||
|
||||
NfsOpen = function(ahost)
|
||||
local nfs_comm, status, err
|
||||
|
||||
nfs_comm = rpc.Comm:new('nfs', nfsport.version.rpc_goodver)
|
||||
status, err = nfs_comm:Connect(host, nfsport)
|
||||
if not status then
|
||||
stdnse.print_debug(4, "NfsOpen: %s", err)
|
||||
return nil, err
|
||||
end
|
||||
|
||||
return nfs_comm, nil
|
||||
end,
|
||||
}
|
||||
return mainaction(host)
|
||||
end
|
||||
|
||||
portaction = function(host, port)
|
||||
procedures = {
|
||||
ShowMounts = function(ahost)
|
||||
return rpc.Helper.ShowMounts(ahost, port)
|
||||
end,
|
||||
MountPath = function(ahost, path)
|
||||
return rpc.Helper.MountPath(ahost, port, path)
|
||||
end,
|
||||
NfsOpen = function(ahost)
|
||||
return rpc.Helper.NfsOpen(ahost, port)
|
||||
end,
|
||||
}
|
||||
return mainaction(host)
|
||||
end
|
||||
|
||||
local ActionsTable = {
|
||||
-- portrule: use rpcbind service
|
||||
portrule = portaction,
|
||||
-- hostrule: Talk to services directly
|
||||
hostrule = hostaction
|
||||
}
|
||||
|
||||
action = function(...) return ActionsTable[SCRIPT_TYPE](...) end
|
||||
|
||||
@@ -32,14 +32,34 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
categories = {"discovery", "safe"}
|
||||
|
||||
|
||||
portrule = shortport.port_or_service(111, "rpcbind", {"tcp", "udp"} )
|
||||
portrule = shortport.port_or_service(111, {"rpcbind", "mountd"}, {"tcp", "udp"} )
|
||||
|
||||
local function get_exports(host, port)
|
||||
local mnt = rpc.Mount:new()
|
||||
mnt_comm = rpc.Comm:new('mountd', port.version.rpc_highver)
|
||||
status, result = mnt_comm:Connect(host, port)
|
||||
if ( not(status) ) then
|
||||
stdnse.print_debug(4, "get_exports: %s", result)
|
||||
return false, result
|
||||
end
|
||||
status, mounts = mnt:Export(mnt_comm)
|
||||
mnt_comm:Disconnect()
|
||||
if ( not(status) ) then
|
||||
stdnse.print_debug(4, "get_exports: %s", mounts)
|
||||
end
|
||||
return status, mounts
|
||||
end
|
||||
|
||||
action = function(host, port)
|
||||
|
||||
local status, mounts, proto
|
||||
local result = {}
|
||||
|
||||
status, mounts = rpc.Helper.ShowMounts( host, port )
|
||||
if port.service == "mountd" then
|
||||
status, mounts = get_exports( host, port )
|
||||
else
|
||||
status, mounts = rpc.Helper.ShowMounts( host, port )
|
||||
end
|
||||
|
||||
if not status or mounts == nil then
|
||||
return stdnse.format_output(false, mounts)
|
||||
|
||||
@@ -4,6 +4,7 @@ local stdnse = require "stdnse"
|
||||
local string = require "string"
|
||||
local tab = require "tab"
|
||||
local table = require "table"
|
||||
local nmap = require "nmap"
|
||||
|
||||
description = [[
|
||||
Retrieves disk space statistics and information from a remote NFS share.
|
||||
@@ -40,6 +41,35 @@ categories = {"discovery", "safe"}
|
||||
|
||||
portrule = shortport.port_or_service(111, "rpcbind", {"tcp", "udp"} )
|
||||
|
||||
local mountport = nil
|
||||
local nfsport = nil
|
||||
hostrule = function(host)
|
||||
for _,proto in ipairs({"tcp","udp"}) do
|
||||
local port = nmap.get_ports(host, nil, proto, "open")
|
||||
while port do
|
||||
if port.version then
|
||||
if port.service == "mountd" then
|
||||
mountport = port
|
||||
elseif port.service == "nfs" then
|
||||
nfsport = port
|
||||
end
|
||||
end
|
||||
if mountport and nfsport then break end
|
||||
port = nmap.get_ports(host, port, proto, "open")
|
||||
end
|
||||
if mountport and nfsport then break end
|
||||
end
|
||||
if nfsport == nil then return false end
|
||||
if nfsport.version.rpc_highver == 4 and nfsport.version.rpc_lowver <= 3 then
|
||||
nfsport.version.rpc_goodver = 3
|
||||
else
|
||||
nfsport.version.rpc_goodver = nfsport.version.rpc_highver
|
||||
end
|
||||
return (mountport and nfsport)
|
||||
end
|
||||
|
||||
local procedures = { }
|
||||
|
||||
local function table_fsstat(nfs, mount, stats)
|
||||
local fs, err = rpc.Util.calc_fsstat_table(stats, nfs.version, nfs.human)
|
||||
if fs == nil then
|
||||
@@ -111,12 +141,12 @@ local function nfs_filesystem_info(nfs, mount, filesystem)
|
||||
local nfsobj = rpc.NFS:new()
|
||||
local mnt_comm, nfs_comm, fhandle
|
||||
|
||||
mnt_comm, fhandle = rpc.Helper.MountPath(nfs.host, nfs.port, mount)
|
||||
mnt_comm, fhandle = procedures.MountPath(nfs.host, mount)
|
||||
if mnt_comm == nil then
|
||||
return false, fhandle
|
||||
end
|
||||
|
||||
local nfs_comm, status = rpc.Helper.NfsOpen(nfs.host, nfs.port)
|
||||
local nfs_comm, status = procedures.NfsOpen(nfs.host)
|
||||
if nfs_comm == nil then
|
||||
rpc.Helper.UnmountPath(mnt_comm, mount)
|
||||
return false, status
|
||||
@@ -124,8 +154,8 @@ local function nfs_filesystem_info(nfs, mount, filesystem)
|
||||
|
||||
nfs.version = nfs_comm.version
|
||||
|
||||
-- use simple check since NFSv1 is not used anymore.
|
||||
if (mnt_comm.version ~= nfs_comm.version) then
|
||||
-- use simple check since NFSv1 is not used anymore, and NFSv4 not supported
|
||||
if (nfs_comm.version <= 2 and mnt_comm.version > 2) then
|
||||
rpc.Helper.UnmountPath(mnt_comm, mount)
|
||||
return false, string.format("versions mismatch, nfs v%d - mount v%d",
|
||||
nfs_comm.version, mnt_comm.version)
|
||||
@@ -179,16 +209,15 @@ local function nfs_filesystem_info(nfs, mount, filesystem)
|
||||
return true, nil
|
||||
end
|
||||
|
||||
action = function(host, port)
|
||||
mainaction = function(host)
|
||||
local fs_info, mounts, status = {}, {}, {}
|
||||
local nfs_info =
|
||||
{
|
||||
host = host,
|
||||
port = port,
|
||||
}
|
||||
nfs_info.human = stdnse.get_script_args('nfs-statfs.human')
|
||||
|
||||
status, mounts = rpc.Helper.ShowMounts( host, port )
|
||||
status, mounts = procedures.ShowMounts( host )
|
||||
if (not(status)) then
|
||||
return stdnse.format_output(false, mounts)
|
||||
end
|
||||
@@ -204,3 +233,85 @@ action = function(host, port)
|
||||
|
||||
return stdnse.format_output(true, report(nfs_info, fs_info))
|
||||
end
|
||||
|
||||
hostaction = function(host)
|
||||
procedures = {
|
||||
ShowMounts = function(ahost)
|
||||
local mnt_comm, status, result, mounts
|
||||
local mnt = rpc.Mount:new()
|
||||
mnt_comm = rpc.Comm:new('mountd', mountport.version.rpc_highver)
|
||||
status, result = mnt_comm:Connect(ahost, mountport)
|
||||
if ( not(status) ) then
|
||||
stdnse.print_debug(4, "ShowMounts: %s", result)
|
||||
return false, result
|
||||
end
|
||||
status, mounts = mnt:Export(mnt_comm)
|
||||
mnt_comm:Disconnect()
|
||||
if ( not(status) ) then
|
||||
stdnse.print_debug(4, "ShowMounts: %s", mounts)
|
||||
end
|
||||
return status, mounts
|
||||
end,
|
||||
|
||||
MountPath = function(ahost, path)
|
||||
local fhandle, status, err
|
||||
local mountd, mnt_comm
|
||||
local mnt = rpc.Mount:new()
|
||||
|
||||
mnt_comm = rpc.Comm:new("mountd", mountport.version.rpc_highver)
|
||||
|
||||
status, err = mnt_comm:Connect(host, mountport)
|
||||
if not status then
|
||||
stdnse.print_debug(4, "MountPath: %s", err)
|
||||
return nil, err
|
||||
end
|
||||
|
||||
status, fhandle = mnt:Mount(mnt_comm, path)
|
||||
if not status then
|
||||
mnt_comm:Disconnect()
|
||||
stdnse.print_debug(4, "MountPath: %s", fhandle)
|
||||
return nil, fhandle
|
||||
end
|
||||
|
||||
return mnt_comm, fhandle
|
||||
end,
|
||||
|
||||
NfsOpen = function(ahost)
|
||||
local nfs_comm, status, err
|
||||
|
||||
nfs_comm = rpc.Comm:new('nfs', nfsport.version.rpc_goodver)
|
||||
status, err = nfs_comm:Connect(host, nfsport)
|
||||
if not status then
|
||||
stdnse.print_debug(4, "NfsOpen: %s", err)
|
||||
return nil, err
|
||||
end
|
||||
|
||||
return nfs_comm, nil
|
||||
end,
|
||||
}
|
||||
return mainaction(host)
|
||||
end
|
||||
|
||||
portaction = function(host, port)
|
||||
procedures = {
|
||||
ShowMounts = function(ahost)
|
||||
return rpc.Helper.ShowMounts(ahost, port)
|
||||
end,
|
||||
MountPath = function(ahost, path)
|
||||
return rpc.Helper.MountPath(ahost, port, path)
|
||||
end,
|
||||
NfsOpen = function(ahost)
|
||||
return rpc.Helper.NfsOpen(ahost, port)
|
||||
end,
|
||||
}
|
||||
return mainaction(host)
|
||||
end
|
||||
|
||||
local ActionsTable = {
|
||||
-- portrule: use rpcbind service
|
||||
portrule = portaction,
|
||||
-- hostrule: Talk to services directly
|
||||
hostrule = hostaction
|
||||
}
|
||||
|
||||
action = function(...) return ActionsTable[SCRIPT_TYPE](...) end
|
||||
|
||||
Reference in New Issue
Block a user