An introduction to stored cross-site scripting (XSS) vulnerabilities

Cross-Site Scripting, or XSS, is one of the most common vulnerabilities that threaten web applications today. It is so prevalent in modern application that it has been consistently named as one of the OWASP top ten vulnerabilities. Today, we’ll dive into what XSS vulnerabilities are, what stored XSS — the most dangerous type of XSS — are, and how to prevent them.

What is XSS?

XSS is when an attacker can execute malicious scripts on a victim’s browser.

A lot of the time, applications use user input to construct web pages. And if that application cannot tell the difference between user input and the legitimate code that makes up a web page, attackers can submit input in the format of executable scripts and get that executed by the victim’s browser.

The victim’s browser will then execute the malicious script, thinking that it is the legitimate code of the webpage. These scripts (Javascript, VBScript, and more) can be used to steal cookies, leak personal information, change site contents, or redirect the user to a malicious site.

There are three main kinds of XSS: stored XSS, reflected XSS, and DOM XSS. The difference between these cross-site scripting flaws is how the malicious code is delivered to the victim. Today, we’ll focus on the most dangerous type of cross-site scripting: stored-XSS.

What is a stored-XSS?

Stored XSS is when the XSS payload, or the malicious script, is stored on a server before being retrieved by the victim’s browser.

When an application accepts user input, stores it in its servers, and uses it to construct webpages without proper precautions, malicious JavaScript code can make its way into the database and then to victims’ browsers.

For example, let’s say an internet forum lets users post comments. When a user submits a comment to a post, that user input is rendered onto the webpage served to anyone who views that blog post. Normally, users would submit text comments like these:

    Vickie: Thanks for this great post!
    Ben: I think this topic is more...
    Jo: Appreciate the discussion, in this case...

But now, what if an attacker submits a comment like this one?

    <script>alert("XSS by Vickie");</script>

This comment contains the syntax of Javascript code. < script >< /script > indicates to the browser that the content contained within the tags should be interpreted as Javascript code, not plain text. So if an attacker submits a comment with JavaScript code, they can have that code executed by the browser of any user who views that blog post! The JavaScript code alert(“XSS by Vickie”) will generate a pop-up on the victim’s browser that reads “XSS by Vickie”. Every time a user views the comment on the forum, their browser will execute the embedded JavaScript. This is called a Stored Cross-Site Scripting, or Stored XSS, because the payload is first stored on the server before being retrieved by the victim’s browser.

During a stored XSS attack, attackers save their malicious scripts on the target application’s server and wait for victims to access it. Every time users access the page, the malicious script executes in their browser. Stored XSS tends to be the most dangerous type of XSS because attackers can attack many victims with a single payload. And during a stored XSS attack, all the user has to do to become a victim is to view a page with the embedded payload, whereas reflected and DOM XSS usually require the victim to click a malicious link.

How can I prevent XSS?

So how could you prevent XSS?

First of all, remember that you should never trust user-submitted input! To prevent XSS, you should make sure that user-submitted input doesn’t contain dangerous characters that might influence the way browsers interpret the information on your webpage. You can do that by implementing robust input validation and output escaping.

You can validate user input and reject input that might contain malicious payloads. For example, user input containing the string “< script >” is a good indicator that the input contains an XSS payload. In this case, you could block the request. Although, keep in mind that it’s better to be strict and explicitly allow a limited set of characters, such as alphanumerics, instead of disallowing known malicious strings because attackers can often bypass these protections by triggering XSS in a different way.

You can also escape special characters in a user’s input before rendering it on a webpage. Escaping means encoding special characters so that they are interpreted literally instead of as a special character by the program. For example, the left and right angle brackets can be encoded into HTML characters &lt and &gt so that they are not seen as actual tags in HTML. Besides the angle brackets < and >, you should escape characters that have special meaning in HTML, such as the & character, single and double quotes, and the forward-slash character. Many modern JavaScript frameworks such as React and Angular automatically do this for you, so many XSS vulnerabilities can be prevented by choosing the right JavaScript framework to use.

There are also ways you can limit the damage an attacker can cause if an XSS bug does happen. To prevent attackers from stealing user cookies via XSS attacks, you should also set the HttpOnly flag on sensitive cookies on your site. Finally, you can instruct the browser to execute only scripts from a list of sources by using the Content-Security-Policy HTTP response header.

But what can you do about the XSS vulnerabilities that already exist in your code? You can detect them by scanning your code with a static analysis (SAST) tool and fix them with one of the strategies I mentioned in this post. Code analysis or static analysis can identify the points in your application where XSS protection is missing and is the most efficient way of uncovering XSS in your applications. ShiftLeft’s static analysis tool NG-SAST can find the cross-site scripting bugs in your code and help you fix them. Learn more by visiting us here.

Thanks for reading! What is the most challenging part of developing secure software for you? I’d love to know. Feel free to connect on Twitter @vickieli7.

About ShiftLeft

ShiftLeft empowers developers and AppSec teams to dramatically reduce risk by quickly finding and fixing the vulnerabilities most likely to reach their applications and ignoring reported vulnerabilities that pose little risk. Industry-leading accuracy allows developers to focus on security fixes that matter and improve code velocity while enabling AppSec engineers to shift security left.

A unified code security platform, ShiftLeft CORE scans for attack context across custom code, APIs, OSS, containers, internal microservices, and first-party business logic by combining results of the company’s and Intelligent Software Composition Analysis (SCA). Using its unique graph database that combines code attributes and analyzes actual attack paths based on real application architecture, ShiftLeft then provides detailed guidance on risk remediation within existing development workflows and tooling. Teams that use ShiftLeft ship more secure code, faster. Backed by SYN Ventures, Bain Capital Ventures, Blackstone, Mayfield, Thomvest Ventures, and SineWave Ventures, ShiftLeft is based in Santa Clara, California. For information, visit:


See for yourself – run a scan on your code right now