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 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.
As you've seen in the previous level, some common JS functions are execution sinks which means that they will cause the browser to execute any scripts that appear in their input. Sometimes this fact is hidden by higher-level APIs which use one of these functions under the hood.
The application on this level is using one such hidden sink.
Since you can't enter your payload anywhere in the application, you will have to manually edit the address in the URL bar below.
Let's jump right into it and see what is this application all about. As you click on the tabs
Image 2 ,
Image 3 the image changes. Notice anything else as well? Yep! the URL.
If we click on
Image 1 the URL is
Image 2 =>
level3/frame#2. Looks like the number followed by
# is referring to the tab number. We'll try passing some other number to see how it behaves.
thing to notice is that what we enter after
# in URL gets displayed in the page. There is a possibility that we can insert some script in the page.
Information (so far):
Entry point: URL
Input in URL gets displayed on the page.
which shows Image NaN on the page. Hmm NaN (not a number),usually returned by a function which expects a number as input but here we provided string. There may be a possibility that the code uses
ParseInt. Let's give it a search in dev tools.
In the upper frame line number 16, 17, 18 are the star of the show. When we entered a string, it was passed to
parseInt which returned NaN at line 16. However there is a flaw.
parseInt saved the application from XSS but here the
num is still being used in line 17 and this time no
parseInt and of course line 18 insects the HTML in the page.
Let's create our payload keeping line 17 in mind.
html += "<img src='/static/level3/cloud" + num + ".jpg' />";
NOTE: another thing we have to keep in mind that this application uses JQuery and at line 18
.html()is equivalent to
so if you have solved level 2 of XSS challenge then you know you can manipulate the
onerror attribute of
img tag and the best part is at line 17 there is already an
img tag so all we need to do is properly inject
onerror to the element.
' onerror="alert(/xss/)" '
The image tag will look something like this after injecting the payload:
' onerror="alert(/xss/)" '
' in payload closes the string in
src which makes it an invalid image URL (
/static/level3/cloud) and will certainly lead to an error that triggers
onerror and rest you know.
this payload can be further condensed to
'onerror="alert(/xss/)". The above payload was to explain the logic behind it.
Go ahead and look for some other payload and think what else you can do apart from popping an alert.
We are not done yet!! We have 3 more levels of Google XSS challenges to complete so head over to the blog section and check out walkthroughs.
🥳 So it's time to wrap up the post with a quote
“For the things we have to learn before we can do them, we learn by doing them.” ― Aristotle