Cross-Site Scripting in WordPress: Practical Tips for Securing Your Site
In this series, we’re taking a look at how to secure our WordPress projects from XSS – or cross-site scripting. In the first article in the series, we defined what cross-site scripting actually is, understanding how it works, and why it’s dangerous.
We also spent some time discussing how this impacts our day-to-day WordPress development efforts and what we can do about it. Although there are some functions that WordPress has available to help validate and sanitize data, there is more work that we can do in order to secure our projects.
In this final article, we’re going to take a look at some practical tips that we can follow and some tests that we can administer to secure our work against XSS attacks.
The Basics of Testing XSS
Generally speaking, the way that you go about testing your site for cross-site script vulnerabilities is to find anywhere in the site or application that accepts user input.
Obviously, this will come in the form of input fields, textareas, or the like.
If the site does not perform proper sanitization and/or validation, then you will normally be successful in finding exploits; however, if the site is properly managing incoming data, then you’ll likely see no result for your efforts.
Let’s take a look at several cases that we can administer on our own sites (or even others, though do that at your own risk!).
1. Locating a Cross-Site Scripting Vulnerability
One of the first things that we can do in order to locate a vulnerability is attempt to inject some code that will determine whether or not a vulnerability exists.
The code in question is as follows:
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//"; alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//-- >">'>
Place this code in any input field and submit it.
If a vulnerability does exist, then the word “XSS” will be output. If it’s not returned, then you’re likely safe (though this can’t be 100% guaranteed); however, if it is output, then this likely means a vulnerability exists that you – or someone more malicious – is able to exploit.
2. Attempting Cross-Site
In the last article, we discussed the same-origin policy which basically dictates that a site should not be able to request assets from any domain other than the one on which it currently resides.
To attempt to execute code from a remote server – or a server that is not part of the same-origin – you can execute the following code:
Note that the prefix for the test case is not a typo. It’s required in order to actually test the vulnerability. If a vulnerability actually exists, then a browser cookie from the remote domain will be displayed; otherwise, you’ll either see nothing or your console may return a message about the same-origin policy.
Props to Janne for this particular tactic.
3. Image Attributes
For example, creating an element such as:
Would reveal a vulnerability that would actually display an alert dialog with ‘XSS’ as the message rather than an actual broken image.
Simple, isn’t it? Nonetheless, it only takes one vulnerability to expose an exploit.
A Wiki of Attacks
The thing is, this is just the tip of the iceberg as it relates to XSS testing. In fact, it would take an entire wiki to help document the various vulnerabilities that are out there.
In fact, that’s exactly what the Open Web Application Security project has aimed to do: document the various XSS vulnerabilities that exist and how to test for them. You can visit the entire list, see the definition of the attacks, as well as how to administer them.
But that’s not all! As newer technologies arise – such as HTML5 – there are plenty of additional things that we should take into consideration.
Though it may seem a bit odd that a markup language could be susceptible to cross-site scripting attacks, it makes sense especially considering some of the attributes that the newer elements allow.
Case in point:
- Form elements support a
- Input elements support an
- The new video element supports a
Granted, not all of these are applicable to each browser, but they’re important to know so that you can properly test in the relevant browsers.
That said, you can find a comprehensive HTML5 cheat sheet of known vulnerabilities and the relevant browsers at the HTML5 security site.
Simply put, aside from offering a dictionary of known vulnerabilities, their calculator will automatically encode your XSS into several different encoding types such as Hex, decimal, Base64, and so on so that you can also attempt to inject those translations into your application.
After all, half of security is making sure that all types of input is properly sanitized, escaped, and validated – not just the base case.
Obviously, the cross-site scripting field is rich with vulnerabilities that aren’t limited to a single browser, let alone a single browser version. Luckily, there are plenty of resources, cheat sheets, how tos, and other educational material at our disposable not only to keep us aware of what’s out there, but how we can defensively program against it.
And although this article is specifically geared towards us WordPress developers, the tactics and techniques transcend WordPress and are applicable to anyone that’s building web applications.
Finally, I’d like to offer a word of thanks to Janne Ahlberg for inspiring the content of this series. He’s a security specialist who does a lot of XSS work that he reports to Envato, so if you’re interested in this topic especially as it relates to promoting your work on one of the Envato marketplaces, I highly recommend following his blog.