[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

UNIRAS Brief - 267/04 - MIT krb5 Security Advisory 2004-001 buffer overflows in krb5_aname_to_localname



----------------------------------------------------------------------------------
   UNIRAS (UK Govt CERT) Briefing Notice - 267/04 dated 03.06.04  Time: 13:50  
  UNIRAS is part of NISCC (National Infrastructure Security Co-ordination Centre)
---------------------------------------------------------------------------------- 
  UNIRAS material is also available from its website at www.uniras.gov.uk and
         Information about NISCC is available from www.niscc.gov.uk
----------------------------------------------------------------------------------

Title
=====

MIT krb5 Security Advisory 2004-001 buffer overflows in krb5_aname_to_localname

Detail
====== 


The krb5_aname_to_localname() library function contains multiple buffer overflows 
which could be exploited to gain unauthorized root access.  Exploitation of these 
flaws requires an unusual combination of factors, including successful authentication 
to a vulnerable service and a non-default configuration on the target service.  



===========================================================================
             
           ESB-2004.0378 -- MIT krb5 Security Advisory 2004-001
                buffer overflows in krb5_aname_to_localname
                               02 June 2004

===========================================================================

        

Product:                krb5_aname_to_localname()
Publisher:              MIT
Operating System:       BSD variants
                        Linux variants
                        UNIX variants
Impact:                 Root Compromise
Access Required:        Remote

- --------------------------BEGIN INCLUDED TEXT--------------------

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

                 MIT krb5 Security Advisory 2004-001

2004-06-01

Topic: buffer overflows in krb5_aname_to_localname

Severity: serious

SUMMARY
=======

The krb5_aname_to_localname() library function contains multiple buffer overflows 
which could be exploited to gain unauthorized root access.  Exploitation of these 
flaws requires an unusual combination of factors, including successful authentication 
to a vulnerable service and a non-default configuration on the target service.  
(See MITIGATING FACTORS below.)  No exploits are known to exist yet.

IMPACT
======

A remote attacker can potentially execute arbitrary code on hosts running vulnerable services.

MITIGATING FACTORS
==================

Only configurations which enable the explicit mapping or rules-based mapping functionality 
of krb5_aname_to_localname() are vulnerable. These configurations are not the default.

If the explicit mapping functionality is enabled, an attacker must authenticate using a principal 
name listed in the explicit mapping list.

If the rules-based mapping functionality is enabled, an attacker must be able to create arbitrary 
principal names either in the local Kerberos realm or in a remote realm from which the local realm's 
services are reachable by cross-realm authentication.

AFFECTED SOFTWARE
=================

All releases of MIT Kerberos 5, up to and including krb5-1.3.3.

The upcoming krb5-1.3.4 release will contain a fix for this problem.

Affected services contained in these releases include the remote login applications 
(e.g., ftp, rsh, rlogin, telnet), as well as ksu. Third-party application servers using the 
affected functionality of the krb5 library may be vulnerable.

These services are only vulnerable in non-default configurations.

FIXES
=====

* If you are using the vulnerable functionality, consider disabling it
  immediately.  Complete disabling of any configuration of explicit
  mapping or rules-based mapping should prevent exploitation.

* The upcoming krb5-1.3.4 release will contain a fix for this problem.

* Apply the following patch to src/lib/krb5/os/an_to_ln.c, and
  recompile the affected libraries and applications.

Index: an_to_ln.c ===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb5/os/an_to_ln.c,v
retrieving revision 5.39
diff -c -r5.39 an_to_ln.c
*** an_to_ln.c	2002/09/03 19:29:34	5.39
- - --- an_to_ln.c	2004/05/14 19:39:21
***************
*** 270,278 ****
   * If no regcomp() then just return the input string verbatim in the output
   * string.
   */
! static void
  do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
  {
  #if	HAVE_REGCOMP
      regex_t	match_exp;
      regmatch_t	match_match;
- - --- 270,283 ----
   * If no regcomp() then just return the input string verbatim in the output
   * string.
   */
! #define use_bytes(x) \
!     out_used += (x); \
!     if (out_used > MAX_FORMAT_BUFFER) goto mem_err
! 
! static int
  do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
  {
+     size_t out_used = 0;
  #if	HAVE_REGCOMP
      regex_t	match_exp;
      regmatch_t	match_match;
***************
*** 287,303 ****
  	do {
  	    if (!regexec(&match_exp, cp, 1, &match_match, 0)) {
  		if (match_match.rm_so) {
  		    strncpy(op, cp, match_match.rm_so);
  		    op += match_match.rm_so;
  		}
  		strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
  		op += strlen(op);
  		cp += match_match.rm_eo;
! 		if (!doall)
  		    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
  		matched = 1;
  	    }
  	    else {
  		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
  		matched = 0;
  	    }
- - --- 292,313 ----
  	do {
  	    if (!regexec(&match_exp, cp, 1, &match_match, 0)) {
  		if (match_match.rm_so) {
+ 		    use_bytes(match_match.rm_so);
  		    strncpy(op, cp, match_match.rm_so);
  		    op += match_match.rm_so;
  		}
+ 		use_bytes(strlen(repl));
  		strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
  		op += strlen(op);
  		cp += match_match.rm_eo;
! 		if (!doall) {
! 		    use_bytes(strlen(cp));
  		    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
+ 		}
  		matched = 1;
  	    }
  	    else {
+ 		use_bytes(strlen(cp));
  		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
  		matched = 0;
  	    }
***************
*** 322,338 ****
- - --- 332,352 ----
  	    sdispl = (size_t) (loc1 - cp);
  	    edispl = (size_t) (loc2 - cp);
  	    if (sdispl) {
+ 		use_bytes(sdispl);
  		strncpy(op, cp, sdispl);
  		op += sdispl;
  	    }
+ 	    use_bytes(strlen(repl));
  	    strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
  	    op += strlen(repl);
  	    cp += edispl;
  	    if (!doall)
+ 		use_bytes(strlen(cp));
  		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
  	    matched = 1;
  	}
  	else {
+ 	    use_bytes(strlen(cp));
  	    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
  	    matched = 0;
  	}
***************
*** 340,346 ****
- - --- 354,368 ----
  #else	/* HAVE_REGEXP_H */
      memcpy(out, in, MAX_FORMAT_BUFFER);
  #endif	/* HAVE_REGCOMP */
+     return 1;
+  mem_err:
+ #ifdef HAVE_REGCMP
+     	regfree(&match_exp);
+ #endif
+ 	return 0;
+ 	
  }
+ #undef use_bytes
  
  /*
   * aname_replacer()	- Perform the specified substitutions on the input
***************
*** 412,418 ****
  
  		    /* Do the replacemenbt */
  		    memset(out, '\0', MAX_FORMAT_BUFFER);
! 		    do_replacement(rule, repl, doglobal, in, out);
  		    free(rule);
  		    free(repl);
  
- - --- 434,445 ----
  
  		    /* Do the replacemenbt */
  		    memset(out, '\0', MAX_FORMAT_BUFFER);
! 		    if (!do_replacement(rule, repl, doglobal, in, out)) {
! 			free(rule);
! 		    free(repl);
! 			kret = KRB5_LNAME_NOTRANS;
! 			break;
! 		    }
  		    free(rule);
  		    free(repl);
  
***************
*** 459,464 ****
- - --- 486,492 ----
      char		*fprincname;
      char		*selstring = 0;
      int			num_comps, compind;
+     size_t selstring_used;
      char		*cout;
      krb5_data		*datap;
      char		*outstring;
***************
*** 479,484 ****
- - --- 507,513 ----
  		     */
  		    current = strchr(current, ':');
  		    selstring = (char *) malloc(MAX_FORMAT_BUFFER);
+ 		    selstring_used = 0;
  		    if (current && selstring) {
  			current++;
  			cout = selstring;
***************
*** 497,502 ****
- - --- 526,539 ----
  								  aname,
  								  compind-1))
  				    ) {
+ 				    if ((datap->length < MAX_FORMAT_BUFFER)
+ 					&&  (selstring_used+datap->length
+ 					     < MAX_FORMAT_BUFFER)) {
+ 					selstring_used += datap->length;
+ 				    } else {
+ 					kret = ENOMEM;
+ 					goto errout;
+ 				    }
  				    strncpy(cout,
  					    datap->data,
  					    (unsigned) datap->length);
***************
*** 527,533 ****
  			else
  			    kret = KRB5_CONFIG_BADFORMAT;
  
! 			if (kret)
  			    free(selstring);
  		    }
  		}
