Portswigger Lab | JWT authentication bypass via unverified signature
In this article, we will explore how to bypass JWT authentication by exploiting an unverified signature vulnerability. JWT is a widely used standard for securing APIs and web applications. However, misconfigurations and vulnerabilities can expose systems to severe security risks. We will use a lab from PortSwigger to demonstrate this attack.
What is an Unverified Signature?
An unverified signature in the context of JWT means that the token’s integrity and authenticity are not checked. When a JWT is created, it is signed with a secret or a private key. This signature ensures that the token has not been tampered with and that it was issued by a trusted source. If a server accepts a JWT without verifying its signature, an attacker can forge tokens with arbitrary content .
Decoding vs. Verifying JWTs in Node.js
In Node.js, the jsonwebtoken
library is commonly used for handling JWTs. There are key differences between decoding a JWT and verifying it:
- Decoding: Extracts the payload from the token without checking the signature. This is useful for reading the contents of the token but does not guarantee the token’s integrity.
- Verifying: Checks the token’s signature against a secret or public key to ensure that it was not altered and was issued by a trusted source.
Vulnerable Code Example
Here’s an example of how a vulnerable code snippet might look when using jsonwebtoken
in Node.js:
const jwt = require('jsonwebtoken');
function authenticateToken(req, res, next) {
const token = req.headers['authorization'];
if (!token) return res.sendStatus(401);
// Vulnerable: Using jwt.decode instead of jwt.verify
const decoded = jwt.decode(token);
if (decoded && decoded.admin) {
req.user = decoded;
next();
} else {
res.sendStatus(403);
}
}
Access the lab using below link :
Lab Setup
Install Jwt Editor extension in burp .
Solution :
- Log in with the credentials wiener/peter.
2. Check all request in the burp .
Jwt editor will automatically highlight all requests with the jwt .
Send request with the GET request to / to repeater , in our case request no 254 .
3. Select Json Web token Option in repeater
Our objective is to log in with the admin account, but we don’t know the admin account’s name.
So, let’s try some common account names:
- admin
- Admin
- administrator
- Administrator
In the admin account it is showing 200 responses , but it does not have any functionality of the admin panel , similar for the “Admin” account .
But when we change sub=Administrator , we can see that it does have an admin panel .
Select right click on response and click on show response in browser .
Start intercepting the request and copy the old JWT from the repeater tab of the Administrator account, as I have noticed that it is always sending requests with the Wiener account’s JWT.
Now click on the Admin Panel
Now , click on delete carlos again change the jwt by intercepting the request .
“The only real security that a man can have in this world is a reserve of knowledge, experience, and ability.” — Henry Ford