一、概要
NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源。NFS是一个使用RPC构造的客户端/服务器应用程序,其客户端通过向一台NFS服务器发送RPC请求来访问其中的文件。尽管这一工作可以使用一般的用户进程来实现,即NFS客户端可以是一个用户进程,对服务器进行显式调用在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。NFS本身没有提供信息传输的协议和功能,但NFS却能让我们通过网络进行资料的分享,就是因为NFS使用了RPC提供的传输协议,可以说NFS就是使用PRC的一个程序。NFS依赖于RPC协议。所谓RPC远程过程调用(Remote Procedure Call),是使客户端能够执行其他系统中程序的一种机制。NFS服务器在端口UDP2049接收作为UDP数据包的客户端请求,NFS服务本身不提供文件传输功能,我们要远程使用NFS文件系统就需要RPC服务的支持;而portmap服务用来为RPC服务进行动态端口分配和映射,所以portmap服务也是NFS服务所必须的。可以把NFS服务看作RPC服务的一种,开启NFS服务其实就是在开启RPC服务,portmap 服务是用于 RPC 服务(如 NIS (network information service)和 NFS)的动态端口分配守护进程。安装NFS服务时所需要的两个软件包nfs-utils和portmap:Nfs-utils软件包提供了rpc.nfsd和rpc.mountd两个RPC的daemon(守护进程)程序,而portmap软件包提供了portmap程序。
目前NFS已具备了防止被利用导出文件夹的功能,但遗留系统中的NFS服务配置不当,则仍可遭到恶意攻击者的利用。

二、安装

#rpm -qa |grep nfs //检查系统是否已经安装
nfs4-acl-tools-0.3.3-13.el7.x86_64
nfs-utils-1.3.0-0.48.el7_4.x86_64 //必要安装
libnfsidmap-0.25-9.el7.x86_64
[root@centosclient ~]# rpm -qa |grep rpc
xmlrpc-c-1.32.5-1905.svn2451.el7.x86_64
xmlrpc-c-client-1.32.5-1905.svn2451.el7.x86_64
libtirpc-0.2.4-0.10.el7.x86_64
rpcbind-0.2.0-42.el7.x86_64 //必要安装
如果没有安装:yum install rpcbind nfs-utils.x86_64 nfs4-acl-tools
systemctl enable rpcbind.service //即之前的portmap
systemctl enable nfs-server.service
systemctl start rpcbind.service
systemctl start nfs-server.service
chkconfig –list nfs
chkconfig –list rpcbind
exportfs -rv //重新读取NFS配置文件

三、服务确认及配置
服务器端/etc/exports就是nfs服务的主配置文件,这个文件不一定会存在,要使用vim手动建立;
/usr/sbin/exportfs:NFS服务的管理命令
/usr/sbin/showmount:客户端的查看命令
/var/lib/nfs/etab:记录NFS分享出来的目录的完整权限设定值
/var/lib/nfs/xtab:记录曾经登录过的客户端信息
systemctl status rpcbind.service //查看RPC的服务状态
netstat -antlp |grep rpc //查看rpcbind服务的端口
rpcinfo -p localhost //查看本地主机是否有端口注册
systemctl status nfs.service //查看nfs服务的状态

/etc/exports文件内容格式:
<输出目录> [客户端1 选项(访问权限,用户映射,其他)] [客户端2 选项(访问权限,用户映射,其他)]

说明:
输出目录:指NFS系统中需要共享给客户机使用的目录;
客户端是指网络中可以访问这个NFS输出目录的计算机,可以这么写:
指定ip地址的主机:192.168.0.200
指定子网中的所有主机:192.168.0.0/24 192.168.0.0/255.255.255.0
指定域名的主机:david.bsmart.cn
指定域中的所有主机:.bsmart.cn
所有主机:

