JWT Parkour Attacking JSON WEB TOKENS Louis Ny ff enegger - - PowerPoint PPT Presentation

jwt parkour
SMART_READER_LITE
LIVE PREVIEW

JWT Parkour Attacking JSON WEB TOKENS Louis Ny ff enegger - - PowerPoint PPT Presentation

JWT Parkour Attacking JSON WEB TOKENS Louis Ny ff enegger @PentesterLab louis@pentesterlab.com About me Security Engineer Pentester/Code Reviewer/Security consultant/Security architect/IANAC Run a website to help people learn security


slide-1
SLIDE 1

JWT Parkour

Attacking JSON WEB TOKENS…

Louis Nyffenegger @PentesterLab louis@pentesterlab.com

slide-2
SLIDE 2

About me

PentesterLab.com / @PentesterLab

Security Engineer

PentesterLab:

Pentester/Code Reviewer/Security consultant/Security architect/IANAC Platform to learn web security/penetration testing 100% Hands-on Available for individuals (free and PRO) and enterprises Run a website to help people learn security https://www.pentesterlab.com/

slide-3
SLIDE 3

Who uses JWT?

PentesterLab.com / @PentesterLab

  • A lot of people for OAuth
  • 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

slide-4
SLIDE 4

Acronyms

PentesterLab.com / @PentesterLab

  • JOSE:
  • Javascript Object Signing and Encryption
  • Also the name of the working group
  • JWT: JSON Web Token == “jot” Token
  • JWE: JSON Web Encryption
  • JWS: JSON Web Signature
  • JWK: JSON Web Key
  • JWA: JSON Web Algorithm
slide-5
SLIDE 5

Crypto 101

slide-6
SLIDE 6

Signature vs Encryption

PentesterLab.com / @PentesterLab

Encryption gives you confidentiality Signature gives you integrity

slide-7
SLIDE 7

Multiple ways of signing

PentesterLab.com / @PentesterLab

  • With a secret using HMAC
  • With a private key using RSA/EC/… (asymmetric)
slide-8
SLIDE 8

Signing with a secret

PentesterLab.com / @PentesterLab

Sign! Verify!

Secret

slide-9
SLIDE 9

Signing: asymmetric

PentesterLab.com / @PentesterLab

Sign!

Private Public

Verify!

slide-10
SLIDE 10

THE JWT FORMAT

slide-11
SLIDE 11

JavaScript Object Notation (JSON)

PentesterLab.com / @PentesterLab

Human readable format to store or transmit objects

slide-12
SLIDE 12

The Compact JWS Format

PentesterLab.com / @PentesterLab

Header Payload Signature

3 parts in a JSON Web Token:

slide-13
SLIDE 13

The Compact JWS Format

PentesterLab.com / @PentesterLab

Header Payload Signature

Separated by a dot

. .

slide-14
SLIDE 14

The Compact JWS Format

PentesterLab.com / @PentesterLab

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

Header and Payload are base64* encoded JSON

. .

* urlsafe base64 encoding without padding

The signature is also base64 encoded

slide-15
SLIDE 15

The Compact JWS Format

PentesterLab.com / @PentesterLab

eyJ0eXAiOiJK V1QiLCJhbGci OiJIUzI1NiJ9 eyJsb2dpbi I6ImFkb WluIn0 FSfvCBAwypJ4abF6 jFLmR7JgZhkW674 Z8dIdAIRyt1E

Separated by a dot

. .

eyJ = Base64('{"')

slide-16
SLIDE 16

The Compact JWS Format: Encoding

PentesterLab.com / @PentesterLab

Urlsafe base64 encoding without padding:

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

slide-17
SLIDE 17

The JWT Format: header

PentesterLab.com / @PentesterLab

Base64({"alg": "HS256",

"typ": "JWS"})

The header contains an algorithm “alg” attribute:

In this example HMAC with SHA256 was used

To tell how the token was signed.

. .

slide-18
SLIDE 18

The JWT Format: Algorithms

PentesterLab.com / @PentesterLab

A lot of different algorithms can be supported*:

None * https://jwt.io/ covers most HS256 HS384 HS512 RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512

slide-19
SLIDE 19

The JWT Format: payload

PentesterLab.com / @PentesterLab

The payload may contain literally anything:

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

. .

slide-20
SLIDE 20

The JWT Format: payload

