JSON Web Tokens: Anatomy of a Break and Fix

Dec. 1, 2025
json web tokens

Security vulnerabilities often stem from implementation errors rather than zero-day exploits. One of the most prevalent vectors for these configuration errors is the JSON Web Token (JWT).

The JWT has become the de facto standard for stateless authentication. It carries identity data, permissions, and expiration details within a compact, URL-safe string.

However, as I discovered during my recent Lab during the CyberSafe API Security Training, default configurations and poor architectural choices can leave these tokens critically vulnerable.

In this lab, I analyzed a compromised token, identified its logic flaws and cryptographic misconfigurations, and then re-architected it using Burp Suite to meet production security standards.

If you want to understand why modern authentication breaks and how to engineer it correctly, this guide covers the technical details you need.

1. Authentication vs. Authorization

Before analyzing the token structure, we must distinguish between the two core security functions it handles.

Authentication: Verifying Identity

Authentication answers the specific question: "Who is this user?" It validates credentials to establish a digital identity. In a typical HTTP flow, a failure at this stage results in a 401 Unauthorized status code.

  • This is handled by verifying factors such as passwords, biometrics, or One-Time Passwords (OTP).
  • When a user successfully authenticates, the server issues a JWT. The existence of a valid, signed JWT proves that the user has successfully passed the authentication check.

Authorization: Verifying Permissions

Authorization answers the question: "What is this user allowed to do?" It validates access rights to specific resources based on the established identity. A failure at this stage results in a 403 Forbidden status code.

  • This involves checking roles, scopes, or access control lists (ACLs).
  • The JWT payload often carries authorization data, such as a role claim (e.g., "admin" or "user") or a scope claim (e.g., "read: messages").

A JWT handles both functions simultaneously. The signature proves Authentication (validating the issuer), while the payload claims handle Authorization (defining the permissions).

2. What Are Tokens? Stateful or Stateless

Stateful Sessions

In traditional web development, applications relied on Sessions. When a user logged in, the server created a record in its memory or database (a session ID) and sent it to the browser as a cookie. For every subsequent request, the browser sent the cookie, and the server looked up the ID in its database to retrieve the user's context.

If an application runs on multiple servers, they must all share access to the same session database. This introduces latency and a single point of failure.

Stateless Tokens

A token is a self-contained credential. Instead of the server storing the user's session data, the data is packaged, cryptographically signed, and issued to the client.

The client presents this token with every request, usually in the Authorization header. The server verifies the token's signature to validate the request without needing to query a central session database. This allows any server in a distributed microservices architecture to verify a user independently.

3. JWT (JSON Web Token)

JSON Web Token (RFC 7519) is the open industry standard for these stateless credentials. It serves as a mechanism for representing claims to be transferred between two parties.

A JWT is constructed from three distinct parts, separated by periods (.).

Part 1: The Header

The header contains metadata about the token. It informs the resource server how to process the token. It is a JSON object encoded in Base64Url.

  • typ: Defines the type of token, which is almost always "JWT".
  • alg: Defines the cryptographic algorithm used to generate the signature. Common examples include HS256 (HMAC with SHA-256) and RS256 (RSA Signature with SHA-256).

Part 2: The Payload

The payload contains the Claims. These are statements about an entity (typically the user) and additional metadata. Like the header, it is a JSON object encoded in Base64Url.

  • Registered Claims: These are predefined by the JWT specification to ensure interoperability and consistency across different implementations. They include iss (Issuer), exp (Expiration Time), sub (Subject), aud (Audience), and iat (Issued At).
  • Private Claims: These are custom fields defined by the developer to convey application-specific data, such as user ID, role, or email address.

Encoding is not encryption. Base64Url encoding is reversible by anyone. Therefore, the payload is transparent. Sensitive data such as passwords, personal health information, or government IDs should never be stored in a JWT payload.

Part 3: The Signature

The signature is the security mechanism that ensures data integrity. To create the signature, the server takes the encoded Header and the encoded Payload, concatenates them, and signs them using the algorithm specified in the Header.

For an HMAC algorithm (like HS256), the formula is:

  • HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

And for an RSA algorithm (like RS256), the formula changes because it uses Asymmetric Encryption. Instead of a shared secret, it uses a Private Key to generate the signature.

  • RSASHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), privateKey)

If a client modifies the payload (for example, changing a user ID), the signature verification will fail because the hash of the manipulated data will not match the original signature.

