Protect users from attacks against their browsers via malicious script-containing...
authorTim Starling <tstarling@users.mediawiki.org>
Tue, 18 Nov 2008 05:57:08 +0000 (05:57 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Tue, 18 Nov 2008 05:57:08 +0000 (05:57 +0000)
1) Requiring a session token before streaming files out via Special:Undelete
2) Restricting img_auth.php to private wikis only (its intended use case)

img_auth.php
includes/specials/SpecialUndelete.php
languages/messages/MessagesEn.php

index bb419b3..4b625e3 100644 (file)
@@ -17,6 +17,12 @@ require_once( dirname( __FILE__ ) . '/includes/WebStart.php' );
 wfProfileIn( 'img_auth.php' );
 require_once( dirname( __FILE__ ) . '/includes/StreamFile.php' );
 
+$perms = User::getGroupPermissions( array( '*' ) );
+if ( in_array( 'read', $perms, true ) ) {
+       wfDebugLog( 'img_auth', 'Public wiki' );
+       wfPublicError();
+}
+
 // Extract path and image information
 if( !isset( $_SERVER['PATH_INFO'] ) ) {
        wfDebugLog( 'img_auth', 'Missing PATH_INFO' );
@@ -88,3 +94,25 @@ ENDS;
        wfLogProfilingData();
        exit();
 }
+
+/**
+ * Show a 403 error for use when the wiki is public
+ */
+function wfPublicError() {
+       header( 'HTTP/1.0 403 Forbidden' );
+       header( 'Content-Type: text/html; charset=utf-8' );
+       echo <<<ENDS
+<html>
+<body>
+<h1>Access Denied</h1>
+<p>The function of img_auth.php is to output files from a private wiki. This wiki
+is configured as a public wiki. For optimal security, img_auth.php is disabled in 
+this case.
+</p>
+</body>
+</html>
+ENDS;
+       wfLogProfilingData();
+       exit;
+}
+
index 42a9df3..d0418ed 100644 (file)
@@ -569,7 +569,7 @@ class PageArchive {
  */
 class UndeleteForm {
        var $mAction, $mTarget, $mTimestamp, $mRestore, $mInvert, $mTargetObj;
-       var $mTargetTimestamp, $mAllowed, $mComment;
+       var $mTargetTimestamp, $mAllowed, $mComment, $mToken;
 
        function UndeleteForm( $request, $par = "" ) {
                global $wgUser;
@@ -588,6 +588,7 @@ class UndeleteForm {
                $this->mDiff = $request->getCheck( 'diff' );
                $this->mComment = $request->getText( 'wpComment' );
                $this->mUnsuppress = $request->getVal( 'wpUnsuppress' ) && $wgUser->isAllowed( 'suppressrevision' );
+               $this->mToken = $request->getVal( 'token' );
 
                if( $par != "" ) {
                        $this->mTarget = $par;
@@ -654,6 +655,9 @@ class UndeleteForm {
                        if( !$file->userCan( File::DELETED_FILE ) ) {
                                $wgOut->permissionRequired( 'suppressrevision' );
                                return false;
+                       } elseif ( !$wgUser->matchEditToken( $this->mToken, $this->mFile ) ) {
+                               $this->showFileConfirmationForm( $this->mFile );
+                               return false;
                        } else {
                                return $this->showFile( $this->mFile );
                        }
@@ -886,6 +890,29 @@ class UndeleteForm {
                        '</div>';
        }
 
+       /**
+        * Show a form confirming whether a tokenless user really wants to see a file
+        */
+       private function showFileConfirmationForm( $key ) {
+               global $wgOut, $wgUser, $wgLang;
+               $file = new ArchivedFile( $this->mTargetObj, '', $this->mFile );
+               $wgOut->addWikiMsg( 'undelete-show-file-confirm',
+                       $this->mTargetObj->getText(),
+                       $wgLang->timeanddate( $file->getTimestamp() ) );
+               $wgOut->addHTML( 
+                       Xml::openElement( 'form', array( 
+                               'method' => 'POST',
+                               'action' => SpecialPage::getTitleFor( 'Undelete' )->getLocalUrl(
+                                       'target=' . urlencode( $this->mTarget ) .
+                                       '&file=' . urlencode( $key ) .
+                                       '&token=' . urlencode( $wgUser->editToken( $key ) ) )
+                               )
+                       ) .
+                       Xml::submitButton( wfMsg( 'undelete-show-file-submit' ) ) .
+                       '</form>'
+               );
+       }
+
        /**
         * Show a deleted file version requested by the visitor.
         */
@@ -1194,13 +1221,15 @@ class UndeleteForm {
         * @return string
         */
        function getFileLink( $file, $titleObj, $ts, $key, $sk ) {
-               global $wgLang;
+               global $wgLang, $wgUser;
 
                if( !$file->userCan(File::DELETED_FILE) ) {
                        return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>';
                } else {
                        $link = $sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ),
-                               "target=".$this->mTargetObj->getPrefixedUrl()."&file=$key" );
+                               "target=".$this->mTargetObj->getPrefixedUrl().
+                               "&file=$key" .
+                               "&token=" . urlencode( $wgUser->editToken( $key ) ) );
                        if( $file->isDeleted(File::DELETED_FILE) )
                                $link = '<span class="history-deleted">' . $link . '</span>';
                        return $link;
index 6b86e66..ac851f0 100644 (file)
@@ -2491,6 +2491,8 @@ It may have already been undeleted.',
 'undelete-error-long'          => 'Errors were encountered while undeleting the file:
 
 $1',
+'undelete-show-file-confirm'   => 'Are you sure you want to view a deleted revision of the file "<nowiki>$1</nowiki>" from $2?',
+'undelete-show-file-submit'    => 'Yes',
 
 # Namespace form on various pages
 'namespace'      => 'Namespace:',