Software Development
Lukasz Kolko, 2021-04-16

Web app security - XSS vulnerability

XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. The main effects of this vulnerability are the possibility of execution of any actions in the context of the logged-in user, and reading any data in the context of the logged-in user.

Attack scenario

  1. The attacker locates the XSS vulnerability on a website used by the victim, e.g., a bank's website
  2. The victim is currently logged on to this page
  3. The attacker sends the victim a crafted URL
  4. The victim clicks on the URL
  5. On the victim's bank website, JavaScript code starts executing to intercept the user's data or execute a transfer on his behalf to the attacker's account

It is worth noting that operations performed on behalf of the victim may be invisible to the victim, as they may take place in the background using the bank's API, or the attacker may perform them later with the data needed for authentication, tokens, cookies, etc.

Code review

XSS types

1. Reflected XSS

This is one where HTML/JavaScript code contained in any parameter (e.g. GET, POST or cookie) is displayed in response.

A page with a text input to search for something that puts the parameter ?search=foo in the URL ending when querying the API. After entering any phrase, if it is not found, a return message is placed in HTML ex.

<div>No result found for <b>foo</b></div>\

We can try to put in the URL ?search=<script>alert('XSS')</script>.


This is when its execution is enabled by the use of dangerous functions in JavaScript, such as eval or innerHtml. The "Live example" below shows a DOM XSS attack based on the innerHtmlfunction.

3. Stored XSS

This is one where the malicious code gets written on the server side. For example, we may send a comment with malicious code to a blog post that is uploaded to the server. Its task is, for example, to wait for the administrator's moderation and then to steal his session data, etc.

Injection methods

  1. In the tag content


<img src onerror=alert('XSS') />
  1. In the content of the attribute

" onmouseover=alert('XSS') into

<div class="" onmouseover=alert('XSS')"></div>
  1. In the content of the attribute without the quotes

x onclick=alert('XSS')into

<div class=x onclick=alert('XSS')></div>
  1. In the hrefef attribute

javascript:alert('XSS') into

<a href="javascript:alert('XSS')"></a>
  1. In the string inside JavaScript code

";alert('XSS')// into

<script>let username="";alert('XSS')//";</script>
  1. In the attribute with the JavaScript event

&#39;);alert('XSS')// where &#39; is a single quote, into

<div onclick="change('&#39;);alert('XSS')//')">John</div>
  1. In the href attribute inside the JavaScript protocol

%27);alert(1)// where %27 is a single quote, into

<a href="javascript:change('%27);alert(1)//')">click</a>

Live example

Defense methods

  1. Data encoding using built-in functions found in many programming languages.
  2. Using template systems with automatic encoding. Most of the popular frameworks that use such systems protect us from XSS injection (Django, Templates, Vue, React etc.).
  3. Do not use functions like eval or Function with untrusted user data.
  4. Do not use functions and properties that assign HTML code directly to the DOM tree elements, e.g., innerHTML, outerHTML, insertAdjacentHTML, ocument.write. Instead, you can use functions that assign text directly to these elements, such as textContent or innerText.
  5. Be careful when you redirect the user to a URL that is under his control. Risk of injection location = 'javascript('XSS')'.
  6. Filter HTML using libraries such as DOMPurify.
  7. Be careful about uploading .html or .svg files. You can create a separate domain from which the uploaded files will be served.
  8. Use the Content-Security-Policy mechanism.
  9. Take a look at the anti-XSS filters built into most popular browsers.

If you find this article interesting, follow Lukasz on Github:

Build a digital product

Read more:

Data fetching strategies in NextJS

Rails API & CORS. A dash of consciousness

Why you should (probably) use Typescript?