JWT Tokens
- Link to PortSwigger
JWT, or JSON Web Token is a form of an authentication token we use.
Like a session cookie, but the data is stored
within
the JWT token itself.
Here is a sample payload. I'd recommend JWT.io
eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.SYZBPIBg2CRjXAJ8vCER0LA_ENjII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW6lKYNdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5ehoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWAbN-xeLwEenaqBiwPVvKixYleeDQiBEIylFdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP1Oe2Spac-6IfA
JWT's always start with eyJ
and is encoded in Base64
(Except for the dots separating the header
, payload
and verify signature
)
Exposed Secret Directory
There may be an exposed secret used to construct the signature
in a JWT-token within the following directory on your target application:
/.well-known/jwks.json
DIFFERENT EXPLOITATIONS
Exploiting flawed JWT signature verification
It is possible to change the payload
without changing the Header or Signature.
Taking the base64 encoded text between the Header and Signature and decode it, you will see something similar to {"isAdmin":"false"}
.
Change the value to true
, encode the payload
in base64 and smuggle it in with the same Header and Signature and see if you've managed to privilege escalate.
Accepting tokens with no signature
It is possible to change the JWT Header where the Algorithm is changed to "none" (can be "None", "NoNe", "nONE" etc...) to confuse the webserver in case "some" protection is in place.
{"alg": "HS256","typ": "JWT"}
-> {"alg": "none","typ": "JWT"}
.
It also works to remove the alg completelt and remain as {"typ": "JWT"}
. All signature checks can break in different ways!
Remember to also remove the whole base64 encoded Signature (NOT
including the dot before the Signature)
Conclusion, the whole string should end with one trailing dot
in the end of the string without a signature.
eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.
Brute-forcing secret keys
Some signing algorithms, such as HS256
(HMAC + SHA-256), use an arbitrary, standalone string as the secret key.
Just like a password, it's crucial that this secret can't be easily guessed or brute-forced by an attacker.
Otherwise, they may be able to create JWTs with any header and payload values they like, then use the key to re-sign the token with a valid signature.
When implementing JWT's in applications, developers sometimes make mistakes like forgetting to change default or placeholder secrets. They may even copy and paste code snippets they find online, then forget to change a hardcoded secret that's provided as an example. In this case, it can be trivial for an attacker to brute-force a server's secret using a wordlist of well-known secrets.
hashcat -a 0 -m 16500 <jwt> <wordlist>
Once the secret key is found, try JWT.io, add the secret and edit the JWT to your desire.
JWT header parameter injections
According to the JWS specification, only the alg
header parameter is mandatory.
In practice, however, JWT headers (also known as JOSE headers) often contain several other parameters.
The following ones are of particular interest to attackers.
jwk
(JSON Web Key) - Provides an embedded JSON object representing the key.jku
(JSON Web Key Set URL) - Provides a URL from which servers can fetch a set of keys containing the correct key.kid
(Key ID) - Provides an ID that servers can use to identify the correct key in cases where there are multiple keys to choose from. Depending on the format of the key, this may have a matching kid parameter. Be sure to try and use the JWT Editor Keys Extension in Burpsuite!