SECURITY: Check read permission when loading page content in ApiParse.
authorDaniel Kinzler <daniel.kinzler@wikimedia.de>
Mon, 13 Jun 2016 08:01:43 +0000 (04:01 -0400)
committerChad Horohoe <chadh@wikimedia.org>
Tue, 23 Aug 2016 01:13:01 +0000 (18:13 -0700)
Prevents leaking page contents for extensions that deny read rights
to certain pages via a userCan hook, but still allow the user to
have read rights in general.

Issue originally reported by Tobias

Bug: T115333
Change-Id: I19f5c2583393794cff802a70af7ccf43c2fed85c

includes/api/ApiParse.php

index 35fad4a..83b5d93 100644 (file)
@@ -36,6 +36,12 @@ class ApiParse extends ApiBase {
        /** @var Content $pstContent */
        private $pstContent = null;
 
        /** @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' );
        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' );
                                }
                                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' );
                                }
                                if ( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
                                        $this->dieUsage( "You don't have permission to view deleted revisions", 'permissiondenied' );
                                }
@@ -161,6 +169,8 @@ class ApiParse extends ApiBase {
                                if ( !$titleObj || !$titleObj->exists() ) {
                                        $this->dieUsage( "The page you specified doesn't exist", 'missingtitle' );
                                }
                                if ( !$titleObj || !$titleObj->exists() ) {
                                        $this->dieUsage( "The page you specified doesn't exist", 'missingtitle' );
                                }
+
+                               $this->checkReadPermissions( $titleObj );
                                $wgTitle = $titleObj;
 
                                if ( isset( $prop['revid'] ) ) {
                                $wgTitle = $titleObj;
 
                                if ( isset( $prop['revid'] ) ) {