Skip to content

Known Exploits and Attacks

ticarpi edited this page Nov 11, 2020 · 3 revisions

A number of exploits have been reported and disclosed that affect various JWT libraries.
It is interesting to note that all of these affect the token by manipulation of the header values. This is mainly because the header controls how or with what a token is signed. Attacks the target values in the payload section are likely platform/service specific, rather than library-specific.

It is also worth noting at this point that (in the absence of extremely verbose errors) it is unlikely that you'll know what JWT library, let alone what version of that library, is signing tokens on a given service. For this reason when testing JWTs our best bet is to try all the hacks and see if anything sticks.

The following CVEs exist for JWT libraries:

  • CVE-2015-9235 alg:none Attack
  • CVE-2016-5431 Key Confusion Attack
  • CVE-2018-0114 Key Injection Attack
  • CVE-2020-28042 Null Signature Attack

Additional known attacks

  • JWKS Spoofing
  • "kid" Injection
  • Cross-service relay attacks
  • Weak secret used as a key

CVE-2015-9235 - alg:none Attack

This attack targets an option in the JWT standard for producing unsigned keys. The output literally omits any signature portion after the second dot.
Due to weaknesses in some libraries or server configurations a service may read our tampered request, see that it does not need to be signed, and then just accept it on trust.

Example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJsb2dpbiI6InRpY2FycGkifQ.
Deconstructed:
{"typ":"JWT","alg":"none"}.
{"login":"ticarpi"}.
[No signature!]

To defend against this attack:
The JWT configuration should specify only the signing algorithms that are required (NEVER "none"!).

CVE-2016-5431 - Key Confusion Attack

This attack plays around with the fact that some libraries use the same variable name for the secret that signs/verifies the HMAC symmetric encryption, and the secret that contains the Public Key used for verifying an RSA-signed token.
By tweaking the algorithm to an HMAC variant (HS256/HS384/HS512) and signing it using the publicly available Public Key we can trick the service into verifying the HMAC token using the hard-coded Public Key in the secret variable.

Example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.I3G9aRHfunXlZV2lyJvWkZO0I_A_OiaAAQakU_kjkJM
Deconstructed:
{"typ":"JWT","alg":"HS256"}.
{"login":"ticarpi"}.
[Signed with HMAC-SHA256, using the Public key file identified for the service as the ‘secret’]

To defend against this attack:
The JWT configuration should only allow either the HMAC algorithms OR the Public Key algorithms, never both.

CVE-2018-0114 - Key Injection Attack

This attack tries out a less-commonly used verification technique in some JWT libraries - the inclusion of an in-line Public Key.
The attacker can sign the token using a new Private Key, include the Public Key in the token and then let the service use that key to verify the token.

Example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp3ayI6eyJrdHkiOiJSU0EiLCJraWQiOiJURVNUIiwidXNlIjoic2lnIiwiZSI6IkFRQUIiLCJuIjoidTdzRU00RmlvT3J6ODFPSENBUGRUZjNncUc4dm12NVJOUndTd0t4X3RqMHBsRjlrdmtEUHVMTDRVa3JqTnVCMWNHdU1hanFxR0xTZXpRQ0xBWmRldC0td3FSbVRfVGNVeGtieVZMV1JiUUg5UWNJRVM0UXpuc20yckR0Wnp4U1VHNnVlNzBBRm1EZkdiSkVQMGI5Nkllc0JfNlBTOS1FWXdLXzl5X3ZwRTloZTNNTUo4WEROSVM5amNSUkNqc21DVldQb1BGX01NcUZjZmZfeWZPNDRPQkVSZWdOOHB2b19UX3Bial91ZkU2X1pGek80VUl6QkNzRUR4RE5mZk9RRkdNRzZoaXRjQm8wTmJSUkFVYUY3dmhMYVRkQjNjRXdPLWVoNEZpSm9nRVRMZGxPRVFXRlZCZldLUWh1YWJEU0FnWGZQOUNXbXh1Smg5YzNRX0tMZFF3In19.eyJsb2dpbiI6InRpY2FycGkifQ.jFu8Kewp-tJ4uLVTRm6D5wBkbikNtLufGHa8ZmEutAZyrPETaD5JaLHZ8Mlw6zBxCNKzmAXbEaDGtNoQ6rfIGHwiTwzk2C897HNR-vwTAyHh7lAgixelqrlkAP7OBWEALH_u7QuIDZpu79V4Aur9CzYai9UvaLqsHhFLf4Gwha9CGV68BnO_Cxye_5vRhzcWEPXIAp8DQMHEDovS6NF_CTEvKA8I6jp2nb726m0nLJo-WWKlCF0UNwSGZ3R3A0YFPL-I1Ld6_8W2dIZRKt4PAtEAPde-RIyf9vKWaHsQDaxnI40xxN3IwvkB2-nDUaTLZtVwBBiTEMoUrkoNTY6XKg
Deconstructed:
{"typ":"JWT","alg":"RS256","jwk":{"kty":"RSA","kid":"TEST","use":"sig","e":"AQAB","n":"u7sEM4FioOrz81OHCAPdTf3gqG8vmv5RNRwSwKx_tj0plF9kvkDPuLL4UkrjNuB1cGuMajqqGLSezQCLAZdet--wqRmT_TcUxkbyVLWRbQH9QcIES4Qznsm2rDtZzxSUG6ue70AFmDfGbJEP0b96IesB_6PS9-EYwK_9y_vpE9he3MMJ8XDNIS9jcRRCjsmCVWPoPF_MMqFcff_yfO44OBERegN8pvo_T_pbj_ufE6_ZFzO4UIzBCsEDxDNffOQFGMG6hitcBo0NbRRAUaF7vhLaTdB3cEwO-eh4FiJogETLdlOEQWFVBfWKQhuabDSAgXfP9CWmxuJh9c3Q_KLdQw"}}.
{"login":"ticarpi"}.
[Signed with new Private key; Public key injected]

