# 运维安全之NFS安全

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2014-04-20T06:46:00Z
Canonical: https://wepostx.com/topics/439

> 乌云历史资料归档
>
> **原始作者：** rootsecurity
> **原始编号：** superkieran-wooyundrops:225
> **原始发布时间：** 2014-04-20 14:46
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

说起NFS是（Network File System）的缩写，相信这很多人都知道。其最大的优点就是可以在网络里使不同的主机，不同的操作系统来互相分享文件。由于NFS不像WEB那样经常使用，一般也就用到的时候去网上随便找篇文档安装一下，剩下的就是能用就行了。所以安全性往往是比较容易忽略的问题。
NFS的联动进程有nfsd，rpc.mountd，rpc.statd， locked，rpc.idmapd，rpc.gssd，rpc.svcgssd，其主进程nfsd使用的是TCP/UDP的2049端口，其中TCP协议是在V3版本才引入的。下面是NFS的发展历程：

```text
NFS V1是SUN公司研发，包含在SUN操作系统里。 NFS V2是最原始的NFS协议，在RFC1904中有相关描述，这个版本是基于UDP的，单个文件最大支持4G NFS V3在RFC1813中描述，相对于V2增加了TCP协议的相关支持，安全异步，服务端ACL，V3相对于V2来说性能上有一个很大的提升，但是安全性并没有多少改进。 NFS V4在RFC3530中描述，相对于V3版本，它把lock喝mount整合进协议中，开发了新的AC L控制机制，引入对UTF-8字符集的支持，NFS V4要求所有实现都必须支持kerberos的身份验证，替代了原有的基于UID/GID的身份验证
```

### 下面阐述一下V3的连接过程：
NFSv3协议的服务器端是无状态的，所以就算机器重启了，NFS服务起来以后，客户端依然可以拿着旧文件句柄继续读写文件。但是服务器端的lockd进程是有状态的，重启就有点麻烦，解决方案是服务器端的rpc.statd让客户端报告自己手里的锁，然后重新让lockd恢复锁状态。
客户端问服务器端的portmap：rpc.mount目前的用哪个端口？客户端向服务器端的rpc.mount请求挂载NFS； 服务器端的rpc.mount判断权限后给客户端一个文件句柄； 客户端使用这个句柄与服务器端的nfsd交流（使用TCP/UDP的2049端口），以读写文件。

### NFS V3的验证机制及安全：
NFS V3及其附属协议采用标准的RPC AUTH_SYS（又称AUTH_UNIX）机制验证挂载后的客户端对具体文件的权限，服务器完全信任客户端声名的自己的权限（其实不能被称为是“验证”了
大概过程就是客户端会在读写之前告诉服务器自己的UID和GID，然后NFS就把这些ID视同自己系统上的ID来验证权限；
客户端可以很容易伪造出高权限的ID以达到攻击的目的，防御的临时解决之道是不让NFS暴露在公有网络上且不打开NFS的root权限（是比较弱的防御）
还有一个麻烦是，不同客户端上同一个username的UID想保持同步是件不容易的事。
不要把包含配置文件的目录export出去
export整个文件系统的根出去，而不是export文件系统中某个目录出去。因为即使只是export一个目录出去，攻击者也可能通过猜测的方式得到文件系统中其它目录的读写权限。比如说一个ext3挂载在/mnt/下了，用NFS export/mnt/data1/出去，攻击者就可能读写/mnt/data2/下的文件。这显然不是我们希望的，因此不如干脆共享整个文件系统（也就是/mnt/）出去。或者也可以使用NFS的substree_check来帮我们做检查来防止这种入侵，但是这个选项会较大幅度降低NFS的性能
如果一个文件系统挂载点是另一个文件系统的子目录，那么父系统开启crossmnt或者子系统开启nohide就可以把两个文件系统都共享出去，使用这个选项的时候要小心，别共享了自己不想共享的内容出去
虽然nfsd固定使用2049端口，但是lockd、mountd、statd都使用portmap随机分配的端口，这让防火墙很难配置，而且还可能占用还没起来的其它服务的端口。可以在/etc/sysconfig/nfs中把这些进程的端口都配置成固定的，这样配置防火墙（只放行自己信任的IP）就容易了
rpcinfo -p可以查看portmap分配出去的端口。

## Replies
