From ba2e4d66198025c638b79859b30c35b5e23a9e96 Mon Sep 17 00:00:00 2001
From: Kunal Mehta <legoktm@debian.org>
Date: Fri, 10 Dec 2021 22:27:08 -0800
Subject: [PATCH] SECURITY: Fix permissions checks in undo action
 (CVE-2021-44858)

The traditional action=edit&undo= endpoint suffers from a flaw that
allows for leaking entire private wikis by enumerating through revision
IDs when at least one page was publicly accessible via $wgWhitelistRead.

05f06286f4def removed the restriction that user-supplied undo IDs belong
ot the same page. This check has been restored by using
RevisionLookup::getRevisionByTitle(), which returns null if the revid is
on a different page. This will break the workflow outlined in T58184,
but that could be restored in the future with better access control
checks.

Kudos to Dylsss for the identification and report.

Bug: T297322
Change-Id: I496093adfcf5a0e30774d452b650b751518370ce
---
 includes/EditPage.php | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/includes/EditPage.php b/includes/EditPage.php
index 1d19123b3f..32747a3ba9 100644
--- a/includes/EditPage.php
+++ b/includes/EditPage.php
@@ -1190,8 +1190,10 @@ class EditPage {
 				$undo = $request->getInt( 'undo' );
 
 				if ( $undo > 0 && $undoafter > 0 ) {
-					$undorev = Revision::newFromId( $undo );
-					$oldrev = Revision::newFromId( $undoafter );
+					// The use of newFromTitle() is intentional, as allowing access to
+					// arbitrary revisions on arbitrary pages bypass partial visibility restrictions (T297322).
+					$undorev = Revision::newFromTitle( $this->mTitle, $undo );
+					$oldrev = Revision::newFromTitle( $this->mTitle, $undoafter );
 
 					# Sanity check, make sure it's the right page,
 					# the revisions exist and they were not deleted.
-- 
2.33.1

