Intigriti’s September XSS challenge Writeup.

pr0fessor
5 min readSep 13, 2021

--

Introduction:

Intigriti again hosted another challenge for the month of september this time its made by @BugEmir and Pepijn. This challenge features a lot of reverse engineering and deobfuscation of javascript code. Additionally a bit of dev console knowledge is something that is more than useful for this kind of challenge.

Lets Start:

So another great challenge from Intigriti for the cozy month. So what do we do first ? Right look at the challenge. (https://challenge-0921.intigriti.io/)

Intigriti Challenge
Hmm a passwordmanager interesting……

So before we start we try to find the url of the password application so we can inspect it further without the information of the Challenge. Seems (https://challenge-0921.intigriti.io/challenge/manager.html) will be our friend the next hours.

Lets dig into the code:

The first thing we have to find out will be the parameter the application asks for when we enter a password.

Without the right parameter the application does not seem to work properly and wont make us run anything malicious on it.

Hmm what could the parameter be ?

So after digging through the files of the website we find “manager.js” which looks pretty promising. We open the file aaaaaaaaannnnnnnnnd ………

Nice obfuscation

We find bunch of rubbish we cant really read. So this seems like deobfuscation is the only answer to this mess. After running the js through an online tool we can now read portions of the code and have some of that hexadecimal stuff decoded.

After decluttering the code online it looks way more readable

In our readable code we find an interesting array. “_0x5195” seems to store multiple HTML elements of the code by renaming it to “HTML_functions” and importing it into our js console we can read the contents of it. “HTML_functions” is basically an array and the code is made unreadable by requesting the html function calls through this array by doing some unnecessary math.

For example HTML_Functions[2005*2 – 4010 +1] refers to the 2nd element of the array in this case length.

So when an element calls something like array[HTML_Functions[2005*2–4010 +1]] it refers to its own length. By randomizing the numbers the code becomes even more unreadable. But the scheme is the same.

Lets find our parameter the smart route!

Interesting……

Now after inserting the array into our js console we can read more of our code and might even be able to trace some parts of it.

Maybe our searched parameter is inside the array. Lets run some regex to check.

function param(instr) {
var reg = new RegExp(/^\?.*/g)
return reg.test(instr);
}

Let’s say this will be our regex to check for our parameter starting with “?”. We enter this into the JS console.

We now search the array with.

HTML_functions.find(param)

Nice seems like it worked and we find our parameter “?password=” that one could have been guessed.

So let’s use the website with our parameter and enter something like “test” to the end of it.

Nice the website works sort of ?

So now what? We have the website working with our parameter but it seems like its not reflecting our input correctly. Seems like its encoded and after a bit of research we find out that the input is encoded via “atob()” so its base64.

Lets try to enter the payload but encode it base64.

<img/src=x/onerror=alert(document.domain)>

We enter the payload but nothing happens. It reflects our img tag but we don’t find any onerror event inside it. After testing further it seems like every event is blocked.

Nice the payload worked but wait …… it didn’t

So something is escaping our events. Maybe have a look at the code again. After scrolling and reading a few lines of code where the parameter is red we find something interesting.

Now thats probably where we have to dig on.

After placing breakpoints around the suspicious part we can now run the code and inspect the potential replacement of the event. By inspecting the variable storing our xss payload we can pinpoint the line where our change happens.

This gives us the ability to understand the code a bit better even when its unreadable.

So we run our code line by line and inspect the memory for any weird or replacement looking like things.

And there we find this line looks suspicious

We know now how the program probably reformats our string as one escaping the event of it. So with that in mind we place our breakpoints once again and debug the program line by line. We know that the code looks at every attribute of our inserted HTML and tries to check if it is an illegal attribute or not.

By debugging the code line by line we now are able to maybe find out how we can evade the detection and find a way to exploit the application.

When we look into the other tools the js console of chrome gives us we can see the word “DOMpurify”. This seems to be interesting so we look it up.

It seems to be a library that should exclude dangerous javascript from inputted data.

Now let’s try exploiting it.

After a few hours of debugging we find the line that is probably responsible for the replacement of the code. Additionally we find that its using a library called “DOMpurify” with which you can easily remove xss from the code. So after a bit of google fu we can find an exploit to run on the app.

<form><math><mtext></form><form><mglyph><style></math><img/src/onerror=alert(document.domain)>

We encode and run the exploit.

Aaaaaaannnd…….

After hours finally the alert

IT WORKS !!!

We now can run xss with minimal user input.

Intigriti verified that this is only possible with a click of the user.

Thanks for reading .!!!!!!!!n

--

--