Exploiting JWT - Lack of Signature Verification

I'm leading the Research at Credshields, and Pentest teams at Cobalt Labs and HackerOne. I occasionally blog about my findings and adventures in pentesting.
Search for a command to run...

I'm leading the Research at Credshields, and Pentest teams at Cobalt Labs and HackerOne. I occasionally blog about my findings and adventures in pentesting.
No comments yet. Be the first to comment.
Overview During a recent pentest of an iOS health application (let's call it MedVault), I came across something interesting. The app was using custom URL schemes for deep linking but had no Universal

Analysis and PoC of Damn Vulnerable DeFi Level 06 - Selfie

Analysis and PoC of Damn Vulnerable DeFi Level 05 - The Rewarder

Analysis and PoC of Damn Vulnerable DeFi Level 04 - Side Entrance

Analysis and PoC of Damn Vulnerable DeFi Level 03 - Truster

TL;DR
Here goes the short PoC -
"alg": "HS256"JSON Web Tokens are one of the most in-trend authentication mechanisms that are currently being used in modern applications to protect their data and maintain a tight access control over their apps and API endpoints.
The basic structure of a JSON Web Token can be explained really well by https://jwt.io/
As it can be seen in the above image, the left side consist of an encoded JWT i.e.,
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
These tokens follow a format, that is, all of the token can be divided into three parts separated by a . (dot) and each part is encoded separately using Base64.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQSflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cThe signature of a JSON Web token is calculated by
. and alg specified in the Header using a SecretIn the above-mentioned token, this can be achieved using -
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
The Base64-decoded data can be seen in the above image. It should however be noted that this is a basic JWT architecture and a JWT supports loads of other parameters as well but we'll talk about them in upcoming articles.
They define a secure way of transmission of data which, if implemented correctly, verifies that the data that is being passed in the JWT is tamper-free because the developers can sign the token using their public/private key pairs or using a Secret with HMAC. This approves the integrity of the data.
JWT has been exploited multiple times in numerous articles wherein a vulnerable library is being used that allows attackers to use "alg": "None" and an empty Signature to forge their own Payloads and tokens but this PoC exploits a JWT misconfiguration that occured due to missing Signature verification.
Also take a look at this tool, it's pretty helpful in exploiting those "None" algorithm attacks and has a ton of other features - https://github.com/ticarpi/jwt_tool
Let's call the vulnerable site redacted.com
redacted.com has a subdomain called training.redacted.com that hosts an application which is authenticating users using JWT and signing all their API requests with that JWT.
The JWT is contained in a Cookie value RedactedAuthCookie= and the token looks something like this -
My first thought was obviously to test the "None" attack so I used jwt_tool (link above) and a plugin in Burp called JSON Web Tokens to test all kind of attacks.
From what I've learned, to make it work, we have to change the "alg" to "None" and remove the Signature part but even after trying all variations of None - none, None, NONE, and nOnE, none of them worked.
Then I kept the algorithm in the Header as it was in the original request, i.e., HS256 and removed the Signature completely which gave a success response.
This proved that there is in-fact a bug here, probably the signature is not being verified at all, a disaster from the developers side, which made me think of the possibilities of forging my own tokens.
Then I had to manually try each of the three parameters to find which one of them might lead to access into another account - userid, clientid, and userauthenticationid.
It was found that the parameter clientid stores session information.
And we have ourselves a complete Account takeover bug PoC
