What Is Stored XSS (Cross Site Scripting)?
XSS is an attack technique that injects malicious code into vulnerable web applications. Unlike other attacks, this technique does not target the web server itself, but the user’s browser.
Stored XSS is a type of XSS that stores malicious code on the application server. Using stored XSS is only possible if your application is designed to store user input—a classic example is a message board or social media website.
In this article:
- Why Is Stored XSS Dangerous?
- Stored XSS Attack Example
- How to Find and Test for Stored XSS Vulnerabilities
- Stored XSS Prevention
- Stored XSS with Bright
How Does a Stored XSS Attack Work?
A stored XSS attack typically works as follows:
- An attacker injects malicious code in a request to submit content to the application.
- The application believes the request is innocent, processes the user input and stores it in the database.
- From this point onwards, every time the submitted content is displayed to users, the malicious code executes on their browsers.
Depending on the type of payload and the vulnerabilities present in the user’s browser, stored XSS attacks can allow attackers to:
- Hijack the user’s session and perform actions on their behalf
- Steal the user’s credentials
- Hijacking the user’s browser or delivering browser-based exploits
- Obtain sensitive information stored in the user’s account or in their browser
- Port scanning of hosts the web application can connect to
- Website defacement
Why Is Stored XSS Dangerous?
Stored XSS (also known as second-order XSS) is the most dangerous type of cross-site scripting attack. The reason is that it does not require users to click a malicious link or perform any activity, other than browsing to a legitimate web page. Once an attacker discovers a stored XSS vulnerability and injects XSS code into the database, all visitors to affected pages are compromised, until the exploit is discovered.
Stored XSS attacks are even more significant in websites that require authentication. When an authenticated user visits a page with stored XSS, attackers are usually able to hijack their session and perform actions on their behalf. On some websites, such as those of financial or medical institutions, this can result in financial loss or exposure of highly sensitive data.
The most damaging scenario is when the user exposed to stored XSS is a highly privileged user, such as the administrator of the web application or other systems. Attackers may be able to obtain the session authentication token, gaining admin-level access to the network.
While stored XSS attacks are severe, they are also quite rare, because an attacker needs to find a combination of a website with high traffic, which also accepts user inputs, and suffers from an XSS vulnerability.
Stored XSS Attack Example
Consider an attacker browsing a retail website. The attacker notices a vulnerability that allows HTML tags to be included in the comments section, including the
The comment is published on the page and every time the page loads for a visitor, the malicious script runs. In this case, the script is designed to steal a visitor’s session cookie, meaning the attacker can take over a user’s account. This gives them access to credit card and other personal data, and also lets them make purchases on behalf of the user.
What is important to realize is that any visitor who clicks through to a page where this comment appears, even if they don’t scroll down to the comment section, will be affected by the attack without knowing it. This is in contrast to a reflected XSS attack, in which victims must click a malicious link to be affected. This means stored XSS can impact many more website users, including those who are security conscious and careful about clicking unknown links.
See real life examples of attacks in our guide to XSS attacks
How to Find and Test for Stored XSS Vulnerabilities
There are multiple website vulnerability scanners available that can automatically detect stored XSS vulnerabilities. Dynamic Application Security Testing (DAST) tools like Bright go one step further, exercising user inputs and demonstrating if the vulnerability can be exploited or not.
Can you test for stored XSS manually?
Testing for stored XSS vulnerabilities manually can be difficult. A stored XSS vulnerability means that an entry point, where the application accepts user input, connects to an exit point where that input is displayed to a user.
Systematically testing for stored XSS means inspecting all entry points via HTTP request headers, URL query string and message body, URL path, or specific application functionality such as commenting, messaging, or any submission of data via forms.
Large web applications may have a large number of entry points. The main challenge is that the tester cannot foresee which exit point will display a user input. For example, user-provided display names can appear in multiple places in the user interface, in an audit log, and in many other locations.
Stored XSS testing method
- Identifying entry points to the application
- Submitting inputs into each entry point
- Checking to see where the application displays those entry points
- Ensuring that the displayed content is persistent across sessions, and not only shown for the current session
- Testing the XSS payload itself, like in a reflected XSS attack
Related content: Read our guide to XSS vulnerabilities
Stored XSS Prevention
There are several factors to keep in mind to help you prevent stored XSS:
- Secure handling of user input—you must never implicitly trust input submitted by a user. Inspect all user-submitted input to ensure it doesn’t include risky characters that may affect how a user’s browser interprets the data on your website. Implement thorough input validation and ensure characters are output-escaped.
- Request blocking—you can allow or block user-submitted input based on its risk of containing a malicious payload. For example, if the input contains