Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Oct 1995 03:24:22 -0400
From:      Sam Hartman <hartmans@mit.edu>
To:        security-alert@sgi.com, miguel@sgi.com, security-alert@hp.com, rich.boren@cxo.mts.dec.com, eichin@cygnus.com, bjaspan@cam.ov.com, volkerdi@wcarchive.cdrom.com, mycroft@mit.edu, bruce@pixar.com, tobias@server.et-inf.fho-emden.de, ache@astral.msk.su, jkh@time.cdrom.com, bugs@redhat.com, mark.graff@eng.sun.com
Cc:        tytso@mit.edu, jis@mit.edu, hartmans@mit.edu, brlewis@mit.edu, jhawk@mit.edu, cert@cert.org, lrr@cert.org
Subject:   timely: details on announcement of telnetd vulnerability
Message-ID:  <199510240724.DAA15744@tertius.mit.edu>
Resent-Message-ID: <11889.814540558@time.cdrom.com>

next in thread | raw e-mail | index | archive | help


-----BEGIN PGP SIGNED MESSAGE-----

			 History and Preface

	NOTICE: Because we have found a temporary work around,
Theodore Ts'o <tytso@mit.edu> has asked me to announce this bug
publicly next Tuesday.  The announcement will be issued soon after
10:30 EDT on Tuesday, October 31, 1995.  If your patch isn't listed,
tell me about it by Monday, October 30.  If your system is vulnerable
and the suggested quick fix won't work, it's probably in your best
interest to tell me this too; that way your users won't get a false
sense of security.  For such reports to be useful, I need to receive
them by this Thursday evening.  Also, if there are comments that can
help the structure of this memo as it evolves from a memo for vendors
to a bug description/announcement, let me know.  I know the following
changes will be made before the announcement:

* The 'Public Exposure' section will go away -- the announcement will
  be very public, so exposure will no longer be an interesting issue.

* Information in 'Availability of Patches' regarding the announcement
  date will go away. 

* A section describing how to test for the bug (not an exploit,
  although it'll probably have to be close enough that anyone who
  understands how to build a new library on their platform can figure
  out an exploit) will be added.

* The section on verifying patches will be  cleaned up/expanded.

Things you should note that have changed:
* Bugs have been found in the first Borman patch, and in the sample
  patch I originally sent out.

* A few more environment variables have been added.  The latest is
  ELF_LD_LIBRARY_PATH, which, according to Linux documentation is used
  as an ELF library search path.  The code tends to disagree with the
  documentation, using LD_ELF_LIBRARY_PATH; I'm still waiting to hear
  from H. J. Lu <hjl@nynexst.com> on this one.

* Other information has been added about patches.

* Clarification: if you require external authentication, only your
  valid users can break in.


	On Sunday, October 15, I discovered a bug in some versions of
telnetd on some platforms that allows a user making a connection to
cause login to load an alternate C library from an arbitrary location
in the filesystem of the machine running telnetd.  In the case of
machines mounting distributed filespaces such as AFS or NFS,
containing publicly writable anonymous FTP directories, or on which
the user already has a non-root account, it is possible to gain root
access.

	The problem is that telnetd will allow the client to pass
LD_LIBRARY_PATH, LD_PRELOAD, and other run-time linker options into the
process environment of the process that runs login.  If the runtime
linker honors these options for login, the attacker can cause a custom
libc to be loaded. Such a libc could, for example, start a shell
whenever some function like crypt() is called.  If login calls this
function before the setuid call, then the attacker will gain root
access.

	Note that the user must be able to convince telnetd to run
login in order for this attack to be successful.  In particular, if an
authentication system such as Kerberos is employed, and the telnetd
requires authentication, then only users with valid accounts will be
able to use this attack.


			      Quick Fix

	Most runtime linkers treat set user-id and set group-id
programs specially: for these programs the environment variables are
ignored when the program is run by a user other than the owner of the
file, or by someone in a group other than the primary group of the
file.  Even though login is often set user-id, the environment
variables are used because it is run by telnetd which runs as root.

	However, if you force login to be set-uid another user, or
