From 57d0dee1922bef3d13079887f3f516e83d9ef624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Taavi=20V=C3=A4=C3=A4n=C3=A4nen?= Date: Wed, 23 Feb 2022 15:21:49 +0200 Subject: [PATCH] SECURITY: Ignore cached CentralAuthUser entries with expired groups This is a hardening measure, since the cache TTLs are supposed to prevent expired values being cached. Bug: T302248 Change-Id: If7471bef9438c20c336cbf3ed09685833354fae4 --- includes/User/CentralAuthUser.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/includes/User/CentralAuthUser.php b/includes/User/CentralAuthUser.php index f0ce7aea..4a11a417 100644 --- a/includes/User/CentralAuthUser.php +++ b/includes/User/CentralAuthUser.php @@ -474,9 +474,11 @@ class CentralAuthUser implements IDBAccessObject { /** * Load user groups and rights from the database. + * + * @param bool $force Set tu true to load even when already loaded. */ - protected function loadGroups() { - if ( isset( $this->mGroups ) ) { + protected function loadGroups( bool $force = false ) { + if ( isset( $this->mGroups ) && !$force ) { // Already loaded return; } @@ -695,6 +697,24 @@ class CentralAuthUser implements IDBAccessObject { $this->mIsAttached = $this->exists() && in_array( WikiMap::getCurrentWikiId(), $this->mAttachedArray ); $this->mFromPrimary = false; + + $closestUserGroupExpiration = $this->getClosestGlobalUserGroupExpiry(); + if ( $closestUserGroupExpiration !== null && $closestUserGroupExpiration < time() ) { + LoggerFactory::getInstance( 'CentralAuth' ) + ->warning( + 'Cached user {user} had a global group expiration in the past ({unixTimestamp}), this should not be possible', + [ + 'user' => $this->getName(), + 'unixTimestamp' => $closestUserGroupExpiration, + ] + ); + + // load accurate data for this request from the database + $this->loadGroups( true ); + + // kill the current cache entry so that next request can use the cached value + $this->quickInvalidateCache(); + } } /** -- 2.34.1