r89397 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r89396‎ | r89397 | r89398 >
Date:05:32, 3 June 2011
Author:tstarling
Status:resolved
Tags:
Comment:
(bug 28840) If the query string hits bug 28235, redirect to a safer URL instead of showing an unhelpful error message. IE 6 will only use the extension of the final destination for its cache filename.
Modified paths:
  • /trunk/phase3/api.php (modified) (history)
  • /trunk/phase3/includes/RawPage.php (modified) (history)
  • /trunk/phase3/includes/WebRequest.php (modified) (history)
  • /trunk/phase3/load.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/WebRequest.php
@@ -767,6 +767,69 @@
768768 }
769769
770770 /**
 771+ * Check if Internet Explorer will detect an incorrect cache extension in
 772+ * PATH_INFO or QUERY_STRING. If the request can't be allowed, show an error
 773+ * message or redirect to a safer URL. Returns true if the URL is OK, and
 774+ * false if an error message has been shown and the request should be aborted.
 775+ */
 776+ public function checkUrlExtension() {
 777+ $query = isset( $_SERVER['QUERY_STRING'] ) ? $_SERVER['QUERY_STRING'] : '';
 778+ if ( self::isUrlExtensionBad( $query ) ) {
 779+ if ( !$this->wasPosted() ) {
 780+ if ( $this->attemptExtensionSecurityRedirect() ) {
 781+ return false;
 782+ }
 783+ }
 784+ wfHttpError( 403, 'Forbidden',
 785+ 'Invalid file extension found in the query string.' );
 786+
 787+ return false;
 788+ }
 789+
 790+ if ( $this->isPathInfoBad() ) {
 791+ wfHttpError( 403, 'Forbidden',
 792+ 'Invalid file extension found in PATH_INFO.' );
 793+ return false;
 794+ }
 795+ return true;
 796+ }
 797+
 798+ /**
 799+ * Attempt to redirect to a URL with a QUERY_STRING that's not dangerous in
 800+ * IE 6. Returns true if it was successful, false otherwise.
 801+ */
 802+ protected function attemptExtensionSecurityRedirect() {
 803+ $url = self::fixUrlForIE6( $this->getFullRequestURL() );
 804+ if ( $url === false ) {
 805+ return false;
 806+ }
 807+
 808+ header( 'Location: ' . $url );
 809+ header( 'Content-Type: text/html' );
 810+ $encUrl = htmlspecialchars( $url );
 811+ echo <<<HTML
 812+<html>
 813+<head>
 814+<title>Security redirect</title>
 815+</head>
 816+<body>
 817+<h1>Security redirect</h1>
 818+<p>
 819+We can't serve non-HTML content from the URL you have requested, because
 820+Internet Explorer would interpret it as an incorrect and potentially dangerous
 821+content type.</p>
 822+<p>Instead, please use <a href="$encUrl">this URL</a>, which is the same as the URL you have requested, except that
 823+"&amp;*" is appended. This prevents Internet Explorer from seeing a bogus file
 824+extension.
 825+</p>
 826+</body>
 827+</html>
 828+HTML;
 829+ echo "\n";
 830+ return true;
 831+ }
 832+
 833+ /**
771834 * Returns true if the PATH_INFO ends with an extension other than a script
772835 * extension. This could confuse IE for scripts that send arbitrary data which
773836 * is not HTML but may be detected as such.
@@ -884,8 +947,18 @@
885948 if ( !isset( $_SERVER['QUERY_STRING'] ) ) {
886949 return false;
887950 }
 951+ return self::isUrlExtensionBad( $_SERVER['QUERY_STRING'] );
 952+ }
888953
889 - $extension = self::findIE6Extension( $_SERVER['QUERY_STRING'] );
 954+ /**
 955+ * The same as WebRequest::isQueryStringBad() except as a static function.
 956+ */
 957+ public static function isUrlExtensionBad( $query ) {
 958+ if ( strval( $query ) === '' ) {
 959+ return false;
 960+ }
 961+
 962+ $extension = self::findIE6Extension( $query );
890963 if ( strval( $extension ) === '' ) {
891964 /* No extension or empty extension (false/'') */
892965 return false;
@@ -902,6 +975,31 @@
903976 }
904977
905978 /**
 979+ * Returns a variant of $url which will pass isUrlExtensionBad() but has the
 980+ * same GET parameters, or false if it can't figure one out.
 981+ */
 982+ public static function fixUrlForIE6( $url ) {
 983+ $questionPos = strpos( $url, '?' );
 984+ if ( $questionPos === false || $questionPos === strlen( $url ) - 1 ) {
 985+ return $url;
 986+ }
 987+
 988+ $beforeQuery = substr( $url, 0, $questionPos + 1 );
 989+ $query = substr( $url, $questionPos + 1 );
 990+ // Multiple question marks cause problems. Encode the second and
 991+ // subsequent question mark.
 992+ $query = str_replace( '?', '%3E', $query );
 993+ // Append an invalid path character so that IE6 won't see the end of the
 994+ // query string as an extension
 995+ $query .= '&*';
 996+ if ( self::isUrlExtensionBad( $query ) ) {
 997+ // Avoid a redirect loop
 998+ return false;
 999+ }
 1000+ return $beforeQuery . $query;
 1001+ }
 1002+
 1003+ /**
9061004 * Parse the Accept-Language header sent by the client into an array
9071005 * @return array( languageCode => q-value ) sorted by q-value in descending order
9081006 * May contain the "language" '*', which applies to languages other than those explicitly listed.
Index: trunk/phase3/includes/RawPage.php
@@ -118,22 +118,8 @@
119119 function view() {
120120 global $wgOut, $wgRequest;
121121
122 - if( $wgRequest->isPathInfoBad() ) {
123 - # Internet Explorer will ignore the Content-Type header if it
124 - # thinks it sees a file extension it recognizes. Make sure that
125 - # all raw requests are done through the script node, which will
126 - # have eg '.php' and should remain safe.
127 - #
128 - # We used to redirect to a canonical-form URL as a general
129 - # backwards-compatibility / good-citizen nice thing. However
130 - # a lot of servers are set up in buggy ways, resulting in
131 - # redirect loops which hang the browser until the CSS load
132 - # times out.
133 - #
134 - # Just return a 403 Forbidden and get it over with.
135 - wfHttpError( 403, 'Forbidden',
136 - 'Invalid file extension found in PATH_INFO or QUERY_STRING. ' .
137 - 'Raw pages must be accessed through the primary script entry point.' );
 122+ if( !$wgRequest->checkUrlExtension() ) {
 123+ $wgOut->disable();
138124 return;
139125 }
140126
Index: trunk/phase3/api.php
@@ -61,18 +61,7 @@
6262 $starttime = microtime( true );
6363
6464 // URL safety checks
65 -//
66 -// See RawPage.php for details; summary is that MSIE can override the
67 -// Content-Type if it sees a recognized extension on the URL, such as
68 -// might be appended via PATH_INFO after 'api.php'.
69 -//
70 -// Some data formats can end up containing unfiltered user-provided data
71 -// which will end up triggering HTML detection and execution, hence
72 -// XSS injection and all that entails.
73 -//
74 -if ( $wgRequest->isPathInfoBad() ) {
75 - wfHttpError( 403, 'Forbidden',
76 - 'Invalid file extension found in PATH_INFO or QUERY_STRING.' );
 65+if ( !$wgRequest->checkUrlExtension() ) {
7766 return;
7867 }
7968
Index: trunk/phase3/load.php
@@ -45,17 +45,7 @@
4646 wfProfileIn( 'load.php' );
4747
4848 // URL safety checks
49 -//
50 -// See RawPage.php for details; summary is that MSIE can override the
51 -// Content-Type if it sees a recognized extension on the URL, such as
52 -// might be appended via PATH_INFO after 'load.php'.
53 -//
54 -// Some resources can contain HTML-like strings (e.g. in messages)
55 -// which will end up triggering HTML detection and execution.
56 -//
57 -if ( $wgRequest->isPathInfoBad() ) {
58 - wfHttpError( 403, 'Forbidden',
59 - 'Invalid file extension found in PATH_INFO or QUERY_STRING.' );
 49+if ( !$wgRequest->checkUrlExtension() ) {
6050 return;
6151 }
6252

Follow-up revisions

RevisionCommit summaryAuthorDate
r89558* Added a REQUEST_URI check to the bug 28235 handling....tstarling11:59, 6 June 2011
r89627MFT r89397, r89558, etc.: bug 28840 IE URL extensiontstarling05:57, 7 June 2011
r89628Merge r89627 from 1.18, equivalent to trunk r89558, r89397, etc.: bug 28840 I...tstarling07:00, 7 June 2011
r91440* Merged r89628 from 1.17: bug 28840 IE URL extension fixes....tstarling06:35, 5 July 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r85844Fix for bug 28235: IE6 looks for the file extension in the query stringtstarling00:55, 12 April 2011
r85845MFT r85844, fix for bug 28235 (IE6 looks for the file extension in the query ...tstarling01:07, 12 April 2011
r85846MFT r85844, fix for bug 28235 (IE6 looks for the file extension in the query ...tstarling01:15, 12 April 2011
r86027(bug 28507) Fix for r85844: that revision was not actually sufficient to fix ...tstarling07:10, 14 April 2011
r87711(bug 28840) Commit patch by bawolff that encodes dots in ResourceLoader modul...catrope13:10, 9 May 2011
r88883(bug 28840) URLs with dots break because of IE6 security check...catrope09:49, 26 May 2011

Status & tagging log