set-gid, you can cause the runtime linker to ignore the environment
variables, protecting your system from this attack until your vendor
prepares a patch.  It turns out that login needs to be root, so making
login set-uid doesn't work.  However, there is nothing that stops you
from making login set-gid.  To do so, follow these steps:

1) Create a new group (you might want to call it 'login', 'telnet_bug',
   tnbug', '__login' or something of the sort). In the rest of this
   document, I will assume that you have called the group 'login'.
   Make sure the group doesn't already exist, and make sure that no
   other programs are moved into this group.  For information on how
   to create a group, consult your vendor's manuals and the man page
   for /etc/group.

2) Find your login program; it is often /usr/bin/login or /bin/login.
   I will assume here that it is /bin/login.  Under AIX and some other
   operating systems, login may be a symlink to another program; we
   are interested in changing the group of the actual program, not of
   the symlink.

3) Look at the current permissions on login:
   bash$ ls -l /bin/login
   lrwxrwxrwx   1 root     system        13 Mar  8 1994  /bin/login ->
								/usr/sbin/tsm
   bash$ ls -lL /bin/login
   -r-sr-xr-x   3 root     security   59217 Aug 23 1994  /bin/login
   bash$ 

	Note that because I am running on an AIX system, I gave the -L
option to the second ls in order to trace through the symlink and find
the real login.  You should remember what group login is in so you can
change things back after you get a a vendor patch.

4) Change the group of login and set the set GID bit:
   bash$ su
   root's Password:
   bash# chgrp login /bin/login
   bash# chmod g+s /bin/login
   bash# ls -lL /bin/login
   -r-sr-sr-x   3 root     login      59217 Aug 23 1994  /bin/login
   bash# 


		  Environment Variables that Matter

	This is not an exhaustive list of environment variables
telnetd should filter, but it does contain several of the key
variables on systems used at MIT and by people with whom I have
consulted:

LD_LIBRARY_PATH: At least Solaris, SunOS, NetBSD, Linux and Digital
   Unix use this as the path to look for shared libraries in.

LD_PRELOAD: Solaris and possibly others load these object modules into
   the address space of the process before loading other shared
   libraries.

LIBPATH: AIX uses this to locate its shared libraries.

ELF_LD_LIBRARY_PATH: May be used by the Linux Elf loader; similar to
   LD_LIBRARY_PATH in function.

LD_AOUT_LIBRARY_PATH: Another Linuxism from ld.so-1.7.3.  Same as
   LD_LIBRARY_PATH but only for a.out libraries.

_RLD_ROOT: Digital Unix uses this to specify a prefix prepended to
   library paths stored inside executables.

_RLD_LIST: A list of objects dynamically loaded into an executable by
   Digital Unix.

_RLD_*: Used by Digital Unix and SGI.  There are several apparently
   undocumented variables in /sbin/loader on Digital Unix and in the
   SGI runtime linker.

LD_*: Several other variables have special meaning to certain
   operating systems.  Stripping all these variables would probably be
   a good idea.

IFS: It is possible that setting IFS could cause damage in
   environments where the user logs into an account that runs a shell
   script instead of granting full access.


			  Affected Telnetds

	All telnetds derived from the Telnet package distributed by
David Borman allow the environment options to be passed.  Mr. Borman
has released a patch for the problem as of October 19.  The patch
released on October 19, while secure, has a bug that prevents any
telnet environment options from being handled.  Another patch was
released on October 23 that appears to work; see below for details.
Besides his original release, here are a list of operating systems and
security packages I'm aware of that include derivatives of this work:

* NetBSD and FreeBSD are distributed with a vulnerable
  telnetd.  (See below for patch info)

* The telnet94 with the fixed Kerberos version 4 authentication and
  encryption distributed by MIT on net-dist.mit.edu and used in MIT's
  Athena computing environment. (see below for patch location)

* The version of telnetd maintained in the Kerberos version 5
  distribution by MIT. (patch available)

* The Cygnus Network Security V4 95q1 Free Network Release includes a
  vulnerable telnetd. (Previous releases did not contain telnetd.) A
  patch has been released.

* Openvision's OVSecure may contain a telnetd that is vulnerable.


	       Other Vulnerable Telnetd Implementations

	This problem is not unique to code derived from the Borman
telnet distribution.  Other vulnerable implementations are known to
include:

* SGI Irix 5.3

* Digital Unix. The telnetd distributed with stock Digital Unix
  appears to be vulnerable.  

* Linux. The telnetd distributed with Slackware Linux appears to be
  vulnerable, although I have not verified this.  The maintainers of
  Debian GNU/Linux confirm their telnetd is vulnerable and released a
  patch; see below.


			  Telnetds that Work

	Below is a list of operating systems which come with telnetds
that we know are not vulnerable.

* SunOS 4.1.4. The Sunos 4.1.4 telnetd does not support passing of
  environment variables, so it is not vulnerable. 

* IBM AIX 4.1. This telnetd does not support environment options.

* BSDI's BSD/OS. While the telnetd will pass any environment option,
  there doesn't appear to be an option to override the shared library
  path, so BSD/OS is probably not vulnerable.  On October 19, Dave 
  Borman <dab@cray.com> confirmed that BSDI is not vulnerable to the
  attack, although the telnetd will accept any environment variable.

* Telnetd on other systems that do not support shared libraries.
  This includes DEC Ultrix, and Cray Unicos.

	Note that both AIX and SunOS can be vulnerable if the stock
telnetd is replaced.  Also, note that the stock Solaris telnetd has
not been tested.


		       Availability of Patches

	This is a list of patches I'm aware of at this time.  As you
develop a patch for your product/platform, please let me know;
considering free operating systems affected by this problem, widely
announcing the bug once patches are available is very important.
Nevertheless, it is important that we cooperate in timing the
announcement of patches so that all can be announced within a short
time range.

	Hopefully, I will be able to wait until October 31 before
announcing the bug, but if it becomes widely known (say, for example,
discussed on bugtraq), I will announce the patches I know about at
that time.  Note that these patches are provided as-is, without any
guarantee of correctness or security on the part of MIT, myself, or
the patch creator.  They are provided in a spirit of cooperation, not
as a guaranteed fix.

* On October 19, David Borman <dab@cray.com> released a new version of
  his telnet package, containing a fix to the problem.  This original
  patch disabled passing environment options entirely, but was revised
  on October 23.  The revised patch, and instructions for obtaining it
  are contained at the bottom of this message.  Note that this patch
  does not deal with the possibly problematic ELF_LD_LIBRARY_PATH.

* Greg Hudson <ghudson@mit.edu> checked a patch into the
  NetBSD-current source tree.  This patch will be incorporated by any
  NetBSD-current users who update to the current telnetd.  It will be in
  the NetBSD 1.1 release.  NetBSD developers have not indicated whether
  they plan on releasing a patch for NetBSD 1.0 users.  Note that the
  sample NetBSD patch distributed with an earlier version of the memo
  was incomplete; the version in the source tree as of October 18 is
  correct.

* Sam Hartman <hartmans@mit.edu> patched the upcoming release of
  Kerberos 5.  In addition, patches were generated against Kerberos 5
  beta 5 and beta 4-3.

* Mark Eichin <eichin@cygnus.com> prepared patches for CNS.  These
  patches will be available on the Cygnus web site
  <http://www.cygnus.com/>; support customers are being contacted
  directly.

* Peter Tobias, <tobias@server.et-inf.fho-emden.de> released a patch
  for Debian GNU/Linux.  This patch can be found in the networking
  utilities at
  ftp://ftp.debian.org/debian/debian-0.93/binary/net/netstd-1.20-1.deb
  Note that this patch does not currently deal ELF_LD_LIBRARY_PATH.

* Andrey A. Chernov <ache@astral.msk.su> released a patch for FreeBSD,
  but did not include an URL where the patch could be obtained.

