r55178 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r55177‎ | r55178 | r55179 >
Date:13:23, 17 August 2009
Author:tstarling
Status:ok (Comments)
Tags:
Comment:
* Fixed XSS vulnerability introduced by r49833. Only pre-release versions of MediaWiki were affected.
* Refactored the IE script entry point security check into WebRequest::isPathInfoBad(). Use the standard CGI variable PATH_INFO to do this check instead of the various potential non-standard solutions. Made the check fairly permissive to avoid a repeat of bug 13049 due to broken CGI setups especially with cgi.fix_pathinfo=0. This should theoretically be very portable and secure, but I have not tested it widely.
* Removed Chris Wrinn from the credits since his patch was wrong and has been removed.
* Made the error message more informative.
Modified paths:
  • /trunk/phase3/CREDITS (modified) (history)
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/api.php (modified) (history)
  • /trunk/phase3/includes/RawPage.php (modified) (history)
  • /trunk/phase3/includes/WebRequest.php (modified) (history)
  • /trunk/phase3/mwScriptLoader.php (modified) (history)

Diff [purge]

Index: trunk/phase3/CREDITS
@@ -63,7 +63,6 @@
6464 * Brent G
6565 * Brianna Laugher
6666 * Carlin
67 -* Chris Wrinn
6867 * church of emacs
6968 * Dan Nessett
7069 * Daniel Arnold
Index: trunk/phase3/includes/WebRequest.php
@@ -670,6 +670,33 @@
671671 public function setSessionData( $key, $data ) {
672672 $_SESSION[$key] = $data;
673673 }
 674+
 675+ /**
 676+ * Returns true if the PATH_INFO ends with an extension other than a script
 677+ * extension. This could confuse IE for scripts that send arbitrary data which
 678+ * is not HTML but may be detected as such.
 679+ *
 680+ * Various past attempts to use the URL to make this check have generally
 681+ * run up against the fact that CGI does not provide a standard method to
 682+ * determine the URL. PATH_INFO may be mangled (e.g. if cgi.fix_pathinfo=0),
 683+ * but only by prefixing it with the script name and maybe some other stuff,
 684+ * the extension is not mangled. So this should be a reasonably portable
 685+ * way to perform this security check.
 686+ */
 687+ public function isPathInfoBad() {
 688+ global $wgScriptExtension;
 689+
 690+ if ( !isset( $_SERVER['PATH_INFO'] ) ) {
 691+ return false;
 692+ }
 693+ $pi = $_SERVER['PATH_INFO'];
 694+ $dotPos = strrpos( $pi, '.' );
 695+ if ( $dotPos === false ) {
 696+ return false;
 697+ }
 698+ $ext = substr( $pi, $dotPos );
 699+ return !in_array( $ext, array( $wgScriptExtension, '.php', '.php5' ) );
 700+ }
674701 }
675702
676703 /**
@@ -740,4 +767,8 @@
741768 $this->notImplemented( __METHOD__ );
742769 }
743770
 771+ public function isPathInfoBad() {
 772+ return false;
 773+ }
 774+
744775 }
Index: trunk/phase3/includes/RawPage.php
@@ -109,19 +109,9 @@
110110 }
111111
112112 function view() {
113 - global $wgOut, $wgScript;
 113+ global $wgOut, $wgScript, $wgRequest;
114114
115 - $url = wfGetScriptUrl();
116 - if( $url == '' ) {
117 - # This will make the next check fail with a confusing error
118 - # message, so we should mention it separately.
119 - wfHttpError( 500, 'Internal Server Error',
120 - "\$_SERVER['URL'] is not set. Perhaps you're using CGI" .
121 - " and haven't set cgi.fix_pathinfo = 1 in php.ini?" );
122 - return;
123 - }
124 -
125 - if( strcmp( $wgScript, $url ) ) {
 115+ if( $wgRequest->isPathInfoBad() ) {
126116 # Internet Explorer will ignore the Content-Type header if it
127117 # thinks it sees a file extension it recognizes. Make sure that
128118 # all raw requests are done through the script node, which will
@@ -135,6 +125,7 @@
136126 #
137127 # Just return a 403 Forbidden and get it over with.
138128 wfHttpError( 403, 'Forbidden',
 129+ 'Invalid file extension found in PATH_INFO. ' .
139130 'Raw pages must be accessed through the primary script entry point.' );
140131 return;
141132 }
Index: trunk/phase3/mwScriptLoader.php
@@ -30,8 +30,9 @@
3131 wfProfileIn( 'mwScriptLoader.php' );
3232
3333
34 -if( strpos( wfGetScriptUrl(), "mwScriptLoader{$wgScriptExtension}" ) === false ){
 34+if( $wgRequest->isPathInfoBad() ){
3535 wfHttpError( 403, 'Forbidden',
 36+ 'Invalid file extension found in PATH_INFO. ' .
3637 'mwScriptLoader must be accessed through the primary script entry point.' );
3738 return;
3839 }
@@ -51,4 +52,4 @@
5253 $myScriptLoader = new jsScriptLoader();
5354 $myScriptLoader->doScriptLoader();
5455
55 -wfProfileOut( 'mwScriptLoader.php' );
\ No newline at end of file
 56+wfProfileOut( 'mwScriptLoader.php' );
Index: trunk/phase3/api.php
@@ -49,16 +49,10 @@
5050 // which will end up triggering HTML detection and execution, hence
5151 // XSS injection and all that entails.
5252 //
53 -// Ensure that all access is through the canonical entry point...
54 -//
55 -if( isset( $_SERVER['SCRIPT_NAME'] ) ) {
56 - $url = $_SERVER['SCRIPT_NAME'];
57 -} else {
58 - $url = $_SERVER['URL'];
59 -}
60 -if( strcmp( "$wgScriptPath/api$wgScriptExtension", $url ) ) {
 53+if( $wgRequest->isPathInfoBad() ) {
6154 wfHttpError( 403, 'Forbidden',
62 - 'API must be accessed through the primary script entry point.' );
 55+ 'Invalid file extension found in PATH_INFO. ' .
 56+ 'The API must be accessed through the primary script entry point.' );
6357 return;
6458 }
6559
Index: trunk/phase3/RELEASE-NOTES
@@ -406,6 +406,8 @@
407407 * (bug 20273) Fix broken output when no pages are found in the content
408408 namespaces
409409 * (bug 20265) Make AncientPages and UnusedFiles work on SQLite
 410+* Fixed XSS vulnerability for Internet Explorer clients (only pre-release
 411+ versions of MediaWiki were affected).
410412
411413 == API changes in 1.16 ==
412414

Follow-up revisions

RevisionCommit summaryAuthorDate
r55179Merging r55178 from trunk to wmf-deploymenttstarling13:24, 17 August 2009
r55180Merged r55178 (second attempt). Removed live patch to make secure.wikimedia.o...tstarling13:29, 17 August 2009

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r49833API: (bug 13049) This'll hopefully fix the 403 Forbidden error in api.php for...catrope19:50, 24 April 2009

Comments

#Comment by Brion VIBBER (talk | contribs)   21:42, 18 August 2009

Ahhhh this makes me warm and fuzzy :D much cleaner than the previous stuff. Thanks Tim!

Status & tagging log