From owner-freebsd-security@FreeBSD.ORG Wed Feb 25 10:54:32 2004 Return-Path: Delivered-To: freebsd-security@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8D0F116A4CE; Wed, 25 Feb 2004 10:54:32 -0800 (PST) Received: from kientzle.com (h-66-166-149-50.SNVACAID.covad.net [66.166.149.50]) by mx1.FreeBSD.org (Postfix) with ESMTP id E106443D1F; Wed, 25 Feb 2004 10:54:31 -0800 (PST) (envelope-from tim@kientzle.com) Received: from kientzle.com (54.kientzle.com [66.166.149.54] (may be forged)) by kientzle.com (8.12.9/8.12.9) with ESMTP id i1PIsV7g008367; Wed, 25 Feb 2004 10:54:31 -0800 (PST) (envelope-from tim@kientzle.com) Message-ID: <403CEF67.5040004@kientzle.com> Date: Wed, 25 Feb 2004 10:54:31 -0800 From: Tim Kientzle User-Agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20031006 X-Accept-Language: en-us, en MIME-Version: 1.0 To: freebsd-security@freebsd.org, das@freebsd.org Content-Type: multipart/mixed; boundary="------------000701060105000106090207" X-Mailman-Approved-At: Thu, 26 Feb 2004 01:56:58 -0800 Subject: Environment Poisoning and login -p X-BeenThere: freebsd-security@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: kientzle@acm.org List-Id: Security issues [members-only posting] List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 25 Feb 2004 18:54:32 -0000 This is a multi-part message in MIME format. --------------000701060105000106090207 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit There's been an ongoing discussion (started by Colin Percival's recent work on nologin) about environment-poisoning attacks via "login -p". I thought I saw a way to address this, but the more I learn, the uglier this looks. Maybe some of the good folks who read freebsd-security can puzzle this one out: Problem: login -p can be used to propagate environment flags in order to trojan the user shell of the target account. There are several significant cases: * Dynamically-linked target shell. * Target account shell is a shell script. Both of these are quite common in practice. (However, I will note that in -CURRENT, both "nologin" and /bin/sh are statically-linked and thus currently immune to this.) The particular thread that started me looking at this concerned "nologin" scripts or programs that attempt to block access to certain accounts. David Schultz has demonstrated that login -p can be used to circumvent a dynamically-linked nologin program, for example. If your friend's account hasn't been blocked, you may be able use that to circumvent any blocks placed on your own account. Possible fix: Ignore "-p" flag if target shell is not in /etc/shells. In this scenario, a nologin program would not be listed in /etc/shells, and thus such attacks would be blocked. Problem: One common use of nologin scripts is to create ftp-only accounts. However, ftpd(8) limits ftp access to accounts with "standard" shells. As a result, ftp-only accounts must have their shell listed in /etc/shells. Possible fix: Have login unconditionally discard LD_LIBRARY_PATH and LD_PRELOAD from the environment, even if "-p" is specified. I'm unsure that this is sufficient. I'm also unsure whether this blocks legitimate use of "login -p." I am generally distrustful of blacklist security approaches; I'd prefer a whitelist approach that only passed through selected environment variables. Possible fix: Eliminate the "-p" option to login. This would certainly close the hole, but could introduce complications elsewhere. (I've looked at telnetd, which uses this flag. However, it appears to use it only to propagate the TERM flag, which our login program does even without -p.) Part of the issue here is an underlying disagreement about the meaning of "standard shell." Skimming the -CURRENT source tree reveals several different definitions of "standard shell": * A group of "equivalent" shells from which users can choose. (from chpass(1)) * An indicator that the user is allowed ftp access (from ftpd(8)) * An indicator that su is permitted * An indicator that mail include files should be honored (in sendmail; based on a very quick skimming of the source) These are not entirely consistent interpretations, resulting in security problems with "ftp-only" access, for example. I've attached a patch to "login" that implements the two "Possible Fixes" above. I'm not entirely happy with it, though, for the reasons I've indicated. Suggestions? Tim Kientzle --------------000701060105000106090207 Content-Type: text/plain; name="kientzle-login.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="kientzle-login.diff" Index: login.c =================================================================== RCS file: /home/ncvs/src/usr.bin/login/login.c,v retrieving revision 1.98 diff -r1.98 login.c 86a87 > static int chshell(const char *); 468c469,472 < * preservation - but preserve TERM in all cases --- > * preservation or the user has a non-standard shell. In > * particular, this "non-standard shell" check blocks certain > * environment-poisoning exploits against nologin scripts. > * Preserve TERM in all cases. 471c475 < if (!pflag) --- > if (!pflag || !chshell(shell)) 476a481,491 > * The chshell() check above isn't sufficient, though. > * For example, consider a custom nologin script used > * to limit accounts to ftp-only access. ftpd(8) requires > * the user shell to be in /etc/shells, thus crippling > * the above check. The following provides some modest > * additional security limits in such cases. > */ > unsetenv("LD_LIBRARY_PATH"); > unsetenv("LD_PRELOAD"); > > /* 935a951,968 > } > > /* > * Return TRUE if the shell is a "standard" shell. > * (That is, one listed in /etc/shells.) > */ > static int > chshell(const char *sh) > { > int r; > const char *cp; > > r = 0; > setusershell(); > while ((cp = getusershell()) != NULL && !r) > r = (strcmp(cp, sh) == 0); > endusershell(); > return (r); --------------000701060105000106090207--