* Bruce Lewis <brlewis@mit.edu> is preparing a patch for the
  MIT-distributed Athena telnet/telnet95.  His patch is currently
  available within MIT and should be available soon in the version of
  telnet on net-dist.mit.edu.


			   Public Exposure

	This problem is believed not to have wide circulation, and I
am not aware of any incidents of illicit penetration.  However, it has
received public exposure in three places.  First, Richard Basch's
patch was inadvertently sent to the krb5-bugs mailing list, which is
small but public; a publicly readable archive is maintained on an
MIT Discuss server.  In response to this exposure, the MIT Student
Information Processing Board's Linux development group released a new
kerberos package, including a fixed telnetd.  The announcement of this
package indicated the existence of a telnet security hole; SIPB's
sources are publicly readable to the MIT community.

	Greg Hudson's patch to NetBSD was included in an automatic
summary of source changes sent to the source-changes@netbsd.org
mailing list.  The summary said that the patch prevented telnetd from
setting dangerous environment variables.

	Finally, David Borman's announcement of the new version of
telnet was posted to several public lists on October 19.  The
announcement did not say anything about a security hole, nor did it
contain a diff.  However, a diff is available at the Cray ftp site.


			  Verifying a Patch

	In the process of talking to vendors, distributing patches,
and getting feedback, I've come up with a lot of 'almost solutions' --
patches that are good enough to make you think they work, but that can
be compromised.

* A clever trick to get around exact match patches is to embed an
  equals sign in a variable name.  For example, ask your client to send
  an option requesting that the variable
  LD_LIBRARY_PATH=/home/hartmans/exploits/sun4lib: be set to the value
  invalid:/lib:/usr/lib.  Naturally, the call to setenv in telnetd adds
  another =, but that's soaked up by 'invalid', and I still get to
  break into the system.  I.E.  Deal with variable names containing
  equals signs (=).

* At least in the Borman BSD telnet, there are two calls to setenv:
  one for the last part of an environment option and one for the other
  parts.  Make sure you cover both; this was the biggest problem with
  the sample patch I first distributed.

* If it is possible to stuff a string into the environment twice with
  your telnetd, make sure you check all entries in the environment.  For
  example, if you have a setenv() that doesn't check for duplicates,
  don't just use unsetenv() as this will remove the last item in the
  environment, leaving the others to be used by login.


			     Sample Patch

	Below, I include the official patch to telnet from David
Borman <dab@cray.com> as of October 23.  Before the patch, I include a
message I received on October 19; this includes useful information.
As I received the message, it was not PGP-signed; its inclusion in
this signed summary indicates that it has not been modified since I
received it, and says nothing about the integrity of the
communications link between myself and Mr. Borman.  However, I have
examined the patch, and it appears to be a valid fix for the bug.  It
also corresponds to the appropriate sections of the diff on the ftp
server.  Again, patches are provided as-is without a guarantee of
correctness; you assume all risk for applying this patch. (As with all
PGP-signed patches, you will need to remove leading dashes.)

Date: Thu, 19 Oct 95 13:54:56 CDT 
From: dab@berserkly.cray.com (David A. Borman)
Message-Id: <9510191854.AA03474@frenzy.cray.com>
To: hartmans@MIT.EDU
Subject: Re: telnet vulnerability giving root access
Cc: cert@cert.org, tytso@MIT.EDU


I have placed a version of the BSD Telnet distribution at:

	ftp://ftp.cray.com/src/telnet/telnet.95.10.23.NE.tar.Z

with a fix for this problem.  It changes telnetd to remove the LD_*,
_RLD_*, IFS and LIBPATH environment variables before execing login.

The version on ftp.cray.com does not contain the encryption code,
that is on net-dist.mit.edu, and I have sent a new copy off to
them to replace the current distribution.

(The attached diffs also show a bugfix for a problem that was
screwing up /etc/utmp on Solaris.)

Also, BSDI is not affected, as they do not provide any way for
the user to override the search path for shared libraries.
UNICOS is unaffected, since we don't have shared libraries.

Please feel free to pass on this message.

			-David Borman, dab@cray.com
diff -cbr telnet.95.05.31/telnetd/sys_term.c telnet.95.10.23/telnetd/sys_term.c
*** telnet.95.05.31/telnetd/sys_term.c	Wed May 31 00:50:57 1995
- --- telnet.95.10.23/telnetd/sys_term.c	Mon Oct 23 09:47:17 1995
***************
*** 32,38 ****
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)sys_term.c	8.4 (Berkeley) 5/30/95";
  #endif /* not lint */
  
  #include "telnetd.h"
- --- 32,38 ----
   */
  
  #ifndef lint
! static char sccsid[] = "@(#)sys_term.c	8.4+1 (Berkeley) 5/30/95";
  #endif /* not lint */
  
  #include "telnetd.h"
***************
*** 1570,1579 ****
  	utmpx.ut_id[3] = SC_WILDC;
  	utmpx.ut_type = LOGIN_PROCESS;
  	(void) time(&utmpx.ut_tv.tv_sec);
! 	if (pututxline(&utmpx) == NULL)
! 		fatal(net, "pututxline failed");
  #endif
  
  	/*
  	 * -h : pass on name of host.
  	 *		WARNING:  -h is accepted by login if and only if
- --- 1570,1581 ----
  	utmpx.ut_id[3] = SC_WILDC;
  	utmpx.ut_type = LOGIN_PROCESS;
  	(void) time(&utmpx.ut_tv.tv_sec);
! 	if (makeutx(&utmpx) == NULL)
! 		fatal(net, "makeutx failed");
  #endif
  
+ 	scrub_env();
+ 
  	/*
  	 * -h : pass on name of host.
  	 *		WARNING:  -h is accepted by login if and only if
***************
*** 1809,1814 ****
- --- 1811,1836 ----
  	return(argv);
  }
  #endif	/* NEWINIT */
+ 
+ /*
+  * scrub_env()
+  *
+  * Remove a few things from the environment that
+  * don't need to be there.
+  */
+ scrub_env()
+ {
+ 	register char **cpp, **cpp2;
+ 
+ 	for (cpp2 = cpp = environ; *cpp; cpp++) {
+ 		if (strncmp(*cpp, "LD_", 3) &&
+ 		    strncmp(*cpp, "_RLD_", 5) &&
+ 		    strncmp(*cpp, "LIBPATH=", 8) &&
+ 		    strncmp(*cpp, "IFS=", 4))
+ 			*cpp2++ = *cpp;
+ 	}
+ 	*cpp2 = 0;
+ }
  
  /*
   * cleanup()


			   Acknowledgments

	In preparing this bug summary, I have received the help of
several people.  In particular, I would like to thank David Borman for
quickly fixing the problem once notified, and Bruce Lewis for
supplying a timely solution to the problem within MIT.  In addition,
John Hawkinson <jhawk@mit.edu> provided help developing exploit
scripts and confirming that the bug existed on several systems.  I
would also like to thiank those at MIT who reviewed drafts of this
announcement and suggested improvements.

- - -- Sam Hartman, MIT Kerberos Development team


-----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQEUAwUBMIyQAEJYVPVo3rXRAQE4Lwf46xcucSdiA/uKBOfEIAZM394nIJ6mcYCD
gQb7Le+R6Tx9dFYU7rbAvsaoxaeh70ikAXpl0U+wE8kV86u8NuM7RXPkLrwWJWPt
Po2EjrPGneLvxBovAReZPUEZQxRbFvOWKU4tXSPsQJpAY3o6p4sRAG4d3hMal9KP
miD5RB65ow8dq46n+VA+t1O4BfuiMkdTwToEt3tMV7dCTJCydZkMg0ZUmg6q6MeB
BoXxMELmVJXxof2pmpg4bw1yWkoX1oWvdFJu2qpAF/oC/jY5f4VbtDnorEVpjgVz
UMqQIcYpESisGuGk0xvJtPdo7ZPUXWgvk//Vo3sNnpMKvl2CTuH+
=CWs7
-----END PGP SIGNATURE-----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199510240724.DAA15744>