Jakub Brzozowski

Pentester, bug bounty hunter and security researcher. Also huge fan of Star Wars and coffee connaisseur :coffee:

Yeswehack's Dojo #17 XSS challenge writeup

06 Jun 2022 » web-applications


This is a short writeup of the lastest Yeswehack’s Dojo challenge. The challnege is all about bypassing the XSS filter and exfiltrating sensitive data. From the challenge description, we can read the following:

  • This code runs a JavaScript code inside a script that craft a “secret” variable,
  • Execute Javascript (XSS) and alert (popup) the value of the original variable secret,
  • Alert (popup) the value of the original variable secret.

So to solve this challenge we have to bypass the filter and get our hands on some “secret” variable. When we open the challene page we can see the following code snippet where the injection happens.

<script type="text/javascript" src="$inject"></script>

<script type="text/javascript">

//Get Access and *alert()* the "secret" variable! 
const date = Date.now().toString();
const addOn = "Pa$$w0rd";
const secret = addOn+date


Our injection point is the $inject variable. I decided to try a standard quote-closing payload only to see that the XSS filter blocked some of the payload. This was the result of payload x" onerror="alert(document.domain):

<script type="text/javascript" src=""__Nope__onerror__Nope__"alert(document.domain"></script>

We can see that the filter used the following rules to neutralize our payload:


So no HTML tag injection, JavaScript events or pointing the src attribute to our own server as the :// part is filtered and for some reason the script source cannot be loaded with double backslash (\\) bypass. Then I remembered that the script resources can be loaded with the data: URI scheme. We can base64-encode our JavaScript payload and then pass it to the src attribute using data: scheme which is not filtered! I quickly crafted the following payload:

Plaintext Payload 1


Base64-encoded Payload 1 with ‘data’ URI scheme


After submitting the payload I could see that I’m able to bypass the filter and execute JS code.

Reflected payload:

<script type="text/javascript" src="data:;base64,YWxlcnQoIlhTUyIp"></script>

Javascript code execution:


However when I tried to read the secret variable, I got the following error in Dev Tools:


This happens as the secret variable is initialized after the injection point happens, so when we execute our JS code, there is no secret variable to access! We can fix this error by adding document.addEventListener("DOMContentLoaded", function(){<PAYLOAD>}) to our payload. This way our code will wait before the DOM finishes loading so we will be able to access every variable initialized.

Plaintext Payload 2

document.addEventListener("DOMContentLoaded", function(){alert(secret);;}); //extra semicolons (;) are to remove equality symbols (=) from the base64 payload as they get filtered out and brake our payload 

Base64-encoded Payload 2 with ‘data’ URI scheme


After injecting the final payload we can successfuly access the secret variable thus completing the challenge: