Intigriti 1337UP CTF | Cat Club (Web, JWT Token Alg Confusion, Pug SSTI)
Difficulty : Medium

The Challenge
The Intigriti 1337 UP CTF was very interesting, this task in particular was made by CryptoCat, it's a medium level task that would require chaining multiple vulnerabilites together to gain RCE.
Accessing the website, we are greeted with a register and login, upon registering we can access the /cat path, from there we have a message with our username.

Let's start by reading the code, there are some notable files :
jwt_helpers.js :
routers.js :
sanitizer.js :
The other files are basic and are not relevant to our challenge.
from what we read we can see the first vulnerability in routers.js :
this is an SSTI vulnerability in pugjs, so we know that we must access the /cats path with a user that would inject code in the template.
since we cannot create a username non alphanumerical letters, we need to inject the payload into a forged JWT token.
Secondly we see that the decode method dosen't check for the algorithm and will take the public key as any from key be it a secret key for HS algorithms or a public to decrypt JWT tokens for RSA.
so we can change the algorithm to HS256 and use the public key as our secret key.
Third we can see that the public key is leaked on /jwks.json, we can get the public key by accessing it and copying the value to this script :
Now that we have the public key we can craft our payload, we can reuse the NodeJs code to create our JWT tokens more easily :

That we feed the forged JWT token to our request and get the flag with RCE using the SSTI we mentioned first.

Remediation
The decode method could be exploited if it were to be used poorly, the best way is to enforce the algorithm to avoid an algorithm confusion attack.
The other better solution is to not use the json-web-token module because it's outdated and dosen't integrate methods that help in such situations, you can instead use the jsonwebtoken module that has methods like verify which integrates the verification of algorithms.
That is a better version of the code that forces the RS256 algorithm.
Last updated