Unix系统的NFS服务相当于MS系统上的文件共享服务。也许有人认为这是一个不恰当的比喻,但二者在安全问题上有惊人的类似,正如NT/Windows机器上的安全问题很多来自共享资源一样,NFS服务的错误配置,也可以让你的系统被入侵者接管。NFS建立在RPC(远程过程调用)机制上,同样地,基于RPC机制上的NT服务也不安全;针对MS共享资源的攻击是当前Internet上最流行的攻击NT方式,对NFS的攻击也对UNix平台机器的最常用手段。
NFS的不安全性主要体现于以下4个方面:
1、新手对NFS的访问控制机制难于做到得心应手,控制目标的精确性难以实现
2、NFS没有真正的用户验证机制,而只有对RPC/Mount请求的过程验证机制
3、较早的NFS可以使未授权用户获得有效的文件句柄
4、在RPC远程调用中,一个SUID的程序就具有超级用户权限。
我们分别从这几个方面加以论述:
1、在大多数Unix系统的缺省的情况下,Export目录时,如果不指定只读,该目录为可写;NFS的访问控制文件很容易出现错误配置,很多情况下配置为可以被网上任何一台机器访问,远程用户可以用这条命令来查到是否有NFS的配置漏洞,这个命令是几乎所有的NFS攻击的必经步骤:
# showmount -e www.xxx.com
可能结果如下:
/usr (everyone) /export/target1 -access=target2 /export/target2 -access=target1
可以把这个NFS server上的/usr目录mount成本地目录:
# mount www.xxx.com:/usr /tmp
这表明,/usr目录可以被任何一台机器mount,甚至可能有写的权限;而/export/target1目录指定了主机访问限制,必须是target2.xxx.com这个机器或者target2这个Netgroup的成员才能mount。入侵者大多都先用这个命令来查询目标上的NFS漏洞,正如对NT的Netview命令一样。值得提醒的是,现在流行的入侵方式已经从以前的对确定目标的攻击方式转为不管对方是谁,只要有机可乘就入侵的方式。
入侵者可能会写一个脚本或者一个程序,用来对一大段地址进行扫描,列出结果报告给自己。所以,正确的配置是非常重要的。在Internet上,NFS设置错误的机器比比皆是。这个配置一般存放于/etc/exports文件或/etc/dfs/dfstab中。
2、来自客户端的NFS请求的用户认证,由用户的UID和所属组的GID组成,这种文件访问的安全验证对于没有开NFS的系统当然是安全的;但是在网上,其它机器的root完全有权在自己的机器上设置这样一个UID,而NFS服务器不管这个UID是不是自己机器上的,只要UID符合,就赋予这个用户对这个文件的操作权.比如,目录/home/frank只能由UID为501的用户打开读写,而这个目录可以被远程机器mount,那么,这台机器的root用户新增一个UID为501的用户,然后用这个用户登录并mount该目录,就可以获得相当于NFS server上的UID为501用户操作权限,从而读写/home/frank。要解决这个问题必须正确配置exports,限制客户的主机地址,明确设置rw=host的选项,ro(只读)的选项和access=host的选项。
另外,还有一种UID欺骗,是关于16位UID和32位UID的问题。大多NFS服务接受的来自客户对NFS请求所发送的UID标志都是16位的(Solaris是一个例外),这是不安全的。
在这种情况下,如果用一个32位UID,并把这个UID最左边的位置设置为0,那么,体现在NFS server上,解释为16位的UID,这个UID就相当于root;任何用户引用32位UID并且这个UID最左边的数字是0,那么就可以读/写属于root的任何文件。要解决这个问题,可以从Sun的正式站点获取#1095935补丁。
3、以前的文件句柄无须mount守护进程的帮助就可以构造,使客户直接可以和NFS通信。而现在的Unix系统大多进行了改进。但BSD系统还有问题。关于BSD文件句柄的问题涉BSD OS2.0,2.1,3.0;FreeBSD2.1.5~2.1.7,openBSD2.0和2.0以前。其它一些BSD也可能有类似的问题。例如在4.4BSD中,与其它的UNix文件系统不同的是,一个文件的信息,除了创建时间、文件大小、连接个数和更新时间等信息外,还有一个st_gen信息,st_gen是一个4位的值,目的是使NFS文件句柄难于猜到。这个信息是stat(2)系统调用生成的。不幸的是,这个调用用到的一个函数vn_stat()有问题:
...
sb->st_gen = vap->va_gen;
sb->st_blocks = vap->va_bytes / S_BLKSIZE;
return (0); }
上面这段程序码暴露了用来生成st_gen这个数的所有信息,利用这些信息,未授权用户可以得到文件的句柄。正确的程序应该只允许这些信息暴露给root:
...
sb->st_flags = vap->va_flags;
if (suser(p->p_ucred, &p->p_acflag)) {
sb->st_gen = 0;
} else {
sb->st_gen = vap->va_gen;
}
sb->st_blocks = vap->va_bytes / S_BLKSIZE;
return (0);
}
这样,如果不是root,他只能得到0这个信息。
4、最危险的错误是把含有SUID程序的目录export,并且该文件有执行权。SUID程序相当于超级用户本身。
解决方案
1、和从NT中删除任何共享的解决方案一样,最好的解决方案是禁止NFS服务,或以AFS服务取而代之(Andrew File System)。
2、如果一定要开NFS,不要让一个单机可以既是client,也是server;
3、export出的文件系统只设置为只读
4、禁止那些有SUID特性的程序的执行
5、不要export home 目录
6、不要export可执行特性
7、使用一些安全NFS实现方案(虽然未必真的很安全)
NFS的不安全性主要体现于以下4个方面:
1、新手对NFS的访问控制机制难于做到得心应手,控制目标的精确性难以实现
2、NFS没有真正的用户验证机制,而只有对RPC/Mount请求的过程验证机制
3、较早的NFS可以使未授权用户获得有效的文件句柄
4、在RPC远程调用中,一个SUID的程序就具有超级用户权限。
我们分别从这几个方面加以论述:
1、在大多数Unix系统的缺省的情况下,Export目录时,如果不指定只读,该目录为可写;NFS的访问控制文件很容易出现错误配置,很多情况下配置为可以被网上任何一台机器访问,远程用户可以用这条命令来查到是否有NFS的配置漏洞,这个命令是几乎所有的NFS攻击的必经步骤:
# showmount -e www.xxx.com
可能结果如下:
/usr (everyone) /export/target1 -access=target2 /export/target2 -access=target1
可以把这个NFS server上的/usr目录mount成本地目录:
# mount www.xxx.com:/usr /tmp
这表明,/usr目录可以被任何一台机器mount,甚至可能有写的权限;而/export/target1目录指定了主机访问限制,必须是target2.xxx.com这个机器或者target2这个Netgroup的成员才能mount。入侵者大多都先用这个命令来查询目标上的NFS漏洞,正如对NT的Netview命令一样。值得提醒的是,现在流行的入侵方式已经从以前的对确定目标的攻击方式转为不管对方是谁,只要有机可乘就入侵的方式。
入侵者可能会写一个脚本或者一个程序,用来对一大段地址进行扫描,列出结果报告给自己。所以,正确的配置是非常重要的。在Internet上,NFS设置错误的机器比比皆是。这个配置一般存放于/etc/exports文件或/etc/dfs/dfstab中。
2、来自客户端的NFS请求的用户认证,由用户的UID和所属组的GID组成,这种文件访问的安全验证对于没有开NFS的系统当然是安全的;但是在网上,其它机器的root完全有权在自己的机器上设置这样一个UID,而NFS服务器不管这个UID是不是自己机器上的,只要UID符合,就赋予这个用户对这个文件的操作权.比如,目录/home/frank只能由UID为501的用户打开读写,而这个目录可以被远程机器mount,那么,这台机器的root用户新增一个UID为501的用户,然后用这个用户登录并mount该目录,就可以获得相当于NFS server上的UID为501用户操作权限,从而读写/home/frank。要解决这个问题必须正确配置exports,限制客户的主机地址,明确设置rw=host的选项,ro(只读)的选项和access=host的选项。
另外,还有一种UID欺骗,是关于16位UID和32位UID的问题。大多NFS服务接受的来自客户对NFS请求所发送的UID标志都是16位的(Solaris是一个例外),这是不安全的。
在这种情况下,如果用一个32位UID,并把这个UID最左边的位置设置为0,那么,体现在NFS server上,解释为16位的UID,这个UID就相当于root;任何用户引用32位UID并且这个UID最左边的数字是0,那么就可以读/写属于root的任何文件。要解决这个问题,可以从Sun的正式站点获取#1095935补丁。
3、以前的文件句柄无须mount守护进程的帮助就可以构造,使客户直接可以和NFS通信。而现在的Unix系统大多进行了改进。但BSD系统还有问题。关于BSD文件句柄的问题涉BSD OS2.0,2.1,3.0;FreeBSD2.1.5~2.1.7,openBSD2.0和2.0以前。其它一些BSD也可能有类似的问题。例如在4.4BSD中,与其它的UNix文件系统不同的是,一个文件的信息,除了创建时间、文件大小、连接个数和更新时间等信息外,还有一个st_gen信息,st_gen是一个4位的值,目的是使NFS文件句柄难于猜到。这个信息是stat(2)系统调用生成的。不幸的是,这个调用用到的一个函数vn_stat()有问题:
...
sb->st_gen = vap->va_gen;
sb->st_blocks = vap->va_bytes / S_BLKSIZE;
return (0); }
上面这段程序码暴露了用来生成st_gen这个数的所有信息,利用这些信息,未授权用户可以得到文件的句柄。正确的程序应该只允许这些信息暴露给root:
...
sb->st_flags = vap->va_flags;
if (suser(p->p_ucred, &p->p_acflag)) {
sb->st_gen = 0;
} else {
sb->st_gen = vap->va_gen;
}
sb->st_blocks = vap->va_bytes / S_BLKSIZE;
return (0);
}
这样,如果不是root,他只能得到0这个信息。
4、最危险的错误是把含有SUID程序的目录export,并且该文件有执行权。SUID程序相当于超级用户本身。
解决方案
1、和从NT中删除任何共享的解决方案一样,最好的解决方案是禁止NFS服务,或以AFS服务取而代之(Andrew File System)。
2、如果一定要开NFS,不要让一个单机可以既是client,也是server;
3、export出的文件系统只设置为只读
4、禁止那些有SUID特性的程序的执行
5、不要export home 目录
6、不要export可执行特性
7、使用一些安全NFS实现方案(虽然未必真的很安全)