From 6f115d9f3fe3ae109e535fe5957bf2145edcd290 Mon Sep 17 00:00:00 2001
From: Daniel Kinzler <daniel.kinzler@wikimedia.de>
Date: Mon, 13 Jun 2016 04:01:43 -0400
Subject: [PATCH] SECURITY: Check read permission when loading page content in
 ApiParse.

Modified from Daniel's original patch to also check if the user
can read the pre-redirect page name.

Issue originally reported by Tobias

Bug: T115333
Change-Id: I19f5c2583393794cff802a70af7ccf43c2fed85c
---
 includes/api/ApiParse.php | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/includes/api/ApiParse.php b/includes/api/ApiParse.php
index fe418e3..fe276f8 100644
--- a/includes/api/ApiParse.php
+++ b/includes/api/ApiParse.php
@@ -36,6 +36,12 @@ class ApiParse extends ApiBase {
 	/** @var Content $pstContent */
 	private $pstContent = null;
 
+	private function checkReadPermissions( Title $title ) {
+		if ( !$title->userCan( 'read', $this->getUser() ) ) {
+			$this->dieUsage( "You don't have permission to view this page", 'permissiondenied' );
+		}
+	}
+
 	public function execute() {
 		// The data is hot but user-dependent, like page views, so we set vary cookies
 		$this->getMain()->setCacheMode( 'anon-public-user-private' );
@@ -102,6 +108,8 @@ class ApiParse extends ApiBase {
 				if ( !$rev ) {
 					$this->dieUsage( "There is no revision ID $oldid", 'missingrev' );
 				}
+
+				$this->checkReadPermissions( $rev->getTitle() );
 				if ( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
 					$this->dieUsage( "You don't have permission to view deleted revisions", 'permissiondenied' );
 				}
@@ -134,11 +142,17 @@ class ApiParse extends ApiBase {
 					$reqParams = [
 						'redirects' => '',
 					];
+					$pageParams = [];
 					if ( !is_null( $pageid ) ) {
 						$reqParams['pageids'] = $pageid;
+						$pageParams['pageid'] = $pageid;
 					} else { // $page
 						$reqParams['titles'] = $page;
+						$pageParams['title'] = $page;
 					}
+					$this->checkReadPermissions(
+						$this->getTitleOrPageId( $pageParams )->getTitle()
+					);
 					$req = new FauxRequest( $reqParams );
 					$main = new ApiMain( $req );
 					$pageSet = new ApiPageSet( $main );
@@ -161,6 +175,8 @@ class ApiParse extends ApiBase {
 				if ( !$titleObj || !$titleObj->exists() ) {
 					$this->dieUsage( "The page you specified doesn't exist", 'missingtitle' );
 				}
+
+				$this->checkReadPermissions( $titleObj );
 				$wgTitle = $titleObj;
 
 				if ( isset( $prop['revid'] ) ) {
-- 
2.0.1

