Token-based authentication is implemented by sending a signed token (verified by the server) with each HTTP request. The most commonly used token format is the JSON Web Token, defined
in RFC7519. A JWT may encode the complete session state as a JSON object. Therefore, the server doesn’t have to store any session data or authentication information.
JWT tokens consist of three Base64Url-encoded parts separated by dots. The Token structure is as follows:
base64UrlEncode(header).base64UrlEncode(payload).base64UrlEncode(signature)
The following example shows aBase64Url-encoded JSON Web Token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva G4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Theheadertypically consists of two parts: the token type, which is JWT, and the hashing algorithm being used to compute the signature. In the example above, the header decodes as follows:
{"alg":"HS256","typ":"JWT"}
The second part of the token is thepayload, which contains so-called claims. Claims are state- ments about an entity (typically, the user) and additional metadata. For example:
{"sub":"1234567890","name":"John Doe","admin":true}
The signature is created by applying the algorithm specified in the JWT header to the encoded header, encoded payload, and a secret value. For example, when using the HMAC SHA256 algo- rithm the signature is created in the following way:
HMACSHA256(base64UrlEncode(header) +"."+base64UrlEncode(payload),secret)
Note that the secret is shared between the authentication server and the backend service - the client does not know it. This proves that the token was obtained from a legitimate authentication service. It also prevents the client from tampering with the claims contained in the token.
Static Analysis
Identify the JWT library that the server and client use. Find out whether the JWT libraries in use have any known vulnerabilities.
Verify that the implementation adheres to JWTbest practices:
• Verify that the HMAC is checked for all incoming requests containing a token;
• Verify the location of the private signing key or HMAC secret key. The key should remain on the server and should never be shared with the client. It should be available for the issuer and verifier only.
• Verify that no sensitive data, such as personal identifiable information, is embedded in the JWT. If, for some reason, the architecture requires transmission of such information in the token, make sure that payload encryption is being applied. See the sample Java implemen- tation on theOWASP JWT Cheat Sheet.
• Make sure that replay attacks are addressed with the jti (JWT ID) claim, which gives the JWT a unique identifier.
• Make sure that cross service relay attacks are addressed with theaud(audience) claim, which defines for which application the token is entitled.
• Verify that tokens are stored securely on the mobile phone, with, for example, KeyChain (iOS) or KeyStore (Android).
Enforcing the Hashing Algorithm
An attacker executes this by altering the token and, using the ‘none’ keyword, changing the signing algorithm to indicate that the integrity of the token has already been verified. Some libraries might treat tokens signed with the ‘none’ algorithm as if they were valid tokens with verified signatures, so the application will trust altered token claims.
For example, in Java applications, the expected algorithm should be requested explicitly when creating the verification context:
// HMAC key - Block serialization and storage as String in JVM memory private transientbyte[]keyHMAC=...;
//Create a verification context for the token requesting explicitly the use of the HMAC-256 HMAC generation JWTVerifier verifier=JWT.require(Algorithm.HMAC256(keyHMAC)).build();
//Verify the token; if the verification fails then an exception is thrown DecodedJWT decodedToken=verifier.verify(token);
Token Expiration
Once signed, a stateless authentication token is valid forever unless the signing key changes. A common way to limit token validity is to set an expiration date. Make sure that the tokens include an“exp” expiration claimand the backend doesn’t process expired tokens.
A common method of granting tokens combines access tokens and refresh tokens. When the user logs in, the backend service issues a short-livedaccess tokenand a long-livedrefresh token.
The application can then use the refresh token to obtain a new access token, if the access token expires.
For apps that handle sensitive data, make sure that the refresh token expires after a reasonable period of time. The following example code shows a refresh token API that checks the refresh token’s issue date. If the token is not older than 14 days, a new access token is issued. Otherwise, access is denied and the user is prompted to login again.
app.post('/renew_access_token',function(req,res) { // verify the existing refresh token
var profile=jwt.verify(req.body.token,secret);
// if refresh token is more than 14 days old, force login if(profile.original_iat-newDate() >14) {// iat == issued at
returnres.send(401);// re-login }
// check if the user still exists or if authorization hasn't been revoked if(!valid)returnres.send(401);// re-logging
// issue a new access token
var renewed_access_token=jwt.sign(profile,secret, {expiresInMinutes:60*5});
res.json({token:renewed_access_token});
});
Dynamic Analysis
Investigate the following JWT vulnerabilities while performing dynamic analysis:
• Token Storage on the client:
– The token storage location should be verified for mobile apps that use JWT.
• Cracking the signing key:
– Token signatures are created via a private key on the server. After you obtain a JWT, choose a tool forbrute forcing the secret key offline.
• Information Disclosure:
– Decode the Base64Url-encoded JWT and find out what kind of data it transmits and whether that data is encrypted.
• Tampering with the Hashing Algorithm:
– Usage of asymmetric algorithms. JWT offers several asymmetric algorithms as RSA or ECDSA. When these algorithms are used, tokens are signed with the private key and the public key is used for verification. If a server is expecting a token to be signed with an asymmetric algorithm and receives a token signed with HMAC, it will treat the public key as an HMAC secret key. The public key can then be misused, employed as an HMAC secret key to sign the tokens.
– Modify thealgattribute in the token header, then deleteHS256, set it tonone, and use an empty signature (e.g., signature = ”“). Use this token and replay it in a request. Some libraries treat tokens signed with the none algorithm as a valid token with a verified signature. This allows attackers to create their own”signed” tokens.
There are two different Burp Plugins that can help you for testing the vulnerabilities listed above:
• JSON Web Token Attacker
• JSON Web Tokens
Also, make sure to check out theOWASP JWT Cheat Sheetfor additional information.