Disable user scripts on Special:Preferences, to prevent a compromised
authorIlmari Karonen <vyznev@users.mediawiki.org>
Tue, 8 May 2007 20:48:02 +0000 (20:48 +0000)
committerIlmari Karonen <vyznev@users.mediawiki.org>
Tue, 8 May 2007 20:48:02 +0000 (20:48 +0000)
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
includes/OutputPage.php
includes/Skin.php
includes/SkinTemplate.php
includes/SpecialPreferences.php
skins/Standard.php

index 54289ff..2b11115 100644 (file)
@@ -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 ==
 
index baf9f3e..76c2871 100644 (file)
@@ -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 .= "<link rel='stylesheet' type='text/css' $media href='$printsheet' />\n";
 
                $sk = $wgUser->getSkin();
-               $ret .= $sk->getHeadScripts();
+               $ret .= $sk->getHeadScripts( $this->mAllowUserJs );
                $ret .= $this->mScripts;
                $ret .= $sk->getUserStyles();
                $ret .= $this->getHeadItems();
index 0e3e4aa..c038738 100644 (file)
@@ -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 .= "<script type=\"$wgJsMimeType\" src=\"".htmlspecialchars(self::makeUrl('-','action=raw&gen=js'))."\"><!-- site js --></script>\n";
                        }
                }
-               if( $wgAllowUserJs && $wgUser->isLoggedIn() ) {
+               if( $allowUserJs && $wgUser->isLoggedIn() ) {
                        $userpage = $wgUser->getUserPage();
                        $userjs = htmlspecialchars( self::makeUrl(
                                $userpage->getPrefixedText().'/'.$this->getSkinName().'.js',
index 1929ff8..9d09077 100644 (file)
@@ -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 = '/*<![CDATA[*/ ' . $wgRequest->getText('wpTextbox1') . ' /*]]>*/';
index 05605d3..e9c5418 100644 (file)
@@ -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( '<div class="successbox"><strong>'. wfMsg( 'savedprefs' ) . '</strong></div>' );
                } else  if ( 'error' == $status ) {
index f79571a..84885c4 100644 (file)
@@ -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 .= "<script language='javascript' type='$wgJsMimeType' " .
                          "src='{$wgStylePath}/common/sticky.js?$wgStyleVersion'></script>\n";