JWT stands for JSON Web Token, and it is an open standard (RFC 7519) that is used to securely transfer information between two parties as a JSON object. It is commonly used for authentication and authorization in stateless environments, such as, token-based applications and RESTful Web services like APIs.
JWTs are terse, they’re URL-safe, and they can be digitally signed with a secret (using an HMAC algorithm) or a public/private key pair (using RSA or ECDSA). They can be used to authenticate a user and ensure data integrity without authorizing a database request for every single request.
The JWT Algorithm Confusion (also known as key confusion) vulnerability [1] [2] occurs when a server supports both “RS256” (asymmetric) and “HS256” (symmetric) algorithms but uses the same key (public key) for verifying tokens created with either algorithm. The token validation logic must be written in such a way that for both the asymmetric and symmetric algorithms, the same public key is used for verifying the token.
Since the public key could be known to an external attacker, forging tokens and using the public key value as the HMAC secret (HS256) is something that could be exploited if the backend functionality supports this and does not implement a sufficient validation mechanism or different flows for each algorithm used.
Setup
In order to demonstrate how the vulnerability could occur and be exploited by an attacker, a simple application was created. The application was developed using Python (3.11.1)/Flask, SQLite as the database, and PyJWT (2.0.0) as the JWT library used to manage tokens [4].
The application allowed self-registration, login, access to a profile page to display the current user’s information and an administrative page, where privileged users can view the list of users, make modifications to existing users and create new users – either standard users or administrators.
Web Application Development
We won’t go into too much detail for all the sections of the application’s source code; however, sections that were deemed important or needed to follow along with the exploitation are highlighted below.
To support the creation of a “Users” table in the database, the following “User” class was added, defining an “id” (unique id for each user), an “email” variable to store the username, the “password_hash” to store the hashed value of passwords and the “role” variable indicating each user’s permissions: