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

Cyrus SASL library buffer overflows



These overflows are found at least in version 2.1.9, none of them are
present in 1.5.28. 2.1.10 was just released which fixed the problems.

Note that besides the Cyrus project itself, the SASL library is also used
by Postfix-TLS patch, OpenLDAP and probably some other servers.

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.

patch
-----

If you need for some reason.

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