0% found this document useful (0 votes)
26 views58 pages

Jku X5u

The document discusses JSON web tokens (JWT) and attacks against them. It provides an overview of JWT format and components, how they are signed and verified, and common ways they are used. It also describes the jku and x5u parameters that can be included in JWT headers to reference a URL for JSON web keys (JWK) used to verify signatures. This allows the verification process to fetch keys over HTTP to validate tokens, but opens possibilities for attackers to point to malicious JWK URLs.

Uploaded by

Crystal Prueba
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views58 pages

Jku X5u

The document discusses JSON web tokens (JWT) and attacks against them. It provides an overview of JWT format and components, how they are signed and verified, and common ways they are used. It also describes the jku and x5u parameters that can be included in JWT headers to reference a URL for JSON web keys (JWK) used to verify signatures. This allows the verification process to fetch keys over HTTP to validate tokens, but opens possibilities for attackers to point to malicious JWK URLs.

Uploaded by

Crystal Prueba
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 58

JWT jku&x5u = ❤

Attacking JSON WEB TOKENS…

Louis Nyffenegger
@PentesterLab
louis@pentesterlab.com
About me

Security Engineer

Pentester/Code Reviewer/Security consultant/Security architect


Run a website to help people learn security

PentesterLab:
Platform to learn web security/penetration testing

100% Hands-on

Available for individuals (free and PRO) and enterprises

PentesterLab.com / @PentesterLab
Who uses JWT?

• A lot of people for OAuth2


• A lot of people for sessions
• A lot of people to manage trust
• A lot of people for password reset
• A lot of people who care about being stateless
and multi-datacenter architecture

PentesterLab.com / @PentesterLab
Crypto 101
Signature vs Encryption

Encryption gives you confidentiality

Signature gives you integrity

PentesterLab.com / @PentesterLab
Multiple ways of signing

• With a secret using HMAC


• With a private key using RSA/EC/… (asymmetric)

PentesterLab.com / @PentesterLab
Signing with a secret

Sign! Verify!

Secret

PentesterLab.com / @PentesterLab
Signing: asymmetric

Sign! Verify!

Public Private

PentesterLab.com / @PentesterLab
THE JWT FORMAT
JavaScript Object Notation (JSON)

Human readable format to store or transmit objects

PentesterLab.com / @PentesterLab
The Compact JWS Format

3 parts in a JSON Web Token:

Header Payload Signature

PentesterLab.com / @PentesterLab
The Compact JWS Format

Separated by a dot

Header
. Payload
. Signature

PentesterLab.com / @PentesterLab
The Compact JWS Format

Separated by a dot

eyJ0eXAiOiJK eyJsb2dpbi FSfvCBAwypJ4abF6


V1QiLCJhbGci
OiJIUzI1NiJ9
. I6ImFkb
WluIn0
. jFLmR7JgZhkW674
Z8dIdAIRyt1E

eyJ = Base64('{"')

PentesterLab.com / @PentesterLab
The Compact JWS Format

Header and Payload are base64* encoded JSON


* urlsafe base64 encoding without padding

Base64({…})
. Base64({…})
. Base64(…)

The signature is also base64 encoded

PentesterLab.com / @PentesterLab
The Compact JWS Format: Encoding

Urlsafe base64 encoding without padding:

* https://tools.ietf.org/html/rfc7515#appendix-C

PentesterLab.com / @PentesterLab
The JWT Format: header

The header contains an algorithm “alg” attribute:

Base64({"alg": "HS256",
"typ": "JWS"}) . …
. …

To tell how the token was signed.


In this example HMAC with SHA256 was used

PentesterLab.com / @PentesterLab
The JWT Format: Algorithms

A lot of different algorithms are supported*:


None RS256 ES256 PS256
HS256 RS384 ES384 PS384
HS384 RS512 ES512 PS512
HS512

* https://jwt.io/ covers most

PentesterLab.com / @PentesterLab
The JWT Format: payload

The payload may contain literally anything:


. Base64({"user":"admin",
"roles": ["adm","users"]}) . …

PentesterLab.com / @PentesterLab
The JWT Format: payload

The payload may contain registered claims:


. Base64({"user":"admin",
"exp":12…, "iat":1234.. }) . …

PentesterLab.com / @PentesterLab
The JWT Format: creating a token

