diff -u mediawiki-1.11.2/debian/patches/series mediawiki-1.11.2/debian/patches/series --- mediawiki-1.11.2/debian/patches/series +++ mediawiki-1.11.2/debian/patches/series @@ -9,0 +10,2 @@ +CSRF-Special-Userlogin-no-CVE_rev-66991.patch +XSS-IE-no-CVE_rev-66992.patch diff -u mediawiki-1.11.2/debian/changelog mediawiki-1.11.2/debian/changelog --- mediawiki-1.11.2/debian/changelog +++ mediawiki-1.11.2/debian/changelog @@ -1,3 +1,25 @@ +mediawiki (1:1.11.2-2ubuntu0.6) hardy-security; urgency=low + + * SECURITY UPDATE: A CSRF vulnerability was discovered in our login + interface. Although regular logins are protected as of 1.15.3, it was + discovered that the account creation and password reset features were not + protected from CSRF. This could lead to unauthorised access to private + wikis. (LP: #586773) + - debian/patches/CSRF-Special-Userlogin-no-CVE_rev-66991.patch + - patch from upstream SVN rev. 66991 + - http://lists.wikimedia.org/pipermail/mediawiki-announce/2010-May/000091.html + - https://bugzilla.wikimedia.org/show_bug.cgi?id=23371 + * SECURITY UPDATE: Noncompliant CSS parsing behaviour in Internet Explorer + allows attackers to construct CSS strings which are treated as safe by + previous versions of MediaWiki, but are decoded to unsafe strings by + Internet Explorer. (LP: #586773) + - debian/patches/XSS-IE-no-CVE_rev-66992.patch + - patch from upstream SVN rev. 66992 + - http://lists.wikimedia.org/pipermail/mediawiki-announce/2010-May/000091.html + - https://bugzilla.wikimedia.org/show_bug.cgi?id=23687 + + -- Andreas Wenning Mon, 31 May 2010 00:45:24 +0200 + mediawiki (1:1.11.2-2ubuntu0.5) hardy-security; urgency=low * SECURITY UPDATE: MediaWiki was found to be vulnerable to login CSRF. An only in patch2: unchanged: --- mediawiki-1.11.2.orig/debian/patches/CSRF-Special-Userlogin-no-CVE_rev-66991.patch +++ mediawiki-1.11.2/debian/patches/CSRF-Special-Userlogin-no-CVE_rev-66991.patch @@ -0,0 +1,190 @@ +Subject: Fixes CSRF vulnerability in "e-mail me my password", "create account" +and "create by e-mail" features of [[Special:Userlogin]] +Origin: http://svn.wikimedia.org/viewvc/mediawiki?view=rev&revision=66991 +Index: b/includes/SpecialUserlogin.php +=================================================================== +--- a/includes/SpecialUserlogin.php 2010-05-28 10:51:52.000000000 +0200 ++++ b/includes/SpecialUserlogin.php 2010-05-28 10:58:29.639536046 +0200 +@@ -67,6 +67,7 @@ + $this->mRemember = $request->getCheck( 'wpRemember' ); + $this->mLanguage = $request->getText( 'uselang' ); + $this->mToken = $request->getVal( 'wpLoginToken' ); ++ $this->mToken = ($this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' ); + + if( $wgEnableEmail ) { + $this->mEmail = $request->getText( 'wpEmail' ); +@@ -233,6 +234,25 @@ + return false; + } + ++ # Request forgery checks. ++ if ( !self::getCreateaccountToken() ) { ++ self::setCreateaccountToken(); ++ $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); ++ return false; ++ } ++ ++ # The user didn't pass a createaccount token ++ if ( !$this->mToken ) { ++ $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); ++ return false; ++ } ++ ++ # Validate the createaccount token ++ if ( $this->mToken !== self::getCreateaccountToken() ) { ++ $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); ++ return false; ++ } ++ + # Check anonymous user ($wgUser) limitations : + if (!$wgUser->isAllowedToCreateAccount()) { + $this->userNotPrivilegedMessage(); +@@ -244,7 +264,7 @@ + $wgUser->inSorbsBlacklist( $ip ) ) + { + $this->mainLoginForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . htmlspecialchars( $ip ) . ')' ); +- return; ++ return false; + } + + # Now create a dummy user ($u) and check if it is valid +@@ -300,6 +320,7 @@ + return false; + } + ++ self::clearCreateaccountToken(); + return $this->initUser( $u, false ); + } + +@@ -514,13 +535,26 @@ + return; + } + +- # Check against blocked IPs +- # fixme -- should we not? ++ # Check against blocked IPs so blocked users can't flood admins ++ # with password resets + if( $wgUser->isBlocked() ) { + $this->mainLoginForm( wfMsg( 'blocked-mailpassword' ) ); + return; + } + ++ # If the user doesn't have a login token yet, set one. ++ if ( !self::getLoginToken() ) { ++ self::setLoginToken(); ++ $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); ++ return; ++ } ++ ++ # If the user didn't pass a login token, tell them we need one ++ if ( !$this->mToken ) { ++ $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); ++ return; ++ } ++ + # Check against the rate limiter + if( $wgUser->pingLimiter( 'mailpassword' ) ) { + $wgOut->rateLimited(); +@@ -541,6 +575,12 @@ + return; + } + ++ # Validate the login token ++ if ( $this->mToken !== self::getLoginToken() ) { ++ $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); ++ return; ++ } ++ + # Check against password throttle + if ( $u->isPasswordReminderThrottled() ) { + global $wgPasswordReminderResendTime; +@@ -555,6 +595,7 @@ + $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) ); + } else { + $this->mainLoginForm( wfMsg( 'passwordsent', $u->getName() ), 'success' ); ++ self::clearLoginToken(); + } + } + +@@ -723,11 +764,18 @@ + $template->set( 'canreset', $wgAuth->allowPasswordChange() ); + $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember ); + +- if ( !self::getLoginToken() ) { +- self::setLoginToken(); ++ if ( $this->mType == 'signup' ) { ++ if ( !self::getCreateaccountToken() ) { ++ self::setCreateaccountToken(); ++ } ++ $template->set( 'token', self::getCreateaccountToken() ); ++ } else { ++ if ( !self::getLoginToken() ) { ++ self::setLoginToken(); ++ } ++ $template->set( 'token', self::getLoginToken() ); + } +- $template->set( 'token', self::getLoginToken() ); +- ++ + # Prepare language selection links as needed + if( $wgLoginLanguageSelector ) { + $template->set( 'languages', $this->makeLanguageSelector() ); +@@ -786,7 +834,7 @@ + } + + /** +- * Generate a new login token and attach it to the current session ++ * Randomly generate a new login token and attach it to the current session + */ + public static function setLoginToken() { + global $wgRequest; +@@ -798,12 +846,36 @@ + /** + * Remove any login token attached to the current session + */ +- public static function clearLoginToken() { ++ public static function clearLoginToken() { + global $wgRequest; + $wgRequest->setSessionData( 'wsLoginToken', null ); + } + + /** ++ * Get the createaccount token from the current session ++ */ ++ public static function getCreateaccountToken() { ++ global $wgRequest; ++ return $wgRequest->getSessionData( 'wsCreateaccountToken' ); ++ } ++ ++ /** ++ * Randomly generate a new createaccount token and attach it to the current session ++ */ ++ public static function setCreateaccountToken() { ++ global $wgRequest; ++ $wgRequest->setSessionData( 'wsCreateaccountToken', User::generateToken() ); ++ } ++ ++ /** ++ * Remove any createaccount token attached to the current session ++ */ ++ public static function clearCreateaccountToken() { ++ global $wgRequest; ++ $wgRequest->setSessionData( 'wsCreateaccountToken', null ); ++ } ++ ++ /** + * @private + */ + function cookieRedirectCheck( $type ) { +Index: b/includes/templates/Userlogin.php +=================================================================== +--- a/includes/templates/Userlogin.php 2010-05-28 10:51:52.000000000 +0200 ++++ b/includes/templates/Userlogin.php 2010-05-28 10:52:07.340680820 +0200 +@@ -209,6 +209,7 @@ + + + haveData( 'uselang' ) ) { ?> ++haveData( 'token' ) ) { ?> + + +
msgWiki( 'signupend' ); ?>
only in patch2: unchanged: --- mediawiki-1.11.2.orig/debian/patches/XSS-IE-no-CVE_rev-66992.patch +++ mediawiki-1.11.2/debian/patches/XSS-IE-no-CVE_rev-66992.patch @@ -0,0 +1,83 @@ +Subject: Fixed XSS vulnerability affecting IE clients only, due to a CSS +validation issue. +Origin: http://svn.wikimedia.org/viewvc/mediawiki?view=rev&revision=66992 +Index: b/includes/Sanitizer.php +=================================================================== +--- a/includes/Sanitizer.php 2010-05-28 10:51:52.679428131 +0200 ++++ b/includes/Sanitizer.php 2010-05-28 10:59:10.380680524 +0200 +@@ -609,10 +609,6 @@ + # http://msdn.microsoft.com/workshop/author/dhtml/overview/recalc.asp + if( $attribute == 'style' ) { + $value = Sanitizer::checkCss( $value ); +- if( $value === false ) { +- # haxx0r +- continue; +- } + } + + if ( $attribute === 'id' ) +@@ -668,10 +664,8 @@ + $value = StringUtils::delimiterReplace( '/*', '*/', ' ', $value ); + + // Decode escape sequences and line continuation +- // See the grammar in the CSS 2 spec, appendix D, Mozilla implements it accurately. +- // IE 8 doesn't implement it at all, but there's no way to introduce url() into +- // IE that doesn't hit Mozilla also. +- static $decodeRegex; ++ // See the grammar in the CSS 2 spec, appendix D. ++ static $decodeRegex, $reencodeTable; + if ( !$decodeRegex ) { + $space = '[\\x20\\t\\r\\n\\f]'; + $nl = '(?:\\n|\\r\\n|\\r|\\f)'; +@@ -680,29 +674,40 @@ + (?: + ($nl) | # 1. Line continuation + ([0-9A-Fa-f]{1,6})$space? | # 2. character number +- (.) # 3. backslash cancelling special meaning ++ (.) | # 3. backslash cancelling special meaning ++ () | # 4. backslash at end of string + )/xu"; + } +- $decoded = preg_replace_callback( $decodeRegex, ++ $value = preg_replace_callback( $decodeRegex, + array( __CLASS__, 'cssDecodeCallback' ), $value ); +- if ( preg_match( '!expression|https?://|url\s*\(!i', $decoded ) ) { +- // Not allowed +- return false; +- } else { +- // Allowed, return CSS with comments stripped +- return $value; ++ ++ // Reject problematic keywords and control characters ++ if ( preg_match( '/[\000-\010\016-\037\177]/', $value ) ) { ++ return '/* invalid control char */'; ++ } elseif ( preg_match( '! expression | filter\s*: | accelerator\s*: | url\s*\( !ix', $value ) ) { ++ return '/* insecure input */'; + } ++ return $value; + } + + static function cssDecodeCallback( $matches ) { + if ( $matches[1] !== '' ) { ++ // Line continuation + return ''; + } elseif ( $matches[2] !== '' ) { +- return codepointToUtf8( hexdec( $matches[2] ) ); ++ $char = codepointToUtf8( hexdec( $matches[2] ) ); + } elseif ( $matches[3] !== '' ) { +- return $matches[3]; ++ $char = $matches[3]; ++ } else { ++ $char = '\\'; ++ } ++ if ( $char == "\n" || $char == '"' || $char == "'" || $char == '\\' ) { ++ // These characters need to be escaped in strings ++ // Clean up the escape sequence to avoid parsing errors by clients ++ return '\\' . dechex( ord( $char ) ) . ' '; + } else { +- throw new MWException( __METHOD__.': invalid match' ); ++ // Decode unnecessary escape ++ return $char; + } + } +