diff -u squirrelmail-1.4.15/src/redirect.php squirrelmail-1.4.15/src/redirect.php --- squirrelmail-1.4.15/src/redirect.php +++ squirrelmail-1.4.15/src/redirect.php @@ -31,8 +31,6 @@ require_once(SM_PATH . 'functions/constants.php'); require_once(SM_PATH . 'functions/page_header.php'); -$base_uri = sqm_baseuri(); - header('Pragma: no-cache'); $location = get_location(); @@ -69,6 +67,22 @@ if (!sqsession_is_registered('user_is_logged_in')) { do_hook ('login_before'); + /** + * Regenerate session id to make sure that authenticated session uses + * different ID than one used before user authenticated. This is a + * countermeasure against session fixation attacks. + * NB: session_regenerate_id() was added in PHP 4.3.2 (and new session + * cookie is only sent out in this call as of PHP 4.3.3), but PHP 4 + * is not vulnerable to session fixation problems in SquirrelMail + * because it prioritizes $base_uri subdirectory cookies differently + * than PHP 5, which is otherwise vulnerable. If we really want to, + * we could define our own session_regenerate_id() when one does not + * exist, but there seems to be no reason to do so. + */ + if (function_exists('session_regenerate_id')) { + session_regenerate_id(); + } + $onetimepad = OneTimePadCreate(strlen($secretkey)); $key = OneTimePadEncrypt($secretkey, $onetimepad); sqsession_register($onetimepad, 'onetimepad'); diff -u squirrelmail-1.4.15/src/webmail.php squirrelmail-1.4.15/src/webmail.php --- squirrelmail-1.4.15/src/webmail.php +++ squirrelmail-1.4.15/src/webmail.php @@ -26,8 +26,6 @@ require_once(SM_PATH . 'include/validate.php'); require_once(SM_PATH . 'functions/imap.php'); -$base_uri = sqm_baseuri(); - sqgetGlobalVar('username', $username, SQ_SESSION); sqgetGlobalVar('delimiter', $delimiter, SQ_SESSION); sqgetGlobalVar('onetimepad', $onetimepad, SQ_SESSION); diff -u squirrelmail-1.4.15/debian/changelog squirrelmail-1.4.15/debian/changelog --- squirrelmail-1.4.15/debian/changelog +++ squirrelmail-1.4.15/debian/changelog @@ -1,3 +1,42 @@ +squirrelmail (2:1.4.15-4ubuntu0.1) jaunty-security; urgency=low + + * SECURITY UPDATE: (LP: #375513) + * Multiple cross site scripting issues. Two issues were fixed that both + allowed an attacker to run arbitrary script (XSS) on most any + SquirrelMail page by getting the user to click on specially crafted + SquirrelMail links. + - http://squirrelmail.org/security/issue/2009-05-08 + - CVE-2009-1578 + - Patch taken from upstream svn rev. 13670. Applied inline. + * Cross site scripting issues in decrypt_headers.php. An issue was fixed + wherein input to the contrib/decrypt_headers.php script was not sanitized + and allowed arbitrary script execution upon submission of certain values. + - http://squirrelmail.org/security/issue/2009-05-09 + - CVE-2009-1578 + - Patch taken from upstream svn rev. 13672. Applied inline. + * Server-side code injection in map_yp_alias username map. An issue was + fixed that allowed arbitrary server-side code execution when SquirrelMail + was configured to use the example "map_yp_alias" username mapping + functionality. + - http://squirrelmail.org/security/issue/2009-05-10 + - CVE-2009-1579 + - Patch taken from upstream svn rev. 13674. Applied inline. + * Session fixation vulnerability. An issue was fixed that allowed an + attacker to possibly steal user data by hijacking the SquirrelMail + login session. + - http://squirrelmail.org/security/issue/2009-05-11 + - CVE-2009-1580 + - Patch taken from upstream svn rev. 13676. Applied inline. + * CSS positioning vulnerability. An issue was fixed that allowed phishing + and cross-site scripting (XSS) attacks to be run by surreptitious + placement of content in specially-crafted emails sent to SquirrelMail + users. + - http://squirrelmail.org/security/issue/2009-05-12 + - CVE-2009-1581 + - Patch taken from upstream svn rev. 13667. Applied inline. + + -- Andreas Wenning Tue, 12 May 2009 21:06:15 +0200 + squirrelmail (2:1.4.15-4) unstable; urgency=high * Address cross site scripting issue in the HTML filter diff -u squirrelmail-1.4.15/debian/control squirrelmail-1.4.15/debian/control --- squirrelmail-1.4.15/debian/control +++ squirrelmail-1.4.15/debian/control @@ -1,7 +1,8 @@ Source: squirrelmail Section: web Priority: optional -Maintainer: Jeroen van Wolffelaar +Maintainer: Ubuntu MOTU Developers +XSBC-Original-Maintainer: Jeroen van Wolffelaar Uploaders: Thijs Kinkhorst Build-Depends: debhelper (>= 5) Standards-Version: 3.8.0 diff -u squirrelmail-1.4.15/functions/global.php squirrelmail-1.4.15/functions/global.php --- squirrelmail-1.4.15/functions/global.php +++ squirrelmail-1.4.15/functions/global.php @@ -64,14 +64,28 @@ unset($GLOBALS['value']); } -/* - * strip any tags added to the url from PHP_SELF. +/** + * Strip any tags added to the url from PHP_SELF. * This fixes hand crafted url XXS expoits for any - * page that uses PHP_SELF as the FORM action + * page that uses PHP_SELF as the FORM action. * Must be executed before strings.php is loaded (php_self() call in strings.php). + * Update: strip_tags() won't catch something like + * src/right_main.php?sort=0&startMessage=1&mailbox=INBOX&xxx="> + * or + * contrib/decrypt_headers.php/%22%20onmouseover=%22alert(%27hello%20world%27)%22%3E + * because it doesn't bother with broken tags. + * htmlspecialchars() is the preferred method. */ if (isset($_SERVER['PHP_SELF'])) { - $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']); + $_SERVER['PHP_SELF'] = htmlspecialchars($_SERVER['PHP_SELF']); +} +/* + * same needed for QUERY_STRING because SquirrelMail + * uses it along with PHP_SELF when using location + * strings + */ +if (isset($_SERVER['QUERY_STRING'])) { + $_SERVER['QUERY_STRING'] = htmlspecialchars($_SERVER['QUERY_STRING']); } /** @@ -110,6 +124,13 @@ ini_set('session.use_cookies','1'); } +/** + * Make sure to have $base_uri always initialized to avoid having session + * cookie set separately for each $base_uri subdirectory that receives direct + * requests from user's browser (typically $base_uri and $base_uri/src). + */ +$base_uri = sqm_baseuri(); + sqsession_is_active(); /* if running with magic_quotes_gpc then strip the slashes @@ -347,7 +368,27 @@ global $base_uri; - if (isset($_COOKIE[session_name()])) sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri); + if (isset($_COOKIE[session_name()])) { + sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri); + + /* + * Make sure to kill /src and /src/ cookies, just in case there are + * some left-over or malicious ones set in user's browser. + * NB: Note that an attacker could try to plant a cookie for one + * of the /plugins/* directories. Such cookies can block + * access to certain plugin pages, but they do not influence + * or fixate the $base_uri cookie, so we don't worry about + * trying to delete all of them here. + */ + sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri . 'src'); + sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri . 'src/'); + } + if (isset($_COOKIE['key'])) sqsetcookie('key', 'SQMTRASH', 1, $base_uri); + /* Make sure new session id is generated on subsequent session_start() */ + unset($_COOKIE[session_name()]); + unset($_GET[session_name()]); + unset($_POST[session_name()]); + $sessid = session_id(); if (!empty( $sessid )) { diff -u squirrelmail-1.4.15/functions/mime.php squirrelmail-1.4.15/functions/mime.php --- squirrelmail-1.4.15/functions/mime.php +++ squirrelmail-1.4.15/functions/mime.php @@ -1910,6 +1910,12 @@ /** * Fix stupid css declarations which lead to vulnerabilities * in IE. + * + * Also remove "position" attribute, as it can easily be set + * to "fixed" or "absolute" with "left" and "top" attributes + * of zero, taking over the whole content frame. It can also + * be set to relative and move itself anywhere it wants to, + * displaying content in areas it shouldn't be allowed to touch. */ $match = Array('/\/\*.*\*\//', '/expression/i', @@ -1917,8 +1923,9 @@ '/binding/i', '/include-source/i', '/javascript/i', - '/script/i'); - $replace = Array('','idiocy', 'idiocy', 'idiocy', 'idiocy', 'idiocy', 'idiocy'); + '/script/i', + '/position/i'); + $replace = Array('','idiocy', 'idiocy', 'idiocy', 'idiocy', 'idiocy', 'idiocy', ''); $contentNew = preg_replace($match, $replace, $contentTemp); if ($contentNew !== $contentTemp) { // insecure css declarations are used. From now on we don't care @@ -2311,12 +2318,28 @@ "/binding/i", "/behaviou*r/i", "/include-source/i", - "/position\s*:\s*absolute/i", + + // position:relative can also be exploited + // to put content outside of email body area + // and position:fixed is similarly exploitable + // as position:absolute, so we'll remove it + // altogether.... + // + // Does this screw up legitimate HTML messages? + // If so, the only fix I see is to allow position + // attributes (any values? I think we still have + // to block static and fixed) only if $use_iframe + // is enabled (1.5.0+) + // + // was: "/position\s*:\s*absolute/i", + // + "/position\s*:/i", + "/(\\\\)?u(\\\\)?r(\\\\)?l(\\\\)?/i", "/url\s*\(\s*([\'\"])\s*\S+script\s*:.*([\'\"])\s*\)/si", "/url\s*\(\s*([\'\"])\s*mocha\s*:.*([\'\"])\s*\)/si", "/url\s*\(\s*([\'\"])\s*about\s*:.*([\'\"])\s*\)/si", - "/(.*)\s*:\s*url\s*\(\s*([\'\"]*)\s*\S+script\s*:.*([\'\"]*)\s*\)/si" + "/(.*)\s*:\s*url\s*\(\s*([\'\"]*)\s*\S+script\s*:.*([\'\"]*)\s*\)/si", ), Array( "", only in patch2: unchanged: --- squirrelmail-1.4.15.orig/src/signout.php +++ squirrelmail-1.4.15/src/signout.php @@ -42,7 +42,6 @@ * because it was deleted with the session. */ if (! sqgetGlobalVar('base_uri', $base_uri, SQ_SESSION) ) { require_once(SM_PATH . 'functions/display_messages.php'); - $base_uri = sqm_baseuri(); } do_hook('logout'); only in patch2: unchanged: --- squirrelmail-1.4.15.orig/src/login.php +++ squirrelmail-1.4.15/src/login.php @@ -36,8 +36,6 @@ */ set_up_language($squirrelmail_language, TRUE, TRUE); -$base_uri = sqm_baseuri(); - /** * In case the last session was not terminated properly, make sure * we get a new one, but make sure we preserve session_expired_* only in patch2: unchanged: --- squirrelmail-1.4.15.orig/contrib/decrypt_headers.php +++ squirrelmail-1.4.15/contrib/decrypt_headers.php @@ -16,7 +16,7 @@ define('SM_PATH','../'); /** - * include SquirrelMail string functions + * include SquirrelMail string and generic functions * script needs OneTimePadDecrypt() (functions/strings.php) * and sqgetGlobalVar() (functions/global.php) */ @@ -59,23 +59,30 @@ .""; if (sqgetGlobalVar('submit',$submit,SQ_POST)) { + $continue = TRUE; if (! sqgetGlobalVar('secret',$secret,SQ_POST) || - empty($secret)) - echo "

You must enter encryption key.

\n"; + empty($secret)) { + $continue = FALSE; + echo "

You must enter an encryption key.

\n"; + } if (! sqgetGlobalVar('enc_string',$enc_string,SQ_POST) || - empty($enc_string)) - echo "

You must enter encrypted string.

\n"; - - if (isset($enc_string) && ! base64_decode($enc_string)) { - echo "

Encrypted string should be BASE64 encoded.
\n" - ."Please enter all characters that are listed after header name.

\n"; - } elseif (isset($secret)) { - $string=OneTimePadDecrypt($enc_string,base64_encode($secret)); + empty($enc_string)) { + $continue = FALSE; + echo "

You must enter an encrypted string.

\n"; + } - if (sqgetGlobalVar('ip_addr',$is_addr,SQ_POST)) { - $string=hex2ip($string); + if ($continue) { + if (isset($enc_string) && ! base64_decode($enc_string)) { + echo "

Encrypted string should be BASE64 encoded.
\n" + ."Please enter all characters that are listed after header name.

\n"; + } elseif (isset($secret)) { + $string=OneTimePadDecrypt($enc_string,base64_encode($secret)); + + if (sqgetGlobalVar('ip_addr',$is_addr,SQ_POST)) { + $string=hex2ip($string); + } + echo "

Decoded string: ".htmlspecialchars($string)."

\n"; } - echo "

Decoded string: ".$string."

\n"; } echo "
"; } @@ -84,7 +91,7 @@

Secret key:
Encrypted string:
-Check, if it is an address string:
+

only in patch2: unchanged: --- squirrelmail-1.4.15.orig/functions/imap_general.php +++ squirrelmail-1.4.15/functions/imap_general.php @@ -973,7 +973,7 @@ * LDAP whatever way to find the users IMAP server. */ function map_yp_alias($username) { - $yp = `ypmatch $username aliases`; + $yp = `ypmatch ' . escapeshellarg($username) . ' aliases`; return chop(substr($yp, strlen($username)+1)); }