Subject: Cyrus Sieve / libSieve buffer overflow problem ------- Cyrus' Sieve implementation contains a couple of classic string based buffer overflows in script parsing code. Anyone who can execute Sieve scripts can exploit these bugs. Versions up to libSieve 2.1.2 and Cyrus IMAP 2.1.10 are affected. Note that with Cyrus IMAP server exploiting this gives you the privileges of Cyrus user, capable of reading all users mails. Problem comes when giving the script a >100 chars long corrupted header name, >100 chars long IMAP flag or a script that contains lots of errors to overflow the 500 char limit in error message. fix --- Apply the included patch. Note that this changes only the yacc files, you still need to generate .c files from them. libSieve 2.1.3 will hopefully also contain some more hardening against potential buffer overflows. diff -ru cyrus-imapd-2.1.10-old/sieve/addr.y cyrus-imapd-2.1.10/sieve/addr.y --- cyrus-imapd-2.1.10-old/sieve/addr.y 2002-10-28 18:30:18.000000000 +0200 +++ cyrus-imapd-2.1.10/sieve/addr.y 2002-12-02 04:52:58.000000000 +0200 @@ -82,8 +82,9 @@ /* copy address error message into buffer provided by sieve parser */ int yyerror(char *s) { -extern char addrerr[]; +extern char addrerr[512]; - strcpy(addrerr, s); + strncpy(addrerr, s, sizeof(addrerr)-1); + addrerr[sizeof(addrerr)-1] = '\0'; return 0; } diff -ru cyrus-imapd-2.1.10-old/sieve/sieve.y cyrus-imapd-2.1.10/sieve/sieve.y --- cyrus-imapd-2.1.10-old/sieve/sieve.y 2002-05-14 19:51:50.000000000 +0300 +++ cyrus-imapd-2.1.10/sieve/sieve.y 2002-12-02 03:57:17.000000000 +0200 @@ -810,7 +810,7 @@ addrptr = s; addrerr[0] = '\0'; /* paranoia */ if (addrparse()) { - sprintf(errbuf, "address '%s': %s", s, addrerr); + snprintf(errbuf, sizeof(errbuf), "address '%s': %s", s, addrerr); yyerror(errbuf); return 0; } @@ -835,7 +835,7 @@ ; controls, SP, and ; ":". */ if (!((*h >= 33 && *h <= 57) || (*h >= 59 && *h <= 126))) { - sprintf(errbuf, "header '%s': not a valid header", hdr); + snprintf(errbuf, sizeof(errbuf), "header '%s': not a valid header", hdr); yyerror(errbuf); return 0; } @@ -853,14 +853,14 @@ if (strcmp(f, "\\seen") && strcmp(f, "\\answered") && strcmp(f, "\\flagged") && strcmp(f, "\\draft") && strcmp(f, "\\deleted")) { - sprintf(errbuf, "flag '%s': not a system flag", f); + snprintf(errbuf, sizeof(errbuf), "flag '%s': not a system flag", f); yyerror(errbuf); return 0; } return 1; } if (!imparse_isatom(f)) { - sprintf(errbuf, "flag '%s': not a valid keyword", f); + snprintf(errbuf, sizeof(errbuf), "flag '%s': not a valid keyword", f); yyerror(errbuf); return 0; }