Image showing the header, payload, and signature sections of a jwt
Image showing the header, payload, and signature sections of a jwt Source: fusionauth.io

Why use JWTs?

  1. Horizontal Scalability: Stateless verification allows traffic to be distributed across unlimited server instances without the bottleneck of synchronizing session data.
  2. Cross-Domain Authentication: A JWT issued by a centralized identity provider (IdP) can be trusted by multiple independent services. This is the foundation of Single Sign-On (SSO).
  3. Mobile Efficiency: Tokens are easier to handle in mobile clients than cookies, which can be difficult to manage outside of a web browser context.

4. Anatomy of a Broken Token

During the lab exercise, I was tasked with analyzing a specific JWT provided by our trainer. While it appeared valid structurally, static analysis tools revealed critical configuration flaws that rendered it insecure.

The Tools

To perform this analysis, I used the following:

  1. Burp Suite: The primary proxy tool used to intercept, analyze, and modify web traffic.
  2. JWT Editor Extension: A specialized plugin for Burp Suite that allows for parsing, editing, signing, and attacking JWTs directly within the Repeater tab.
  3. XJWT.io: A web-based debugger for quick visual inspection and decoding of token segments.

The Token

Here is the raw token I analyzed:

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyIjoiYWRtaW4iLCJleHAiOjE2MDAwMDAwMDAsInJvbGUiOiJhZG1pbiIsInZhbGlkIjpmYWxzZX0.

Upon decoding this token, I identified five critical vulnerabilities.

Flaw 1: The "None" Algorithm

The header configuration was explicitly set as follows:


            {
 "alg": "none",
 "typ": "JWT"
}
        

The "none" algorithm is a feature originally intended for debugging or situations where integrity is provided by the transport layer (like mutual TLS). However, in a standard JWT, it is catastrophic. It tells the server that the token is unsigned and requires no verification.

Flaw 2: Missing Signature (Integrity Failure)

Due to the use of the none algorithm, the token lacked a signature segment.

  • This negated the primary purpose of a token. Without a signature, there is no integrity check. I could modify any value in the payload, and the server had no mathematical way to detect that the data had been tampered with.

Flaw 3: Insecure Logic (valid: false)

The payload included a functional logic claim: "valid": false

This indicates that the application relies on data provided by the client to determine if a session is valid.

Flaw 4: Expired Data (exp)

The exp (expiration) timestamp was 1600000000, which translates to September 2020.

  • The server accepted credentials that had expired years ago. This vulnerability exposes the system to Replay Attacks. If an attacker intercepts a token from logs or via Cross-Site Scripting (XSS), they can use that token to access the API indefinitely, regardless of whether the user has since changed their password.

Flaw 5: Privilege Escalation (role: admin)

The payload explicitly defined the user's role: "role": "admin"

  • In a standard attack scenario, an attacker could modify their role from "user" to "admin." Without signature verification, this modification enables immediate vertical privilege escalation (Mass Assignment).


            {
  "user": "admin",
  "exp": 1600000000,
  "role": "admin",
  "valid": false
}
        

5. The Fix

Identifying vulnerabilities is only the initial step. True security requires re-architecting the system to adhere to best practices.

Here is the remediation strategy I implemented using the JWT Editor in Burp Suite to secure the token.

Step 1: Cryptographic Trust (RS256)

I replaced the none algorithm with RS256 (RSA Signature with SHA-256).

  • RS256 uses Asymmetric Encryption. It requires a Private Key (held strictly by the server) to sign the token and a Public Key (available to any service) to verify it. This is superior to HS256 (Symmetric) because the verification key cannot be used to forge new tokens if it is leaked.
  • I generated a new RSA 2048-bit Key Pair in Burp Suite and configured the token header to use RS256. This ensures that only the entity holding the Private Key can generate valid tokens.

RSA Key Implementation with BurpSuite's JWT Editor
RSA Key Implementation with BurpSuite's JWT Editor

Step 2: Token Freshness

I updated the expiration timestamp (exp) to a future value, specifically one hour from the current time, for testing purposes. Ideally, JWTs should expire after 10 minutes.

  • Short-lived tokens minimize the "blast radius" of a compromise. If a token is stolen, the attacker has a limited window of opportunity before access is denied.
  • I added an iat (Issued At) claim to explicitly track the token's creation time. This helps prevent "time travel" attacks where tokens appear to be generated in the future.

