Preventing Cross Site Scripting (XSS) attacks is a daunting task for developers. In short, XSS attacks are an injection attack in which data that is structurally significant in the current context changes the intended semantics and/or functionality. While there are great resources online that walk you through prevention techniques (one of the best security resources is The Open Web Application Security Project, or OWASP, website), it’s easy to get confused when you try to implement all of the necessary safeguards.
Below, I’ve outlined four simple steps that significantly lower the risk of XSS attacks against your website. By being a bit more restrictive, we can simplify our approach to preventing XSS in the most common use cases. These steps must all be implemented together, but there’s only four of them, so c’mon, you can do it 🙂
Step 1: Escape Output Provided by Users
If you want to include data within a page that’s been provided by users, escape the output. And, in this simplified list, we’re going to stick with one simple escape operation: HTML encode any <, >, &, ‘, “. For example, PHP provides the htmlspecialchars() function to accomplish this common task.
Step 2: Always Use XHTML
Read through OWASP’s XSS prevention strategies, and it becomes apparent that protecting against injection requires much more effort if you use unquoted attributes in your HTML. In contrast, in quoted attributes, escaping data becomes the same process needed to escape data for content within tags, the escape operation we already outlined above. That’s because the only troublemaker in terms of sneaking in structurally significant content within the context of a quoted attribute is the closing quote.
Obviously, your markup doesn’t have to be XHTML in order to contain quoted attributes. However, shooting for and validating against XHTML makes it easy to test if all of the attributes are quoted.
Step 4: URL-Encode URL Query String Parameters
If user data is output within a URL parameter of a link query string, make sure to URL-encode the data. Again, using PHP as example, you can simply use the urlencode() function. Now, let’s be clear on this and work through a couple examples, as I’ve seen much confusion concerning this particular point.
The following example outputs user data that must be URL-encoded because it is used as a value in the query string.
Must Not URL-Encode
The following example outputs the user-supplied data for the entire URL. In this case, the user data should be escaped with the standard escape function (HTML encode any <, >, &, ‘, “), not URL-encoded. URL-encoding this example would lead to malformed links.
That said, these four steps provide a an approach to defending against XSS that is easily remembered and implemented, covers a broad range of typical website scenarios, and serves as a solid start for developers who are learning how to address basic security concerns.