Stored vs Reflected XSS

Posted on Apr 29, 2021

In cross site scripting vulnerabilities, the user of a website executes malicious JavaScript code injected by an attacker. This article is a beginner friendly explanation of two major categories of XSS (Cross Site Scripting) vulnerabilities: “Reflected XSS” and “Stored XSS”.

How XSS Works

HTML uses tags to denote denote page layout. For instance, <p></p> tags indicate plain text. XSS takes advantage of inline scripting, where any HTML content surrounded by <script></script> tags are interpreted as Javascript code and executed. This means that if attackers are able to insert raw HTML into a page that a user is visiting, they can use that power to insert script tags and get a user to run their malicious code.

Reflected XSS

Many sites use URL query parameters to pass information from the user to a remote server. Consider the following URL:

https://www.google.com/search?q=helloworld

This link takes you to a Google search for helloworld. Everything after the ? is data that we want to send to Google, namely q=helloworld. This conveys that our query q will be sent to Google with the value helloworld.

In reflected XSS, an attacker might take advantage of this fact by sending the server a malicious query. This link could contain malicious Javascript code that could be executed by a vulnerable site. If the attacker sends this link to an unsuspecting user and gets that person to click on it, then the attacker’s malicious code will execute when the user visits the URL.

Consider the following example. Say a website has a vulnerable search endpoint:

https://vulnerable-site.com/search?q=helloworld

Unlike google.com, our vulnerable website returns a page that looks like this:

<h1>Search</h1>
<h3>Search results for helloworld</h3>
<table>
  <tr>
    <td>No results!</td>
  </tr>
</table>

It simply takes whatever value q is set to and puts it directly into the webpage after “Search results for”.

Notice how the vulnerable site just injects helloworld directly into the page. Now imagine if the attacker had created a link that looked like this:

https://vulnerable-site.com/search?q=<script>EVIL_CODE</script>

If the attacker gets a user to click on this link, the result page would look something like this:

<h1>Search</h1>
<h3>Search results for <script>EVIL_CODE</script></h3>
<table>
  <tr>
    <td>No results!</td>
  </tr>
</table>

In this example EVIL_CODE is just a placeholder, but this vulnerability allows the attacker to inject any Javascript code into the website.

Stored XSS

Stored XSS is similar to reflected XSS with the exception that the malicious Javascript is stored on the server permanently. Say we have a vulnerable API endpoint:

https://vulnerable-site.com/post?content=helloworld

Let’s say that this endpoint takes whatever value is stored in content and makes a Twitter style post on the site with that content. Instead of sending a link to the victim, say the the attacker logs in and makes his malicious post using the following url (which is stored in the website’s database):

https://vulnerable-site.com/post?content=<script>EVIL_CODE</script>

If the site inserts the content as raw HTML, then the malicious Javascript is loaded when any user views that post.

Terminology

In many cases, we can actually have XSS attacks that are really a mix of reflected and stored XSS (and even a third category called “DOM Based XSS”). If you are interested in learning more about this, OWASP (Open Web Application Security Project) has a really nice article on it linked here .