WP Caching plugin vulnerability debrief

Now that both WP Super Cache and W3 Total Cache developers have released a new version of their respective plugins (upgrade first, continue reading after) it seems time for a small “post mortem“.
The problem was in the interpretation of dynamic snippets, that are contained inside a number of specific HTML-comment tags. These snippets allow both plugins (and their predecessor WP Cache) to cache pages while keeping a limited amount of dynamic, PHP-generated content in them that can be executed on the fly. Think ESI in e.g. Varnish.
The vulnerability, which was originally discovered by kisscsaby and reported 3 weeks ago on the wordpress.org plugins support forum, had multiple causes:

  1. Unlike ESI’s, dynamic snippets can not only be includes (mclude) but also PHP-code (mfunc). Whereas one could consider includes of known files more or less safe, inclusion of PHP-code introduces a risk.
  2. As WP Super Cache & W3 Total Cache keep entire pages in cache and as pages can contain comments, that user generated content is parsed for dynamic snippets as well.
  3. WordPress core by default only allows a limited set of HTML in comments (“a blockquote code em strong ul ol li”), but it also leaves HTML comments in place.

As a result, blogs with WP Super Cache (before version 1.3) and W3 Total Cache (before version 0.9.2.9) were at risk of PHP code injection. Blog comments could contain dynamic snippets (in HTML-comments) and WordPress core did not them filter out. Upon a such a malicious comment having been submitted, a new cached version of the page was created that included the injected PHP-code. Upon the first request of the cached page, that code was successfully executed.
I stumbled on the vulnerability report about a week and a half ago, while researching why dynamic snippets weren’t executing when Autoptimize was active (simple really, Autoptimize by default removes HTML comments, the upcoming 1.6.3 will leave mfunc/mclude in place). As this seemed like a pretty severe security hole and as there was no feedback from developers in the support thread, I created a small “stopgap plugin” to mitigate the threat on April 10th, mailed security@wordpress.org and plugins@wordpress.org and requested WP Safer Cache being published on wordpress.org on the 11th. A couple of hours later WP Super Cache’s Donncha O Caoimh contacted me and the same day he released a version (1.3) that fixed this vulnerability by parsing out potential exploits from comments as they are posted and as they are rendered. On April 12th W3 Total Cache’s Frederick Townes confirmed they were working on a fix. Version 0.9.2.9 got released on April 17th, disabling dynamic snippets by default and when these are enabled, they require a secret alphanumeric key to be included in the snippet which is checked against one that is defined in wp-config.php.
Conclusions; The fact that this didn’t generate any fuss (as opposed to W3 Total Cache’s widely published information disclosure vulnerability in December 2012) is surprising. PHP Code injection clearly is a more severe security risk that must have been there for a long time already. The fact that this only got discovered recently is baffling. And why WordPress core doesn’t filter out HTML-comments from submitted blog comments, others seem to understand, but to me that remains the biggest mystery of all.

WP Safer Cache: stopgap for WordPress Cache plugins vulnerability

[UPDATE April 18th 2013: this vulnerability has been fixed in both WP Super Cache and W3 Total Cache. You can find more information in this “post mortem” blogpost]
[UPDATE April 11th to reflect that WP Super Cache version 1.3 fixed this issue]
There was a pretty severe vulnerability in WordPress installations that had WP Super Cache (until version 1.2, 1.3 fixed this issue) or W3 Total Cache (up until version 0.9.2.8) plugins activated. This security bug would, under certain circumstances, allow attackers to inject and execute arbitrary PHP code in comments.
The vulnerability could have been handled in WordPress core or in WP Super Cache and W3 Total Cache separately (with my preference being a fix in  comment sanitization in core). On April 11th WP Super Cache version 1.3 was released, fixing this issue and W3 Total Cache released a fix on April 18th. If you are on an older version of WP Super Cache or W3 Total Cache (do upgrade!), you might be interested in installing this little plugin that cleans out malicious … stuff from comments being posted.
As always; comments, bugs & improvements are welcome in the comment-field below or via the contact form.

iGoogle Facebook gadget security flaw fixed & explained

I just received confirmation from the Google Security Team that the bug I discovered in the iGoogle Facebook Gadget which allowed attackers to log into an other user’s Facebook account bypassing all authentication, has been fixed. So now that the hole has been closed, let’s look at what was happening, shall we?
The gadget uses the Facebook’s Javascript API to the connect with Facebook, asking you for permission to access your FB data. In the process of getting that authorization, the gadget exchanges tokens with Facebook, some of which should absolutely be kept safe from prying eyes. And that’s where things went wrong: the gadget had the authentication info in the URL. So if a user of the iGoogle Facebook gadget clicked a link to an external site in the news feed, the request for that page had a referrer that contained all authentication-info.
And that’s exactly what happened on last week, when I spotted this referrer in my blog stats:

http://facebookiggadget.appspot.com/?exp_rpc_js=1&exp_track_js=1&st=c%3Dig%26e%3DAPu7icpJzJJhOouS8TuGegSqFHHI8XHU1r55OllrNbk0ey/aTpkUFx9jPKB/cwgcEZoGfcBuc43x/CuzuEL2cQinYglFvhFWKtlXg6j/JtKC0%252BWsAu3vo/3ZR/WA64J/Fmw1YuUFgT7q&v=fdb2b406636e1f3cff1c5d7e660f59eb&container=ig&view=home&lang=nl&country=BE&up_session=%7B%22uid%22:%221165373488%22, %22session_key%22:%2291d52d2ed5a130fd941b11f1-1175373488%22, %22secret%22:%22fdee68961b3cdee5b51390a4bdeac7a0%22,%22expires%22:0, %22access_token%22:%2283101558C90fd9KfA9KJQh5uT98TqIjxQpzUi4.%22,
%22sig%22:%22dd635ef67af1f59c1c671215076cce10%22%7D
&parent=http://google.be&libs=7ndonz73vUA/lib/liberror_tracker.js,iHKb-4mKuMY/lib/librpc.js,vrFMICQBNJo/lib/libcore.js,a5j4V1JuNVE/lib/libsetprefs.js&is_signedin=1&synd=ig&view=home

You can guess what happened when I opened that URL; the iGoogle Facebook gadget initialized using the embedded credentials, automatically logging me in as the guy that was unlucky enough to have clicked the link to my blog.
But how could this vulnerability have been exploited, you may ask? Well, easy enough; create a page that is viral enough for people to share or like  (likespam or even likejacking) and wait for users of the iGoolge Facebook-gadget (there’s over 1 million of them after all) to follow the links, feeding your webserver logfiles with credential-rich referrers.
As Google confirmed this bug indeed has been fixed. The new version of the gadget, which was deployed late last week, does not leak credentials in the referrer-URL any more:

http://facebookiggadget.appspot.com/?lang=en&country=us&.lang=en&.country=us&synd=ig&mid=101&ifpctok=6472409229927695377&exp_rpc_js=1&exp_track_js=1&exp_ids=17259&parent=http://www.google.com&libs=7ndonz73vUA/lib/liberror_tracker.js,iHKb-4mKuMY/lib/librpc.js,vrFMICQBNJo/lib/libcore.js,a5j4V1JuNVE/lib/libsetprefs.js

So if anyone asks me what my good deed for this year was; I helped protect 1 million people’s Facebook accounts from being hacked.
Sounds swell, no? 😉