JSON Web Token (JWT) is a standard that defines a safe, compact, and self-contained way of transmitting information between a client and a server in the form of a JSON object.
Although JWT is a robust mechanism, it is still prone to attacks. This is because a JWT string is the Base64 encoding of the header, payload, and signature. If an attacker gets access to the token, they can decode it and see the information within it.
We can use the following approaches to break JWS authentication:
Some JWTs are signed using the HS256
algorithm. This algorithm uses a secret key to sign and verify messages. It is possible to break an HS256
JWT with a brute-force attack if the key used to sign the JWT is not sufficiently robust. Interestingly, this is an offline attack. Therefore, no requests are sent to the server.
If we attain a valid JWT, we can make various
We can use the following tools for a brute-force attack on the HS256
signature on a JWT:
jwtbrute
(a .NET implementation)
PyJWT
John the Ripper
The alg
field in the JWT header indicates the algorithm used to sign the JWT. All JWT libraries support the none algorithm, which signifies no signature at all. If we specify "none" as the algorithm in the header, and leave out the signature, some implementations may accept our JWT as correctly signed.
{"alg": "HS256","typ": "JWT"}
To implement the none algorithm approach, we follow these steps:
Decode the JWT without validating the signature.
Get a new token using the none algorithm.
If the token is accepted, and the same response of the original token is given, then the authentication functionality arbitrarily accepts the none algorithm.
HS256
uses a secret key to validate and sign the token, and RS256
uses a public key to validate and a private key to sign the token. Now, if we have access to the victim's token (which is signed using RS256
), we can change the token data using the following steps:
Change the algorithm in the alg
parameter from RS256
to HS256
.
Make changes in the payload.
Sign the token using the public key.
Note: We can't use the public key to sign. However, since we change the algorithm to
HS256
, the public key acts as a secret key.
Let's consider the following code that may be present on a server:
jwt = JWT.decode(token, public_key)
If the JWT uses an asymmetric key, this code correctly verifies the signature on the token. If the JWT uses a symmetric key, the code compares the signature to an HMAC of the token, where the public_key
is used as the key. We can exploit this vulnerability by signing our token using HS256
, the public key of the RS256
algorithm.
Note: We can use various public tools to break and test the JWT authentication of an organization and identify its weaknesses.
Free Resources