MediaWiki REL1_31
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}
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:1620
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition injection.txt:37