PentesterLab.com / @PentesterLab

The payload may contain registered claims:

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

. .

… …

slide-21
SLIDE 21

The JWT Format: payload

PentesterLab.com / @PentesterLab

The payload may contain registered claims:

  • “iss”: issuer
  • “sub”: subject
  • “aud”: audience
  • “jti”: claim id
  • “exp”: expiration time
  • “nbf”: not before
  • “iat”: issued at*

* useful for async processing

slide-22
SLIDE 22

The JWT Format: creating a token

PentesterLab.com / @PentesterLab

  • 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
slide-23
SLIDE 23

The JWT Format: verifying a token

PentesterLab.com / @PentesterLab

  • 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
slide-24
SLIDE 24

Keep in mind

PentesterLab.com / @PentesterLab

  • Multiple systems can issue tokens
  • A token can be used by multiple systems
  • All these systems can use different libraries
slide-25
SLIDE 25

Attacking JWT

PentesterLab.com / @PentesterLab

When attacking JWT, your main goal is to bypass the signature mechanism

slide-26
SLIDE 26

Not checking the signature

slide-27
SLIDE 27

Not checking the signature

PentesterLab.com / @PentesterLab

Some libraries provide two methods:

  • decode <- don’t use this one
  • verify

Or just people forgetting to re-enforce the signature check after disabling it for some quick testing

slide-28
SLIDE 28

Not checking the signature

PentesterLab.com / @PentesterLab

Exploitation:

  • Get a token
  • Decode and tamper with the payload
  • Profit
slide-29
SLIDE 29

None algorithm

slide-30
SLIDE 30

The None algorithm

PentesterLab.com / @PentesterLab

Remember that slide?

None RS256 ES256 PS256

Basically, don’t sign the token Used to be supported by default in a few libraries

slide-31
SLIDE 31

The None algorithm

PentesterLab.com / @PentesterLab

Exploitation:

  • Get a token
  • Decode the header and change the algorithm to

“None” (or “none”)

  • Decode and tamper with the payload
  • Keep or remove the signature
  • Profit
slide-32
SLIDE 32

Weak Secret

slide-33
SLIDE 33

Trivial secret

PentesterLab.com / @PentesterLab

The security of the signature relies on the strength of the secret The secret can be cracked offline with just one valid token Cracking is supported by hashcat

slide-34
SLIDE 34

Trivial secret

PentesterLab.com / @PentesterLab https://github.com/aichbauer/express-rest-api-boilerplate/blob/master/api/services/auth.service.js

slide-35
SLIDE 35

Trivial secret

PentesterLab.com / @PentesterLab

Exploitation:

  • Get a token
  • Brute force the secret until you get the same

signature

  • Tamper with the payload
  • Re-sign the token using the secret
slide-36
SLIDE 36

Algorithm confusion

slide-37
SLIDE 37

Algorithm confusion

PentesterLab.com / @PentesterLab

The sender controls the algorithm used You can tell the receiver that the token has been signed using HMAC instead of RSA for example With RSA, you sign with the private key and verify with the public key With HMAC, you sign and verify with the same key

slide-38
SLIDE 38

Algorithm confusion

PentesterLab.com / @PentesterLab

You tell the receiver it’s an HMAC (instead of RSA) and it verifies the signature using HMAC with the public key as the secret (thinking it’s RSA) You can sign the token with the public key

slide-39
SLIDE 39

Algorithm confusion

PentesterLab.com / @PentesterLab

How to get the public key:

  • Public key accessible in the javascript code
  • Public key available in a mobile client
  • Public key just available in the documentation.
slide-40
SLIDE 40

Algorithm confusion

PentesterLab.com / @PentesterLab

Exploitation:

  • Get a token signed with RSA (you only have

access to the public key)

  • Decode the header and change the algorithm

from RSA “RS256” to HMAC “HS256”

  • Tamper with the payload
  • Sign the token with the public RSA key
slide-41
SLIDE 41

kid injection

slide-42
SLIDE 42

Kid parameter

PentesterLab.com / @PentesterLab

The header can contain a kid parameter:

  • Key id (https://tools.ietf.org/html/

rfc7515#section-4.1.4)

  • Often used to retrieve a key from:

✴The filesystem ✴A Database

This is done prior to the verification of the signature If the parameter is injectable, you can bypass the signature

slide-43
SLIDE 43

Kid Injection

PentesterLab.com / @PentesterLab

Exploitation:

  • Get a signed token containing a kid parameter
  • Decode the header and change the kid with a

SQL injection payload

  • Tamper with the payload
  • Sign the token using the return value

from the SQL injection

slide-44
SLIDE 44

CVE-2018-0114

slide-45
SLIDE 45

Libraries: CVE-2018-0114

PentesterLab.com / @PentesterLab

JWS allows you to add a “jwk” attribute (JSON Web Key) to the header to tell the receiver what key was used to sign the token:

slide-46
SLIDE 46

Libraries: CVE-2018-0114

PentesterLab.com / @PentesterLab

  • Vulnerability in Cisco Node Jose
  • Node-Jose trusts embedded “jwk” keys to check

the signature

slide-47
SLIDE 47

Libraries: CVE-2018-0114 - Exploitation

PentesterLab.com / @PentesterLab

Exploitation:

  • Get a token
  • Decode and tamper with the payload
  • Generate a RSA key
  • Add “n" & “e” to the header and use

RS256

  • Sign the token with your RSA key
slide-48
SLIDE 48

jku & x5u

slide-49
SLIDE 49

jku and x5u

PentesterLab.com / @PentesterLab

  • 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)
slide-50
SLIDE 50

jku and x5u

PentesterLab.com / @PentesterLab

Application Trusted Server

User

slide-51
SLIDE 51

Application Trusted Server

User

HTTP Request with JWT

1

jku and x5u

PentesterLab.com / @PentesterLab

slide-52
SLIDE 52

Application Trusted Server

User

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

1 2

jku and x5u

PentesterLab.com / @PentesterLab

slide-53
SLIDE 53

Application Trusted Server

User

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

1 2 3

Fetching of the JWK based on the “jku” header

jku and x5u

PentesterLab.com / @PentesterLab

slide-54
SLIDE 54

Fetching of the JWK based on the “jku” header

Application Trusted Server

User

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

1 2 3

Parsing of the JWK

4

jku and x5u

PentesterLab.com / @PentesterLab

slide-55
SLIDE 55

Application Trusted Server

User

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

1 2 3

Parsing of the JWK

4

Verifying the JWT signature using the JWK

5

Fetching of the JWK based on the “jku” header

jku and x5u

PentesterLab.com / @PentesterLab

slide-56
SLIDE 56

Application Trusted Server

User

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

1 6 2 3

Parsing of the JWK

4

Verifying the JWT signature using the JWK

5

Fetching of the JWK based on the “jku” header

jku and x5u

PentesterLab.com / @PentesterLab

slide-57
SLIDE 57

jku and x5u

PentesterLab.com / @PentesterLab

Application Malicious Server

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

1 6 2 3

Parsing of the JWK

4

Verifying the JWT signature using the JWK

5

Attacker

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

slide-58
SLIDE 58

jku and x5u

PentesterLab.com / @PentesterLab

Application Malicious Server

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

1 2 3

Attacker

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

slide-59
SLIDE 59

jku and x5u

PentesterLab.com / @PentesterLab

Turns out filtering URLs is incredibly hard

slide-60
SLIDE 60

jku and x5u : regular expression

PentesterLab.com / @PentesterLab

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

slide-61
SLIDE 61

jku and x5u : starts with

PentesterLab.com / @PentesterLab

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

slide-62
SLIDE 62

3

Fetching of the JWK based on the “jku” header Parsing of the JWT to extract the “jku” header

2

Application Trusted Server

HTTP Request with malicious JWT

1

Malicious Server

Attacker

jku and Open Redirect

PentesterLab.com / @PentesterLab

slide-63
SLIDE 63

Parsing of the JWT to extract the “jku” header

2

Application

Open Redirect

Trusted Server

HTTP Request with malicious JWT

1

Malicious Server

3

Fetching of the JWK based on the “jku” header

Attacker

jku and Open Redirect

PentesterLab.com / @PentesterLab

slide-64
SLIDE 64

Parsing of the JWT to extract the “jku” header

2

Application

Open Redirect

Trusted Server

3

Fetching of the JWK based on the “jku” header

3a Redirect to malicious server

HTTP Request with malicious JWT

1

Malicious Server

Attacker

jku and Open Redirect

PentesterLab.com / @PentesterLab

slide-65
SLIDE 65

Parsing of the JWT to extract the “jku” header

