Intigriti - XSS Challenge 10-21

 Today I'm going to write about the XSS Challenge 1021 from Intigriti which I was able to manage!


Summary


The XSS challenge  hosted by Intigirti occurs once a month, you can follow them on Twitter to stay tuned about upcoming challenges and other nice infosec contents, I really recommend you to try those challenges as it is a good source for learning and they are always very challenging.

The challenge was available on https://challenge-1021.intigriti.io/


Context


The challenge was about executing an XSS where alert(document.domain) would be executed and it could not be a self-XSS.

part 1 of 2 - challenge page






















Reconnaissance


The page was composed by the Instructions as well as an Iframe with the page below. Reading the message we can see an information that could be relevant during the tests, a request parameter ?html=.

Also, as there is only an Iframe and no input field, the only way to insert the XSS would be through the url.



part 2 of 2 - challenge page



















Checking the page using the browser's Developer Tool, I found the page challenge.php being loaded in the iframe as well as some errors in the console.

The errors was showing that the XSS would not be so easy since it was an error related to a Content Security Policy violation that leaded me to find that the page was using nonce in the CSP.

Going  Forward, I started checking the page loaded in the Iframe located on /challenge/challenge.php.

The page had three javascript blocks, the first was popping an error in the console since the element with id = lock was not present in the document, the second block, at first glance, tended to be the entry-point, and the third block had a weird string only.




At this stage, I decided to have a look in the second block, there was an eventListener of type DOMContentLoaded that would ended up creating a script elemet in the document and, in the same code, there was a String concatenation using the value from a request parameter called xss.

Testing a request passing this parameter, I was able to see that the information was stored in the third javascript block.


third javascript block


That would be the way where the alert(document.domain) would be passed, but now the challenge is really beginning.


Exploitation


At this point, I had the parameter to pass the XSS but there was a problem. Let's move back to the second Javascript block:

second js block

As we can see above, the value that was coming in the xss param was concatenated with the characters )]}' and due to that the Javascript was facing execution errors.


js error


This problem forced me to explore more the Javascript implementation, as I would need to find a way to fix this execution error before the alert(document.domain) be executed.

Going to the following lines of code after the String concatenation, we can see the variable c retrieving the last HTML element present in the body and an IF checking if the id is equal to 'intigriti', but this IF was not being executed, as the last element in that execution point was always the container;

lastElementChild



With this information in hand, I was aware that I had to find a way to insert an html with Id equal to 'intigriti' as the last element of the body so that the IF clause could evaluate to true, but how?

The answer for this question was described in the page, as mentioned in the beginning, there was a second request parameter called html.

content


At this point, I had the parameters html and xss to be used and then I started trying to create the necessary element to satisfy the IF clause:

first html injection attempt

This request inserted the div into the document, but it was not as the last element of the body

first html injection result


Immediately, my idea was to start closing the parent elements, something like html=</h1></div></div><div id = 'intrigriti'> but I got the following result:

second html injection

I spent some time stuck on that, my element had to be bellow the <div id='container'> but it was never being placed there...

After some time, I finally found the correct sequence and my <div id='intigriti'> was placed as the last Element of the list with the following payload: ?html=</h1></div></div><div id='intigriti'><div>


lastElement = intigriti



At this point I was able to join in the IF, but another problem came out!!




Inside the IF clause, the variable l was retrieving the lastElementChild from my <div id='intigriti'>, and the i variable was retrieving the html code inside this, and last but not least, the last 4 characters present in this piece was stored in the variable f to be appended in the started value of the variable e.

second js block

Those 4 characters would be the ones appended before the characters )]}' that would be solving the javascript error and triggering the alert(document.domain), but every change that I was doing was always returning a piece of HTML tag in those last 4 digits, something like div> or pan>, those values would never solve the Javascript error.



The hint

On the following day, I started the day checking my Twitter and there was a hint shared by Intigriti that made me find the last thing needed to solve the challenge:





This hint took me to  xkcd story related to a SQLi which provided some ideas to check, and then, adding the value  ') in the payload, I saw the first light to solve the challenge.


It turns that when we add the value ') in the html tag, the same is also added in the closure tag, for example:

?html=</h1></div></div><body><div id='intigriti'><div><div')>

first string change

At this point I was closer! I had to do a tiny change to make it work.


The final payload


To make it work I had to modify not only the html param but also the xss param.

The html param  in the end was modified to:

?html=</h1></div></div><div id='intigriti'><div><body><div'(<aa('

in this way the last 4 characters would be ('<>


and the xss param was also changed to :

&xss=);alert(document.domain)


And with that, the javascript string was appended with the value ('<>)]}');alert(document.domain) which is a valid one, and the xss was executed



Final payload:

https://challenge-1021.intigriti.io/challenge/challenge.php?html=</h1></div></div><body><div id='intigriti'><div><body><div'(<aa('&xss=);alert(document.domain)


What a challenge my friend!!!


Thank you for reading that!!

Comments