Page MenuHomePhabricator

XSS: IE6 looks for the file extension in the query string
Closed, ResolvedPublic

Details

Reference
bz28235

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 11:32 PM
bzimport set Reference to bz28235.
bzimport added a subscriber: Unknown Object (MLST).

Confirmed. We will need to patch WebRequest::isPathInfoBad().

Created attachment 8381
Proposed fix

attachment ie6-percent-2e.patch ignored as obsolete

The proposed fix denies access to vulnerable entry points if the request URL has %2E or %2e anywhere in the path part of the URL, i.e. before the first question mark.

Here is a detailed summary for our users to read after this bug is made public:

MediaWiki has several modules (action=raw, api.php, load.php) which provide access to arbitrary non-HTML content. This content is dangerous if the browser interprets it as HTML. MediaWiki sends a Content-Type header, which is sufficient to prevent a security breach in standards-compliant browsers. However, Internet Explorer ignores this header if it thinks that the file name in the URL it is requesting has a .html extension.

For example, in a URL like:

http://example.com/index.php/x.html

In most webservers, this will invoke index.php with PATH_INFO set to /x.html. Because of the .html extension, Internet Explorer will interpret the response as HTML regardless of its headers, so MediaWiki checks PATH_INFO for such a file extension, and denies the request if it is present.

Masato Kinugawa's discovery is that with a URL like:

http://example.com/index%2Ephp?.html

When the dot in the script name is encoded as %2E, IE 6 erroneously searches for the end of the file path in the query string of the URL, that is, the part after the question mark. So this URL is interpreted as HTML regardless of the response.

I have confirmed that this bug is not present in IE 7 and later. Because the query string may legitimately end in .html, we would prefer not to blacklist this string just to protect IE 6 users.

The CGI specification does not provide a standard method to detect an improperly encoded script name. In Apache, it is possible to use the REQUEST_URI variable. In IIS, HTTP_X_ORIGINAL_URL may work; this is untested at present. Our patch scans REQUEST_URI and HTTP_X_ORIGINAL_URL for %2E, in order to determine if the file extension has been obscured. If %2E is present, the request is denied.

It is difficult to know whether this patch would fix the issue in all webservers. If you are using MediaWiki with a webserver other than Apache, we recommend that you configure your webserver to deny access to URLs with %2E or %2e in the path part of the URL.

For users using Internet Explorer 6, we recommend that you upgrade to a more secure browser.

Further testing indicates that the patch I proposed is not sufficient. You don't need to have %2E in the path to exploit it, since there are some things you can request that don't have a dot in them, like the /wiki alias. Checking QUERY_STRING would be sufficient, but it would have to be done on static file uploads as well as api.php etc. So it can't be comprehensively fixed by patching MediaWiki only, we would need to patch or reconfigure our static file webservers also.

The issue also affects the mobile service (*.m.wikipedia.org).

Reverse engineering of IE 6 suggests a possible non-disruptive solution.

The problem appears to be that the cache filename extension is used to derive the content type, overriding the Content-Type header. The cache filename is determined by HTTP_REQUEST_HANDLE_OBJECT::FHttpBeginCacheWrite(), which calls GetFileExtensionFromUrl(), which has the undesired behaviour in it.

But FHttpBeginCacheWrite() first checks the Content-Disposition header for a "filename" parameter, and if there is one, it uses that for the cache filename. So by sending "Content-Disposition: filename=api.php", we can avoid having to deal with the broken behaviour of GetFileExtensionFromUrl().

I tested it, it seems to work, even with Masato's Content-Disposition override script from bug 27892.

That still leaves static files. I'm going to make a change to the .htaccess we distribute in the images directory, to protect at least some servers.

The problem is not limited to HTML. If you add .exe instead, it will ask you if you want to run the application.

Created attachment 8391
Block suspicious query strings

New proposed patch. I decided to go with QUERY_STRING validation anyway, since some vulnerable entry points were using Content-Disposition for other things.

Attached:

I updated the Squid configuration at Wikimedia to block the same kinds of query strings in upload.wikimedia.org requests.

