W3 Total Cache SSRF vulnerability

W3 Total Cache is a caching plugin with more than a million active installs. Versions prior to 0.9.5 are vulnerable to a server side request forgery (SSRF) attack under default settings. A vulnerable installation can be used as a limited HTTP GET proxy. An attacker could exploit the bug e.g. to access restricted resources on private networks.

Details

W3 Total Cache has a minify functionality that can be configured to optimize JavaScript and CSS delivery. The most common use case is to minify local files. The administrator may also specify a list of remote websites that can be used with the minifier. In this case the minifier PHP script fetches a remote CSS or JavaScript file, optimizes it, caches it on the server, and sends to the user.

The list of allowed remote sites is specified as regular expressions. By default the whitelist only contains one value, “https://ajax.googleapis.com”. The problem is that the value is used as a regular expression without an anchor. Any URL containing the allowed pattern, anywhere in the URL, will pass the test.

For example an attacker could use a URL like http://localhost/server-status#https://ajax.googleapis.com to view a private status report containing potentially sensitive information.

The check happens in the file lib/Minify/Minify/Controller/MinApp.php:

if(preg_match('#'.w3_get_url_regexp($ext).'#',$url) && !$verified){
      $verified = true;
}

The minify script wp-content/plugins/w3-total-cache/pub/minify.php can be used even if minifying is disabled in W3 Total Cache settings. Parameters to the script have to be gzip compressed and base64 encoded – see the PoC below.

Exploit scenarios

The vulnerability can be exploited to retrieve resources on localhost or internal networks.

Another way to exploit is to use the bug with Flash to perform an XSS-like attack. A malicious Flash app loaded through the minifier can send HTTP GET and POST requests to the target host and process the responses. If an administrator views a page embedding such app, this could lead to server-side compromise because the app can pass the WordPress Dashboard CSRF protection. Rosetta Flash is required to prevent the CSS minifier from corrupting the app.

Proof of Concept

This example will retrieve the Google main page through a vulnerable W3 Total Cache minifier.

<?php
$wordpress='https://my.wordpress.site';
$url='http://www.google.com';
$file=strtr(base64_encode(gzdeflate($url.'#https://ajax.googleapis.com')), '+/=', '-_');
$file=chop($file,'=');
$req=$wordpress.'/wp-content/plugins/w3-total-cache/pub/minify.php?file='.$file.'.css';
echo(file_get_contents($req));
?>

Vendor response

W3 Edge was notified on May 25, 2016. The problem was addressed in September 2016. According to the vendor, the allowed URLs list is now empty by default.

Credits

The vulnerability was discovered and researched by Jouko Pynnönen of Klikki Oy, Finland.