portswigger-all-labs

Complete PortSwigger Web Security Academy Lab Writeups Detailed, categorized solutions for every lab — from APPRENTICE to EXPERT — covering all 30 vulnerability types.

View on GitHub

Labs Covered

This write-up focuses on the following PRACTITIONER-level labs from the PortSwigger Web Security Academy related to JWT (JSON Web Token) vulnerabilities:

3 JWT authentication bypass via weak signing key

This lab demonstrates how a weak or guessable signing key allows attackers to forge valid JWTs and bypass authentication.

4 JWT authentication bypass via jwk header injection

This lab demonstrates how attackers can inject a malicious JWK (JSON Web Key) into the JWT header to forge a valid token and bypass authentication.

5 JWT authentication bypass via jku header injection

This lab shows how attackers can manipulate the `jku` header to point to an attacker-controlled key set, allowing them to sign forged tokens.

6 JWT authentication bypass via kid header path traversal

This lab demonstrates how attackers can exploit insecure file path resolution in the `kid` header to retrieve secret keys and forge tokens.

LAB 3 - JWT authentication bypass via weak signing key

Lab Description

image

Brute-Forcing JWT Secret Keys (HS256)

What’s the issue? JWTs signed using symmetric algorithms like HS256 rely on a shared secret key. If this key is weak, predictable, or hardcoded (e.g., "secret", "password", or "123456"), an attacker can brute-force the key and forge valid tokens with arbitrary payloads — including admin access.


How It Happens

Developers sometimes:

If an attacker gets hold of a signed JWT (via a session, HTTP traffic, logs, etc.), and the server uses HS256, the attacker can:

  1. Extract the header and payload.
  2. Brute-force the secret key offline.
  3. Resign a forged JWT with arbitrary claims.

Using hashcat to Crack JWT Secrets

Requires: Kali Linux (or install hashcat), a valid JWT, and a wordlist (e.g., rockyou.txt)

Step 1: Save your JWT to a file (e.g., token.jwt) Step 2: Run the following command:

hashcat -a 0 -m 16500 token.jwt /usr/share/wordlists/rockyou.txt

Explanation:

Option Description
-a 0 Dictionary attack (straight mode)
-m 16500 Hash mode for JWT (HMAC-SHA256)
token.jwt File containing the JWT to crack
rockyou.txt Wordlist to try as potential secrets

Step 3: If successful, Hashcat will output the correct secret key.


Example Output

JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
FOUND: secret = 'supersecret123'

Exploit Path After Cracking

Once you know the key:

  1. Modify the JWT payload (e.g., change "role": "user""role": "admin").
  2. Resign the token using the cracked secret.
  3. Use the modified JWT to bypass authentication or escalate privileges.

    Tools to resign JWTs:


Solution

In this lab js token has weak signature applied.So we can brute force it

So I intercept blue highlight which tell us it is jwt and copy and paste in token.dev as it tell us wiener authetication

image

change sub to adminsitrator

image

The I try to access adminisntaor with above jwt token but I did not get any result

image

Use another method to access admin but no result

image

So Save the jwt token on file and brute force it with with seclist jwt token wordlist we get sign word which which Is used to sign jwt token

image

Chang jwt to adminsitrator and sign it with secret1 key and press go

image

As we can see additional paramter is insert The following….. So it gives us abd request

image

Remove additional header and now we can Access admin

image

Delete user carlos and lab is solved

image


LAB 4 - JWT authentication bypass via jwk header injection

Lab Description

image

JWT Header Parameter Injections – Overview

What is it? JWT header parameter injection occurs when a server blindly trusts JWT header fields such as jwk, jku, or kid to determine which key to use for signature verification. If improperly validated, this can allow an attacker to bypass authentication by supplying their own keys.


Key JWT Header Fields Vulnerable to Abuse