- - --- 564,570 ----
  			else
  			    kret = KRB5_CONFIG_BADFORMAT;
  
! 			errout: if (kret)
  			    free(selstring);
  		    }
  		}
***************
*** 643,649 ****
      const char		*hierarchy[5];
      char		**mapping_values;
      int			i, nvalid;
!     char		*cp;
      char		*typep, *argp;
      unsigned int        lnsize;
  
- - --- 680,686 ----
      const char		*hierarchy[5];
      char		**mapping_values;
      int			i, nvalid;
!     char		*cp, *s;
      char		*typep, *argp;
      unsigned int        lnsize;
  
***************
*** 677,687 ****
  
  		    /* Just use the last one. */
  		    /* Trim the value. */
! 		    cp = &mapping_values[nvalid-1]
! 			[strlen(mapping_values[nvalid-1])];
! 		    while (isspace((int) (*cp))) cp--;
! 		    cp++;
! 		    *cp = '\0';
  
  		    /* Copy out the value if there's enough room */
  		    if (strlen(mapping_values[nvalid-1])+1 <= (size_t) lnsize)
- - --- 714,727 ----
  
  		    /* Just use the last one. */
  		    /* Trim the value. */
! 		    s = mapping_values[nvalid-1];
! 		    cp = s + strlen(s);
! 		    while (cp > s) {
! 			cp--;
! 			if (!isspace((int)(*cp)))
! 			    break;
! 			*cp = '\0';
! 		    }
  
  		    /* Copy out the value if there's enough room */
  		    if (strlen(mapping_values[nvalid-1])+1 <= (size_t) lnsize)

