Cross site scripting: an old-new threat

Developers
Testers
Web

With everything on the Web driven by JavaScript, understanding cross site scripting (XSS) vulnerabilities is critical.

Cross site scripting (XSS) is a major vulnerability that all security experts are familiar with. It is a type of injection targeting web applications, or applications that use a browser as part of their client. Basically, the attacker injects JavaScript (or other malicious active content) into the page displayed to the user. When this active content executes, it can steal the user’s data, do actions in the user’s name, and in general compromise all interaction between the user and the web app.

Cross-site scripting is unusual among web vulnerabilities in that it targets the client instead of the web application itself.

According to NIST’s NVD, cross site scripting or XSS is the single most common vulnerability. It makes up ~12% of all vulnerabilities since 2008 by itself – total, not just in web applications! – and the ratio is increasing.

Cross site scripting has had a spot on the OWASP Top Ten since its inception, though it is not as stable as Injection. Starting off at #4 in 2003-2004, it catapulted to #1 in 2007, #2 in 2010, #3 in 2013, and finally #7 in 2017. Due to its high incidence rate, it is all but guaranteed to stay on the Top Ten, but there are some factors in its significant drop that are worth investigating.

2*2 is sometimes 3, but it’s really just 2

First, let’s take a look at what the various types of cross site scripting are and how they work.

The commonly used classification of cross site scripting (from 2005, as per Amit Klein from WASC) differentiates between three subtypes depending on the source and destination (sink) of the attack string:

    • DOM-based (Type 0): Client side code – typically JavaScript – inserts user input into the DOM as HTML.

DOM-based cross site scripting

    • Persistent (Type I): The web server stores user input (typically in a database). On a later request, it reads the stored data and inserts it into the page as HTML.

persistent or stored cross site scripting

    • Reflected (Type II): The web server parses user input from the request. It then immediately returns it – ‘reflected’ – verbatim to the user in the response as HTML.

reflected cross site scripting

As web technologies evolved and more and more functionality could be done on the client side of a web app (even data storage), it became apparent that ‘DOM-based cross site scripting’ was no longer enough to cover all possibilities involving client-side JavaScript code. OWASP redefined the categories in 2012 as a 2×2 matrix with Stored/Reflected on one side, and Server/Client on the other:

  • Server XSS: The server includes untrusted data (received directly or taken from a persistent storage) in the HTML.
  • Client XSS: The client adds untrusted data (received from the server) to the DOM with JavaScript.

The main distinction between the server/client is where the malicious user input interacts with the logic used to generate or render the page, and what the developer can use to prevent the cross site scripting vulnerability.

The more cross site scripting changes, the more it stays the same

Cross site scripting exploitation has undergone a lot of evolution since the early 1990s, with new techniques in the context of AJAX, HTML5 functionality, and even CSS3. On the other hand, the core cause of the vulnerability and its prevention has basically not changed.

Regardless of subtype, cross site scripting prevention is simple in concept: escape all untrusted input before putting it into the page (depending on context). In addition, templates can help against server-side cross site scripting and safe JavaScript DOM-manipulating methods such as textContent can help against client-side cross site scripting. Also see the excellent OWASP XSS Prevention Cheat Sheet and DOM-based XSS Prevention Cheat Sheet, respectively. There are also numerous mitigation features built into modern browsers, such as the Content Security Policy HTTP header.


testing cross site scriptinghttps://twitter.com/joernchen/status/1086237923652046849

Which brings us to the good news: the increased popularity of auto-escaping frameworks such as Angular / React / Razor / Jinja2 is directly responsible for cross site scripting being a much lower-risk vulnerability today than it was in 2004, which also explains why it only got 7th place in the OWASP Top Ten 2017. It is still possible to use user input in a vulnerable manner in those frameworks, but at least it takes deliberate effort now!