I fixed *.m.wikipedia.org by changing the apache configuration, since I don't have a test server for Ruby.

If we consider .exe to be "dangerous" seing as IE 6 will ask if you want to run the application, we might as well block .7z, .m4a, and .mp3 :
http://en.m.wikipedia.org/wiki?search=Data.7z
http://en.m.wikipedia.org/wiki?search=Data.m4a
http://en.m.wikipedia.org/wiki?search=Data.mp3

Digits may appear anywhere in a file extension, so the [a-z] class is fundamentally flawed.

I'd recommend switching to \.[a-z0-9]{1,4}$, while keeping the case insensitivity, in img_auth.php, WebRequest.php, and the .htaccess

In reply to comment #10)

If we consider .exe to be "dangerous" seing as IE 6 will ask if you want to run
the application, we might as well block .7z, .m4a, and .mp3 :

Those file formats are not especially dangerous. The reason for allowing numbers is because it's not unusual to append numerical version strings to URLs.

Numerical version strings prefixed by a dot ?
As for dangerosity, how are they less problematic than .html, or .gov (as seen in bug 28510 ) ?
http://en.m.wikipedia.org/wiki?search=Data.gov

.gov is not especially dangerous, but .html allows XSS and so complete account compromise, per the original report. With .7z, the user would have to open the file, uncompress it, and run some dangerous thing inside it. With .html, the user only has to visit an external web page which redirects to the malicious URL, and their wiki user account will be compromised.

Starting a thread on wikitech-l for further discussion of the fix for this; there are still some difficulties from broken requests.

http://lists.wikimedia.org/pipermail/wikitech-l/2011-June/053676.html

yellow.teapot wrote:

Hello, I just started setting up private MediaWiki (v1.17.0) and I was going through the steps to make images not load using direct linking for non-logged in users. I managed to set up img_auth.php to handle the image requests and this worked for the actual image files in /images but thumbnails no longer worked. I kept getting a "Forbidden" error: "Invalid file extension found in the path info or query string.".

After playing around a bit and looking at img_auth.php more closely I noticed that on line 52, right under: "// Check for bug 28235: QUERY_STRING overriding the correct extension", $dotPos was being set to: strpos( $path, '.' ). But thumbnail URLs include the file extension in the thumbnail images folder name (as well as the file extension of the files themselves). strpos would therefore return the position of the wrong dot.

Changing strpos to strrpos fixed this and I can now access thumbnails via img_auth.php.

I'm not sure if this has been fixed already nor how to fix it myself (if that's even possible) so I though I'd let someone know. It could also be that I configured something else wrong and this is a hack...

(In reply to comment #15)

I'm not sure if this has been fixed already nor how to fix it myself (if that's
even possible) so I though I'd let someone know. It could also be that I
configured something else wrong and this is a hack...

In theory you would do so by submitting a patch, but since it's literally one character, that's not really needed :)

This issue has already been fixed in trunk in r91153, mentioning a different bug (bug 29531).

s.vanslyck wrote:

I was a new installer of 1.19 recently and using the new .htaccess file is still part of the download.

I think it should prolly be changed to remove the last two lines of the file

Options -Indexes

I was able to leave the IfModule ReWrite rules in place (I trust they do something important):

  1. Protect against bug 28235
  2. <IfModule rewrite_module>
  3. RewriteEngine On
  4. RewriteCond %{QUERY_STRING} \.[^\\/:*?\x22<>|%]+(#|\?|$) [nocase]
  5. RewriteRule . - [forbidden]
  6. </IfModule>

but the rest of the file I had to comment out to get things to work:

  1. Serve HTML as plaintext, don't execute SHTML
  2. AddType text/plain .html .htm .shtml .php
  1. No php execution in the upload area
  2. php_admin_flag engine off

s.vanslyck wrote:

Ahem. I messed up my previous comment. My working .htaccess file is now:

Options -Indexes
<IfModule rewrite_module>

RewriteEngine On
RewriteCond %{QUERY_STRING} \.[^\\/:*?\x22<>|%]+(#|\?|$) [nocase]
RewriteRule . - [forbidden]

</IfModule>

I had to remove everything else.