选项用来设置输出目录的访问权限、用户映射:
设置输出目录只读:ro
设置输出目录读写:rw
all_squash:将远程访问的所有普通用户及所属组都映射为匿名用户或用户组(nfsnobody),即共 享文件的UID和GID映射匿名用户anonymous,适合公用目录;
no_all_squash:与all_squash取反(默认设置),保留共享文件的UID和GID(默认);
root_squash:将root用户及所属组都映射为匿名用户或用户组(默认设置),相当于在服务器使用nobody用户访问目录;
no_root_squash:与rootsquash取反,即root用户及及所属组都不映射(no_root_squash),即相当于在服务器上用root身份访问该目录;如果启用该选项,当客户端用root身份登录时,挂载nfs的共享目录时,客户端的root将对共享目录具备root权限。
anonuid=xxx:将远程访问的所有用户都映射为匿名用户,并指定该用户为本地用户(UID=xxx);
anongid=xxx:将远程访问的所有用户组都映射为匿名用户组账户,并指定该匿名用户组账户为本 地用户组账户(GID=xxx);
secure:限制客户端只能从小于1024的tcp/ip端口连接nfs服务器(默认设置);
insecure:允许客户端从大于1024的tcp/ip端口连接服务器;
sync:将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性;
async:将数据先保存在内存缓冲区中,必要时才写入磁盘;
wdelay:检查是否有相关的写操作,如果有则将这些写操作一起执行,这样可以提高效率(默认设置);
no_wdelay:若有写操作则立即执行,应与sync配合使用;
subtree:若输出目录是一个子目录,则nfs服务器将检查其父目录的权限(默认设置);
no_subtree:即使输出目录是一个子目录,nfs服务器也不检查其父目录的权限,这样可以提高效率;
hide 在NFS共享目录中不共享其子目录
no_hide 共享NFS目录的子目录

【mount挂载参数】

-t ntfs:告诉挂载命令将要挂载的文件系统类型。这个选项并不是必须的,因为mount会自动识别大多数的文件系统。
-r:以只读形式挂载卷。挂载操作默认以可读写形式挂载卷。除非指明,否则驱动将会以只读形式自动挂载文件系统,同-o ro。
-o umask={VALUE}:
-o uid={USERID}
-o gid={GROUPID}:
-o iocharset={NAME}
-o fmask={VALUE}
-o dmask={VALUE}
参数umask同时改变文件和路径两者的权限,fmask以同样的方式作用于文件而dmask作用于路径,这些选项也可以被组合使用
eg:mount /dev/hda1 /mnt/windows -t ntfs -r -o umask=0222
mount /dev/hda1 /mnt/windows -t ntfs -r -o uid=flatcap
mount /dev/hda1 /mnt/windows -t ntfs -r -o uid=500
mount /dev/hda1 /mnt/windows -t ntfs -r -o gid=winusers
mount /dev/hda1 /mnt/windows -t ntfs -r -o gid=520
mount /dev/hda1 /mnt/windows -t ntfs -r -o iocharset=utf8
mount /dev/hda1 /mnt/windows -t ntfs -r -o iocharset=iso8859-2(中欧)
mount /dev/hda1 /mnt/windows -t ntfs -r -o iocharset=gb2312(简体中文)
mount /dev/hda1 /mnt/windows -t ntfs -r -o utf8=tru
mount /dev/hda1 /mnt/windows -t ntfs -r -o fmask=0222
mount /dev/hda1 /mnt/windows -t ntfs -r -o dmask=0222
mount /dev/hda1 /mnt/windows -t ntfs -r -o fmask=0077,dmask=0222

3.1【权限配置】:
1)如果同一目要针对不同用户/不同区域开放不同权限:比如nfs共享目录/home/public
setfacl -m g:blue:rwx /home/public
[root@ ~]# vim /etc/exports
/tmp *(rw,no_root_squash) //因 no_root_squash参数,client上root访问访问/tmp,文件所有者为/root
/home/public 192.168.100.0/24(rw) (ro) //网段不能写成192.168.100. 这样的格式
上面通过配置文件里权限配置内容+acl配置,共同实现/home/public 只有192.168.100.0/24且加入blue组的用户才能读写,其他主机或用户只能读;当用户从客户端挂载NFS共享目录/home/public后,192.168.100.0/24内的主机可以对改目录可以读写,其他的只能只读;

2)如果限制NFS的目录为指定主机是的某一个用户才可以访问:
setfacl -m u:admin:rwx /home/public
[root@ ~]# vim /etc/exports
/tmp *(rw,no_root_squash) //当客户端uid=600用户访问该目录,创建文件是文件uid会变成600,即使NFS服务器上没有uid=600的用户
/home/public 192.168.100.2(rw) //只有100.2上的admin用户才能有完整的访问权限

3)开通匿名访问,假如客户端过来的用户在nfs共享目录存储文件时,希望文件的 UID 與 GID 都变成 45 這個身份的使用者,且改用户的属主为nfsanon,相当于只有uid=45的用户才能访问/home/public 。
[root@ ~]# groupadd -g 45 nfsanon
[root@ ~]# useradd -u 45 -g nfsanon nfsanon
[root@ ~]# setfacl -m u:nfsanon:rwx /home/public
[root@ ~]# vim /etc/exports
/tmp *(rw,no_root_squash)
/home/public 192.168.100.0/24(rw,all_squash,anonuid=45,anongid=45)

