Category Archives: security

Blogposts on blog.futtta.be about IT- and more specifically web application security (e.g. about some dangers in PHP, xss, …)

Dude, where’s my WordPress session?

WordPress is a favourite hackers target. Some say that is because it is inherently insecure, but in reality WordPress is mainly a target because of its popularity, because of people not keeping their installations up to date or using easy to guess usernames and passwords and because of vulnerabilities in plugins rather then WordPress itself.

There is, however, one security-related shortcoming in WordPress from a design point of view: sessions are not stored server-side. If someone logs in, a cookie is set in the browser containing username, a session expiration timestamp and a hash. With every new request to WordPress that cookie (and specifically the hash) is checked to validate the session, but there is no check to see if there indeed was such a session.

This can be considered mainly a theoretical shortcoming, not an immediately exploitable vulnerability, because;

  1. session-cookies are set with the HTTPOnly-flag so XSS should not be an issue
  2. in an ideal world all traffic, once logged in, would be over HTTPS, securing against network sniffing.

But there are other (albeit less obvious) ways to steal cookies or even create create new ones to gain unauthorized access, as demonstrated in this very detailed blogpost. As explained in that article, there is no way to block “fake” session-cookies from gaining access (your OTP plugin won’t protect you either) and there is no functionality to monitor and if needed delete sessions.

So … I wrote a small proof-of-concept plugin that gets triggered upon login, logout and upon session verification (i.e. each request) and which stores sessions server-side, automatically logging out unknown sessions. With that in place, lots of other optional features could easily be added;

  • display a list of all known current sessions
  • allow one or more sessions to be removed
  • compare IP address at session verification against the one at session creation and notify or logout if no match
  • compare User Agent (and optionally some HTTP accept-headers) at session verification against the one at session creation and notify or logout if no match
  • create an audit log

But … I don’t want to do this on my own. I have 3 plugins already, 2 of which are semi-popular and for which I try to do regular releases and provide great support (and I have a daytime-job and a wife and daughter with whom I love to spend quality time as well). Moreover I really don’t want the plugin to “just” be open source, but I want it to be developed in an open source, collaborative manner as well.

So if you’re a WordPress coder, a security consultant or just an innocent passer-by and you are willing to code, review code, translate or document, then do drop me a line. Fame (but not fortune) will be yours!

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.

On WordPress GET floods, plugin fingerprinting & keeping safe

flood sign, by alan in belfast from flickr under ccInfosec consultant and blogger Xavier Mertens suffered from a GET flood last week. The would-be DDOS originated from WordPress blogs that seemed non-related both geographically and content-wise, were using different versions of WordPress and seemed not to be compromised.

So what gives? WordPress blogs autonomously trying to DDOS other WordPress blogs? My best guess; a WordPress plugin gone rogue. The great WordPress HTTP API makes It easy enough to create a plugin that fetches targets from a control server and issues requests to those targets at a given time. It’s only a matter of hiding that behavior inside a plugin that seems useful and getting people to install that. The easiest way; finding an older plugin with an existing userbase and taking over development from the original developer (as i did with Autoptimize) is the easiest route to create your own little DDOS-ing botnet.

But all of this is pure speculation (although the UA matches the one used by WordPress HTTP API) off course. The only way to know for sure is to, for at least a sample of the flooding blogs, check what plugins they have in common. Doing so is frightfully easy using the NMAP HTTP WordPress Pugins script and if I am not mistaking Xavier is indeed looking into this.

But given the ease with which the NMAP-script can scan for WordPress plugins (there are similar scripts for e.g. Drupal modules), you might want to stop this from happening? I for one added this line in my WordPress .htaccess:

RedirectMatch 404 ^/wp-content/plugins/[^\/]*/$

Maybe you would even want to return a 404 for plugin readme.txt and index.html files as well, but I’ll consider that an assignment for you guys to chew over ;-)

And now you can even have my WordPress password!

Being slightly obsessed with security, I was delighted to discover that two factor-authentication (OTP) using Google Authenticator client is not restricted to Google applications, but is fully standardized and as such can be implemented without dependency on Google services on any system. There is code (off course varying in quality and scope) available for PHP, .NET, Java and Python (and I’m sure there are others).

As you might expect after reading the title, there is a great Google Authenticator WordPress plugin which I installed in 5 minutes time earlier today. For the Drupal-heads; Antwerp-based Attiks have a module that implements Google Authenticator OTP which looks worth checking out as well (and I’m interested in your experiences with it, actually).

Learning from my Apache/ CDN mistakes

Earlier this year I configured this here little blog to offload static resources to MaxCDN. I made some mistakes in the process, which I documented in a blogpost that has been in my drafts for too long. So here’s the gist;

  1. Etags misconfiguration:
    • Problem: By default Apache uses the file’s inode to calculate the Etag, but that inode is unknown to the CDN, so Etags can never match.
    • Solution: change the Apache config not to use inode, e.g. “FileETag MTime Size”
  2. Cookies & domains issues:
    • Problem: I created my CDN-domain as a sub-domain of my main one, which led to (small) performance and (potentially huge) security issues.
    • Solution: Make sure your CDN-domain is different from the domain on which your cookies are set. So for example for main domain blog.futtta.be don’t use static-cdn.blog.futtta.be, but rather blog-cdn.futtta.be (except if cookies would be set on futtta.be, in which case I would need cdn-futtta.be).
    • Todo: it might make sense to add some Apache magic to make sure that for requests from the CDN: