From 6b5143fd2c633fe97a09ad3a36455e3f271b0200 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Tue, 18 Nov 2008 05:57:08 +0000 Subject: [PATCH] Protect users from attacks against their browsers via malicious script-containing uploads, by: 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 | 28 +++++++++++++++++++++ includes/specials/SpecialUndelete.php | 35 ++++++++++++++++++++++++--- languages/messages/MessagesEn.php | 2 ++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/img_auth.php b/img_auth.php index bb419b39aa..4b625e3972 100644 --- a/img_auth.php +++ b/img_auth.php @@ -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 << + +

Access Denied

+

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. +

+ + +ENDS; + wfLogProfilingData(); + exit; +} + diff --git a/includes/specials/SpecialUndelete.php b/includes/specials/SpecialUndelete.php index 42a9df3fee..d0418edacd 100644 --- a/includes/specials/SpecialUndelete.php +++ b/includes/specials/SpecialUndelete.php @@ -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 { ''; } + /** + * 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' ) ) . + '' + ); + } + /** * 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 '' . $wgLang->timeanddate( $ts, true ) . ''; } 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 = '' . $link . ''; return $link; diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 6b86e66178..ac851f0a4b 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -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 "$1" from $2?', +'undelete-show-file-submit' => 'Yes', # Namespace form on various pages 'namespace' => 'Namespace:', -- 2.20.1