@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Invalidate outstanding password reset links when users adjust email addresses

Summary:
Fixes T5506. Depends on D10133. When users remove an email address or change their primary email address, invalidate any outstanding password reset links.

This is a very small security risk, but the current behavior is somewhat surprising, and an attacker could sit on a reset link for up to 24 hours and then use it to re-compromise an account.

Test Plan:
- Changed primary address and removed addreses.
- Verified these actions invalidated outstanding one-time login temporary tokens.
- Tried to use revoked reset links.
- Revoked normally from new UI panel.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5506

Differential Revision: https://secure.phabricator.com/D10134

+62 -8
+1 -1
src/applications/auth/controller/PhabricatorAuthRevokeTokenController.php
··· 46 46 47 47 if ($request->isDialogFormPost()) { 48 48 foreach ($tokens as $token) { 49 - $token->setTokenExpires(PhabricatorTime::getNow() - 1)->save(); 49 + $token->revokeToken(); 50 50 } 51 51 return id(new AphrontRedirectResponse())->setURI($panel_uri); 52 52 }
+24
src/applications/auth/storage/PhabricatorAuthTemporaryToken.php
··· 44 44 return false; 45 45 } 46 46 47 + public function revokeToken() { 48 + if ($this->isRevocable()) { 49 + $this->setTokenExpires(PhabricatorTime::getNow() - 1)->save(); 50 + } 51 + return $this; 52 + } 53 + 54 + public static function revokeTokens( 55 + PhabricatorUser $viewer, 56 + array $object_phids, 57 + array $token_types) { 58 + 59 + $tokens = id(new PhabricatorAuthTemporaryTokenQuery()) 60 + ->setViewer($viewer) 61 + ->withObjectPHIDs($object_phids) 62 + ->withTokenTypes($token_types) 63 + ->withExpired(false) 64 + ->execute(); 65 + 66 + foreach ($tokens as $token) { 67 + $token->revokeToken(); 68 + } 69 + } 70 + 47 71 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 48 72 49 73
+20
src/applications/people/editor/PhabricatorUserEditor.php
··· 427 427 $user->endWriteLocking(); 428 428 $user->saveTransaction(); 429 429 430 + $this->revokePasswordResetLinks($user); 431 + 430 432 return $this; 431 433 } 432 434 ··· 489 491 $old_primary->sendOldPrimaryEmail($user, $email); 490 492 } 491 493 $email->sendNewPrimaryEmail($user); 494 + 495 + 496 + $this->revokePasswordResetLinks($user); 492 497 493 498 return $this; 494 499 } ··· 573 578 if (!PhabricatorUserEmail::isAllowedAddress($email->getAddress())) { 574 579 throw new Exception(PhabricatorUserEmail::describeAllowedAddresses()); 575 580 } 581 + } 582 + 583 + private function revokePasswordResetLinks(PhabricatorUser $user) { 584 + // Revoke any outstanding password reset links. If an attacker compromises 585 + // an account, changes the email address, and sends themselves a password 586 + // reset link, it could otherwise remain live for a short period of time 587 + // and allow them to compromise the account again later. 588 + 589 + PhabricatorAuthTemporaryToken::revokeTokens( 590 + $user, 591 + array($user->getPHID()), 592 + array( 593 + PhabricatorAuthSessionEngine::ONETIME_TEMPORARY_TOKEN_TYPE, 594 + PhabricatorAuthSessionEngine::PASSWORD_TEMPORARY_TOKEN_TYPE, 595 + )); 576 596 } 577 597 578 598 }
+17 -7
src/applications/settings/panel/PhabricatorSettingsPanelEmailAddresses.php
··· 276 276 ->setUser($user) 277 277 ->addHiddenInput('delete', $email_id) 278 278 ->setTitle(pht("Really delete address '%s'?", $address)) 279 - ->appendChild(phutil_tag('p', array(), pht( 280 - 'Are you sure you want to delete this address? You will no '. 281 - 'longer be able to use it to login.'))) 279 + ->appendParagraph( 280 + pht( 281 + 'Are you sure you want to delete this address? You will no '. 282 + 'longer be able to use it to login.')) 283 + ->appendParagraph( 284 + pht( 285 + 'Note: Removing an email address from your account will invalidate '. 286 + 'any outstanding password reset links.')) 282 287 ->addSubmitButton(pht('Delete')) 283 288 ->addCancelButton($uri); 284 289 ··· 359 364 ->setUser($user) 360 365 ->addHiddenInput('primary', $email_id) 361 366 ->setTitle(pht('Change primary email address?')) 362 - ->appendChild(phutil_tag('p', array(), pht( 363 - 'If you change your primary address, Phabricator will send'. 364 - ' all email to %s.', 365 - $address))) 367 + ->appendParagraph( 368 + pht( 369 + 'If you change your primary address, Phabricator will send all '. 370 + 'email to %s.', 371 + $address)) 372 + ->appendParagraph( 373 + pht( 374 + 'Note: Changing your primary email address will invalidate any '. 375 + 'outstanding password reset links.')) 366 376 ->addSubmitButton(pht('Change Primary Address')) 367 377 ->addCancelButton($uri); 368 378