Last week I promised to follow up on a few XSS bugs that I found in WordPress. The vulnerabilities are fixed in WordPress 2.0.3, even though the release notes do not mention their existence. I think there are a number of useful lessons that can be drawn from them, so in this post I will describe some more details.
The first was not particularly interesting but still was effective. The confirmation dialog code occurred in many places, but one had simply omitted any input sanitisation on author names. A new HTML tag (e.g.
<script>) could not be added because < and > were escaped as < and >, but the attribute could be closed, with double quotes, and a new one added. In my test I used an
wp_specialchars() which in this respect behaves the same way.
Within seconds of the unlucky admin deleting what appears to be a spam trackback the server is 0wned. Note that to attack the webserver I needed another webserver so by combining the two components you can create a self replicating exploit. There has been a PHP worm before, but I don’t know of any XSS based ones. It would require user interaction, but the social engineering technique, of requiring a victim to delete spam, is perfect. Google could be used to find new blogs to infect, but this introduces a single point of failure. Instead the blog roll feature permits decentralised propagation.
So what can be done to mitigate against such attacks? I think the double-unescaping problem is a further indictment against the technique of removing invalid input. Instead, all input should be considered evil until proven otherwise. Rather than escaping suspect characters, a safer option is to specify what is valid and anything deviating from this is rejected. Or if possible, don’t insert user input into HTML at all, as WordPress have started to do. WordPress could have also enabled HttpOnly cookies, which would have protected users running Microsoft browsers, but not Mozilla/Firefox.
However even with careful design XSS vulnerabilities seem to be inevitable, so steps should be taken to mitigate the damage. In the case of WordPress the theme editor allows XSS to be escalated into arbitrary PHP injection. In my opinion requiring an admin to re-enter the password before editing files would improve resilience against XSS, but cause little interference.
Finally, I you haven’t already upgraded to WordPress 2.0.3 then now would be a good time to do it. If for some reason you can’t, then disabling comments, trackbacks and pingbacks would be an appropriate stop-gap measure.
A description of the second WordPress vulnerability I found will follow next week