How does the idiom go? If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck, right? Well, it is not strictly true. The cybersecurity domain provides plenty of such examples. One is JSON Web Tokens (JSON). The idiom, in this case, goes: If it looks unencrypted, contains something resembling encrypted gibberish, it may very well not be encrypted. And considering JWTs are basically tokens that ensure access to all types of data, it is not hard to understand why they can be a lucrative asset for any bad actor.
Needle In the Grass
JWTs are widely used in web applications as they are compact, self-contained, and can carry information about users and permissions. However, they appear as a string of random characters interspersed by dots. This is also how encrypted data looks: random gibberish. Developers can enter data directly, which is a highly risky move. The data is either encoded or encrypted, hence the gibberish. But unlike encrypted data, encoded data can be easily read by anyone with programming knowledge, as encoding is a reversible process. There are JWT debugging sites that help in the process. This means that unauthorized data access is the mildest fallout. The bad actors can go further and modify the piece, allowing them to change privileges. This type of modified token is then sent ahead, further endangering the data.
Why JWTs show up in breach kill chains
“JSON Web Tokens” (JWTs) are bearer tokens: possession = access. That makes them highly attractive to attackers. JWTs commonly appear in breach kill chains in these ways:
- Token theft: Attackers steal a JWT (from browser localStorage, a mobile app, logs, or a misconfigured S3 bucket) and replay it to authenticate as the victim.
- Token forging / tampering: Flaws in JWT validation allow attackers to create tokens granting themselves privileges.
- Long-lived tokens: Time to Live (TTLs) that decide the time the token will stay active if configured for longer TTLs can make stolen tokens usable for long periods, amplifying the impact of the incident.
- Unencrypted sensitive claims: JWTs carry claims (user IDs, roles, email, tenant IDs). If tokens are intercepted and not encrypted (JWE), attackers learn sensitive info enabling escalation or lateral movement.
- Logging and exposure: JWTs accidentally logged in plaintext (application logs, error traces, analytics) that are then exfiltrated.
Types of attacks
A JWT is made up of three components: header, payload, and signature. The header contains information that specifies metadata about the token, such as the signing algorithm (alg) and token type (typ). Payload contains the token’s “claims,” which are nothing but pieces of information, such as user ID, issuer, and expiration time. This is an area of concern, as this part is encoded, but not encrypted by default. The signature is created by signing the encoded header and payload with a secret or private encryption key, ensuring the token hasn’t been tampered with. However, this encryption has no benefit. The sensitive data remains exposed. With this out of the way, let us look at how the header can be manipulated to launch attacks.
Lokesh Biswal, security analyst at QKS Group, elaborates, “JWTs often give developers a false sense of security. At first glance they may look encrypted, but in reality, they are only encoded, which means sensitive claims can be easily read. Because they are bearer tokens, anyone who obtains one can gain access without further checks, making them highly attractive to attackers and a recurring element in breach kill chains. The only effective defense is to apply strict validation, enforce short lifespans, rotate keys, and handle tokens with the same care as other critical secrets.”
No KIDding, Please
The header includes the key ID or KID parameter, which is needed to locate the appropriate cryptographic key from a database or file system. The application verifies the signature by retrieving and using the key specified in the parameter. Attackers can manipulate the parameter to bypass the verification process, which allows them to launch attacks.
Mitigation Measures
Here is a list of measures that can be implemented immediately to mitigate the danger of unencrypted JWTs:
- Use short token TTLs and rotating signing keys.
- Use encrypted JWT if tokens carry sensitive claims. However, keeping sensitive data out of claims is the best option.
- Use secure storage (httpOnly cookies with SameSite for browser tokens, not localStorage).
- Enforce strong validation by verifying signature algorithm strictly.
- Monitor for token replay (IP/user-agent anomalies, unusual geographic access).
- Protect signing keys with KMS/HSM and audit access.
- Always treat logs as sensitive assets. Avoid logging full tokens and sanitize before shipping logs.
In conclusion
App security remains a minefield. Placing one foot wrong is catastrophic. JSON web tokens are one such minefield where developers can easily get confused and allow unencrypted tokens to function. It is frequently emphasized that humans remain the weak link in the security chain. This is another example that proves the statement right. But rigorous enforcement of security-related policies can ease the pain.
