Page MenuHomePhabricator
Authored By
Bawolff
Oct 27 2015, 3:24 AM
Size
7 KB
Referenced Files
None
Subscribers
None

sec-redir2.patch

From 717544b5880730fbcfaec000563915370c32c4ee Mon Sep 17 00:00:00 2001
From: csteipp <csteipp@wikimedia.org>
Date: Mon, 5 Oct 2015 16:58:42 -0700
Subject: [PATCH] SECURITY: Make Special:MyPage and friends fake redirect to
prevent info leak
This prevents a malicious person from using external resources on their
website to cause the victim's web browser to load
Special:MyPage -> User:Username, and then looking it up in the page hit
statistics in order to correlate IPs from the malicious person's server
log, with usernames on wiki.
This feature can be disabled with $wgHideIdentifiableRedirects.
Bug: T109724
Change-Id: Ia0e742dc92c77af4832174dfa24c6dcaa6ee80e9
---
includes/DefaultSettings.php | 6 ++++
includes/MediaWiki.php | 44 ++++++++++++++++++++----
includes/specialpage/RedirectSpecialPage.php | 12 +++++++
includes/specials/SpecialMyLanguage.php | 11 ++++++
includes/specials/SpecialMyRedirectPages.php | 50 ++++++++++++++++++++++++++++
5 files changed, 117 insertions(+), 6 deletions(-)
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 910c121..e4e77c7 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -4718,6 +4718,12 @@ $wgWhitelistReadRegexp = false;
$wgEmailConfirmToEdit = false;
/**
+ * Should MediaWiki attempt to protect user's privacy when doing redirects?
+ * Keep this true if access counts to articles are made public.
+ */
+$wgHideIdentifiableRedirects = true;
+
+/**
* Permission keys given to users in each group.
*
* This is an array where the keys are all groups and each value is an
diff --git a/includes/MediaWiki.php b/includes/MediaWiki.php
index 676108c..0a9df4b 100644
--- a/includes/MediaWiki.php
+++ b/includes/MediaWiki.php
@@ -37,6 +37,11 @@ class MediaWiki {
private $config;
/**
+ * @var String Cache what action this request is
+ */
+ private $action;
+
+ /**
* @param IContextSource|null $context
*/
public function __construct( IContextSource $context = null ) {
@@ -141,13 +146,11 @@ class MediaWiki {
* @return string Action
*/
public function getAction() {
- static $action = null;
-
- if ( $action === null ) {
- $action = Action::getActionName( $this->context );
+ if ( $this->action === null ) {
+ $this->action = Action::getActionName( $this->context );
}
- return $action;
+ return $this->action;
}
/**
@@ -241,8 +244,37 @@ class MediaWiki {
// Handle any other redirects.
// Redirect loops, titleless URL, $wgUsePathInfo URLs, and URLs with a variant
} elseif ( !$this->tryNormaliseRedirect( $title ) ) {
+ // Prevent information leak via Special:MyPage et al (T109724)
+ if ( $title->isSpecialPage() ) {
+ $specialPage = SpecialPageFactory::getPage( $title->getDBKey() );
+ if ( $specialPage instanceof RedirectSpecialPage
+ && $this->config->get( 'HideIdentifiableRedirects' )
+ && $specialPage->personallyIdentifiableTarget()
+ ) {
+ list( , $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBKey() );
+ $target = $specialPage->getRedirect( $subpage );
+ // target can also be true. We let that case fall through to normal processing.
+ if ( $target instanceof Title ) {
+ $query = $specialPage->getRedirectQuery() ?: array();
+ $request = new DerivativeRequest( $this->context->getRequest(), $query );
+ $request->setRequestURL( $this->context->getRequest()->getRequestURL() );
+ $this->context->setRequest( $request );
+ // Do not varnish cache these. May vary even for anons
+ $this->context->getOutput()->lowerCdnMaxage( 0 );
+ $this->context->setTitle( $target );
+ $wgTitle = $target;
+ // Reset action type cache. (Special pages have only view)
+ $this->action = null;
+ $title = $target;
+ $output->addJsConfigVars( array(
+ 'wgInternalRedirectTargetUrl' => $target->getFullURL(),
+ ) );
+ $output->addModules( 'mediawiki.action.view.redirect' );
+ }
+ }
+ }
- // Special pages
+ // Special pages ($title may have changed since if statement above)
if ( NS_SPECIAL == $title->getNamespace() ) {
// Actions that need to be made when we have a special pages
SpecialPageFactory::executePath( $title, $this->context );
diff --git a/includes/specialpage/RedirectSpecialPage.php b/includes/specialpage/RedirectSpecialPage.php
index 9129ee5..5047354 100644
--- a/includes/specialpage/RedirectSpecialPage.php
+++ b/includes/specialpage/RedirectSpecialPage.php
@@ -94,6 +94,18 @@ abstract class RedirectSpecialPage extends UnlistedSpecialPage {
? $params
: false;
}
+
+ /**
+ * Indicate if the target of this redirect can be used to identify
+ * a particular user of this wiki (e.g., if the redirect is to the
+ * user page of a User). See T109724.
+ *
+ * @since 1.27
+ * @return bool
+ */
+ public function personallyIdentifiableTarget() {
+ return false;
+ }
}
/**
diff --git a/includes/specials/SpecialMyLanguage.php b/includes/specials/SpecialMyLanguage.php
index 3d8ff97..d11fbe6 100644
--- a/includes/specials/SpecialMyLanguage.php
+++ b/includes/specials/SpecialMyLanguage.php
@@ -99,4 +99,15 @@ class SpecialMyLanguage extends RedirectSpecialArticle {
return $base;
}
}
+
+ /**
+ * Target can identify a specific user's language preference.
+ *
+ * @see T109724
+ * @since 1.27
+ * @return bool
+ */
+ public function personallyIdentifiableTarget() {
+ return true;
+ }
}
diff --git a/includes/specials/SpecialMyRedirectPages.php b/includes/specials/SpecialMyRedirectPages.php
index 5ef03f1..850b1f6 100644
--- a/includes/specials/SpecialMyRedirectPages.php
+++ b/includes/specials/SpecialMyRedirectPages.php
@@ -45,6 +45,16 @@ class SpecialMypage extends RedirectSpecialArticle {
return Title::makeTitle( NS_USER, $this->getUser()->getName() . '/' . $subpage );
}
+
+ /**
+ * Target identifies a specific User. See T109724.
+ *
+ * @since 1.27
+ * @return bool
+ */
+ public function personallyIdentifiableTarget() {
+ return true;
+ }
}
/**
@@ -68,6 +78,16 @@ class SpecialMytalk extends RedirectSpecialArticle {
return Title::makeTitle( NS_USER_TALK, $this->getUser()->getName() . '/' . $subpage );
}
+
+ /**
+ * Target identifies a specific User. See T109724.
+ *
+ * @since 1.27
+ * @return bool
+ */
+ public function personallyIdentifiableTarget() {
+ return true;
+ }
}
/**
@@ -90,6 +110,16 @@ class SpecialMycontributions extends RedirectSpecialPage {
public function getRedirect( $subpage ) {
return SpecialPage::getTitleFor( 'Contributions', $this->getUser()->getName() );
}
+
+ /**
+ * Target identifies a specific User. See T109724.
+ *
+ * @since 1.27
+ * @return bool
+ */
+ public function personallyIdentifiableTarget() {
+ return true;
+ }
}
/**
@@ -110,6 +140,16 @@ class SpecialMyuploads extends RedirectSpecialPage {
public function getRedirect( $subpage ) {
return SpecialPage::getTitleFor( 'Listfiles', $this->getUser()->getName() );
}
+
+ /**
+ * Target identifies a specific User. See T109724.
+ *
+ * @since 1.27
+ * @return bool
+ */
+ public function personallyIdentifiableTarget() {
+ return true;
+ }
}
/**
@@ -132,4 +172,14 @@ class SpecialAllMyUploads extends RedirectSpecialPage {
return SpecialPage::getTitleFor( 'Listfiles', $this->getUser()->getName() );
}
+
+ /**
+ * Target identifies a specific User. See T109724.
+ *
+ * @since 1.27
+ * @return bool
+ */
+ public function personallyIdentifiableTarget() {
+ return true;
+ }
}
--
2.0.1

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2891056
Default Alt Text
sec-redir2.patch (7 KB)

Event Timeline