How to Increase Security Against XSS Attacks

Published on November 21, 2014, by Brian


Last week I covered the general idea behind Cross-site Scripting (XSS), and this week I am going to get a little deeper into how you can prevent it happening to your web app or site. There are a number of tactics you can use to make your project a less attractive target, and even though it’s probably impossible to have a complex user app and be totally immune to XSS, you can at least be more difficult than the next guy. This gives you the added advantage of sending wannabe hackers towards easier pickings.

First things first though, you have to test things and see what state your project is in. You can start by using a vulnerability scanner, and there is a long list of them available here. Any one of those will crawl your site, and like a benign criminal let you know where all the open doors and windows are. Usually, they will also give you are list of the links which are the main potential targets and throw in a check for SQL injection issues as well.

Overview

Once you get your report card, the next step in prevention is confining potential injections to a limited number of places. Once you have identified the safe and potentially unsafe areas, it is time to set about hardening those at risk with some basic precautions. There are six main tactics to employ here:

  • Escaping Strings
  • Sufficient Validation
  • Sanitization
  • Code Quality
  • Web Application firewalls
  • Content Security Policy

Escaping Strings

Escaping strings coming from untrusted sources allows you to neutralize many basic XSS injections. In the following examples, escaping the most common code characters to plain-text will help cut down the number of scripts that can be executed on a page. For a full run down on how much more there is to HTML escaping, read this blog, where he does say:

“If I had a dollar for every HTML escaper that only escapes &, <, >, and “, I’d have $0. Because my account would’ve been pwned via XSS.”

  • &lt; (<)
  • &gt; (>)
  • &amp; (&)
  • &quot; (“)
  • &#x2F; (/)

You can now see why I added &#x2F; (/), as I wouldn’t like to lose a dollar over a silly error like that!

Sanitize Content

To sanitize content means that you accept input from untrusted sources and filter it to prevent XSS scripts from executing. This allows web applications to safely use rich text editors, and display HTML input. There are a number of different libraries available for this task and they are relatively easy to implement.

The following example shows the Python bleach sanitizer being imported and checking a suspicious-package script.

&gt;&gt;&gt; import bleach
&gt;&gt;&gt; bleach.clean('a &lt; /script&gt;suspicious-package()&lt;/script&gt; example')
u'an &lt;script&gt;suspicious-package()&lt; /script&gt; example'
&gt;&gt;&gt; bleach.linkify('an http://example.com url') u'an <a href="http://example.com" rel="nofollow">http://example.com</a> url

URL Validation

You should always validate URLs to ensure they do not result in script execution when the page loaded. But before you begin there are a number of best practices you can implement before you start the validation of URLs.

  1. Avoid using redirects and forwards
  2. Disable user input URLs
  3. Create a whitelist of trusted URLs which can be input
  4. Force all redirects to notify users of a redirect
  5. If user input is unavoidable, validate the URLs

To validate URLs you can use a regex to check the format in which they are input. The following examples are potentially dangerous redirects as they could be grabbing from an untrusted location when they are executed. In this Java code example, the URL from the "url" GET parameter is grabbed and then the browser is redirected to whatever link it just received.

response.sendRedirect(request.getParameter("url"));

In this PHP code example, a URL from the query string is grabbed and then redirects the browser.

$redirect_url = $_GET['url']; header("Location: " . $redirect_url);

By checking for redirects that follow unusual patterns such as these you can make it more likely that you catch any attempt at XSS on your site. For more examples see the OWASP Cheat Sheet

Code Quality

Software can be designed to isolate potential areas of XSS injection to a small fraction of the code base. This makes it realistic to deeply review the security needs of those more open areas and to test the application with as many XSS bugs as you can throw at it until you have hardened it to a very high standard. The value of this approach is that it scales to very large complex projects because you only need to focus on certain elements.

While implementing this, and also the above measures can help, it is obviously important that when you try to do it you get it right. This is were code quality and code review come into play. I’ve written about that in the past if you want to read more. When focusing on improving code quality for XSS though, the following factors are important:

  • You need to ensure developers never write application code that directly calls potentially injection-prone areas
  • If possible you should always use the API
  • You need to ensure that unchecked conversions are designed to be easily reviewed and checked

Web Application Firewall

One of the best ways to prevent XSS attacks is to use a web application firewall (WAF). This is usually a proxy-server or reverse-proxy firewall that applies a set of rules to HTTP requests that occur with your web app or site. There are a number of tools that can be used for this, and you can see a comprehensive list here. The difficulty with implementing a WAF though, is that you need to set up and configure the rules that are specific to your site and the content you are willing to accept being input. Once configured, these rules need to be kept up to date as your product evolves. So while this is a great way to prevent XSS attacks, it does add an additional level of maintenance to your release cycle.

Content Security Policy

A Content Security Policy is a relatively new concept when it comes to XSS prevention, first introduced in 2012. Essentially what it does is allow you to declare approved sources of content that browsers will execute when the page loads. All content not flagged as safe will not be run. For a more complete explanation, see the Content Security Policy quick reference guide.

Conclusion

I have bitten off more than I can chew. XSS is a huge area and I’m going to take some times researching it before another blog appears on the topic. But the signals I am getting from the topic is that it is vital for web apps and interactive websites to plan XSS containment into their development cycle and to take steps to minimize the impact of a potential XSS security vulnerability compromising their systems, reputation, and customer data.