wallpaper

The Password Reset Token Leak

When you think about authentication, the first things that come to mind are usually strong passwords, encryption, or multi-factor security. But what if the real problem isn’t a missing cipher or a weak password? What if it’s the logic behind how you handle sensitive data that blows your security wide open?

One classic example? Password reset flows that leak tokens insecurely breaking the whole authentication logic, no matter how tight your password rules are.

The Logic Flaw: Leaking Reset Tokens in API Responses

Password reset tokens are supposed to be secret. But in some apps, when you request a reset, the server sends the token right back in the HTTP response. That means anyone who can see that response whether a hacker sniffing your Wi-Fi, a rogue browser extension, or someone with access to your proxy logs can grab the token and hijack the account.

This isn’t just a bad idea. It’s a fundamental logic flaw:

  • You’re trusting the client to keep the token secret.

  • You’re exposing a sensitive credential through an insecure channel.

  • You’re breaking the authentication flow by giving attackers a shortcut to reset passwords without ever logging in.

Why This Breaks Authentication Logic

Authentication relies on secrets. Reset tokens are one-time secrets meant to verify that only the rightful user can reset their password. But if those secrets are freely shared in API responses, the attacker’s path becomes effortless.

In short: you can have the strongest password hashing, but if you leak your reset tokens, your entire login security is toast.

Breaking Down Authentication: Exploiting the Password Reset Feature

Alright, let’s dive into the authentication flow on the HackMe website and see how we can escalate from a normal user to the admin.

Imagine the login page looks like this:

Welcome to HackMe Website Login | Reset Password

No Detection

For starters, we have these normal user credentials:
user@hackme.com / password123
Logging in with these works fine, and after login, we get this message:

Welcome user@hackme.com! You are logged in as a normal user. Logout

No Detection

No Detection

Cool, but we want to level up specifically, get admin access.

So, let’s check out the Reset Password option. The interface asks for an email:

Reset Password
Enter your email:

We swap out user@hackme.com with admin@hackme.com and hit send. The site responds:

If your email exists, a password reset token has been sent.

No Detection

No Detection

Pretty standard, right? But what’s going on behind the scenes? Time to dig deeper.

We repeat the request but this time, monitor it closely using Burp Suite. On the left, we see the HTTP request, and on the right, the response.

If we inspect carefully, there’s a password reset token inside the response, along with an endpoint URL.

Now, here’s the juicy part using that token, we access the reset endpoint:

No Detection

Confirm Password Reset

Reset Token: [token here]

New Password: [new password here]

No Detection

No Detection

No Detection

No Detection

By plugging the token in and setting a new password, we effectively reset the admin password and gain full access.


This is a classic example of how insecure password reset mechanisms can be abused to escalate privileges. Always check how tokens are generated and validated. Weak flows like this can be your golden ticket.

JWT Vulnerability: Bypassing Role-Based Access


In this example, we’re dealing with a login interface that looks pretty normal on the surface but has a nasty misconfig behind the scenes.

🧪 Credentials

You can log in using:

Username: user Password: userpass

No Detection

No Detection

Once you’re in, you land on this dashboard:

Welcome, user! Your role: user [ Go to Admin Panel ]

No Detection But when you click Go to Admin Panel, you get smacked with:

Access Denied You are not an admin. [ Back ]

No Detection

So far, standard RBAC stuff, right? Let’s peek under the hood.


Token Inspection (Burp Suite)

Open up Burp Suite and log in with the test creds. Go to HTTP History and look for a request to /dashboard. Burp will pick up a JWT token automatically thanks to the JWT Editor extension.

No Detection

You’ll see something like this in the Cookie header:

eyJhbGciOiAibm9uZSIsICJ0eXAiOiAiSldUIn0.eyJ1c2VybmFtZSI6ICJ1c2VyIiwgInJvbGUiOiAidXNlciJ9.

Decode it, and you’ll find:

{ "alg": "none", "typ": "JWT" }

Payload:

{ "username": "user", "role": "user" }

No Detection

Red flag spotted: alg: none. This means the server isn’t verifying the JWT’s signature. We can forge our own token. Let’s do it.


Exploitation: Become Admin

Change the role in the JWT payload to "admin":

New Payload:

{ "username": "user", "role": "admin" }

Re-encode the JWT without a signature (keep alg: none) and replace the token in your browser using a cookie editor or Burp Repeater.

Your forged token might look like:

ewogICAgImFsZyI6ICJub25lIiwKICAgICJ0eXAiOiAiSldUIgp9.ewogICAgInVzZXJuYW1lIjogInVzZXIiLAogICAgInJvbGUiOiAiYWRtaW4iCn0.

No Detection

No Detection

Go back to /admin, refresh the page boom, you’re in.

Admin Panel 🚩 FLAG: FLAG{jwt_admin_escalation_success}

No Detection


Why This Matters

This is a real-world vulnerability. A lot of devs incorrectly implement JWTs and allow alg: none, thinking the payload is safe. But if you don’t validate the signature, you’re literally letting anyone forge roles, identities full takeover.

Bypassing 2FA: How I Sneaked Past OTP with a Simple Bug

Alright, so imagine this: we already cracked the admin password classic admin:adminpass.

No Detection

But boom! There’s a 2FA in place, and it’s asking for an OTP code. For this demo, I simplified it to a 3-digit OTP just to keep things chill. I’m running a Python debug script that simulates the OTP being sent to the admin’s email, so I can spy on the code before it hits their inbox.

No Detection

Next up, the login page asks for the OTP and gives you an option: “Remember this device,” so next time, no OTP hassle.

No Detection

Now, after some failed OTP tries, it says:

Too many OTP attempts. Try again in 60 seconds.

No Detection

No Detection

Classic rate limiting. But let’s peek under the hood using Burp Suite to see what’s really going on with the requests.

No Detection

Notice the parameter: remember_device=on This tells the server to remember your device and skip OTP in the future.

Here’s the trick: what if we send the param but empty? Like: remember_device=

No Detection

When I do that, no more rate limiting. The server isn’t blocking attempts anymore.

On the debug side, the OTP code is logged like this: [DEBUG] OTP for admin: 382

No Detection

Since it’s only 3 digits, I scripted a quick brute force from 300 to 400 keeping it tight to avoid long waits.

No Detection

No Detection

With this, I eventually hit the right OTP: 382. After the correct OTP, the session key updates, and now I’m fully logged in.

No Detection


Why this matters:

  • Rate limiting bypass: The bug with remember_device lets us spam OTP attempts without waiting.