Last modified: 2014-04-18 14:23:33 UTC
I found XSS vulnerability in MediaWiki. I tested on Internet Explorer 6. URL: http://www.mediawiki.org/w/api%2Ephp?action=query&meta=siteinfo&format=json&siprop=%3Cbody onload=alert(1)%3E.html
Confirmed. We will need to patch WebRequest::isPathInfoBad().
Created attachment 8381 [details] Proposed fix
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 [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.
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
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).
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
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.