FreeBSD内核NFS客户端实现多个内核缓冲区溢出漏洞

受影响系统:

FreeBSD FreeBSD 8.0
FreeBSD FreeBSD 7.3
FreeBSD FreeBSD 7.2

描述:
FreeBSD就是一种运行在Intel平台上、可以自由使用的开放源码Unix类系统。

FreeBSD内核的NFS客户端实现没有执行正确地输入验证。第一个漏洞位于nfs_mount()函数中,该函数在将从用户空间的nfs_args类型结构所传送数据拷贝到内核时没有充分的验证输入。具体来讲,所要加载的文件句柄缓冲区(args.fh)及其大小(args.fhsize)是完全受用户控制的。越界拷贝操作发生在src/sys/nfsclient/nfs_vfsops.c文件中:

1094:      if (!has_fh_opt) {
1095:            error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1096:                 args.fhsize);
1097:          if (error) {
1098:               goto out;
1099:            }

args和nfh变量的声明:

786: static int
787: nfs_mount(struct mount *mp)
788: {
789:         struct nfs_args args = {
790:             .version = NFS_ARGSVERSION,
             …
820:         u_char nfh[NFSX_V3FHMAX];

这个漏洞可能导致内核栈溢出。在FreeBSD 7.3-RELEASE和7.2-RELEASE上,利用结果是内核权限提升;在FreeBSD 8.0-RELEASE上,由于默认所启用的SSP/ProPolice内核stack-smashing保护,利用结果是内核崩溃。7.1-RELEASE及之前版本不受漏洞影响。

另一个漏洞位于可从nfs_mount()函数调用的mountnfs()函数中:

1119: error = mountnfs(&args, mp, nam, args.hostname, &vp,
1120:     curthread->td_ucred);

非特权用户可通过mount(2)和nmount(2)系统调用到达 mountnfs()函数。与上述的nfs_mount()情况相同,这要求sysctl(8)变量vfs.usermount设置为非0的值。

所要加载的文件句柄(argp->fh)以及从nfs_mount()传送给mountnfs()函数的大小(argp->fhsize)是由用户控制的,之后在bcopy()调用中使用:

1219: bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);

当argp->fh大于128字节(nmp->nm_fh的大小)时可能触发内核堆溢出,因为nmp是UMA区nfsmount_zone上所分配的项:

1160: static int
1161: mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1162:     char *hst, struct vnode **vpp, struct ucred *cred)
1163: {
1164:         struct nfsmount *nmp;
1165:         struct nfsnode *np;
1166:         int error;
1167:         struct vattr attrs;
1168:
1169:         if (mp->mnt_flag &MNT_UPDATE) {
1170:                 nmp = VFSTONFS(mp);
1171:                 printf("%s: MNT_UPDATE is no longer handled here\n",
__func__);
1172:                 free(nam, M_SONAME);
1173:                 return (0);
1174:         } else {
1175:                 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);

在FreeBSD 8.0-RELEASE、7.3-RELEASE和7.2-RELEASE上,利用结果是内核权限提升或内核崩溃。7.1-RELEASE及之前版本不受漏洞影响。

<*来源:Patroklos Argyroudis
  
  链接:
http://marc.info/?l=bugtraq&m=127505886716741&w=2
        ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-10:06.nfsclient.asc
*>

测试方法:

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

 

http://census-labs.com/media/nfs_mount_ex.c
http://census-labs.com/media/mountnfsex.c

建议:

临时解决方法:

* 不要允许不可信任的用户加载文件系统,将vfs.usermount sysctl变量设置为0:

# sysctl vfs.usermount=0

请注意这个变量的默认值为0,也就是FreeBSD在默认配置中不受这个漏洞影响。

厂商补丁:

FreeBSD
——-
FreeBSD已经为此发布了一个安全公告(FreeBSD-SA-10:06)以及相应补丁:
FreeBSD-SA-10:06:Unvalidated input in nfsclient
链接:
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-10:06.nfsclient.asc

补丁下载:

执行以下步骤之一;

1) 将有漏洞的系统升级到7-STABLE或8-STABLE,,或修改日期之后的RELENG_8_0、RELENG_7_3或RELENG_7_2安全版本。

2) 如果要通过源码路径升级有漏洞的系统:

以下补丁确认可应用于FreeBSD 7.2、7.3和8.0系统。

a) 从以下位置下载相关补丁,并使用PGP工具验证附带的PGP签名。

# fetch http://security.FreeBSD.org/patches/SA-10:06/nfsclient.patch
# fetch http://security.FreeBSD.org/patches/SA-10:06/nfsclient.patch.asc

b) 以root执行以下命令:

# cd /usr/src
# patch < /path/to/patch

c) 如<URL:http://www.FreeBSD.org/handbook/kernelconfig.html> 所述重新编译内核并重启系统。

3) 如果要通过二进制补丁升级有漏洞的系统:

可通过freebsd-update(8)工具升级i386或amd64平台上运行7.2-RELEASE、7.3-RELEASE或8.0-RELEASE的系统:

# freebsd-update fetch
# freebsd-update install

发表评论?

0 条评论。

发表评论