Solution for PortSwigger’s Academy: Reflected XSS into HTML context with most tags and attributes blocked
The following is my documentation on PortSwigger’s Academy labs.
End Goal: Bypass the WAF and call the print() function
The last time we encountered a WAF (Website Application Firewall), our workaround was pretty simple. This time around we are going to have to do a lot of hunting and testing to see just how to get our payload to work.
Encountering the WAF
First, we want to have an idea of what the site does with the input that it is given. Why not go straight for the gold and give it a classic payload and see what happens? Why not indeed? We place the following payload into the search box:
1nfornography<img src=1 onerror=print()>
Upon clicking the search button we are immediately greeted with this:
The message “Tag is not allowed” is certainly telling, and though we cannot really see much else we could at least see our search with URL encoding in the address bar. Something to consider. Unlike in previous labs, there was no document I could reference to try and find what was being filtered. The WAF is not going to be an open book. So what’s next?
Using Burp Suite to find unfiltered events and tags
We are going to be using Burp Suite’s Intruder tool to enumerate what the WAF allows and does not allow. To make this happen we first need to turn our Intercept on, reload the page, and send what we got to Intruder (making sure to turn Intercept off when we are done doing so).
Now we’ll select the search term after “/?search=” and replace it with two angle brackets (greater-than and less-than). Place your cursor between the brackets and hit the “Add §” button twice.
What we plan on doing from here is to create a payload that asks the target site to search for a different tag, one at a time, and then look out for our response. We’ll likely get a lot of 400 errors, but if we can find a 200 response then we are in. Luckily for us, PortSwigger has crafted a list for our payload to go through at their XSS Cheat Sheet.1 All we need to do is go over that page and hit the “Copy tags to clipboard” button…
…and then head over to the “Payloads” tab in Intruder and paste it into our Payload list.
This done, we send out our attack!
…and immediately get confronted with my favorite message because I am using the “Community Edition” of Burp Suite. Unlike last time, however, this did not take as long, only about fifteen minutes. When all the results come in arrange them by “Status code” and look for any 200 responses, like so:
Investigating our 200 responses we learn that body and custom%20tags (%20 being URL encoding for a space). We can try searching for <body> and find that it does not return a “Tag is not allowed” message. Further, the angle brackets are not captured in quotations (this will happen if you search for <>), yet our <body> tag is nowhere to be found as an additional tag when we inspect our elements. So let’s try <body%20> and see what happens.
Our tag escaped the quotations and is automatically followed by an end tag of its own kind. So what can we do with this? We still need an event to trigger our print() function, we just need to find which kind of events the WAF is not looking for. Thus, just like hunting for our tag, we’ll do the same thing for our event. Before we start that though, let’s hit the “Clear §” button to make a fresh payload.
We’ll place our new discovery between our angle brackets like so:
…and return to the XSS cheat sheet, but this time hit “Copy events to clipboard”…
…and paste them into our new Payload list. Just like last time it is time to start a new attack.
After arranging our responses by “Status code” we find a potential event that we can exploit: onresize
Now that we have gathered our workarounds, it is time to craft our final payload.
Using an iframe and delivering our exploit
In our last steps, we will be using the built-in “exploit server” in our lab, located at the header of our page.
When we craft our payload we’ll be placing it inside of an iframe, but why use an iframe?
“An iframe pretty much acts like a mini web browser within a web browser. Also, the content inside an iframe exists entirely independent from the surrounding elements.”2
Looks like there will be little the WAF can do to it, especially with our workarounds. Here is our final payload:
<iframe src="https://YOUR-LAB-ID.web-security-academy.net/?search=%22%3E%3Cbody%20onresize=print()%3E" onload=this.style.width='100px'>
3
For reference, without URL encoding it would look like this:
<iframe src="https://YOUR-LAB-ID.web-security-academy.net/?search="><body onresize=print()>" onload=this.style.width='100px'>
The page will print if it is resized, which it happens when loaded. Finally, we place our payload into the “Body” section of the exploit server. Just make sure to paste in your own lab id.
Once we do so, store it, then “Deliver exploit to victim”.
Once delivered our lab is solved!
Always wanting to see exactly what was happening in the background, I took the extra step of inspecting our page after the attack:
We can see our attack work in plain JavaScript.
Notes:
I used the following resources in this exercise and write-up:
- PortSwigger’s XSS cheat sheet ↩︎
- Tutorial Republic: HTML iframe ↩︎
- PortSwigger’s Solution ↩︎
Share this:
Filed under: Cybersecurity,Pentesting,PortSwigger Academy,XSS attack - @ January 4, 2024 12:06 am
2 thoughts on “Solution for PortSwigger’s Academy: Reflected XSS into HTML context with most tags and attributes blocked”