It’s another Juice Shop challenge. This one involved JSON Web Tokens:
Forge an essentially unsigned JWT token that impersonates the (non-existing) user jwtn3d@juice-sh.op.
As far as I knew, JWTs were a way to determine authorization between a user and a web server, without the web server needing to keep track of sessions.
I had honestly forgotten what they looked like though, and after watching a few Youtube videos, I knew it’d be a Base64-encoded token that included three parts (header, payload, and signature) and was separated by periods. So I decided to see what happened when a user on the Juice Shop site logged in.
I observed the user Amy being given a token after logging in (via SQL injection):
And when I looked at a simple query using the Juice Shop search bar as the user, I could see the same token was in the bearer authorization header:
That looked promising. I went to the site jwt.io, to decode the token. I could see the header, the payload, and that the signature was using asymmetric encryption:
The challenge mentioned an unsigned token, so my guess was that meant that it really wouldn’t matter to the server if the token was signed or not.
I went to CyberChef and started to modify and re-encode the token. First, I changed the header. For the algorithm JSON field I put “none”:
I pasted the header in a text editor, and was careful to get rid of the Base64 padding (the = sign). And then for the payload I put jwtn3d@juice-sh.op as the email:
I pasted that in a text editor as well. I then put the two strings together, separating them by a period. I took that search bar query I had made as the user and sent it to Repeater in Burp Suite, and then I deleted the original token in the bearer header and replaced it with my new one.
For some reason, it wasn’t working after I submitted it a few times. After a bit more digging I realized I also had to put a period at the end of the token for it to work. It’s really important when modifying these tokens to remember the periods and to leave out the Base64 padding. After I added the period to the end of the token it worked, and it was confirmed that the server was accepting unsigned JWT tokens: