JWT

JSON Web Tokens(JWT) contain claims used for authentication & authorization like session related attributes, role of user, session expiry etc, these are verifiable by server cryptographically by validating the signature part of JWT.

JWT Format -

  1. Header - Header contain information about algorithm used for generating JWT Signature, It may also contain keys, key location, key id's used for generating Signature in some cases.

  2. Payload - Payload contains actual information like user identity(email/username),

  3. Signature - Header & Payload, encrypted by server to cryptographically verify that JWT Token isn't modified client side by the attacker.

eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.
eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.
SYZBPIBg2CRjXAJ8vCER0LA_ENjII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW6lKYNdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5ehoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWAbN-xeLwEenaqBiwPVvKixYleeDQiBEIylFdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP1Oe2Spac-6IfA

JWT is of form Header.Payload.Signature, where each part is seperated by full stop(.) & each part is encoded in base64 format.

For example on decoding above payload, we get -

{"iss":"portswigger","exp":1648037164,"name":"Carlos Montoya","sub":"carlos","role":"blog_author","email":"[email protected]","iat":1516239022}

JWT Signature

JWT Signature is generated by hashing & encrypting the header & payload of JWT token with server's secret signing key. This ensures integrity of JWT as if it's tampered the Signature won't match when server verifies it, unless attacker gets to know of Signing key in which case attacker can generate valid Signature using the signing key.

JWT Header Parameters -

  1. alg - Specifies algorithm to use for generating JWT Signatures.

  2. jwk - jwk param may contain public key incase of RS256, private key incase of HS256 where server might use key from jwk to verify signature instead of key stored loczlly in the server.

    {
        "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
        "typ": "JWT",
        "alg": "RS256",
        "jwk": {
            "kty": "RSA",
            "e": "AQAB",
            "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
            "n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"
        }
    }
  3. jku - jku param is like jku, difference being it contains url from where server can fetch keys required to verify signature.

  4. kid - kid param is key id, which specifies server which key to use incase multiple keys are present for signature verification.Sometime's kid also accepts filesystem input(location of file in server's file system), If this is allowed we can use directory traversal payloads to use arbitrary signature from file system or make it use /dev/null which is empty string to be used for signature validation.

Vulnerability Checklist -

  1. Check for Unverified Signature attack, by either removing Signature or Keeping Signature part intact, while modifying header/payload of JWT. [PortSwigger Lab]

  2. Check for None algorithm attack by modifying alg parameter in header part to none & removing the Signature part of JWT. [PortSwigger Lab]

  3. Check for Weak Signing Keys, If symmetric encryption algorithm such as HS256(HMAC+Sha256) is used, you can check for weak signing keys by bruteforcing secret keys using hashcat. If signing key is found you can generate valid JWT signature. [PortSwigger Lab]

  4. Check that Weak Symmetric algorithm such as none & HS256 is not used, instead asymmetric algorithm such as RS256(RSA+Sha256) is used.

  5. Check for Self Signed JWT attack by using jwk paramater to include own public key to use for signature verification, Generate & include signature in JWT using own private key associated with the public key.[PortSwigger Lab]

  6. Check for Self Signed JWT attack by using jku parameter, which includes url from where server fetches public key to verify signature, you can generate signature part using own public key associated with the public key present in the url.[PortSwigger Lab]

  7. Check for Self Signed JWT attack by using kid parameter to use arbitrary public key from url or filesystem. If file system is allowed test for arbitrary path using path traversal payloads, try to use /dev/null filesystem which is empty string to use for signature verification.If /dev/null is allowed you can use empty string to generate signature. [PortSwigger Lab]

  8. Check for JWT Token Confusion attack, change alg type from RS256 to HS256, obtain server's public key from certificate or from common endpoints such as /.well-known/jwks.json or /jwds.json. Sign the JWT token using public key of server, Server might use HS256 algorithm & use public key of server to decrypt & verify the signature instead of RS256. [PortSwigger Blog] [PortSwigger Lab]

Last updated