Codementor Events

Testing for Cross-Site Scripting (XSS)

Published Dec 20, 2018

Learn how to test for Cross-Site Scripting (XSS) in this article by Joseph Marshall, a web application developer and freelance writer with credits from The Atlantic, Kirkus Review, and the SXSW film blog. He also enjoys moonlighting as a freelance security researcher, working with third-party vulnerability marketplaces such as Bugcrowd and HackerOne.

Cross-Site Scripting (XSS) is a vulnerability caused by exceptions built into the browser's same-origin policy restricting how assets (images, style sheets, and JavaScript) are loaded from external sources.

Consistently appearing in the OWASP Top-10 survey of web-application vulnerabilities, XSS has the potential to be a very damaging, persistent exploit that affects large sections of the target site's user base. It can also be difficult to stamp out, especially in sites that have large attack surfaces, with many form inputs, logins, discussion threads, and so on, to secure.

This article will cover the different varieties of XSS (persistent, reflected, DOM-based, and so on), how to test for it. You can find the complete code for this article at https://github.com/PacktPublishing/Hands-On-Bug-Hunting-for-Penetration-Testers.

Technical Requirements

You will need to configure and use tools from the macOS Terminal command line. You'll also need to use Burp Suite, the Burp extension XSS Validator, and information from the SecLists GitHub repository (https://github.com/SecLists) to power your malicious XSS snippet submissions. When you use a browser normally or in conjunction with Burp, you'll continue to use Chrome (66.0.3359.139). Using the XSS Validator extension will require you to install Phantomjs, a scriptable headless browser.

A Quick Overview of XSS – The Many Varieties of XSS

XSS is a weakness inherent in the single-origin policy. The single-origin policy is a security mechanism that's been adopted by every modern browser and only allows pages to load from the same domain as the page doing the loading. But there are exceptions to allow for pages to load third-party assets – most web pages load external JavaScript, CSS, or images – and this is the vector through which XSS occurs.

When a browser is loading the src attribute on an HTML tag, it's executing the code that attribute is pointing to. It doesn't have to be a file – it can just be code included in the attribute string. And it's not just the src attribute that can execute JavaScript.

The following is an example of an XSS testing snippet. It uses the onmouseover attribute to execute a JavaScript alert() as a classic XSS canary:

<a onmouseover="alert(document.location)"href="#">snippet text</a>

document.location is included as a way of easily referencing the exact URL where the XSS is occurring.

The above snippet is an example of stored or persistent XSS because the <a> tag with malicious JavaScript would be inserted via a form input as part of a comment or general text field. This will then be stored in the web app's database, where it could be retrieved and viewed by other users looking at that page. When someone hovers over that element, its onmouseover event will trigger the execution of the malicious XSS code.

Reflected XSS is when the injected script is reflected off of the target server through a page of search results, an error message, or another message made up in part by the user's input. Reflected XSS can be very damaging because it leverages the trust of the server the code is being reflected from.

There's also DOM-based XSS, a more specialized type of the attack that relies on a user being supplied a hacker-generated link containing an XSS payload, which will prompt the user's browser to open the link, echoing back the payload as it constructs the DOM and executes the code.

Although stored/persistent XSS, reflected XSS, and DOM-based XSS are all possible groupings of XSS varieties, another way of thinking about the different types of XSS is dividing the bug into client XSS and server XSS. In this framework, there are both stored and reflected types for both the client and server variations: Server XSS occurs when unverified user data is supplied by the server, either through a request (reflected XSS) or stored locations (stored XSS), while client XSS is just the execution of unverified code in the client, from the same locations.

Testing for XSS – where to find it and how to verify it

There are several great methods for discovering XSS. Start with Burp and an XSS-related Burp extension.

Burp Suite and XSS Validator

One problem with automated and semi-automated solutions for XSS is distinguishing signal from noise. To do this, a useful Burp plugin, XSS Validator, runs a PhantomJS-powered web server to receive the results of Burp queries and looks for a string injected into the alert() call embedded within the applied XSS snippets. It provides a clean way of culling the results of your XSS submissions to absolute confirmed vulnerabilities.

The easiest way to download the XSS Validator Burp extension is through the Bapp store. Just navigate to the store from the Extension tab within the Burp Suite and select the extension from the marketplace (needless to say, it's free). You can also install the extension manually by following the instructions in the XSS Validator GitHub documentation.

In addition to installing the extension, during your actual testing, you'll need to run the server parsing incoming Burp requests. If you clone the XSS Validator git repo, you can navigate to the xss-validator directory and start the xss.js script. You can then bootstrap the server and set it to run as a detached background process in one easy line:

phantomjs xss.js &

With the XSS Validator server and Burp Suite running (boostrap_burp), navigate to the specific form input you'd like to test for XSS. As a way of demonstrating the tool on a proven testing ground, you can test a form input on the Web Scanner Test Site (webscantest.com) that's been designed to be susceptible to XSS:
1.PNG

After arriving on the page – with your Burp Proxy Intercept feature turned off so that you don't have to manually forward all the traffic on the way there – you enter something recognizable into the form fields you're testing:
2.PNG

Now, navigate back to your Burp Suite GUI and turn Intercept back on before you submit:
3.PNG

Now when you submit, you should see the browser favicon indicate a submission without anything changing on the form. If you go back to Burp, you'll see you've intercepted the form's POST request (note that if you have other tabs open, you might see that the Burp proxy has intercepted requests from those pages and has to forward them):
4.PNG

You want to send this request over to the Burp intruder feature, where you can do more to manipulate the POST data. To do this, right-click on the request and click on Send to Intruder:
5.PNG

Once you're at the Intruder window, go to the Positions tab, where you can see the POST request parameters and cookie IDs already selected as Payload Positions. Go ahead and leave these defaults and move over to the Payloads tab to choose what you'll be filling these inputs with. In order to integrate with the XSS Validator extension, you need to make changes to these first three payload-related settings, as follows:

Payload Sets

From the second drop-down, Payload Type, select the Extension-generated option.

Payload Options

When you click Select generator..., you'll open a modal where you can select XSS Validator Payloads as your selected generator.

Payload Processing

Here you'll want to add a rule, choosing Invoke Burp extension as the rule type and then XSS Validator as the processor:
6.PNG

After you've made all these selections, your app's GUI should look like the following:
7.PNG

You need to make one more setting change before you can start your attack. If you head over to the xssValidator tab, you'll see a random string generated in the Grep Phrase field, and you might also spot the bullet point explaining that Successful attacks will be denoted by the presence of the Grep Phrase:
8.PNG

Add that grep phrase into the Grep - Match section in the Options tab so that when you're viewing your attack results, you can see a checkbox indicating whether your phrase turned up in an attack response:
9.PNG

Once that phrase has been added, you're ready to start your attack. Click on the start attack button in the top-right side of the Options (and every other) view.

After clicking the button, you should see an attack window pop up and start to self-populate with the results of the XSS snippet submissions:
10.PNG

And voila! You can see the presence of your grep phrase, which means that your submissions have been a success, for several of the tag/attribute combinations generated by the XSS Validator submissions.

If you found this article interesting, you can explore Hands-On Bug Hunting for Penetration Testers for a detailed walkthrough of how to discover, test, and document common web application vulnerabilities. Hands-On Bug Hunting for Penetration Testers shows you how technical professionals with an interest in security can begin productively—and profitably—participating in bug bounty programs. You can avail all of Packt’s books for just $5 till January 21, 2019. So what are you waiting for? Avail the offer today and become an exceptional IT professional!

Discover and read more posts from PACKT
get started
post commentsBe the first to share your opinion
Show more replies