This post is originally written in my personal blog Anudeep's blog
This post is a walkthrough of a lab from ctflive. You can find this lab here, First give it a try yourself before going through this post. It's a JWT based challenge. For those of you who don't know what a JWT is. don't worry there will be a short introduction about that in this post.
What is JWT🤔?
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties. (source: https://jwt.io). What does this even mean🤷♀️?.
Let us have a look at one of the best explanations i read so far and it's by Kasey Speakman. I am dropping his dev profile here, do drop a heart on his actual comment that is linked below.
Let's get into the actual working now
A JWT is of the format xxxxxxxxx.yyyyyyyyyyy.zzzzzzzzzzzz
.
- x's specify the algorithm used to sign the JWT in base64.
- y's contain the claims in base64.
- z's are the signature that is generated with
xxxxxxxxx.yyyyyyyyyyy
as the data.
The Algorithms that are generally used to sign JWT includes:
- HS256 (Symmetric)
- RS256 (Asymmetric)
Where are these used?
As far as our lab is concerned, we use it to authenticate users to a website. So when a user logins to a website the website will issue a JWT with the claims of who the user is and any additional information. This JWT is sent back to the website in the subsequent requests made by the user. The JWT is first verified to check if the signature is legit, it's basically done by again signing the xxxxxxxxx.yyyyyyyyyyy
of the token and checking if it matches with the signature that is sent as a part of the JWT. If they are equal then the server can trust the claims that come with the JWT. If any user tries to tamper with the claims in the JWT(the data in yyyyyyyyyyyy part) then the signature won't match and in an ideal condition the website should through an unauthorized message.
Now the Lab
Mission 💻
Retrieve the secret information present in the token payload!
We are given with a CMS to interact with. The Lab also gives you with the username and password to login to the user account.
Let's start
Starting the lab you will be given a virtual environment where the CMS is hosted in your local network and you have a machine with all the tools you will need preinstalled.
The challenge page also gives you few instruction on how to access the CMS that is hosted in your local environment.
It says the CMS runs on port 1337 and since I have already worked with a CMS that works on that port, I knew it was strapi already.
Now let us try to login with the credentials given. Strapi currently manages admin and end users separately. I assume that the credentials given to us are of the end user. So we can't access the strapi admin page with these credentials. All we need is the JWT because out flag is hidden these as the name of the challege suggests.
First we need to find the IP address on which the CMS is hosted. For that run ifconfig
in your console to find your IP and then follow the instructions of the challenge to find the IP of the CMS.
In my case my IP was 192.142.236.2 and that of the CMS was 192.142.236.3. It is given in the challenge on what is the auth endpoint and the parameters that it accepts.
Let us use curl to send the request. I ran the following command to send a post request to the CMS and retrieve the JWT from the response.
Now copy that JWT from the console and head over to jwt.io which will decode the JWT for us.
Voila, there's our flag🎉.
Learning
Sometimes developers might end up sending critical information in the JWT. Make sure you check for such information during bug bounty or when you are building your own application.
This one is tough to explain LI5. Most physical analogies fall down. I attempted several already and threw them away. And things that are like JWT (like the chip in credit cards) have to be explained too. Hopefully somebody has a good analogy handy.
Edit: Actually I thought of one.
For background, in the US the legal age to consume alcohol is 21 years. Restaurants are required to verify your age is at least 21 before serving alcohol. They normally do this by checking your driver's license.
Scenario 1: (Not JWT)
I'm at a restaurant and I order a beer. This particular restaurant takes age verification very seriously. So the waiter asks to see my license. I provide it, but then he goes and gets a phone. He calls the DMV, waits on hold for a bit, and asks them to verify the license details. Once he talks to the licensing authority and they confirm my date of birth, then he goes and gets my beer.
This is the old style of authentication, where you present your session cookie. When the server receives the session ID from the cookie, it turns around and calls the session service (or queries a database or memory) to find out if your ID is still good, and additional information that might be stored in that session.
As you can see, this can become a bottleneck to service.
Scenario 2: (JWT)
I'm at a restaurant and I order a beer. This particular restaurant also takes age verification very seriously. The waiter asks to see my license, and I provide it. The waiter pulls out a UV light and inspects the watermark on my license. It checks out ok, so he hands the license back and gets my beer.
In this case, the issuing authority of the license placed a special "seal" into the license that can be used to identify valid licenses. This means that verification can be performed without calling back to the DMV. The waiter has to know exactly what seal to look for. That might mean he has to go look up the state's seal sometimes. Once the waiter determines that the license is valid, they can trust the Date of Birth information on it.
This is the JWT variety of authentication. Once the DMV believes you are who you say (JWT version: autheticated, probably with password), it collects various data about you (JWT version: claims) and puts it on the license (JWT itself). When the license is issued, it is also watermarked with a seal (JWT version: digital signature) so that it can be examined for validity by people who know what to look for (JWT version: your API validates the JWT signature with a shared key). After that, the license (JWT) is trusted and the Date of Birth (claim) is assumed to be true.