• Create the JSON header and base64 encode it


• Create the JSON payload and base64 encode it
• Concatenate with a dot the (encoded) header
and payload
• Sign the result (header+.+payload)
• Base64 encode the signature
• Append a dot then the signature
PentesterLab.com / @PentesterLab
The JWT Format: verifying a token

• Split the token in three parts based on the dots


• Base64 decode each part
• Parse the JSON for the header and payload
• Retrieve the algorithm from the header
• Verify the signature based on the algorithm
• Verify the claims

PentesterLab.com / @PentesterLab
Classic JWT attacks

• None algorithm
• Trivial secret
• Algorithm confusion
• Injection in the kid parameter
• CVE-2018-0114

PentesterLab.com / @PentesterLab
jku & x5u
jku and x5u

• If you read some of the JWS RFC, you probably


learnt about jku and x5u parameter for the headers

• People are starting to use jku (JWK URL)

PentesterLab.com / @PentesterLab
The JWT Format: jku&x5u

Base64({"jku": "https://...",
...}) . …
. …

Base64({"x5u": "https://...",
...}) . …
. …

PentesterLab.com / @PentesterLab
The JWT Format: jwk

{
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "pentesterlab",
"n": "oTtAXRgdJ6Pu0jr3hK3opCF5uqKWKbm4Kkq...vTF0FGw",
"e": "AQAB",
"alg": "RS256"
}
]
}

PentesterLab.com / @PentesterLab
The JWT Format: x5c

{
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "pentesterlab",
"x5c": "MIIDWDCCAkACCQCnE....fpye27SQbC2fBxebsek=",
"alg": "RS256"
}
]
}

PentesterLab.com / @PentesterLab
jku and x5u

User Application

Trusted
Server

PentesterLab.com / @PentesterLab
jku and x5u

1 HTTP Request with JWT

User Application

Trusted
Server

PentesterLab.com / @PentesterLab
jku and x5u

1 HTTP Request with JWT 2 Parsing of the JWT to extract the “jku” header

User Application

Trusted
Server

PentesterLab.com / @PentesterLab
jku and x5u

1 HTTP Request with JWT 2 Parsing of the JWT to extract the “jku” header

User Application

3 Fetching of the JWK based on the “jku” header

Trusted
Server

PentesterLab.com / @PentesterLab
jku and x5u

1 HTTP Request with JWT 2 Parsing of the JWT to extract the “jku” header

User Application 4 Parsing of the JWK

3 Fetching of the JWK based on the “jku” header

Trusted
Server

PentesterLab.com / @PentesterLab
jku and x5u

1 HTTP Request with JWT 2 Parsing of the JWT to extract the “jku” header

User Application 4 Parsing of the JWK

5 Verifying the JWT signature using the JWK

3 Fetching of the JWK based on the “jku” header

Trusted
Server

PentesterLab.com / @PentesterLab
jku and x5u

1 HTTP Request with JWT 2 Parsing of the JWT to extract the “jku” header

User Application 4 Parsing of the JWK

6 Response 5 Verifying the JWT signature using the JWK

3 Fetching of the JWK based on the “jku” header

Trusted
Server

PentesterLab.com / @PentesterLab
jku and x5u

1 HTTP Request with malicious JWT 2 Parsing of the JWT to extract the “jku” header

Attacker Application 4 Parsing of the JWK

6 Response 5 Verifying the JWT signature using the JWK

3 Fetching of the malicious JWK based on the “jku” header

Malicious
Server

PentesterLab.com / @PentesterLab
jku and x5u

1 HTTP Request with malicious JWT 2 Parsing of the JWT to extract the “jku” header
Attacker
Application

3 Fetching of the malicious JWK based on the “jku” header

Malicious
Server

PentesterLab.com / @PentesterLab
jku and x5u

Turns out filtering URLs is incredibly hard

PentesterLab.com / @PentesterLab
jku and x5u : regular expression

https://trusted.example.com => https://trustedzexample.com

PentesterLab.com / @PentesterLab
jku and x5u : starts with

https://trusted => https://trusted@pentesterlab.com


https://trusted/jwks/ => https://trusted/jwks/../file_uploaded
https://trusted/jwks/ => https://trusted/jwks/../open_redirect
https://trusted/jwks/ => https://trusted/jwks/../header_injection

