Last modified: 2014-04-18 14:23:33 UTC

Wikimedia Bugzilla is closed!

Wikimedia has migrated from Bugzilla to Phabricator. Bug reports should be created and updated in Wikimedia Phabricator instead. Please create an account in Phabricator and add your Bugzilla email address to it.
Wikimedia Bugzilla is read-only. If you try to edit or create any bug report in Bugzilla you will be shown an intentional error message.
In order to access the Phabricator task corresponding to a Bugzilla report, just remove "static-" from its URL.
You could still run searches in Bugzilla or access your list of votes but bug reports will obviously not be up-to-date in Bugzilla.
Bug 28235 - XSS: IE6 looks for the file extension in the query string
XSS: IE6 looks for the file extension in the query string
Product: MediaWiki
Classification: Unclassified
General/Unknown (Other open bugs)
All All
: Normal normal (vote)
: ---
Assigned To: Nobody - You can work on this!
Depends on:
  Show dependency treegraph
Reported: 2011-03-25 14:05 UTC by Masato Kinugawa
Modified: 2014-04-18 14:23 UTC (History)
11 users (show)

See Also:
Web browser: ---
Mobile Platform: ---
Assignee Huggle Beta Tester: ---

Proposed fix (1.03 KB, patch)
2011-04-06 12:49 UTC, Tim Starling
Block suspicious query strings (4.31 KB, patch)
2011-04-11 05:02 UTC, Tim Starling

Description Masato Kinugawa 2011-03-25 14:05:01 UTC
I found XSS vulnerability in MediaWiki.
I tested on Internet Explorer 6.

URL: onload=alert(1)%3E.html
Comment 1 Tim Starling 2011-03-28 02:02:06 UTC
Confirmed. We will need to patch WebRequest::isPathInfoBad().
Comment 2 Tim Starling 2011-04-06 12:49:00 UTC
Created attachment 8381 [details]
Proposed fix
Comment 3 Tim Starling 2011-04-06 12:52:01 UTC
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.
Comment 4 Tim Starling 2011-04-07 02:42:26 UTC
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:

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:

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.
Comment 5 Tim Starling 2011-04-07 06:49:47 UTC
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 (*
Comment 6 Tim Starling 2011-04-08 06:24:39 UTC
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.
Comment 7 Tim Starling 2011-04-11 05:02:17 UTC
Created attachment 8391 [details]
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.
Comment 8 Tim Starling 2011-04-11 05:19:27 UTC
I updated the Squid configuration at Wikimedia to block the same kinds of query strings in requests.
Comment 9 Tim Starling 2011-04-12 00:48:30 UTC
I fixed * by changing the apache configuration, since I don't have a test server for Ruby.
Comment 10 Alphos 2011-04-13 04:39:30 UTC
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 :

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
Comment 11 Tim Starling 2011-04-13 04:46:25 UTC
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.
Comment 12 Alphos 2011-04-13 04:52:46 UTC
Numerical version strings prefixed by a dot ?
As for dangerosity, how are they less problematic than .html, or .gov (as seen in bug 28510 ) ?
Comment 13 Tim Starling 2011-04-13 05:05:12 UTC
.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.
Comment 14 Brion Vibber 2011-06-02 20:59:19 UTC
Starting a thread on wikitech-l for further discussion of the fix for this; there are still some difficulties from broken requests.
Comment 15 Damian 2011-11-11 03:58:12 UTC
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...
Comment 16 Roan Kattouw 2011-11-11 12:50:29 UTC
(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).
Comment 17 Steve 2013-01-22 02:10:33 UTC
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):

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

but the rest of the file I had to comment out to get things to work:
# Serve HTML as plaintext, don't execute SHTML
# AddType text/plain .html .htm .shtml .php
# No php execution in the upload area
# php_admin_flag engine off
Comment 18 Steve 2013-01-22 02:12:54 UTC
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]

I had to remove everything else.

Note You need to log in before you can comment on or make changes to this bug.