Published:
15 September 1999
Protect yourself against future threats.
-----BEGIN PGP SIGNED MESSAGE----- ========================================================================== AUSCERT External Security Bulletin Redistribution ESB-1999.144 -- FreeBSD-SA-99:04 Coredumps and symbolic links 16 September 1999 =========================================================================== The FreeBSD Security Team has released the following advisory concerning a vulnerability in the kernel's implementation which allows it to follow symbolic links when creating core files. A user may create or overwrite a file on the system with the privileges of a process which produces a core in a accessible location. This vulnerability may allow local users to gain root access. - --------------------------BEGIN INCLUDED TEXT-------------------- - -----BEGIN PGP SIGNED MESSAGE----- ============================================================================= FreeBSD-SA-99:04 Security Advisory FreeBSD, Inc. Topic: Coredumps and symbolic links Category: core Module: kernel Announced: 1999-09-15 Affects: FreeBSD 3.2 (and earlier) FreeBSD-current before the correction date. FreeBSD 3.2-stable before the correction date. FreeBSD 2.2.8-stable before the correction date. Corrected: FreeBSD-3.3 RELEASE FreeBSD-current as of 1999/08/26 FreeBSD-3.2-stable as of 1999/08/26 FreeBSD-2.2.8-stable as of 1999/08/29 The FreeBSD-3.3-RC series of releases are not affected. FreeBSD only: NO Patches: ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-99:04/ I. Background As a diagnostic aid to help programmers find bugs in their programs, the system creates core files when an illegal instruction or other fatal error happens. A flaw in the kernel allowed it to follow symbolic links when creating core files. II. Problem Description The fts library functions had a flaw in them where which would lead to a core dump when periodic ran the security checking scripts (or other scripts which traverse trees that can be controlled by users). periodic(3) should limit core size to zero to disable core dumps while it is executing commands, but does not do so. In addition, the kernel should not follow symbolic links. All three of these problems caused a situation where it was possible for an attacker could create or overwrite an arbitrary file on the system with a moderate degree of controll of its contents to cause a problem. III. Impact Local users could gain root access. IV. Workaround One can workaround this problem by preventing core dumps for periodic. This solution is less than completely satisfying, since it only plugs the known exploit hole. None the less, this may provide a short term stopgap solution until a new kernel and/or userland can be installed. # mv /usr/sbin/periodic /usr/sbin/periodic.bin # cat > /usr/sbin/periodic #!/bin/sh ulimit -c 0 /usr/sbin/periodic.bin $* ^D # chmod 555 /usr/sbin/periodic Another alternative would be to update the fts routines to a version newer than 1999/09/02 (for -current or 3.3-stable) or 1999/09/04 (for 2.2.8-stable). However, this requires that you rebuild via "make world" to take effect. V. Solution Please note: there is a separate advisory describing the fts problem and solution. Please see FreeBSD-SA-99:05.fts.asc in the advisories directory for additional information about the fts patch. Apply the following patches to your kernel. They will disallow following symbolic links when creating core files. This will stop this attack, and all similar such attacks. Here's the patch for freebsd-current: *** kern/imgact_elf.c 1999/07/09 19:10:14 1.61 --- kern/imgact_elf.c 1999/08/26 17:32:48 1.62 *************** *** 722,729 **** if (name == NULL) return (EFAULT); /* XXX -- not the best error */ ! NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); ! error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); --- 722,729 ---- if (name == NULL) return (EFAULT); /* XXX -- not the best error */ ! NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p); ! error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); *** kern/imgact_aout.c 1999/05/17 00:53:36 1.52 --- kern/imgact_aout.c 1999/08/26 17:32:48 1.53 *************** *** 264,271 **** name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid); if (name == NULL) return (EFAULT); /* XXX -- not the best error */ ! NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); ! error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); --- 264,271 ---- name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid); if (name == NULL) return (EFAULT); /* XXX -- not the best error */ ! NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p); ! error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); Here's the patch for freebsd-3.2-stable: *** kern/imgact_elf.c 1999/07/15 13:01:54 1.44.2.4 --- kern/imgact_elf.c 1999/08/26 17:35:03 1.44.2.5 *************** *** 699,706 **** if (name == NULL) return (EFAULT); /* XXX -- not the best error */ ! NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); ! error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); --- 699,706 ---- if (name == NULL) return (EFAULT); /* XXX -- not the best error */ ! NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p); ! error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); *** kern/imgact_aout.c 1999/04/14 04:55:22 1.44.2.1 --- kern/imgact_aout.c 1999/08/26 17:35:02 1.44.2.2 *************** *** 259,266 **** name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid); if (name == NULL) return (EFAULT); /* XXX -- not the best error */ ! NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); ! error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); --- 259,266 ---- name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid); if (name == NULL) return (EFAULT); /* XXX -- not the best error */ ! NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p); ! error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); Here's the patch for FreeBSD-2.2.8-stable *** sys/LINK/fcntl.h Wed Dec 18 05:08:08 1996 --- sys/fcntl.h Fri Aug 27 14:39:26 1999 *************** *** 84,89 **** --- 84,90 ---- #define O_EXLOCK 0x0020 /* open with exclusive file lock */ #define O_ASYNC 0x0040 /* signal pgrp when data ready */ #define O_FSYNC 0x0080 /* synchronous writes */ + #define O_NOFOLLOW 0x0100 /* don't follow symlinks */ #endif #define O_CREAT 0x0200 /* create if nonexistent */ #define O_TRUNC 0x0400 /* truncate to zero length */ *** kern/LINK/kern_sig.c Sat Dec 21 10:57:24 1996 --- kern/kern_sig.c Fri Aug 27 14:38:25 1999 *************** *** 1241,1249 **** p->p_rlimit[RLIMIT_CORE].rlim_cur) return (EFAULT); sprintf(name, "%s.core", p->p_comm); ! NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); if ((error = vn_open(&nd, ! O_CREAT | FWRITE, S_IRUSR | S_IWUSR))) return (error); vp = nd.ni_vp; --- 1241,1249 ---- p->p_rlimit[RLIMIT_CORE].rlim_cur) return (EFAULT); sprintf(name, "%s.core", p->p_comm); ! NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p); if ((error = vn_open(&nd, ! O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR))) return (error); vp = nd.ni_vp; *** kern/LINK/vfs_vnops.c Sat Mar 8 07:16:18 1997 --- kern/vfs_vnops.c Fri Aug 27 14:37:01 1999 *************** *** 87,93 **** if (fmode & O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; ! if ((fmode & O_EXCL) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; error = namei(ndp); if (error) --- 87,93 ---- if (fmode & O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; ! if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; error = namei(ndp); if (error) *************** *** 119,125 **** } } else { ndp->ni_cnd.cn_nameiop = LOOKUP; ! ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF; error = namei(ndp); if (error) return (error); --- 119,126 ---- } } else { ndp->ni_cnd.cn_nameiop = LOOKUP; ! ndp->ni_cnd.cn_flags = ! ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF; error = namei(ndp); if (error) return (error); *** kern/LINK/vfs_syscalls.c Wed Aug 4 12:44:30 1999 --- kern/vfs_syscalls.c Sat Aug 28 10:48:51 1999 *************** *** 694,699 **** --- 694,701 ---- flags = FFLAGS(uap->flags); if ((flags & FREAD + FWRITE) == 0) return (EINVAL); + if (flags & O_NOFOLLOW) + flags &= ~O_NOFOLLOW; error = falloc(p, &nfp, &indx); if (error) return (error); ============================================================================= FreeBSD, Inc. Web Site: http://www.freebsd.org/ Confidential contacts: security-officer@freebsd.org Security notifications: security-notifications@freebsd.org Security public discussion: freebsd-security@freebsd.org PGP Key: ftp://ftp.freebsd.org/pub/FreeBSD/CERT/public_key.asc Notice: Any patches in this document may not apply cleanly due to modifications caused by digital signature or mailer software. Please reference the URL listed at the top of this document for original copies of all patches if necessary. ============================================================================= - -----BEGIN PGP SIGNATURE----- Version: 2.6.3ia Charset: noconv Comment: Processed by Mailcrypt 3.4, an Emacs/PGP interface iQCVAwUBN+B44VUuHi5z0oilAQHkwwP9HeLkRJY/iXIYXUx8/A38EAxM/TAqxoiI ym7ZyktNtuCbum8ovCIfmkpnafaFyXmVSDhCX77LbIy+1clEBnelyueJ9TbKpBgU KWjTWmfj/7QsU2Ya/f7FK80ee8y7GjTTYxilnxxzTmM8ihHzFXrPHudoO4lTR7Op 2VII3pQVxOM= =bJXX - -----END PGP SIGNATURE----- - --------------------------END INCLUDED TEXT-------------------- This security bulletin is provided as a service to AusCERT's members. As AusCERT did not write the document quoted above, AusCERT has had no control over its content. The decision to use any or all of this information is the responsibility of each user or organisation, and should be done so in accordance with site policies and procedures. NOTE: This is only the original release of the security bulletin. It will not be updated when updates to the original are made. If downloading at a later date, it is recommended that the bulletin is retrieved directly from the original authors to ensure that the information is still current. Contact information for the authors of the original document is included in the Security Bulletin above. If you have any questions or need further information, please contact them directly. Previous advisories and external security bulletins can be retrieved from: http://www.auscert.org.au/Information/advisories.html If you believe that your system has been compromised, contact AusCERT or your representative in FIRST (Forum of Incident Response and Security Teams). Internet Email: auscert@auscert.org.au Facsimile: (07) 3365 7031 Telephone: (07) 3365 4417 (International: +61 7 3365 4417) AusCERT personnel answer during Queensland business hours which are GMT+10:00 (AEST). On call after hours for emergencies. -----BEGIN PGP SIGNATURE----- Version: 2.6.3i Charset: noconv Comment: ftp://ftp.auscert.org.au/pub/auscert/AUSCERT_PGP.key iQCVAwUBN+dwNyh9+71yA2DNAQFunwP9Gk3FTPmJd5Y9w4thcBvQqDIPfstv+HJv piZxyDdFs2oCLRzPyIO+wSWxro3B7lXqL0wtLK8OZahmr3UBSLyMZEmkVxc4CXwo iL6pcW+/J5FERLgNsFcAVztB+8ov+G6UtTUfWniiRFYsQSPjlmBkH4757tiONvxS Xf3NxfhwvUs= =/Mq1 -----END PGP SIGNATURE-----