Hey Everyone! ๐Ÿ‘‹ I am Isira Adithya and I am a 16 years old ethical hacker from Sri Lanka. Recently (21/03/2021), I found out that the Intigriti, Europe's #1 ethical hacking and bug bounty platform was releasing XSS Challenge. I've never participated to these before, but I found some cool write-ups about previous challenges on the internet. Those XSS challenges were very interesting and I thought this may be my chance to win. (But, It was hard. ๐Ÿ˜…) Sorry, for my bad english. ๐Ÿ˜…

Website Overview

Website is very simple. I will highlight the interesting parts. There is a little text box below to save notes. ๐Ÿค” It's kinda weird that there is a box to save notes. So, I immediately thought that will be the target. ๐Ÿ˜Ž We can type anything in the textbox and we can save it. 3cd0fc0316239690cf461230d298a784.png

When we click the save button, it reloads the website. So, That means web browser is sending a request to the server. Hopefully, It is not using AJAX. That's great because javascript code will be very simple. ๐Ÿ˜œ


Now, let's analyze deeply how the website works. ๐Ÿ‘€ I used Chrome Dev Tools to analyze the website. (Ctrl + Shift + I)a39dba950ea557a660b9ee0ab6a02c7e.png

As you can see, our data is injected into a <p> tag with id called notes-display. But, if you try to inject something like <script> it will be encoded with HTML entities. So, there's no hope using tags.

Also, the javascript was very simple and there's no vulnerability in the code. So, the only way to get XSS is to use http requests.

Then, let's navigate to the networks tab and analyze what kinda request this website uses. As always, GET Request was not interesting at all. But, when we save a note, it sends a POST request to the server with csrf & notes as parameters.


As you can see I highlighted 3 major parameters,

  • Request Headers
    • Method: POST (A common method used to send data to server)
    • Cookies: PHPSESSID:3d34ex7... (Used to track your browser's session)
  • Form Data
    • csrf: [MD5 Hash] (Used to protect against Cross-Site Request Forgery ๐Ÿ˜ค)
    • notes: [Your_Data] (Our data... This is the parameter we are going to use to get XSS ๐Ÿ˜Ž)
Note:- Also, I noticed that every time we update the notes or refresh the website we get new csrf token with a very interesting comment. ๐Ÿคจ c3c154ab274e4da68fb16623b6da70c2.png

So, whenever we refresh the page, it returns a new CSRF token with a new Date\Time in that comment. ๐Ÿค” That gives us a hint ๐Ÿคฉ. So, I was thinking how the CSRF could be generated.

Now, I will show you how to decode this using Cyber Chef.

Analyzing CSRF Token

If you look closer in the Response headers you will find that the website uses PHP/7.2. (This is useful to know.) 35881a91cb256d0d013d648d655cdd3a.png

Paste the CSRF token, and analyze hash. It shows some interesting hashing functions there. But, we already know that server-side language is PHP. So, It's super clear that developers are using MD5 to generate the hash. (There is a function called md5 in PHP)


So, Intigriti is giving us the date and the time when the page was generated. If you know about Unix Timestamp it's good way to generate current time in a number. Ex: 1616914585 -> Sun 28 March 2021 06:56:45 UTC So, I thought that the CSRF is generated based on the time that web page generated.

Then, I navigated to Cyberchef
The Cyber Swiss Army Knife - Cyberchef


In the above picture, You can see the recipe I used.

I know about PHP and I knew it's very easy to generate MD5 hash of something in PHP. You just have to call md5(data) also I knew that time() function returns the current time in Unix Timestamp. So, dev only have to call <?php echo md5(time()) ?> output the CSRF to the page. (I am developing a Android Application. Server-side is written in PHP that's why I already knew about these. ๐Ÿ˜Ž)

So, let's discover how to exploit it in my way.

Finding the XSS

OK, First of all, I have to tell this. I know everyone uses BurpSuite by Portswigger when it comes to Web Application Testing. dc248dfe82c296068fedb734522acd6b.png

However, I am not used to burp at all. I know the basics but I don't know how to use it with this kinda CSRF token ๐Ÿ˜‚. I will learn how to use it in the future. But, for this challenge I used Python Programming Language


I wrote a little script to test my custom payloads. I will add the Github link below.

Inti-0321 XSS Tester - Github

Here's a little preview how the tool works. (It helped me a lot)

So, I tried basic functions and All of the payloads returns encoded data. (Html Entities) But, as you can see in the above (Terminal Animate - Ascii Cinema) urls returns a <a> tag. That's kinda good right?

When we send something like, [email protected] it detects it as a Email and returns a <a> tag with following code in it.

<a href="mailto:[email protected]"> [email protected] </a>

There was some hints about the challenge in Intigriti's Twitter Announcement and in one of them they mentioned a RFC.


Then, I started to search about this and eventually I came across this payload by PayloadsAllTheThings - Github.

Payload is "><svg/onload=confirm(1)>"@x.y and I tried it.

As you can see it returned, <a &gt;&lt;svg="" href="mailto:" onload='confirm(1)&gt;"@x.y"'> "&gt;&lt;svg/onload=confirm(1)&gt;"@x.y </a>.

Then, I tried it in the browser and it didn't triggered the XSS. I was so confused and I found out that the problem is onload attribute. As you can see that < and > was encoded in that <svg> payload. But, onload attribute is in the <a> tag and that's enough to perform a XSS attack.

I modified the onload attribute to onmouseover then I tried once again and Boom! ๐Ÿ’ฅ. It triggered the xss when I got my mouse pointer over it.


That's it. Then, I modified the payload little bit according to the Intigriti.

So, after modifying it. The final payload looks like this. "><svg/onmouseover=alert('flag{THIS_IS_THE_FLAG}')>"@x.y.


Finally, I got the CSRF Bypass and XSS. Then, I started to create a POC.

Writing a POC

So, This was my solution to the problem.

To reset the CSRF token, I used a <iframe> tag with sandbox attribute in it. So, the browser will send the cookies to the https://challenge-0321.intigriti.io/ website. Remember, we need to send the PHPSESSID cookie to the server. That's important if not the XSS attack is useless because we can't interact with victim's account. So, we have to send the cookies with the iframe request.

You can get more details from below website. Check it out. HTML5Rocks.com - Sandboxed Iframe

But, chrome was more protective about this. Chrome checks if the cookie has the attribute SameSite= None, if not it won't send those cookies to server. But, in the other hand firefox was vulnerable to this. So, You have to use Firefox to trigger the XSS with CSRF Bypass.

Now, It's time to write the code. However you can use below link to read the whole code. Replit - Intigriti 0321 POC You can read the code to understand the attack, but I am trying my best to explain it further. ๐Ÿ˜…

First, I created the iframe in the html. <iframe sandbox="allow-scripts" src="https://challenge-0321.intigriti.io/"&gt;&lt;/iframe> <script src="script.js"></script>

Then, I found a MD5 function for javascript from CSS-Tricks thanks to Chris Coyier ๐Ÿ™๐Ÿฝ.

I copied it directly in to my javascript file and wrote the rest of the javascript like below.

Replit - Intigriti 0321 POC - script.js

That's it. Whenever, someone open this code, the iframe is going to reset the CSRF token of the intigriti's challenge website and the javascript will redirect the page to the intigriti's challenge's website via POST request containing the XSS payload.

That's the solution for the Intigriti 0321 - XSS challenge. I hope you learned something from this writeup.

Thanks โค

Thanks Intigriti for creating a such a great challenge. Also, I went through lot of rabbit holes and I learned lot of new things from this challenge.