Step 3: Hardening the Logic

I removed the insecure "valid": false claim.

  • Session validity must be determined by the integrity of the cryptographic signature and the expiration timestamp. It should never rely on a mutable field within the payload that the client can manipulate.

Step 4: Contextual Binding (Audience & Issuer)

I added iss (Issuer) and aud (Audience) claims.

  • These claims prevent Token Confusion attacks. They ensure that a token issued by one service (e.g., the Identity Provider) cannot be maliciously reused against a different service (e.g., the Billing API), even if they utilize similar configurations.

The Final Secure Token

The remediated payload follows this structure:

Final secured jwt signed with an RSA key
Final secured jwt signed with an RSA key

            {
 "user": "admin",
 "role": "admin",
 "iss": "https://cybersafe-api-sec.com",
 "aud": "https://secure-app.com",
 "exp": 1764523600,
 "iat": 1764520000
}
        

This token is now cryptographically signed, time-limited, context-aware, and tamper-resistant.

6. Incidents that were a result of Weak JWTs

These vulnerabilities are not theoretical exercises. Weak JWT implementations have led to significant security breaches in major production environments.

a. File Browser Session Replay (CVE-2025-53826)

In late 2025, a critical vulnerability was identified in File Browser version 2.39.0.

  • Vulnerability: The application was found to have improper JWT handling (CWE-613). The authentication system relied solely on the token's expiration timestamp (exp) and failed to maintain a server-side list of invalidated sessions.
  • Impact: This flaw enabled a Session Replay Attack. An attacker who captured a valid, non-expired JWT could maintain unauthorized access to the system even after the legitimate user had explicitly logged out. The session remained active until the token naturally expired, regardless of the user's actions.
  • Mitigation: As of late 2025, no official patches were available. Mitigation required implementing server-side invalidation (token blocklisting) or significantly reducing token lifetimes to minimize the attack window.

b. KubePi Hardcoded Secret (CVE-2023-22463)

KubePi, a Kubernetes management panel, was found to have an Admin Authentication Bypass vulnerability caused by hardcoded secrets.

  • Vulnerability: The application used hardcoded JwtSigKey values within the JWT authentication function across all deployments of versions up to v1.6.2.
  • Impact: Because the "Secret Key" was universal and publicly accessible, attackers could forge their own JWTs. This allowed them to gain unauthorized administrative access to any affected KubePi instance, potentially leading to the full compromise of the underlying Kubernetes cluster.
  • Remediation: The vulnerability was patched in version 1.6.3. The fix involved making the JWT key configurable in the app.yml file and ensuring a random key is generated if the configuration is left blank.

c. Java's "Psychic Signatures" (CVE-2022-21449)

A severe security flaw was discovered in Java's implementation of the Elliptic Curve Digital Signature Algorithm (ECDSA), affecting Java SE versions 15 through 18.

  • Vulnerability: The rewrite of the ECDSA implementation from C++ to native Java failed to verify that the signature values r and s were non-zero.
  • Impact: An attacker could present a forged signature where r and s were both set to zero. Due to the mathematical flaw, the verification equation would calculate 0 = 0 and accept the signature as valid for anymessage or public key. This effectively allowed attackers to bypass authentication in JWTs, SAML assertions, and OIDC tokens, creating a "blank ID card" that was universally accepted.
  • Remediation: Oracle released a Critical Patch Update (CPU) in April 2022. Organizations were urged to update immediately to patched versions (e.g., Java SE 17.0.3) to close this validation gap.

Verification is Key

A token is only as secure as its implementation.

Using standard technology like JWT does not guarantee security. As this analysis demonstrated, a JWT is simply a data structure. If implemented without signature verification, without proper expiration enforcement, or with weak signing keys, it offers no protection against unauthorized access.

Key Takeaways for Developers and Security Testers:

  1. Secure your keys: Utilize strong, asymmetric encryption (RS256) where possible to separate signing and verification duties.
  2. Verify your signatures: Ensure the backend middleware strictly validates the signature before processing any claims. Reject the none algorithm by default.
  3. Sanitize your claims: Never rely on client-side input for session validity or privilege assignment. Authorization logic must reside on the server.

Security is a continuous process of verification and validation. By dissecting these tokens, we ensure that the credentials we build are robust enough to protect the systems they govern.

Made With Traleor