#如果要开放匿名,那麼重点是 all_squash,且要配合 anonuid 使用!这样当客户端访问 NFS 主机,且在 /home/public 写入文件时,该文件的所有者或所有組,就會变成 /etc/passwd 裡面对应的 UID 为 45 的那个用户!

3.2 Linux漏洞:showmount -e信息泄露(CEE-1999-0554)
修改该漏洞,实现允许指定主机通过mount到nfs服务器上,阻止其他主机通过showmount -e方式,泄露NFS共享目录结构信息。
在这里插入图片描述
1)在目标主机上编辑:vi /etc/hosts.allow
NFS如何限制可以获取NFS输出列表的IP和用户第1张图片
2)vi /etc/hosts.deny
NFS如何限制可以获取NFS输出列表的IP和用户
第2张图片
注:上述所有操作无需重启rpc.bind和nfs
3)验证:
本机验证:# showmount -a
clnt_create: RPC: Unknown host
远程验证:showmount -e 172.13.14.15 //远程主机ip
clnt_create: RPC: Port mapper failure - Authentication error

4)联系安全部分扫描确认,正常应该漏洞已经无法扫描到。

四、客户端命令:

#showmount -e 192.168.0.10 //将得到一个在 192.168.0.10 上可用的 NFS 共享的列表,命令执行会检索给定主机的导出文件夹列表,这些信息将被用于访问这些文件夹。
显示指定NFS服务器连接NFS客户端的信息

showmount 192.168.1.1 #此ip为nfs服务器的
显示输出目录列表

showmount -e
显示被挂载的共享目录

showmount -d
显示客户端信息和共享目录

showmount -a
显示指定NFS服务器的客户端信息和共享目录

#showmount -a 192.168.1.1
客户端维护工具:NFS Shell;它可以连接到NFS共享并可以帮助我们手动识别一些常见的安全问题
安装:
apt-get install libreadline-dev libncurses5-dev
make
gcc -g -o nfsshell mount_clnt.o mount_xdr.o nfs_prot_clnt.o nfs_prot_xdr.o nfsshell.o -L/usr/local/lib -lreadline -lhistory -lncurses
./nfsshell
nfs> host IP // 连接NFS服务
nfs> export // 导出NFS列表
mount -t nfs 192.168.1.172:/ /temp -o nolock //将共享文件夹或导出的NFS列表挂载到客户端一个空目录来访问
挂载后,如果对于共享上的文件我们没有读取权限,可改写文件所有者的UID来欺骗NFS服务器,ls-al列出访问文件的UID,可在客户端本地创建一个新用户,并将该用户的UID和名称修改为与文件所有者相同。当然UID可以在passwd文件中更改,vi /etc/passwd将第2、3个冒号后id改为同文件的UID和GID;执行su到新用户后,由于该文件的UID与新用户的UID相同,因此系统会误认为这是文件权限的所有者,这样我们就可以以一个合法的用户身份来读取文件的内容了。

造成这种问题,原因在于导出文件夹并未设置root_squash选项。root_squash登入NFS主机,使用该共享目录时相当于该目录的拥有者。但是如果是以root身份使用这个共享目录的时候,那么这个使用者(root)的权限将被压缩成为匿名使用者,即通常他的UID与GID都会变成nobody那个身份,以防止越权访问。如果passwd文件还具有写入权限,那么我们可以通过将一些非特权用户的UID更改为0,使其具有根级别的访问权限,因此要跟passwd加权限限制chattr +i禁止修改。

禁用root_squash选项:
vi /etc/exports编辑:
/home 192.168.1.47(root_squash) // Enables Root Squash
/home 192.168.1.47(no_root_squash) // Disables Root Squash

注:NFS共享目录可能含:authorized_keys和rhosts2个文件,而.rhosts文件用来配置哪些远程主机或用户可以访问系统上的本地帐户。如果.rhosts文件的内容为++符号,则说明它允许来自网络上的任何主机和用户的连接。这样的话,
cd /root/.ssh/
ssh-keygen -t rsa -b 4096
cp /root/.ssh/id_rsa.pub /temp/root/.ssh/
cat id_rsa.pub >> /temp/root/.ssh/authorized_keys
ssh -i /root/.ssh/id_rsa root@192.168.1.189 //
以下命令将允许系统的root用户直接连接目标系统,系统将不会提示密码输入,因为来自系统的所有用户都将被信任。
rsh -l root IP
rlogin -l root IP
应定期检查文件将有助于确定哪些主机和用户是可信的,因此可以在无需密码的情况下进行身份验证。

文档更新时间: 2021-06-10 04:07   作者:月影鹏鹏