r66991 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r66990‎ | r66991 | r66992 >
Date:07:02, 28 May 2010
Author:tstarling
Status:ok
Tags:
Comment:
MFT r65760: CSRF in create account and password reset. Release notes will come in a subsequent commit.
Modified paths:
  • /branches/REL1_15/phase3/includes/specials/SpecialUserlogin.php (modified) (history)
  • /branches/REL1_15/phase3/includes/templates/Userlogin.php (modified) (history)

Diff [purge]

Index: branches/REL1_15/phase3/includes/specials/SpecialUserlogin.php
@@ -69,7 +69,7 @@
7070 $this->mRemember = $request->getCheck( 'wpRemember' );
7171 $this->mLanguage = $request->getText( 'uselang' );
7272 $this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' );
73 - $this->mToken = $request->getVal( 'wpLoginToken' );
 73+ $this->mToken = ($this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' );
7474
7575 if ( $wgRedirectOnLogin ) {
7676 $this->mReturnTo = $wgRedirectOnLogin;
@@ -246,6 +246,25 @@
247247 return false;
248248 }
249249
 250+ # Request forgery checks.
 251+ if ( !self::getCreateaccountToken() ) {
 252+ self::setCreateaccountToken();
 253+ $this->mainLoginForm( wfMsg( 'sessionfailure' ) );
 254+ return false;
 255+ }
 256+
 257+ # The user didn't pass a createaccount token
 258+ if ( !$this->mToken ) {
 259+ $this->mainLoginForm( wfMsg( 'sessionfailure' ) );
 260+ return false;
 261+ }
 262+
 263+ # Validate the createaccount token
 264+ if ( $this->mToken !== self::getCreateaccountToken() ) {
 265+ $this->mainLoginForm( wfMsg( 'sessionfailure' ) );
 266+ return false;
 267+ }
 268+
250269 # Check permissions
251270 if ( !$wgUser->isAllowed( 'createaccount' ) ) {
252271 $this->userNotPrivilegedMessage();
@@ -260,7 +279,7 @@
261280 $wgUser->inSorbsBlacklist( $ip ) )
262281 {
263282 $this->mainLoginForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . htmlspecialchars( $ip ) . ')' );
264 - return;
 283+ return false;
265284 }
266285
267286 # Now create a dummy user ($u) and check if it is valid
@@ -336,6 +355,7 @@
337356 return false;
338357 }
339358
 359+ self::clearCreateaccountToken();
340360 return $this->initUser( $u, false );
341361 }
342362
@@ -638,13 +658,26 @@
639659 return;
640660 }
641661
642 - # Check against blocked IPs
643 - # fixme -- should we not?
 662+ # Check against blocked IPs so blocked users can't flood admins
 663+ # with password resets
644664 if( $wgUser->isBlocked() ) {
645665 $this->mainLoginForm( wfMsg( 'blocked-mailpassword' ) );
646666 return;
647667 }
648668
 669+ # If the user doesn't have a login token yet, set one.
 670+ if ( !self::getLoginToken() ) {
 671+ self::setLoginToken();
 672+ $this->mainLoginForm( wfMsg( 'sessionfailure' ) );
 673+ return;
 674+ }
 675+
 676+ # If the user didn't pass a login token, tell them we need one
 677+ if ( !$this->mToken ) {
 678+ $this->mainLoginForm( wfMsg( 'sessionfailure' ) );
 679+ return;
 680+ }
 681+
649682 # Check against the rate limiter
650683 if( $wgUser->pingLimiter( 'mailpassword' ) ) {
651684 $wgOut->rateLimited();
@@ -665,6 +698,12 @@
666699 return;
667700 }
668701
 702+ # Validate the login token
 703+ if ( $this->mToken !== self::getLoginToken() ) {
 704+ $this->mainLoginForm( wfMsg( 'sessionfailure' ) );
 705+ return;
 706+ }
 707+
669708 # Check against password throttle
670709 if ( $u->isPasswordReminderThrottled() ) {
671710 global $wgPasswordReminderResendTime;
@@ -680,6 +719,7 @@
681720 $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) );
682721 } else {
683722 $this->mainLoginForm( wfMsg( 'passwordsent', $u->getName() ), 'success' );
 723+ self::clearLoginToken();
684724 }
685725 }
686726
@@ -911,11 +951,18 @@
912952 $template->set( 'canremember', ( $wgCookieExpiration > 0 ) );
913953 $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember );
914954
915 - if ( !self::getLoginToken() ) {
916 - self::setLoginToken();
 955+ if ( $this->mType == 'signup' ) {
 956+ if ( !self::getCreateaccountToken() ) {
 957+ self::setCreateaccountToken();
 958+ }
 959+ $template->set( 'token', self::getCreateaccountToken() );
 960+ } else {
 961+ if ( !self::getLoginToken() ) {
 962+ self::setLoginToken();
 963+ }
 964+ $template->set( 'token', self::getLoginToken() );
917965 }
918 - $template->set( 'token', self::getLoginToken() );
919 -
 966+
920967 # Prepare language selection links as needed
921968 if( $wgLoginLanguageSelector ) {
922969 $template->set( 'languages', $this->makeLanguageSelector() );
@@ -974,7 +1021,7 @@
9751022 }
9761023
9771024 /**
978 - * Generate a new login token and attach it to the current session
 1025+ * Randomly generate a new login token and attach it to the current session
9791026 */
9801027 public static function setLoginToken() {
9811028 global $wgRequest;
@@ -986,12 +1033,36 @@
9871034 /**
9881035 * Remove any login token attached to the current session
9891036 */
990 - public static function clearLoginToken() {
 1037+ public static function clearLoginToken() {
9911038 global $wgRequest;
9921039 $wgRequest->setSessionData( 'wsLoginToken', null );
9931040 }
9941041
9951042 /**
 1043+ * Get the createaccount token from the current session
 1044+ */
 1045+ public static function getCreateaccountToken() {
 1046+ global $wgRequest;
 1047+ return $wgRequest->getSessionData( 'wsCreateaccountToken' );
 1048+ }
 1049+
 1050+ /**
 1051+ * Randomly generate a new createaccount token and attach it to the current session
 1052+ */
 1053+ public static function setCreateaccountToken() {
 1054+ global $wgRequest;
 1055+ $wgRequest->setSessionData( 'wsCreateaccountToken', User::generateToken() );
 1056+ }
 1057+
 1058+ /**
 1059+ * Remove any createaccount token attached to the current session
 1060+ */
 1061+ public static function clearCreateaccountToken() {
 1062+ global $wgRequest;
 1063+ $wgRequest->setSessionData( 'wsCreateaccountToken', null );
 1064+ }
 1065+
 1066+ /**
9961067 * @private
9971068 */
9981069 function cookieRedirectCheck( $type ) {
Index: branches/REL1_15/phase3/includes/templates/Userlogin.php
@@ -268,6 +268,7 @@
269269 </tr>
270270 </table>
271271 <?php if( @$this->haveData( 'uselang' ) ) { ?><input type="hidden" name="uselang" value="<?php $this->text( 'uselang' ); ?>" /><?php } ?>
 272+<?php if( @$this->haveData( 'token' ) ) { ?><input type="hidden" name="wpCreateaccountToken" value="<?php $this->text( 'token' ); ?>" /><?php } ?>
272273 </form>
273274 </div>
274275 <div id="signupend"><?php $this->msgWiki( 'signupend' ); ?></div>

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r65760Bug 23371: Fix CSRF similar to r64677 covering the other three execute()...platonides20:16, 1 May 2010

Status & tagging log