To defend against this attack:
The JWT configuration should explicitly define which Public Keys are accepted for verification.

CVE-2020-28042 Null Signature Attack

This attack targets a logic error in vulnerable libraries that fail to process the signature verification check when the signature is of zero-length. Like the alg:none attack the output omits any signature portion after the second dot, although in this case the algorithm in the header is left unchanged.

Example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.
Deconstructed:
{"typ":"JWT","alg":"HS256"}.
{"login":"ticarpi"}.
[No signature!]

To defend against this attack:
The JWT library should be patched against this issue.

JWKS Spoofing

This attack plays with the "jku" and "x5u" header values, which point to the URL of the JWKS file or x509 certificate (often itself in a JWKS file) that are used to verify the Asymmetrically-signed token. By replacing the "jku" or "x5u" URL with an attacker-controlled URL containing the Public Key, an attacker can use the paired Private Key to sign the token and let the service retrieve the malicious Public Key and verify the token.

Example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vdGljYXJwaS5jb20vandrcy5qc29uIn0.eyJsb2dpbiI6InRpY2FycGkifQ.FgnNEj7qm6PPQCCL_f6krxcTSg4uKJSOQf2kTNOQQty25o9ON1SkEpuRgbg54TOjBz7hoqCKc9qRP6GcFy4-5vPVh_lk8x9lQmm7A34Bqkmr41Y8oCIKzlxrdqRxm-gVRkrAXti5slICzRijThkTixe2oem4_q4_8jP01jjuVTK-h3h2ZBQ7GvICEbOTv2ffd_IB-EF6Aua4Mt1164SNamvq3XQ58pLRuZCiR2wjoj1rJ8IkND3pRfg-ziYc86RSLEqq44HCQZ9Suq2r9XGrPkKUE30O6hFCrWJYfaQUTAya8PndhxWrgV5WRzIHYA9Br0kQ29q0DUz-GESLRaK2Ww
Deconstructed:
{"typ":"JWT","alg":"RS256", "jku":"https://ticarpi.com/jwks.json"}.
{"login":"ticarpi"}.
[Signed with new Private key; Public key exported]

To defend against this attack:
The JWT configuration should explicitly define which JWKS files/URLs are permitted.

"kid" Injection

This attack messes with the way that the Key ID value is processed by the application. Some libraries use system calls (such as file-system lookups), or database queries to extract the key specified in the "kid" Header value. By injecting malicious data into this claim an attacker may be able to force the application to perform arbitrary SQL queries, system commands, or maybe even redirect the target of the 'key file' to be a known file on the system, in order to force a new secret to be used to sign and decrypt HMAC tokens.

To defend against this attack:
The "kid" value should be given set parameters in the application, and input deviating from this be discarded before processing.

Cross-service Relay Attacks

Some services use an external authentication service, or share a local authentication server to generate tokens. If these tokens do not specify the specific target service it might be possible to sign up for one service and replay the token to another service and gain access with different permissions.

To defend against this attack:
Make sure that all shared authentication service tokens contain an "aud" (audience) claim, specifying the intended audience of the token, or some other custom method to differentiate replayed tokens.

Weak secret used as a key

Ah the joys of cracking!
When the HMAC symmetric signing algorithms are used these can be cracked offline using a variety of simple CPU cracking tools, or plugged into a GPU-powered brute-force cracking rig.
A humble £100 GPU I bought recently can crack HMAC-SHA256 tokens at over 100 million password guesses per second! So if you have a weak or short secret set on your token do expect it to be cracked.

To defend against this attack:
Skip HMAC signing and go for asymmetric crypto. It's a lot stronger.
If for some reason you can't avoid HMAC signing then make sure you implement long, random secret key strings. Rotate them often.