Hacking Tutorials XSS

Solution of Google’s XSS Challenge [Explained]

Hello Guys! Today we are here to face Google’s XSS challenge. It is a set of 6 challenges and each challenge has a Code Viewer which can be used to view the source code of target webpage and a hint section which can be used if you get stuck somewhere.

Here’s the welcome page

google xss challenge

Now lets start hitting the challenges:

Challenge 1 : Hello, world of XSS

Well there’s nothing much in this challenge because all you have to do is to inject the classic script i.e.


challenge 1

Challenge 2 : Persistence is key

Well you literally don’t have to do anything in challenge 2 as the payload we entered in challenge 1 got stored and this is what we call Stored or Persistence XSS.

Note: If you are using a chrome based browser then you may need to inject a payload manually.

xss challenge 2

Challenge 3 : That sinking feeling…

This is where the the real game starts. Here’s the challenge number 3.

As you can see there are 3 tabs or you can see images labeled as Image 1, Image 2 and Image 3. So initially we are on image number 1 and now I am going to click on image 2,

If you look close enough then you will see that when we change the image the URL also changes in a certain way.

Image 1: https://xss-game.appspot.com/level3/frame#1

Image 2: https://xss-game.appspot.com/level3/frame#2

Image 3: https://xss-game.appspot.com/level3/frame#3

Can you see that? Only thing that changes in the URL is the integer at the end i.e. 1, 2 and 3. Something which changes with different conditions is called a variable, so its a variable. So lets a take a look at the source code to see how the image is loaded


      function chooseTab(num) {
        // Dynamically load the appropriate image.
        var html = "Image " + parseInt(num) + "<br>";
        html += "<img src='/static/level3/cloud" + num + ".jpg' />";

The code I highlighted is responsible for loading the requested image. Let me make it more simpler

<img src=path ” + num + “.jpg />

The image source is enclosed within ‘ quotes so we can simply close the img tag by adding ‘/> or just ‘>.

So here’s our payload


And here is the proof of concept

Challenge 4 : Context matters

Basically its a basic web app which works like a stop watch. Enter the number of seconds and you will get a pop-up after that number of seconds. So lets take a look at its source code to understand how it works.

<body id=”level4″>
<img src=”/static/logos/level4.png” />
<img src=”/static/loading.gif” onload=”startTimer(‘{{ timer }}’);” />
<div id=”message”>Your timer will execute in {{ timer }} seconds.</div>

So when the user enters a value, the startTimer function is called with the onload event handler. Let me make it simpler,

<img src=source_of_image onload=stopwatch(‘value’); />

The single quote and bracket ( contain the value entered by the user and semi colon ; is being used to declare the end of the query. So we can add as much as queries we want like this,

onload=query(‘value’); query2(‘value’); query3(‘value’);

If you are following my articles on XSS you might have guessed the the scheme of the payload. Well now its very easy to execute our payload because the onload handler can easily execute javascript for us. We will simply use ‘) to declare the end of the value of stopwatch then we will add ; to declare the end of the stopwatch function so we can add our own function after it. So here is how it will work

onload=stopwatch (‘ ‘); our_function_here ‘);

So here’s the final payload


Now you must be wondering why added (‘ in the end. Here you go

onload=stopwatch (‘ ‘); alert (‘ ‘);

So as you can see we are using the existing characters in the code to close our alert statement and it works perfectly

Challenge 5 : Breaking protocol

This one is really easy if you can identify the injection point. So here’s a sign up page

When we click on Sign Up it takes us to another page where we can enter our email.

So I tried crafting payloads according to the source code of the page but failed but then accidentally I saw that there is parameter named next with the value confirm, in the URL. For the sake of testing I entered <script>alert()</script> and press enter but nothing happened, then I entered “test” in the email form and clicked Next and I got redirected to this page

As you can see it included the payload in the URL so maybe its the injection point. So I entered javascript:alert(); in the vulnerable parameter i.e. next= and clicked on Go in the address bar and then entered a random word in the Email form and it worked.
and it worked pretty well

Challenge 6 : Follow the rabbit

Its a very simple one. I figured out the solution in less than a minute and now we will show you how.

It says Loaded gadget from /static/gadget.js and /static/gadget.js is also included in the URL which means its importing a javascript file from there and hopefully we can make it import our malicious javascript file. So I am going to use this as my malicious file https://www.google.com/jsapi?callback=alert

So replaced /static/gadget.js with our malicious file’s URL but the webpage blocked it

Hmmm its some kind of filter, lets check out the source code for clues

function includeGadget(url) {
var scriptEl = document.createElement(‘script’);

// This will totally prevent us from loading evil URLs!
if (url.match(/^https?:\/\//)) {
“Sorry, cannot load a URL containing \”http\”.”);

Haha such a poor filter. Its case insensitive which means it will block http but not HtTp. So lets make changes to our URL


Aaannnnnd Go! Go! Go!
challenge 6
This is the last challenge.
I hope you enjoyed this walk through and learned something new.
Also Read: Bypassing WAF with Shortest XSS Payload

About the author


I am Somdev Sangwan also known as D3V. I am n00b and I love computers and hacking. I am a python freak and your friendly neighborhood hacker.

Subscribe Now

Subscribe for free and get latest articles delivered right into your inbox.

Thank you for subscribing.

Something went wrong.