The patch was generated against krb5-1.3.3; it may apply, with some offset, to other releases.

This patch may also be found at:

http://web.mit.edu/kerberos/advisories/2004-001-an_to_ln_patch.txt

The associated detached PGP signature is at:

http://web.mit.edu/kerberos/advisories/2004-001-an_to_ln_patch.txt.asc

REFERENCES
==========

This announcement and related security advisories may be found on the MIT Kerberos security 
advisory page at:

        http://web.mit.edu/kerberos/advisories/index.html

The main MIT Kerberos web page is at:

        http://web.mit.edu/kerberos/index.html

ACKNOWLEDGMENTS
===============

Thanks to Christopher Nebergall for finding the single-byte overflow.

Thanks to Nico Williams for finding a vulnerability in the rules-based mapping.

Thanks to Matt Crawford for useful comments.

DETAILS
=======

krb5_aname_to_localname() translates a Kerberos principal name to a local account name, 
typically a UNIX username.  In the file src/lib/krb5/os/an_to_ln.c, the helper functions 
aname_replacer(), do_replacement(), and rule_an_to_ln() do not perform adequate checks of 
the lengths of strings which contain the name of the principal whose authorization is being 
checked.  This can result in the overflow of heap buffers when an attacker authenticates 
using a sufficiently long principal name.

In addition, the implementation of the explicit mapping functionality in krb5_aname_to_localname() 
consistently writes a zero byte at a location one byte past the end of a heap buffer when handling 
a principal name matching an explicit mapping.  Single-byte overflows of heap buffers are known 
to be exploitable on some architectures.  The vulnerability in the explicit mapping functionality 
was fixed around December 2003 in the development sources, but the fix was not propagated to the 
krb5-1.3.x release branch.

REVISION HISTORY
================

2004-06-01      original release

Copyright (C) 2004 Massachusetts Institute of Technology
- -----BEGIN PGP SIGNATURE-----


----------------------------------------------------------------------------------

For additional information or assistance, please contact the HELP Desk by 
telephone or Not Protectively Marked information may be sent via 
EMail to: uniras@xxxxxxxxxxxx

Office Hours:
Mon - Fri: 08:30 - 17:00 Hrs
Tel: +44 (0) 20 7821 1330 Ext 4511
Fax: +44 (0) 20 7821 1686

Outside of Office Hours:
On Call Duty Officer:
Tel: +44 (0) 20 7821 1330 and follow the prompts

----------------------------------------------------------------------------------
UNIRAS wishes to acknowledge the contributions of Massachusetts Institute of Technology 
for the information contained in this Briefing. 
----------------------------------------------------------------------------------
This Briefing contains the information released by the original author. Some 
of the information may have changed since it was released. If the vulnerability 
affects you, it may be prudent to retrieve the advisory from the canonical site 
to ensure that you receive the most current information concerning that problem.

Reference to any specific commercial product, process, or service by trade 
name, trademark manufacturer, or otherwise, does not constitute or imply 
its endorsement, recommendation, or favouring by UNIRAS or NISCC.  The views 
and opinions of authors expressed within this notice shall not be used for 
advertising or product endorsement purposes.

Neither UNIRAS or NISCC shall also accept responsibility for any errors 
or omissions contained within this briefing notice. In particular, they shall 
not be liable for any loss or damage whatsoever, arising from or in connection 
with the usage of information contained within this notice.

UNIRAS is a member of the Forum of Incident Response and Security Teams (FIRST) 
and has contacts with other international Incident Response Teams (IRTs) in 
order to foster cooperation and coordination in incident prevention, to prompt 
rapid reaction to incidents, and to promote information sharing amongst its 
members and the community at large. 
----------------------------------------------------------------------------------
<End of UNIRAS Briefing>