August 25, 2026
Try Hack Me-TryHeartMe CTF Challenge
Room Link:https://tryhackme.com/room/lafb2026e5
By Karthik Warrier
4 min read
After practicing my web hacking skills in port swigger for the past few days, I thought maybe I should put my skills to test, and so I found this interesting try hack me ctf challenge. Honestly it was a straightforward room.
Enumeration
The first thing I did was to go through the website, look around see what I could find. Honestly it was just a simple website, a home page with 4 items, a login page and a register page:
After some time trying maybe some SQLi and some common email password combos, I decided to sign up with random credentials.
The first thing I noticed after logging in was that there is a credit value onthe right side of the page. The first thought that came to me was that maybe I could increase my credit value. We can see that we need credit to buy these items. But I kept that thought for later and decided maybe its time I see what these items are:
Okay so I clicked the first product, again, there is our credit on the right side, but there is now a new value, our role. Interesting.
The rest of the website was pretty much the same.
Exploitation
The first thing I did was to somehow find a way to get more details. I wanted to know how the website knew how much credit I had and my role. So I went to my account page:
Nothing Eventful here, I intercepted using burp suite and inspected what the response was, it was html.
The next thing I did was to logout and login again, but this time I intercepted the login using burp suite and read the response using repeater, I changed some values here and there, but did not find anything useful.
My next idea was to create a new account and this time, maybe I could add my role or my credits after intercepting the request.
next=&email=random%40rd.com&password=random
This was the payload while registering, I thought why not add a role at the end, it could hurt right…
next=&email=random%40rd.com&password=121212&role=adminnext=&email=random%40rd.com&password=121212&role=adminI forwarded the request hoping it would work, but No luck….
Okay so after that failed, I went into the dev tool -> memory and found the jwt token and decoded it from jwt.io :
And here we can see that, values like credits and role is encoded into the token. The first thing that came into my head is alg: None vulnerability. I thought maybe I should try it, so I made a simple payload:
{
"email": "test@test.com",
"role": "admin",
"credits": 0,
"iat": 1787587436,
"theme": "valentine"
}{
"email": "test@test.com",
"role": "admin",
"credits": 0,
"iat": 1787587436,
"theme": "valentine"
}It was a simple payload, basically replacing role from "user" to "admin".
I encoded it, pasted it in the cookies session and reloaded, and there boom, I got admin access:
From here it was pretty straightforward, just go to the admin section, there we need to buy the 'Valenflag' and then we get the flag. We can see that we have 5000 credits. So we could buy the 'ValenFlag' item.
Root Cause Analysis
My assumption was actually wrong, it was never Alg:None vulnerability. This is an Authentication Bypass via missing JWT signature verification. So basically when I forged a jwt token:
a-string-secret-at-least-256-bits-longa-string-secret-at-least-256-bits-longThis was the default string and I didn't change it. Later after the admin access, I went back and played with it a few more times. No matter what signature I give, the jwt token works. Which means, there is no verification happening internally. The token is decoded and the values are taken in as it is. This could easily be manipulated by jwt forgery as shown above.
Remediation
Okay so The main problem here, as I mentioned above was that the token's payloads were treated as authentic without verifying it first. The fix is simple, always verify jwt tokens cryptographically before their claims are trusted. Its an important rule in security to never trust any data without proper verification. Its also worth noting that values such as credits or roles are sometimes treated as sensitive and it don't need to be a part of payload in the jwt token. Instead fetch it directly from the database. This may need some extra computation, but its a valid trade-off for security.
What I learned
This was a very simple yet one of the important rooms I have done. I basically saw how easy it is to forge and manipulate jwt tokens. It made me realise that authorization is not just checking if password entered is right or wrong, but there is more to it. Authentication failures is 7th in OWASP top 10. that actually tells you something about this type of vulnerabilities.