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