BugPoC XSS Challenge- Wacky

Gaurav Mishra
Nov 10, 2020 · 5 min read

Introduction

In this writeup, I am going to explain my approach towards solving the Wacky XSS Challenge. The challenge is primarily about bypassing Content Security Policy (CSP) and DOM Clobbering due to insecure coding practice.

Challenge Rules

  1. You must alert(origin) showing https://wacky.buggywebsite.com
  2. You must bypass CSP
  3. It must be reproducible using the latest version of Chrome
  4. You must provide a working proof-of-concept on bugpoc.com

Here’s how the challenge page looks like:

Image for post
Image for post

Upon clicking Make Whacky! button, I noticed a GET request being made to /frame.html page along with a query parameter called param

Image for post
Image for post

Noticing the reflection of text on the page, I tried supplying the h1 tag to see how it is getting rendered in the response.

Image for post
Image for post

The h1 tag was not rendering as an HTML element, although it was getting included in the response without any modification or encoding and that’s because I was not following the proper HTML semantics.

Image for post
Image for post

Upon including the closed title tag before h1, I could see that the h1 tag is rendered as an HTML element. However, it was still not displaying on the page due to it being included inside the head tag and not body.

Image for post
Image for post

Since one can define the scripts and other meta-information inside the head tag, let’s try to inject some JavaScript code into the DOM.

</title><script>alert()</script>

Image for post
Image for post

The browser refused to execute the inline JavaScript code as it violates the Content Security Policy implemented by the application. The policy was implemented via the following response header:

Let’s try to examine it with the help of Google’s CSP evaluator.

Image for post
Image for post

The application was generating a random nonce for each subsequent request. Therefore, it was not possible to execute JavaScript via script tags. However, it was possible to include base tags and load relatively imported scripts through a third-party domain.

Upon looking into the page source, I noticed a JS file called frame-analytics.js being imported relatively but that block of code was not getting executed because window.name is not equals to iframe.

Image for post
Image for post

Is there a way to control window.name property?

Yes, you can create an HTML page with an anchor tag and set its target attribute to iframe or else you can add a base tag and set its target attribute value as iframe, it will automatically set the defaulttarget attribute value for all anchor tags on the page.

Now that we are able to control the code flow, let’s try to load frame-analytics.js file from an arbitrary domain (for example:hackerone.com) by including a base tag with href value as //hackerone.com/

Image for post
Image for post
Image for post
Image for post

As you could notice, the application is trying to load a JavaScript file from hackerone.com

The next task was to host a file called frame-analytics.js on the same path /files/analytics/js/ using a website that we can control.

Image for post
Image for post

Let’s try to exploit it using //gauravmishra.co.in/

Image for post
Image for post

It again failed to execute because the browser couldn’t find a valid digest in the integrity attribute for resource https://gauravmishra.co.in/files/analytics/js/frame-analytics.js with computed SHA-256 3ZbQn3cmhPcHyOq0jZelWqoZGQdBdhSIoBWzDdFJFt4=

The integrity hash value was hardcoded in the JavaScript code. However, due to insecure coding practice, it was possible to control fileIntegrity object and its attributes (including value).

Image for post
Image for post

Taking help from the Gareth Heyes research article on DOM Clobbering, I was able to control thefileIntegrity or integrity attribute value. Here is the technique I referred to:

Image for post
Image for post

Injected the following HTML code to control fileIntegrity.value

Decoded URI:

Let’s try to execute it now:

Image for post
Image for post

Still no alert pop-up :-(

The analytics iframe was sandboxed and it didn’t include allow-modals in the sandbox attribute value. Therefore, the browser stopped the execution of alert function.

Image for post
Image for post

Is there a way to control sandbox attribute (in this case)?

No.

Though it was not possible to execute the alert function in the iframe context but it was possible to do so in the parent window’s context using window.parent.alert method.

Let’s update the frame-analytics.js code and execute!

Image for post
Image for post
Image for post
Image for post

And still no JavaScript execution. Why?

The integrity hash value has changed, we need to update it again.

And there you go !!

Image for post
Image for post

Here is the final exploit code:

I have published a PoC on BugPoC Frontend Wizard. Here is the PoC link and password:

https://bugpoc.com/poc#bp-7903j8v0
Password: LasTINGaNt01

References:

For any feedback or CTF invitation, please reach out to me on Twitter.

Thanks for reading!

The Startup

Medium's largest active publication, followed by +775K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store