Prerequisite
Before getting started one should be familiar with XSS or at least have an idea about it. Here is a good article which you may give a read to understand what is XSS. Read!
Also, I assume that readers are at least familiar with JavaScript. If not then I'll suggest to spend some time with JS and get comfortable with the basics. You can refer to javascript.info and MDN which are extremely helpful.
π‘ Also in this whole series we'll not even roll our eyes on Hints and Toggle Code as in real-world bug hunting no one will give you hints or non-obfuscator source code so you have to figure out things yourself.
Mission Description
Every bit of user-supplied data must be correctly escaped for the context of the page in which it will appear. This level shows why.
Mission Objective
Inject a script to pop up a JavaScript alert() in the application.
Breaking In
Without any shit talk let's jump in. First, we understand what the app does. Click on the create timer button and a timer starts for 3 seconds and returns us to the home page after 3 seconds.
Noticed anything else? Try the above again and have a look around.
Yes! the URL bar. On starting the timer a query is passed to the URL: level4/frame?timer=3
. Passing HTML as input is not working as well.
Since it's setting a timer, I bet that it's using setTimeout
function in JS but can't be sure. Let's give it a search and you'll see a result but unfortunately, it is not what we want. It's related to the game evaluation mechanism.
Okay how about we roll over our eyes on the network tab in dev tools?
and we can see the code in the response tab as shown in the above gif.
so what must be happening is when we start the timer a request is sent along with the query i.e timer=3
and then in response an HTML file is received where the setTimeout
function is used. As soon as the timer ends it sends us back to the last webpage we were on.
here is the code :
1| function startTimer(seconds) {
2| seconds = parseInt(seconds) || 3;
3| setTimeout(function() {
4| window.confirm("Time is up!");
5| window.history.back();
6| }, seconds * 1000);
7| }
If you have solved the previous level i.e level 3 then you can easily spot the flaw in the above code but if you are still stuck then no worries.
So the argument seconds
is user input. In line 2 parseInt()
saves the application as it returns NaN
but at line 6 no such measure is taken.
also notice line 21 in the same file we found the above script tag.
<img src="/static/loading.gif" onload="startTimer('3')" />
we have an onload
attribute so all we need to do is inject an alert. This is that payload I came up with. Let's break it down.
Payload: ');alert(/xss 4/);('
After payload is injected:
<img src="/static/loading.gif" onload="startTimer('');alert(/xss 4/)('')" />
<img src="/static/loading.gif" onload="startTimer('
');alert(/xss 4/)('
');" />
The first '
,)
and ;
closes the function startTimer()
with empty input but as per line 2 of JS code above the value of timer sets to 3. The second (
and the '
balances the ending ');
to prevent any error.
The above payload can be written in following ways as well:
Payload: ');alert('xss 4
After payload is injected:
<img src="/static/loading.gif" onload="startTimer('');alert('xss 4');" />
<img src="/static/loading.gif" onload="startTimer('
');alert('xss 4
');" />
and I'm sure you are smart enough to understand what's happening over here.
Boom! you popped an alert. Try thinking about some other payloads of your own.
We are not done yet!! We have 2 more levels of Google XSS challenges to complete so head over to the blog section and checkout walkthroughs.
π₯³ So it's time to wrap up the post with a quote
βThe average dog is a nicer person than the average person.β β Andy Roon
Top comments (0)