10th Dec 2002 [SBWID-5865]
COMMAND

	Cyrus SASL lib buffer overflows (used  by  Postfix-TLS  patch,  OpenLDAP
	and other)

SYSTEMS AFFECTED

	These overflows are found at least in version 2.1.9

PROBLEM

	Timo Sirainen [tss@iki.fi] says :
	
	 Problem 1
	 ---------
	
	Insufficient buffer length checking in user  name  canonicalization  may
	allow attacker to execute arbitrary code on  servers  using  Cyrus  SASL
	library. Client side library also has the bug but since  the  user  name
	is asked from the local user, there's  probably  not  many  applications
	that care about it, except maybe webmails and the  like.  This  overflow
	only happens if default realm is set.
	
	Exploiting may not  be  too  easy  though,  since  you  can  only  write
	"@default.realm.name"  to  limited  space  in  heap  past  the   buffer,
	depending on how long user name is allowed. With postfix this is  around
	2048 BASE64 encoded bytes (around 1500 bytes) by default.  Postfix  uses
	$myhostname as default realm name.
	
	We can  overflow  two  different  buffers  at  the  end  of  sasl_conn_t
	structure:
	
	  char user_buf[CANON_BUF_SIZE+1], authid_buf[CANON_BUF_SIZE+1];
	
	sasl_conn_t is malloc()ed, so the  most  obvious  exploit  could  happen
	with modifying malloc headers.  Since  we  can  use  only  few  specific
	characters, the possibility to exploit is very system dependant.
	
	 Problem 2
	 ---------
	
	LDAP authentication with saslauthd doesn't allocate enough  memory  when
	it needs to escape characters '*', '(', ')', '\' and  '\0'  in  username
	and  realm.  This  should  be  easily  exploited  with  glibc's   malloc
	implementation.
	
	 Problem 3
	 ---------
	
	Log writer might not have  allocated  memory  for  the  trailing  \0  in
	message. Probably hard to exploit, although you can affect  the  logging
	data with at least anonymous authentication.

SOLUTION

	Get release 1.5.28. or 2.1.10, see diff below
	
	diff -ru cyrus-sasl-2.1.9-old/lib/canonusr.c cyrus-sasl-2.1.9/lib/canonusr.c
	--- cyrus-sasl-2.1.9-old/lib/canonusr.c	2002-09-16 21:37:20.000000000 +0300
	+++ cyrus-sasl-2.1.9/lib/canonusr.c	2002-12-05 06:18:36.000000000 +0200
	@@ -306,6 +306,7 @@
	     /* Now copy! (FIXME: check for SASL_BUFOVER?) */
	     memcpy(out_user, begin_u, MIN(ulen, out_umax));
	     if(sconn && u_apprealm) {
	+        if(ulen >= out_umax) return SASL_BUFOVER;
	 	out_user[ulen] = '@';
	 	memcpy(&(out_user[ulen+1]), sconn->user_realm,
	 	       MIN(u_apprealm-1, out_umax-ulen-1));
	diff -ru cyrus-sasl-2.1.9-old/saslauthd/lak.c cyrus-sasl-2.1.9/saslauthd/lak.c
	--- cyrus-sasl-2.1.9-old/saslauthd/lak.c	2002-08-01 22:58:24.000000000 +0300
	+++ cyrus-sasl-2.1.9/saslauthd/lak.c	2002-12-05 07:43:34.000000000 +0200
	@@ -279,7 +279,7 @@
	 	char *buf;
	 	char *end, *ptr, *temp;
	 
	-	buf = malloc(strlen(s) * 2 + 1);
	+	buf = malloc(strlen(s) * 3 + 1);
	 	if (buf == NULL) {
	 		return LAK_NOMEM;
	 	}
	@@ -358,7 +358,8 @@
	 		if( *buf == '%' ) percents++;
	 	}
	 
	-	buf=malloc(strlen(lak->conf->filter) + (percents * maxparamlength) +1);
	+	buf=malloc(strlen(lak->conf->filter) +
	+		   (percents * maxparamlength * 3) + 1);
	 	if(buf == NULL) {
	 		syslog(LOG_ERR|LOG_AUTH, "Cannot allocate memory");
	 		return LAK_NOMEM;
	diff -ru cyrus-sasl-2.1.9-old/lib/common.c cyrus-sasl-2.1.9/lib/common.c
	--- cyrus-sasl-2.1.9-old/lib/common.c	2002-09-19 01:07:54.000000000 +0300
	+++ cyrus-sasl-2.1.9/lib/common.c	2002-12-05 08:11:49.000000000 +0200
	@@ -1326,6 +1326,8 @@
	     }
	   }
	 
	+  result = _buf_alloc(&out, &alloclen, outlen+1);
	+  if (result != SASL_OK) goto done;
	   out[outlen]=0; /* put 0 at end */
	 
	   va_end(ap);