2

Application

Open Redirect

Trusted Server

3

Fetching of the JWK based on the “jku” header

3a Redirect to malicious server 3b Fetching of the malicious JWK

after following the redirect HTTP Request with malicious JWT

1

Malicious Server

Attacker

jku and Open Redirect

PentesterLab.com / @PentesterLab

slide-66
SLIDE 66

Parsing of the JWT to extract the “jku” header

2

Application

Open Redirect

Trusted Server

3

Parsing of the JWK

4

Fetching of the JWK based on the “jku” header

3a Redirect to malicious server 3b Fetching of the malicious JWK

after following the redirect HTTP Request with malicious JWT

1

Malicious Server

Attacker

jku and Open Redirect

PentesterLab.com / @PentesterLab

slide-67
SLIDE 67

Parsing of the JWT to extract the “jku” header

2

Application

Open Redirect

Trusted Server

3

Parsing of the JWK

4

Verifying the JWT signature using the malicious JWK

5

Fetching of the JWK based on the “jku” header

3a Redirect to malicious server 3b Fetching of the malicious JWK

after following the redirect HTTP Request with malicious JWT

1

Malicious Server

Attacker

jku and Open Redirect

PentesterLab.com / @PentesterLab

slide-68
SLIDE 68

3

Fetching of the JWK based on the “jku” header Parsing of the JWT to extract the “jku” header

2

Application Trusted Server

HTTP Request with malicious JWT

1

Attacker

jku and Header Injection

PentesterLab.com / @PentesterLab

slide-69
SLIDE 69

Parsing of the JWT to extract the “jku” header

2

Application

Header Injection

Trusted Server

3

Fetching of the JWK based on the “jku” header HTTP Request with malicious JWT

1

Header Injection

Attacker

Parsing of the JWT to extract the “jku” header

2

Application

Header Injection

Trusted Server

3

Fetching of the JWK based on the “jku” header HTTP Request with malicious JWT

1

Header Injection

Attacker

jku and Header Injection

PentesterLab.com / @PentesterLab

slide-70
SLIDE 70

Parsing of the JWT to extract the “jku” header

2

Application

Header Injection

Trusted Server

3

Fetching of the JWK based on the “jku” header

3a The jku uses the header injection

to reflect the jwk in a response HTTP Request with malicious JWT

1

Header Injection

Attacker

jku and Header Injection

PentesterLab.com / @PentesterLab

slide-71
SLIDE 71

Parsing of the JWT to extract the “jku” header

2

Application

Header Injection

Trusted Server

3

Parsing of the JWK

4

Fetching of the JWK based on the “jku” header

3a The jku uses the header injection

to reflect the jwk in a response HTTP Request with malicious JWT

1

Header Injection

Attacker

jku and Header Injection

PentesterLab.com / @PentesterLab

slide-72
SLIDE 72

Parsing of the JWT to extract the “jku” header

2

Application

Header Injection

Trusted Server

3

Parsing of the JWK

4

Verifying the JWT signature using the JWK from the header injection

5

Fetching of the JWK based on the “jku” header

3a The jku uses the header injection

to reflect the jwk in a response HTTP Request with malicious JWT

1

Header Injection

Attacker

jku and Header Injection

PentesterLab.com / @PentesterLab

slide-73
SLIDE 73

Libraries: jku header injection - Exploitation

PentesterLab.com / @PentesterLab

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
slide-74
SLIDE 74

jku and x5u: downgrade

PentesterLab.com / @PentesterLab

  • The RFC calls out enforcing TLS to avoid MITM
  • Few implementations get it wrong:

Enforcing when you set the header vs Enforcing when you fetch the key

slide-75
SLIDE 75

Conclusion

slide-76
SLIDE 76

Recommendations

PentesterLab.com / @PentesterLab

✓ Use strong keys and secrets ✓ Don’t store them in your source code ✓ Make sure you have key rotation built-in

slide-77
SLIDE 77

Recommendations

PentesterLab.com / @PentesterLab

✓ Review the libraries you pick (KISS library) ✓ Make sure you check the signature ✓ Make sure your tokens expire ✓ Enforce the algorithm

slide-78
SLIDE 78

Conclusion

PentesterLab.com / @PentesterLab

  • 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

slide-79
SLIDE 79

Any questions?

FOR YOUR TIME !

THANKS

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