COMMAND
Kerberos
SYSTEMS AFFECTED
KTH Kerberos IV
PROBLEM
Jouko Pynnonen found following. Kerberos is a network
authentication protocol which by using secret-key cryptography
provides authentication over insecure networks. There are at
least two common free Kerberos implementations: MIT and KTH
(Royal Institute of Techology, Sweden). The latter is included
in OpenBSD and FreeBSD.
The KTH Kerberos IV implementation (http://www.pdc.kth.se/kth-krb)
contains the following vulnerabilities:
1) Honoring certain environment variables
2) Buffer overflow in protocol parsing code
3) File system race when writing ticket files
The vulnerabilities may lead to local and remote root compromise
if the system supports Kerberos authentication and uses the KTH
implementation (as is the case with e.g. OpenBSD per default).
The system needn't be specifically configured to use Kerberos for
all of the issues to be exploitable; some of the vulnerabilities
are exploitable even if Kerberos is disabled by commenting out
the realm name in the "krb.conf" file.
It should be noted that the MIT implementation of Kerberos is
probably NOT vulnerable for most of the problems discussed here;
however a quick glance at the MIT code reveals that the krb4
compatibility code of krb5 seems to honor "KRB_CONF" and
"KRB_REALMS" while running setuid (the package inspected was
krb5-1.1.1-9.src.rpm on a Red Hat Linux system, vulnerability
wasn't further tested). The telnetd versions used on most Linux
systems don't pass the mentioned environment variables to the
login process.
1) Honoring certain environment variables
=========================================
The variable "krb4_proxy" is used regardless of setuidness of the
process. A local user may set the variable to intercept the
authentication requests with their own proxy and generate false
replies. In conjunction with the buffer overflow (see below) this
could lead to root compromise. The variable is used when an
authentication request is being sent, thus to be exploitable with
this environment variable the system must be configured to use
Kerberos.
The "krb4_proxy" variable can be imported through a telnet session
to fool the login process to proxy its authentication requests in
the same way. This is possible without having a local account on
the system. However it's unclear at this point (for us at least)
whether exploiting this without the buffer overflow is possible;
the password check itself can be bypassed, but the login program
does an additional check to find out if it's talking with a bogus
server. The encryption key used for this is contained in the
local srvtab file. If this key can be retrieved by the bogus
proxy, or the verification request can be validly proxied to the
original server as normally, then it would be possible to exploit
this without the buffer overflow.
The environment variable "KRBCONFDIR" is used if the process isn't
running setuid. The variable can be brought in via a telnet
session to redefine the directory containing Kerberos
configuration files. A local user, or a remote user who is able
to upload files on the system, can supply their own configuration
files (krb.conf, krb.extra, krb.realms, srvtab) to be used by the
login program, which at the moment of authentication has both
effective and real user id equal to zero. It is thus possible to
define an arbitrary Kerberos server which may then tell the login
program to accept the authentication. For this issue to be
exploitable, the system needn't be configured to use Kerberos, or
Kerberos may be disabled in the original configuration file
/etc/kerberosIV/krb.conf.
This scenario was successfully tested on an OpenBSD-2.7 system and
a Linux system with the latest kth-krb4 package compiled (no Linux
distributions as far as I know use the KTH Kerberos
implementation). Logins with any user with a valid shell defined
were accepted when using a password coded in the bogus server
code. To get root access, a login name such as nobody.root can
be issued, as plain root logins aren't usually accepted.
2) Buffer overflow in protocol parsing code
===========================================
There is at least one easily producable buffer overflow in the
Kerberos library. When parsing an authentication reply from a
Kerberos server a memcpy() call without bound checking is done.
This happens in function kdc_reply_cipher(), end of file
lib/krb/kdc_reply.c:
p += krb_get_int(p, &clen, 2, little_endian);
cip->length = clen;
memcpy(cip->dat, p, clen);
p += clen;
The code reads a 16-byte length value from the packet and without
further checking copies the amount of bytes to a fixed-sized
buffer. This causes a segmentation fault, but has turned out to
be not-so-trivial to exploit; writing over return address
happens, but setting the address isn't necessarily easy because
there's a limit for the maximal length of a reply that is read
from the server (MAX_KTXT_LEN, 1250 bytes). The length parameter
itself contained by the packet can be set to any value between 0
and 65535.
3) File system races
====================
The Kerberos system stores ticket files in /tmp. When a
privileged process writes such a file, there exists a race
condition which can be used to overwrite arbitrary files with the
ticket data. The ticket file name is predictable and a user may
create a symbolic link having the same name. This was tested on
an OpenBSD system.
SOLUTION
OpenBSD has published information about the vulnerabilities and a
patch for the problem at
ftp://ftp.openbsd.org/pub/OpenBSD/patches/2.8/common/006_kerberos.patch
A patch fixing the buffer overflow problem by from Assar
Westerlund:
diff -u -w -u -w -r1.13 kdc_reply.c
--- kdc_reply.c 2000/05/15 00:15:26 1.13
+++ kdc_reply.c 2000/12/04 14:23:30
@@ -124,6 +124,9 @@
p += krb_get_int(p, &exp_date, 4, little_endian);
p++; /* master key version number */
p += krb_get_int(p, &clen, 2, little_endian);
+ if (reply->length - (p - reply->dat) < clen)
+ return INTK_PROT;
+
cip->length = clen;
memcpy(cip->dat, p, clen);
p += clen;
To check whether your login process is linked against the Kerberos
library issue the command
ldd /usr/bin/login
If "libkrb" is included in the library listing, then the program
is likely to have Kerberos code compiled in. In this case you
should consider recompiling it and possibly Kerberos-aware "su"
or "ksu", "rlogin", and "rsh" without Kerberos support, or
upgrading them.
To test if your telnetd filters out the dangerous environment
variables, you can do this:
$ telnet
telnet> environ define KRBCONFDIR /tmp
telnet> environ export KRBCONFDIR
telnet> environ define krb4_proxy http://your.host:80
telnet> environ export krb4_proxy
telnet> open localhost
Then you can login with your username and password. If you now
issue the command
$ env | grep -i \^krb
you will see the currently defined environment variables
concerning Kerberos. If you get no output you are safe; if you
see KRBCONFDIR or krb4_proxy listed, then the telnetd of your
system lets the Kerberos environment variables through (assuming
your login scripts don't set them).
You can check with file timestamps if arbitrary Kerberos
configuration files get read (in the above example, ls -lu
/tmp/krb.conf shows the time the file was last read, assuming
you've created it first). For the krb4_proxy exploitableness you
can use "nc -l -p <port>" or another program to listen on a port
and then check if the login program connects to it while logging
in with krb4_proxy defined to http://your.host:<port>.
The problem was fixed in NetBSD-current on 2000/12/09; systems
running NetBSD-current dated from before that date should be
upgraded to NetBSD-current dated 2000/12/09 or later. The 1.5
branch was fixed by 2000/12/15. Systems running 1.4.x are not
vulnerable to this problem as they do not contain this version of
kerberos. Systems running 1.5 should apply the patch found in:
ftp://ftp.NetBSD.ORG/pub/NetBSD/misc/security/patches/20001220-krb
and then rebuild and reinstall both the "libkrb" library and
telnetd. Systems running NetBSD-current dated from before
2000/12/09 should be upgraded to NetBSD-current dated 2000/12/09
or later.
KTH-KRB Kerberos Release 1.0.4 is now available with bug-fixes
(including one exploitable buffer overrun):
http://www.pdc.kth.se/kth-krb
ftp://ftp.pdc.kth.se/pub/krb/src/
For FreeBSD upgrade your vulnerable FreeBSD system to 4.2-STABLE
or 3.5-STABLE after the respective correction dates. Otherwise
apply the relevant patch from below and recompile the affected
files:
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-01:25/telnetd-krb.4.2.patch
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-01:25/telnetd-krb.4.2.patch.asc
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-01:25/telnetd-krb.3.5.1.patch
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-01:25/telnetd-krb.3.5.1.patch.asc