From 183818b0a7a8723605e237da709ed7cd19cb14a6 Mon Sep 17 00:00:00 2001 From: Ilmari Karonen Date: Tue, 8 May 2007 20:48:02 +0000 Subject: [PATCH] Disable user scripts on Special:Preferences, to prevent a compromised script from being able to sniff passwords etc. (The control flow here is hopelessly tangled between OutputPage and the skins, and it doesn't help that Skin and SkinTemplate do things differently for no particular reason. I haven't made any attempt to untangle it in this commit, but hopefully I at least haven't made it too much worse. Cleanup is welcome.) --- RELEASE-NOTES | 2 ++ includes/OutputPage.php | 8 +++++++- includes/Skin.php | 6 +++--- includes/SkinTemplate.php | 8 ++++---- includes/SpecialPreferences.php | 2 ++ skins/Standard.php | 4 ++-- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 54289ffa65..2b111157b0 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -40,6 +40,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN like [[User:#123|#123]] * Use the standard HTTP fetch functions when retrieving remote wiki pages through transwiki, so we can take advantage of cURL goodies if available +* Disable custom user javascript in Special:Preferences, to avoid the risk + of a compromised script sniffing passwords etc. == Maintenance script changes since 1.10 == diff --git a/includes/OutputPage.php b/includes/OutputPage.php index baf9f3e590..76c287147e 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -15,6 +15,7 @@ class OutputPage { var $mLastModified, $mETag, $mCategoryLinks; var $mScripts, $mLinkColours, $mPageLinkTitle; + var $mAllowUserJs; var $mSuppressQuickbar; var $mOnloadHandler; var $mDoNothing; @@ -33,6 +34,8 @@ class OutputPage { * Initialise private variables */ function __construct() { + global $wgAllowUserJs; + $this->mAllowUserJs = $wgAllowUserJs; $this->mMetatags = $this->mKeywords = $this->mLinktags = array(); $this->mHTMLtitle = $this->mPagetitle = $this->mBodytext = $this->mRedirect = $this->mLastModified = @@ -283,6 +286,9 @@ class OutputPage { public function suppressQuickbar() { $this->mSuppressQuickbar = true; } public function isQuickbarSuppressed() { return $this->mSuppressQuickbar; } + public function disallowUserJs() { $this->mAllowUserJs = false; } + public function isUserJsAllowed() { return $this->mAllowUserJs; } + public function addHTML( $text ) { $this->mBodytext .= $text; } public function clearHTML() { $this->mBodytext = ''; } public function getHTML() { return $this->mBodytext; } @@ -1138,7 +1144,7 @@ class OutputPage { $ret .= "\n"; $sk = $wgUser->getSkin(); - $ret .= $sk->getHeadScripts(); + $ret .= $sk->getHeadScripts( $this->mAllowUserJs ); $ret .= $this->mScripts; $ret .= $sk->getUserStyles(); $ret .= $this->getHeadItems(); diff --git a/includes/Skin.php b/includes/Skin.php index 0e3e4aa2c1..c038738fb7 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -334,8 +334,8 @@ class Skin extends Linker { return self::makeVariablesScript( $vars ); } - function getHeadScripts() { - global $wgStylePath, $wgUser, $wgAllowUserJs, $wgJsMimeType, $wgStyleVersion; + function getHeadScripts( $allowUserJs ) { + global $wgStylePath, $wgUser, $wgJsMimeType, $wgStyleVersion; $r = self::makeGlobalVariablesScript( array( 'skinname' => $this->getSkinName() ) ); @@ -348,7 +348,7 @@ class Skin extends Linker { $r .= "\n"; } } - if( $wgAllowUserJs && $wgUser->isLoggedIn() ) { + if( $allowUserJs && $wgUser->isLoggedIn() ) { $userpage = $wgUser->getUserPage(); $userjs = htmlspecialchars( self::makeUrl( $userpage->getPrefixedText().'/'.$this->getSkinName().'.js', diff --git a/includes/SkinTemplate.php b/includes/SkinTemplate.php index 1929ff85ba..9d090774ee 100644 --- a/includes/SkinTemplate.php +++ b/includes/SkinTemplate.php @@ -179,7 +179,7 @@ class SkinTemplate extends Skin { $this->usercss = $this->userjs = $this->userjsprev = false; $this->setupUserCss(); - $this->setupUserJs(); + $this->setupUserJs( $out->isUserJsAllowed() ); $this->titletxt = $this->mTitle->getPrefixedText(); wfProfileOut( "$fname-stuff" ); @@ -984,14 +984,14 @@ class SkinTemplate extends Skin { /** * @private */ - function setupUserJs() { + function setupUserJs( $allowUserJs ) { $fname = 'SkinTemplate::setupUserJs'; wfProfileIn( $fname ); - global $wgRequest, $wgAllowUserJs, $wgJsMimeType; + global $wgRequest, $wgJsMimeType; $action = $wgRequest->getText('action'); - if( $wgAllowUserJs && $this->loggedin ) { + if( $allowUserJs && $this->loggedin ) { if( $this->mTitle->isJsSubpage() and $this->userCanPreview( $action ) ) { # XXX: additional security check/prompt? $this->userjsprev = '/*getText('wpTextbox1') . ' /*]]>*/'; diff --git a/includes/SpecialPreferences.php b/includes/SpecialPreferences.php index 05605d3808..e9c5418f95 100644 --- a/includes/SpecialPreferences.php +++ b/includes/SpecialPreferences.php @@ -496,6 +496,8 @@ class PreferencesForm { $wgOut->setArticleRelated( false ); $wgOut->setRobotpolicy( 'noindex,nofollow' ); + $wgOut->disallowUserJs(); # Prevent hijacked user scripts from sniffing passwords etc. + if ( $this->mSuccess || 'success' == $status ) { $wgOut->addWikitext( '
'. wfMsg( 'savedprefs' ) . '
' ); } else if ( 'error' == $status ) { diff --git a/skins/Standard.php b/skins/Standard.php index f79571a5af..84885c4901 100644 --- a/skins/Standard.php +++ b/skins/Standard.php @@ -18,10 +18,10 @@ class SkinStandard extends Skin { /** * */ - function getHeadScripts() { + function getHeadScripts( $allowUserJs ) { global $wgStylePath, $wgJsMimeType, $wgStyleVersion; - $s = parent::getHeadScripts(); + $s = parent::getHeadScripts( $allowUserJs ); if ( 3 == $this->qbSetting() ) { # Floating left $s .= "\n"; -- 2.20.1