[2814] in Kerberos-V5-bugs

home help back first fref pref prev next nref lref last post

krb5-appl/494: Ticket-forwarding security hole

daemon@ATHENA.MIT.EDU (ghudson@MIT.EDU)
Mon Nov 10 20:16:40 1997

Resent-From: gnats@rt-11.MIT.EDU (GNATS Management)
Resent-To: krb5-unassigned@RT-11.MIT.EDU
Resent-Reply-To: krb5-bugs@MIT.EDU, ghudson@MIT.EDU
Date: Mon, 10 Nov 1997 20:15:25 -0500
From: ghudson@MIT.EDU
Reply-To: ghudson@MIT.EDU
To: krb5-bugs@MIT.EDU


>Number:         494
>Category:       krb5-appl
>Synopsis:       krlogind, telnetd chown tickets before invoking login
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    krb5-unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   unknown
>Arrival-Date:   Mon Nov 10 20:16:00 EST 1997
>Last-Modified:
>Originator:     Greg Hudson
>Organization:
MIT
>Release:        1.0
>Environment:
System: SunOS mary-kay-commandos 5.5.1 Generic_103640-12 sun4m sparc SUNW,SPARCstation-5
Architecture: sun4

>Description:
The krb5 klogind and telnetd chown the forwarded ticket file before
invoking login.  At this point, the user might delete the ticket file
and replace it with a symlink.  login.c will then read in the ticket
file and write out a new one.  Or it might destroy the file if the
login fails.  Either way, a security hole.
>How-To-Repeat:
>Fix:
This is a fix for klogind, which is the hard part because you have to
change forward.c and then fix kshd to do the chown since kshd does not
invoke login.  Fixing telnetd should involve simply deleting some code.

Index: krshd.c
===================================================================
RCS file: /afs/dev.mit.edu/source/repository/third/krb5/src/appl/bsd/krshd.c,v
retrieving revision 1.6
diff -c -r1.6 krshd.c
*** krshd.c	1997/10/21 02:01:27	1.6
--- krshd.c	1997/10/25 22:58:15
***************
*** 1721,1726 ****
--- 1721,1729 ----
      krb5_authenticator *authenticator;
      krb5_ticket        *ticket;
      krb5_rcache		rcache;
+     struct passwd *pwd;
+     uid_t uid;
+     gid_t gid;
  
      *valid_checksum = 0;
      len = sizeof(laddr);
***************
*** 1876,1885 ****
      }
  
      if (inbuf.length) { /* Forwarding being done, read creds */
  	if ((status = rd_and_store_for_creds(bsd_context, auth_context, &inbuf,
! 					     ticket, locuser, &ccache))) {
  	    error("Can't get forwarded credentials: %s\n",
  		  error_message(status));
  	    exit(1);
  	}
      }
--- 1879,1900 ----
      }
  
      if (inbuf.length) { /* Forwarding being done, read creds */
+ 	pwd = getpwnam(locuser);
+ 	if (!pwd) {
+ 	    error("Login incorrect.\n");
+ 	    exit(1);
+ 	}
+ 	uid = pwd->pw_uid;
+ 	gid = pwd->pw_gid;
  	if ((status = rd_and_store_for_creds(bsd_context, auth_context, &inbuf,
! 					     ticket, &ccache))) {
  	    error("Can't get forwarded credentials: %s\n",
  		  error_message(status));
+ 	    exit(1);
+ 	}
+ 	if (chown(krb5_cc_get_name(bsd_context, ccache), uid, gid) == -1) {
+ 	    error("Can't chown forwarded credentials: %s\n",
+ 		  error_message(errno));
  	    exit(1);
  	}
      }
Index: forward.c
===================================================================
RCS file: /afs/dev.mit.edu/source/repository/third/krb5/src/appl/bsd/forward.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 forward.c
*** forward.c	1996/09/12 04:42:06	1.1.1.1
--- forward.c	1997/10/24 22:15:20
***************
*** 21,27 ****
  
  #if defined(KERBEROS) || defined(KRB5)
  #include <stdio.h>
- #include <pwd.h>
  #include <netdb.h>
  #include <sys/types.h>
  #include <sys/stat.h>
--- 21,26 ----
***************
*** 30,51 ****
  
  /* Decode, decrypt and store the forwarded creds in the local ccache. */
  krb5_error_code
! rd_and_store_for_creds(context, auth_context, inbuf, ticket, lusername, ccache)
      krb5_context context;
      krb5_auth_context auth_context;
      krb5_data *inbuf;
      krb5_ticket *ticket;
-     char *lusername;
      krb5_ccache *ccache;
  {
      krb5_creds ** creds;
      krb5_error_code retval;
      char ccname[35];
-     struct passwd *pwd;
  
      *ccache  = NULL;
-     if (!(pwd = (struct passwd *) getpwnam(lusername)))
- 	return ENOENT;
  
      if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)) 
  	return(retval);
--- 29,46 ----
  
  /* Decode, decrypt and store the forwarded creds in the local ccache. */
  krb5_error_code
! rd_and_store_for_creds(context, auth_context, inbuf, ticket, ccache)
      krb5_context context;
      krb5_auth_context auth_context;
      krb5_data *inbuf;
      krb5_ticket *ticket;
      krb5_ccache *ccache;
  {
      krb5_creds ** creds;
      krb5_error_code retval;
      char ccname[35];
  
      *ccache  = NULL;
  
      if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)) 
  	return(retval);
***************
*** 67,85 ****
      if (retval = krb5_cc_store_cred(context, *ccache, *creds)) 
  	goto cleanup;
  
-     if (retval = chown(ccname+5, pwd->pw_uid, -1)) {
- 	/* 
- 	 * If the file owner is the same as the user id then return ok.
- 	 * This is for testing only --proven
- 	 */
- 	struct stat statbuf;
- 
- 	if (stat(ccname + 5, & statbuf) == 0) {
- 	    if (statbuf.st_uid == pwd->pw_uid)
- 		retval = 0;
- 	}
-     }
-     
  cleanup:
      krb5_free_creds(context, *creds);
      return retval;
--- 62,67 ----
>Audit-Trail:
>Unformatted:

home help back first fref pref prev next nref lref last post