PentesterLab.com / @PentesterLab
jku and Open Redirect

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker Application

3 Fetching of the JWK based on the “jku” header

Trusted
Malicious
Server
Server

PentesterLab.com / @PentesterLab
jku and Open Redirect

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker Application

3 Fetching of the JWK based on the “jku” header

Trusted
Malicious
Server
Server
Open Redirect

PentesterLab.com / @PentesterLab
jku and Open Redirect

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker Application

3 Fetching of the JWK based on the “jku” header

3a Redirect to malicious server

Trusted
Malicious
Server
Server
Open Redirect

PentesterLab.com / @PentesterLab
jku and Open Redirect

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker Application

3 Fetching of the JWK based on the “jku” header

3a Redirect to malicious server

3b Fetching of the malicious JWK Trusted


Malicious after following the redirect Server
Server
Open Redirect

PentesterLab.com / @PentesterLab
jku and Open Redirect

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker Application 4 Parsing of the JWK

3 Fetching of the JWK based on the “jku” header

3a Redirect to malicious server

3b Fetching of the malicious JWK Trusted


Malicious after following the redirect Server
Server
Open Redirect

PentesterLab.com / @PentesterLab
jku and Open Redirect

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker Application 4 Parsing of the JWK

5 Verifying the JWT signature using the malicious JWK

3 Fetching of the JWK based on the “jku” header

3a Redirect to malicious server

3b Fetching of the malicious JWK Trusted


Malicious after following the redirect Server
Server
Open Redirect

PentesterLab.com / @PentesterLab
jku and Header Injection

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker Application

3 Fetching of the JWK based on the “jku” header

Trusted
Server

PentesterLab.com / @PentesterLab
jku and Header Injection

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker
Application

3 Fetching of the JWK based on the “jku” header

Trusted
Server
Header Injection

PentesterLab.com / @PentesterLab
jku and Header Injection

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker
Application

3 Fetching of the JWK based on the “jku” header

3a The jku uses the header injection


to reflect the jwk in a response
Trusted
Server
Header Injection

PentesterLab.com / @PentesterLab
jku and Header Injection

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker
Application 4 Parsing of the JWK

3 Fetching of the JWK based on the “jku” header

3a The jku uses the header injection


to reflect the jwk in a response
Trusted
Server
Header Injection

PentesterLab.com / @PentesterLab
jku and Header Injection

1 HTTP Request with malicious JWT


2 Parsing of the JWT to extract the “jku” header
Attacker
Application 4 Parsing of the JWK

5 Verifying the JWT signature using the


JWK from the header injection
3 Fetching of the JWK based on the “jku” header

3a The jku uses the header injection


to reflect the jwk in a response
Trusted
Server
Header Injection

PentesterLab.com / @PentesterLab
Libraries: jku header injection - Exploitation

Exploitation:
• Find a Header Injection
• Use the Header Injection to return
your JWK
• Add the Header Injection as jku
• Sign the token with your RSA key
PentesterLab.com / @PentesterLab
jku and x5u: downgrade

• The RFC calls out enforcing TLS to avoid MITM


• Few implementations get it wrong:
Enforcing when you set the value
vs
Enforcing when you fetch the key

PentesterLab.com / @PentesterLab
Conclusion
Recommendations

✓ Use strong keys and secrets

✓ Don’t store them in your source code

✓ Make sure you have key rotation built-in

PentesterLab.com / @PentesterLab
Recommendations

✓ Review the libraries you pick (KISS library)

✓ Make sure you check the signature

✓ Make sure your tokens expire

✓ Enforce the algorithm


PentesterLab.com / @PentesterLab
Recommendations

✓ Test for x5u and jku


✓ Don't burn Open Redirect

✓ Read RFC

✓ Hack all the things!


PentesterLab.com / @PentesterLab
Conclusion

• JWT are complex and kind of insecure by design


(make sure you check https://github.com/paragonie/paseto)

• JWT libraries introduce very interesting bugs

• Make sure you test for those if you write code,


pentest or do bug bounties

PentesterLab.com / @PentesterLab
THANKS
FOR YOUR TIME !

Any questions?

louis@pentesterlab.com / PentesterLab.com / @PentesterLab

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy