Algorithm confusion attacks (also known as key confusion attacks) occur when an attacker is able to force the server to verify the signature of a JSON web token (JWT) using a different algorithm than is intended by the website’s developers.
How Do Algorithm Confusion Vulnerabilities Arise?
Many libraries provide a single, algorithm-agnostic method for verifying signatures that relies on the alg parameter in the token’s header:
Problems arise when website developers use this method assume that it will exclusively handle JWTs signed using an asymmetric algorithm like RS256. Due to this flawed assumption, they may always pass a fixed public key to the method as follows:
In this case, if the server receives a token signed using a symmetric algorithm like HS256, the library’s generic verify() method will treat the public key as an HMAC secret. An attacker could sign the token using HS256 and the public key, and the server will use the same public key to verify the signature.
Performing an Algorithm Confusion Attack
An algorithm confusion attack generally involves the following high-level steps:
Obtain the server’s public key: servers sometimes expose JWK via a standard endpoint mapped to /jwks.json or /.well-known/jwks.json.
Convert the public key to a suitable format: in addition to being in the same format, every single byte must match, including any non-printing characters.
Create a malicious JWT with a modified payload and the alg header set to HS256.
Sign the token with HS256, using the public key as the secret.
To convert the public key to a suitable format using JWT Editor extension:
With the extension loaded, in Burp’s main tab bar, go to the JWT Editor Keys tab.
Click New RSA Key. In the dialog, paste the JWK that you obtained earlier.
Select the PEM radio button and copy the resulting PEM key.
Go to the Decoder tab and Base64-encode the PEM.
Go back to the JWT Editor Keys tab and click New Symmetric Key.
In the dialog, click Generate to generate a new key in JWK format.
Replace the generated value for the k parameter with a Base64-encoded PEM key that you just copied.
Save the key.
Lab: JWT Authentication Bypass via Algorithm Confusion
There is a public key located at /jwks.json endpoint:
The public key in PEM format:
Follow the above steps to turn the public key into a symmetric key:
Change header and payload into this:
Sign it with the generated symmetric key and send the request.
Deriving Public Keys From Existing Tokens
You may still be able to test for algorithm confusion by deriving the key from a pair of existing JWTs. This process is relatively simple using tools such as jwt_forgery.py. You can find this, along with several other useful scripts, on the silentsignal/rsa_sign2n.
We have also created a simplified version of this tool, which you can run as a single command:
This uses the JWTs that you provide to calculate one or more potential values of n. For each potential value, our script outputs:
A Base64-encoded PEM key in both X.509 and PKCS1 format.
A forged JWT signed using each of these keys.
Lab: JWT Authentication Bypass via Algorithm Confusion with No Exposed Key