Header Description
alg Algorithm used to sign the JWT (e.g., HS256, RS256) — already well-known for misuse.
jwk JSON Web Key — allows the client to embed a public key directly in the header.
jku JSON Web Key Set URL — tells the server where to fetch public keys (remotely).
kid Key ID — used to select a key from a set of public keys based on an identifier.

Exploiting jwk: Injecting Self-Signed JWTs

  1. Attacker creates their own RSA key pair.
  2. They generate a valid JWT with arbitrary claims (e.g., admin: true).
  3. They sign it with their private key.
  4. They place the matching public key in the JWT header’s jwk field.

Example JWT Header with JWK:

{
  "alg": "RS256",
  "jwk": {
    "kty": "RSA",
    "n": "base64url-modulus",
    "e": "AQAB"
  }
}
  1. If the server uses the embedded key for verification, it will accept the forged token.

Real-World Risk


🧰 Tools


Solution

As we know from descrption that 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.login as wiener and peter While intercepting request at back where blue sign come we will intercept it

image

Now I try to login as adminstarator directly 302 found,I open the request in browser and see that we are logout of our account

image

Now I try to access admin but Unauthorized message came up

image

Now using jwt editor genarartor to get rsa key,We can see that RSA key is genrated but we donot specify any size it automatically select size Since I did not have the private key to sign my forged token, I decided to create my own key pair using the JWT Editor extension and use that key pair for signing my JWT and somehow enforce the server to verify the token using my public key.

image

After pressing ok this tab below will come

image

Now we have genrated RSA , now it time to select it we can select it through JSON WEB TOKEN , So I clicked on attack and the embedded JWK According to the lab title, some header injection was possible in the token. I decoded the header, and the signing key was using the RS256 algorithm unlike the previous lab. This meant that there was no shared key and the server was using an RSA key pair for signing and verifying the JWTs. Private key is used to sign the token and public key is used to verify the token.

image

And we can see select the same rsa key that we have generated in other tab

image

One mistake I have done is that I doesnot change it to adminsiator So First change sub and Then repeat above step of embedded jwk,after repeating above step we can see that jwk header is added

image

Now the jwk header is added we click on send and we can see that admin panel came

image

Now delete carlos to solve the lab

image


LAB 5 - JWT authentication bypass via jku header injection

Lab Description

image

Overview: Injecting Self-Signed JWTs via the jku Header Parameter

What is it? This vulnerability occurs when a server trusts and fetches public keys from a user-specified jku (JSON Web Key Set URL) in the JWT header to verify the token’s signature.

Attackers can exploit this by hosting their own JWK Set, signing a forged JWT using their private key, and directing the server to fetch the public key from a malicious jku URL. If the server doesn’t validate the source properly, the forged token is accepted — enabling authentication bypass.


How It Works

  1. Generate RSA Key Pair

    • Attacker creates their own private/public RSA keys.
  2. Host a Malicious JWK Set

    • The attacker sets up a JWK Set containing the public key on a server they control (e.g., https://evil.com/jwks.json).
    {
      "keys": [
        {
          "kty": "RSA",
          "kid": "attacker-key",
          "n": "<modulus>",
          "e": "AQAB"
        }
      ]
    }
    
  3. Craft a Malicious JWT

    • Header:

      {
        "alg": "RS256",
        "jku": "https://evil.com/jwks.json",
        "kid": "attacker-key"
      }
      
    • Payload:

      {
        "user": "admin"
      }
      
    • Signature: Signed using the attacker’s private key.

  4. Send the JWT to the server

    • If the server is vulnerable, it will:

      • Fetch the key from the jku URL.
      • Use the attacker’s public key to verify the forged token.
      • Accept the token and grant unauthorized access.

What Is a JWK Set?

A JWK Set is a JSON object containing an array of JWKs (JSON Web Keys):

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "example-key-id",
      "n": "base64url-modulus",
      "e": "AQAB"
    }
  ]
}

Servers often expose these at:

/.well-known/jwks.json

Why It’s Dangerous


Attack Surface Expansion

