When we discuss vulnerabilities in applications, there are different categories that we come across. Some vulnerabilities are extremely common yet allow for little or no damage should an attacker discover and exploit them, while others are incredibly rare but can have major, lasting impact on the organizations behind the attacked application. Then, there’s the third category: Common and deadly. Cross-Site Scripting, commonly shortened to XSS, is one of the most common vulnerabilities found in applications, and can cause serious damage given the right time and the right attacker.
XSS vulnerabilities are common enough to have graced applications as big and popular as Facebook, Google, and PayPal, and XSS has been a mainstay on the OWASP Top 10 list since its inception. XSS vulnerabilities are especially dangerous because an attacker exploiting an XSS attack can gain the ability to do whatever the user can do, and to see what the user sees – including passwords, payment and financial information, and more. Worse – the victims, both the user and the vulnerable application, often won’t be aware they’re being attacked.
XSS vulnerabilities are difficult to prevent simply because there are so many vectors where an XSS attack can be used in most applications. In addition, whereas other vulnerabilities, such as SQL injection or OS command injection, XSS only affects the user of the website, making them more difficult to catch and even harder to fix. Also unlike SQL injection, which can be eliminated with the proper use of prepared statements, there’s no single standard or strategy to preventing cross-site scripting attacks.
There are two main types of cross-site scripting attacks: Stored (or persistent) XSS, which is when malicious script is injected directly into the vulnerable application, and reflected XSS, which involves ‘reflecting’ malicious script into a link on a page, which will activate the attack once the link has been clicked.
Read more about the anatomy of an XSS attack here.
Preventing XSS: 3 Ways to Keep Cross-Site Scripting Out of Your Apps
So, now that we understand a bit more about what cross-site scripting attacks are and how damaging they can be to your application, let’s dive into the best known practices in preventing them in the first place.
The first method you can and should use to prevent XSS vulnerabilities from appearing in your applications is by escaping user input. Escaping data means taking the data an application has received and ensuring it’s secure before rendering it for the end user. By escaping user input, key characters in the data received by a web page will be prevented from being interpreted in any malicious way. In essence, you’re censoring the data your web page receives in a way that will disallow the characters – especially < and > characters – from being rendered, which otherwise could cause harm to the application and/or users.
2. Validating Input
As Troy Hunt so eloquently puts it: “The theory goes like this: Expect any untrusted data to be malicious. What’s untrusted data? Anything that originates from outside the system and you don’t have absolute control over so that includes form data, query strings, cookies, other request headers, data from other systems (i.e. from web services) and basically anything that you can’t be 100% confident doesn’t contain evil things.”
Validating input is the process of ensuring an application is rendering the correct data and preventing malicious data from doing harm to the site, database, and users. While whitelisting and input validation are more commonly associated with SQL injection, they can also be used as an additional method of prevention for XSS. Whereas blacklisting, or disallowing certain, predetermined characters in user input, disallows only known bad characters, whitelisting only allows known good characters and is a better method for preventing XSS attacks as well as others.
Input validation is especially helpful and good at preventing XSS in forms, as it prevents a user from adding special characters into the fields, instead refusing the request. However, as OWASP maintains, input validation is not a primary prevention method for vulnerabilities such as XSS and SQL injection, but instead helps to reduce the effects should an attacker discover such a vulnerability.
A third way to prevent cross-site scripting attacks is to sanitize user input. Sanitizing data is a strong defense, but should not be used alone to battle XSS attacks. It’s totally possible you’ll find the need to use all three methods of prevention in working towards a more secure application. Sanitizing user input is especially helpful on sites that allow HTML markup, to ensure data received can do no harm to users as well as your database by scrubbing the data clean of potentially harmful markup, changing unacceptable user input to an acceptable format.
While using layers of security, such as the methods above, is a great way to helm the majority of XSS attacks, it’s important to remember that while the above prevention methods will cover most XSS attack vectors, they won’t cover everything. In order to be truly vigilant against XSS and other common, debilitating vulnerabilities, like the rest of the OWASP Top 10, it’s important to use a mix of code review, automated static testing during development and dynamic testing once the application is live, in addition, of course, to using secure coding practices that will help prevent vulnerabilities like cross-site scripting in the first place.
- OWASP XSS Prevention Cheat Sheet
- OWASP XSS Filter Evasion Cheat Sheet
- Understanding XSS on Troy Hunt’s blog