Securing JSON Web Tokens

Introduction

JSON Web Tokens are a storage mechanism for data. JWT can provide the following security mechanisms:

  • Encryption.

  • Signature.

    • Authorizes the person requesting the information

Critical Vulnerabilities in JWT libraries : https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/.

Structure

  • Header & Payload are plain JSON objects & encoded used Base64url.

  • No sensitive information should be passed in Header & Payload.

  • Base64url is a variant of Base64.

  • Signature is used to validate the payload on the Resource Server

Header

  • This information is essential for the resource server to be able to validate the signature, by using an appropriate algorithm before providing access to the requested resource.

    • {Type:JWS} : Tells us its a signed token.

Payload

  • Contains user identification information for authorization.

Signature

  • Contains information for the resource server in order to verify the tokens integrity.

  • Calculated using the header,payload and key.

  • These are some popular types:

    • HS256

    • RS256

    • Elliptic Curves

    • None

HS256

  • Symmetric signature, which means the same secret must be used to sign the JWT and verify the signature.

  • Uses SHA256-HMAC(Hash-Based Message Authentication Code)

key = 'privatekey'
unsignedToken = encodeBase64(header) + '.' + encodeBase64(payload)
signature = HMAC-SHA256(key, unsignedToken)

Workflow

  1. Client authenticates with the Authorization Server.

  2. Authorization server verifies credentials against stored DB.

  3. Once verified, a Secret Key is used to sign & generate a JWT.

  4. This Secret Key also needs to be distributed on all the Resource Servers.

  5. Client sends the JWT to the Resource Server.

  6. Resource Server validates the JWT by recreating it with the same Secret Key.

Risks:

  • Stolen Credentials

  • Insecure distribution of Secret Keys.

  • Compromise of any Resource Server/Authorization Server.

  • Brute-forcing the Secret Key

RS256

  • Asymmetric signature, which means a private key must be used to sign the JWT and a different public key must be used to verify the signature.

  • Signature=Base64url encoded (RSA Private Key Signed {SHA256[encodedHeader, encodedPayload]} )

  • Resource Servers have the public key to validate if the Signature is valid. It cannot create JWTs.

  • Signature is much longer in RS256 in comparison to HS256

Workflow

  1. Client authenticates with the Authorization Server.

  2. Authorization server verifies credentials against stored DB.

  3. Once verified, an RSA Private Key is used to generate a JWT.

  4. Client sends the JWT to the Resource Server.

  5. Resource Server uses a Public Key to validate the signature in JWT.

  6. Public Key is available with all Resource Servers.

Benefits:

  • Private is known only to Authorization Server.

  • Only server with Private Key can create JTWs.

  • RSA Key is long enough to prevent Brute-force attacks.

Attacks Against JWT

Empty Signature

  • No signature present in JWT.

  • Vulnerable to tampering of Payload as Resource Server cannot validate the JWT.

  • Base64url decode Payload - -> Change username to admin - ->Base64url encode - -> Send request with new JWT.

  • Online Encoder/Decoder: http://www.base64url.com/

    • When encoding/decoding, make sure there are no spaces between the parameters. like so, {"alg":"HS256","typ":"JWS"}

Signature Stripping

  • Vulnerable if the Resource Server supports "None" signature algorithm and allows the user to choose which algorithm to use when validating JWT.

  • Base64url decode Header- -> Change algorithm to "None" - -> Base64url encode - -> Send request with new JWT.

    • Use capital 'N' for 'None'.

Brute-Force HS256 Shared Key

jwt-cracker <token> [<alphabets in Key>] [<maxLength of Key>]
  • Once the key is cracked, one can create JWT tokens using HS256 algorithm.

Substitution Attack

  • Occurs when RS256 algorithm is used.

  • Vulnerable if Resource Server accepts RS256 and HS256.

  • First decode the JWT and tamper the Header & Payload

  • We will use the RSA Public Key as HS256 Shared Secret to sign and create a JWT.

  • Perform recon for the Public Key:

    • https://YOUR_DOMAIN/.well-known/jwks.json

    • WaybackURL

    • Javascript files

  • Force the Resource Server to accept HS256, so that the server will validate using the same Public Key.

  • The vulnerability occurs because in this case, the client can choose between RS256 and HS256.

    • If RS256 is used, the Public Key is used to verify the signature, as expected.

    • If HS256 is used the Public Key is again used to verify the signature. But HS256 algorithm uses a shared key to create the signature as well as verifying the signature.

KID manipulation

KID stands for “Key ID”. It is an optional header field in JWTs, and it allows developers to specify the key to be used for verifying the token. The proper usage of a KID parameter looks like this:

{
 "alg" : "HS256",
 "typ" : "JWT",
 "kid" : "1"       // use key number 1 to verify the token 
}

Since this field is controlled by the user, it can be manipulated by attackers and lead to dangerous consequences.

Defenses

  • Do not use 'None' Type Algorithm

  • Use a white-list of allowed algorithms['HS256',none]

  • Use strong shared secrets

  • Use one algorithm method instead of white-list['RS256']

  • Don't carry sensitive information in the token.

Resources

Last updated