By Andy Pantelli
JSON web tokens are most used for authorisation, with the format taking 3 parts: header, payload, and signature. A token (JWT) is used as a standard format to transfer information between two parties. This information can be trusted and verified because it has been digitally signed. The JWT token can also be signed using a Hashed Message Authentication Code (HMAC), or by using a Public/Private key pair using ECDSA or RSA.
Due to design issues and flawed handling of the JWTs, this can leave web applications vulnerable to several high-severity attacks. With the very nature of JWTs which are most commonly used in session management, access control mechanisms and authentication these vulnerabilities can have a severe impact and could even compromise an entire website and its users.
Understanding a JSON Object
A header is a JSON object which provides the Metadata of the token and is used to define the algorithm name for signing the signature & the type.
The payload is also a JSON object and is used to store user information, such as the ID, role, username and token generation.
The last part is the Signature, which also happens to be the most important part and is used to determine the integrity of the take by signing a Base64-URL encoded Header and Payload with the secret key. Looking more closely at the format, the JWT as already explained comprises of three parts with each separated by a period or ‘dot’ as illustrated below:
JWT FORMAT
eyJraWKiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9xIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYJJsb3NAY2FybG9zLW1vbnRveeWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.SYZBPIBg2CRjXAJ8vCER0LA_ENMII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW67KONdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5fhoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWBbN-xeLwEenaqBiwPVvKixYleeDQiBEIy2FdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP9Oe2Spac-6IfA
The data can be easily read in most cases or modified by anyone with the token. The security of any JWT token is dependent upon the cryptographic signature, looking this token the Payload is broken down to reveal the following claims:
{
“iss”: “packtsecpro”,
“exp”: 1342047144,
“name”: “Andy Pantelli”,
“sub”: “Andy”,
“role”: “Admin”,
“email”: “[email protected]”,
“iat”: 1515239002
}
JWT SIGNATURE
The issuing server typically generates the token signature by using a hash of the header and the payload. In some instances, the resulting hash is also encrypted. In both cases, the process requires a secret key. Without having knowledge of the secret, it is impossible to generate a valid signature for the Header & the Payload, locking down the contents against adversarial threats (in theory).
Any changes to the header or payload would result in a mismatch of the signature. This provides an integrity check for servers to verify none of the data in the header or payload has been tampered or modified.
JWT ATTACKS
JWT attacks are when modified tokens are sent to the server with the aim of compromise to achieve part or all of the adversary’s objectives. Typically, this will be with the intent of bypassing authentication and any access controls to impersonate a user that has already been authenticated. This can obviously have severe impact, if the attacker is able to craft their own tokens with arbitrary values, they may be able to escalate privileges or to impersonate an authenticated user to take full control of their accounts.
Vulnerabilities within JWTs typically arise from flawed handling of the token by the application. JWTs are very flexible and adaptable by design which gives developers a great degree of control but also creates insecurity providing the capability to decide upon implementation details for themselves. This can lead to the unintentional creation of vulnerabilities, even if using established or mature libraries.
This lack of validation is a known flaw in which JWT signatures are not correctly verified and allowing an adversary to modify values passed to the application via the Payload. Even if the signature is verified, whether it can actually be trusted is reliant upon the server’s secret key’s integrity. If this is compromised in any way, such as by using brute-force techniques for example then the attacker can generate a valid signature for any arbitrary token and thereby compromising the entire system.
EXPLOITING JWT SIGNATURE VERIFICATION
Servers do not usually store the JWT information which they themselves issue. Rather each token is an entirely self-contained entity. Whilst this does have advantages, this also introduces a significant problem. The Server is unaware of the token’s original contents, or what the signature was. This provides a suitable vulnerability to exploit.
{
“username”:“Andy”,
“isAdmin”: “true”
}
If the Server matches a session based on this username, modifying the value could enable an attacker to impersonate other logged-in users. Alternatively, if the “isAdmin” value is used this can provide a simple technique for privilege escalation
JWT Attack Vectors
Exploiting Signatures is not the only attack vector or technique used by adversaries. Many options exist which contribute to the criticality of enforcing strict security controls and validations in application libraries. Accepting arbitrary signatures JWT libraries provide one method for decoding tokens and another for verifying. If a developer passes incoming tokens to the decode method then the application will not verify the signature. Another inherent flaw is the acceptance of implicitly trusted user input from the token, which to this point hasn’t been verified.
This allows an attacker to control how a Server checks if a token is trustworthy. Secret Keys can be brute-forced, using tools such as hashcat. Obtaining a valid, signed JWT from a target Server and word list then run the following command hashcat -a 0 -m 16500 <jwt> <wordlist> hashcat then signs the Payload, and the Header from the JWT using each secret in the wordlist then comparing the resulting signature with the original from the Server. If the signatures match, hashcat will output the identified secret in the following format <jwt>:<compromised-secret>.
Other techniques include algorithm confusion, Header injection of self-signed JWTs via the kid, jwk & jku parameters.
JWT Attack Prevention Techniques
Following best practices when using JWTs in applications
- Enable the issuing Server to revoke tokens on logout
- If possible do not send token via URL parameters
- Set expiry date for tokens
- Always include the aud (audience) claim, to specify the recipient of the token to avoid it being used on different websites.
Learning to work around JWT attacks
In this article, we have learned about JSON Web Tokens, what they are & how they are used. We have also looked at some of the techniques used by adversaries and lastly some of the simple mitigation steps that can be taken to secure your applications from JWT Attacks.
If you want to learn more about JWTs please visit JSON Web Tokens – jwt.io , any vulnerabilities or mitigations described in the article are purely the personal view of the author and no development or design advice should be accepted without your own research.