CVE-2010-2020: FreeBSD kernel NFS client local vulnerabilities

From: Patroklos Argyroudis <argp@census-labs.com>
To: bugtraq@securityfocus.com
Cc:
Subject: CVE-2010-2020: FreeBSD kernel NFS client local vulnerabilities
Date:


Census ID:          census-2010-0001
URL:               
http://census-labs.com/news/2010/05/26/freebsd-kernel-nfsclient/
CVE ID:             CVE-2010-2020
Affected Products:  FreeBSD 8.0-RELEASE, 7.3-RELEASE, 7.2-RELEASE
Class:              Improper Input Validation (CWE-20)
Remote:             No
Discovered by:      Patroklos Argyroudis

We have discovered two improper input validation vulnerabilities in the
FreeBSD kernel's NFS client-side implementation (FreeBSD 8.0-RELEASE,
7.3-RELEASE and 7.2-RELEASE) that allow local unprivileged users to
escalate their privileges, or to crash the system by performing a denial
of service attack.

Details

FreeBSD (http://www.freebsd.org/) is an advanced operating system which
focuses on reliability and performance. More information about its
features can be found at http://www.freebsd.org/about.html.

FreeBSD 8.0-RELEASE, 7.3-RELEASE and 7.2-RELEASE employ an improper input
validation method in the kernel's NFS client-side implementation.
Specifically, the first vulnerability is in function nfs_mount() (file
src/sys/nfsclient/nfs_vfsops.c) which is reachable from the mount(2) and
nmount(2) system calls. In order for them to be enabled for unprivileged
users the sysctl(8) variable vfs.usermount must be set to a non-zero
value.

The function nfs_mount() employs an insufficient input validation method
for copying data passed in a structure of type nfs_args from userspace to
kernel. Specifically, the file handle buffer to be mounted (args.fh) and
its size (args.fhsize) are completely user-controllable. The unbounded copy
operation is in file src/sys/nfsclient/nfs_vfsops.c (the excerpts are from
8.0-RELEASE):

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:            }

The declaration of the variables args and nfh is at:

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];

This vulnerability can cause a kernel stack overflow which leads to
privilege escalation on FreeBSD 7.3-RELEASE and 7.2-RELEASE. On FreeBSD
8.0-RELEASE the result is a kernel crash/denial of service due to the
SSP/ProPolice kernel stack-smashing protection which is enabled by
default. Versions 7.1-RELEASE and earlier do not appear to be
vulnerable since the bug was introduced in 7.2-RELEASE. In order to
demonstrate the impact of the vulnerability we have developed a
proof-of-concept privilege escalation exploit:

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

A sample run of the exploit follows:

[argp@julius ~]$ uname -rsi
FreeBSD 7.3-RELEASE GENERIC
[argp@julius ~]$ sysctl vfs.usermount
vfs.usermount: 1
[argp@julius ~]$ id
uid=1001(argp) gid=1001(argp) groups=1001(argp)
[argp@julius ~]$ gcc -Wall nfs_mount_ex.c -o nfs_mount_ex
[argp@julius ~]$ ./nfs_mount_ex
[*] calling nmount()
[!] nmount error: -1030740736
nmount: Unknown error: -1030740736
[argp@julius ~]$ id
uid=0(root) gid=0(wheel) egid=1001(argp) groups=1001(argp)

The second vulnerability exists in the function mountnfs() that is called
from function nfs_mount():

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

The function mountnfs() is reachable from the mount(2) and nmount(2) system
calls by unprivileged users. As with the nfs_mount() case above, this
requires the sysctl(8) variable vfs.usermount to be set to a non-zero value.

The file handle to be mounted (argp->fh) and its size (argp->fhsize)
are passed to function mountnfs() from function nfs_mount() and are
user-controllable. These are subsequently used in an unbounded bcopy()
call (file src/sys/nfsclient/nfs_vfsops.c):

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

The above can cause a kernel heap overflow when argp->fh is bigger than 128
bytes (the size of nmp->nm_fh) since nmp is an allocated item on the
Universal Memory Allocator (UMA, the FreeBSD kernel's heap allocator)
zone nfsmount_zone (again from src/sys/nfsclient/nfs_vfsops.c):

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);

This kernel heap overflow can lead on FreeBSD 8.0-RELEASE, 7.3-RELEASE and
7.2-RELEASE to privilege escalation and/or a kernel crash/denial of
service attack. Similarly to the first vulnerability, FreeBSD 7.1-RELEASE
and earlier versions do not appear to be vulnerable. We have developed a
proof-of-concept DoS exploit to demonstrate the vulnerability:

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

Furthermore, we have also developed a privilege escalation exploit for this
second vulnerability which will not be released at this point.

FreeBSD has released an official advisory and a patch to address both
vulnerabilities:

http://security.freebsd.org/advisories/FreeBSD-SA-10:06.nfsclient.asc

All affected parties are advised to follow the upgrade instructions
included in the advisory and patch their systems.

--
Patroklos Argyroudis
http://www.census-labs.com/





Copyright © 1995-2018 LinuxRocket.net. All rights reserved.