MediaWiki REL1_33
IEUrlExtension.php
Go to the documentation of this file.
1<?php
62 public static function areServerVarsBad( $vars, $extWhitelist = [] ) {
63 // Check QUERY_STRING or REQUEST_URI
64 if ( isset( $vars['SERVER_SOFTWARE'] )
65 && isset( $vars['REQUEST_URI'] )
66 && self::haveUndecodedRequestUri( $vars['SERVER_SOFTWARE'] )
67 ) {
68 $urlPart = $vars['REQUEST_URI'];
69 } elseif ( isset( $vars['QUERY_STRING'] ) ) {
70 $urlPart = $vars['QUERY_STRING'];
71 } else {
72 $urlPart = '';
73 }
74
75 if ( self::isUrlExtensionBad( $urlPart, $extWhitelist ) ) {
76 return true;
77 }
78
79 // Some servers have PATH_INFO but not REQUEST_URI, so we check both
80 // to be on the safe side.
81 if ( isset( $vars['PATH_INFO'] )
82 && self::isUrlExtensionBad( $vars['PATH_INFO'], $extWhitelist )
83 ) {
84 return true;
85 }
86
87 // All checks passed
88 return false;
89 }
90
100 public static function isUrlExtensionBad( $urlPart, $extWhitelist = [] ) {
101 if ( strval( $urlPart ) === '' ) {
102 return false;
103 }
104
105 $extension = self::findIE6Extension( $urlPart );
106 if ( strval( $extension ) === '' ) {
107 // No extension or empty extension
108 return false;
109 }
110
111 if ( in_array( $extension, [ 'php', 'php5' ] ) ) {
112 // Script extension, OK
113 return false;
114 }
115 if ( in_array( $extension, $extWhitelist ) ) {
116 // Whitelisted extension
117 return false;
118 }
119
120 if ( !preg_match( '/^[a-zA-Z0-9_-]+$/', $extension ) ) {
121 // Non-alphanumeric extension, unlikely to be registered.
122 // The regex above is known to match all registered file extensions
123 // in a default Windows XP installation. It's important to allow
124 // extensions with ampersands and percent signs, since that reduces
125 // the number of false positives substantially.
126 return false;
127 }
128
129 // Possibly bad extension
130 return true;
131 }
132
140 public static function fixUrlForIE6( $url, $extWhitelist = [] ) {
141 $questionPos = strpos( $url, '?' );
142 if ( $questionPos === false ) {
143 $beforeQuery = $url . '?';
144 $query = '';
145 } elseif ( $questionPos === strlen( $url ) - 1 ) {
146 $beforeQuery = $url;
147 $query = '';
148 } else {
149 $beforeQuery = substr( $url, 0, $questionPos + 1 );
150 $query = substr( $url, $questionPos + 1 );
151 }
152
153 // Multiple question marks cause problems. Encode the second and
154 // subsequent question mark.
155 $query = str_replace( '?', '%3E', $query );
156 // Append an invalid path character so that IE6 won't see the end of the
157 // query string as an extension
158 $query .= '&*';
159 // Put the URL back together
160 $url = $beforeQuery . $query;
161 if ( self::isUrlExtensionBad( $url, $extWhitelist ) ) {
162 // Avoid a redirect loop
163 return false;
164 }
165 return $url;
166 }
167
192 public static function findIE6Extension( $url ) {
193 $pos = 0;
194 $hashPos = strpos( $url, '#' );
195 if ( $hashPos !== false ) {
196 $urlLength = $hashPos;
197 } else {
198 $urlLength = strlen( $url );
199 }
200 $remainingLength = $urlLength;
201 while ( $remainingLength > 0 ) {
202 // Skip ahead to the next dot
203 $pos += strcspn( $url, '.', $pos, $remainingLength );
204 if ( $pos >= $urlLength ) {
205 // End of string, we're done
206 return false;
207 }
208
209 // We found a dot. Skip past it
210 $pos++;
211 $remainingLength = $urlLength - $pos;
212
213 // Check for illegal characters in our prospective extension,
214 // or for another dot
215 $nextPos = $pos + strcspn( $url, "<>\\\"/:|?*.", $pos, $remainingLength );
216 if ( $nextPos >= $urlLength ) {
217 // No illegal character or next dot
218 // We have our extension
219 return substr( $url, $pos, $urlLength - $pos );
220 }
221 if ( $url[$nextPos] === '?' ) {
222 // We've found a legal extension followed by a question mark
223 // If the extension is NOT exe, dll or cgi, return it
224 $extension = substr( $url, $pos, $nextPos - $pos );
225 if ( strcasecmp( $extension, 'exe' ) && strcasecmp( $extension, 'dll' ) &&
226 strcasecmp( $extension, 'cgi' )
227 ) {
228 return $extension;
229 }
230 // Else continue looking
231 }
232 // We found an illegal character or another dot
233 // Skip to that character and continue the loop
234 $pos = $nextPos;
235 $remainingLength = $urlLength - $pos;
236 }
237 return false;
238 }
239
257 public static function haveUndecodedRequestUri( $serverSoftware ) {
258 static $whitelist = [
259 'Apache',
260 'Zeus',
261 'LiteSpeed' ];
262 if ( preg_match( '/^(.*?)($|\/| )/', $serverSoftware, $m ) ) {
263 return in_array( $m[1], $whitelist );
264 } else {
265 return false;
266 }
267 }
268
269}
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two and(2) offer you this license which gives you legal permission to copy
Internet Explorer derives a cache filename from a URL, and then in certain circumstances,...
static areServerVarsBad( $vars, $extWhitelist=[])
Check a subset of $_SERVER (or the whole of $_SERVER if you like) to see if it indicates that the req...
static haveUndecodedRequestUri( $serverSoftware)
When passed the value of $_SERVER['SERVER_SOFTWARE'], this function returns true if that server is kn...
static findIE6Extension( $url)
Determine what extension IE6 will infer from a certain query string.
static isUrlExtensionBad( $urlPart, $extWhitelist=[])
Given a right-hand portion of a URL, determine whether IE would detect a potentially harmful file ext...
static fixUrlForIE6( $url, $extWhitelist=[])
Returns a variant of $url which will pass isUrlExtensionBad() but has the same GET parameters,...
static configuration should be added through ResourceLoaderGetConfigVars instead & $vars
Definition hooks.txt:2228
null for the local wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition hooks.txt:1617