If the server restricts key-fetching to trusted domains:


Solution

jku provides a URL from which servers can fetch a set of keys containing the correct key.

First we can see that its wiener account

image

Now after looking at json web Token we can see algo and sub=wiener

image

So we can see the content of RSA KEY.

image

Now we copy public key from above made rsa key

image

Format of jku to store on sever

image

So we paste the rsa public key on exploit sever as shown below just we add keys parameter synatx remaing are the copy form rsa from rsa

file name : /.well-known/jwks.json(you can also give any_name in this case

image

Now navigate to exploit to look at it its working

image

Now sign with key(I think private) because public is in exploit sever and add administarator in sub and jku:url added as shown below

image

Or we can do above task as this way choosing 3 option

image

Then we clcik on go and we get admin now delete carlos and lab will be solved

image


LAB 6 - JWT authentication bypass via kid header path traversal

Lab Description

image

Overview: Injecting Self-Signed JWTs via the kid Parameter

What is it? The kid (Key ID) JWT header parameter helps the server decide which key to use when verifying the token’s signature. This seems benign — but when developers fail to sanitize or control this input, attackers can abuse kid to:


Why It’s Dangerous

  1. kid is attacker-controlled, but is blindly used to locate a verification key.
  2. The kid value might reference:

    • A file path (e.g., /dev/null, keys/admin.key)
    • A database entry (e.g., ' OR 1=1 --)
    • A JWK ID in a JWK Set
  3. If the server supports symmetric signing algorithms like HS256, the attacker can forge valid tokens if they guess or control the secret key.

Example Exploit Scenarios

1. Directory Traversal (kid → file path)

If the server uses something like this:

with open("keys/" + kid + ".key", "r") as key_file:

An attacker can submit:

{ "kid": "../../../../../dev/null" }

Then sign the token using an empty secret string, which matches the contents of /dev/null.

2. SQL Injection in kid

If the server looks up keys from a database:

SELECT secret FROM jwt_keys WHERE kid = '$kid'

Then injecting:

{ "kid": "' OR '1'='1" }

Could return the wrong key or bypass filtering.


Other Header Parameters of Interest

Parameter Risk / Use Case
cty (Content Type) Used to define the type of payload (e.g., text/xml, application/x-java-serialized-object). If signature checks are bypassed, can be used to trigger XXE or Java deserialization attacks.
x5c (X.509 Certificate Chain) May allow injection of self-signed certificates if not validated properly. Parsing flaws in certificate chains have led to critical bugs (e.g., CVE-2017-2800, CVE-2018-2633).

Solution

Access the admin Panel directly it is giving us administrator can access it.So we have to bypass it

image

Now Intercept the request when I login as wiener:peter and send myaccount?id=wiener to repeater

image

As we can below decoded jwt we can see that hs256 which is symmetric key

image

Now will generate New symmetric key

image

click Generate to generate a new key in JWK format. Note that you don’t need to select a key size as this will automatically be updated later.

image

image

Replace the generated value for the k property with a Base64-encoded null byte (AA==). Note that this is just a workaround because the JWT Editor extension won’t allow you to sign tokens using an empty string.

image

• For symmetric encryption (where the same key is used for both encryption and decryption), “k” would typically contain the secret key encoded in Base64. • For asymmetric encryption (where a pair of public and private keys are used), “k” would usually represent either the public key or the private key, depending on the context.

After changing the k to null we can see that that Public key is removed

image

• In the header of the JWT, change the value of the kid parameter to a path traversal sequence pointing to the /dev/nullfile:../../../../../../../dev/null and changing sub to administrator

image

At the bottom of the tab, click Sign, then select the symmetric key that you generated in the previous section. Make sure that the Don’t modify header option is selected, then click OK. The modified token is now signed using a null byte as the secret key.

image

Now access the admin panel by sign and hangin jwt and now we can access the admin panel

image

Now we are deleting Carlos to solve the lab

image