JWT Token Manipulation: A Wake-Up Call for Developers on Access Control and Data Security

JWT Token Manipulation: A Wake-Up Call for Developers on Access Control and Data Security

Unveiling the Risks of JWT Vulnerabilities and How Developers Can Strengthen Access Control

Introduction


Let’s set the scene: You’re logging into a website, feeling pretty secure about your data. You trust that the developers have done everything right. Now, imagine a scenario where, with just a few small adjustments, someone can gain access not just to your profile but to other private data and sections of the website that were never meant for them. Surprising, right? Well, that’s exactly what happened in a recent security assessment I conducted. The website I assessed was using JSON Web Tokens (JWTs) for managing user sessions. Now, JWTs are fantastic when used correctly, but a few oversights in their implementation here turned a strong security measure into a vulnerability. This blog isn’t about calling anyone out - it’s about sharing what happened so that we can all learn and implement better security practices. So, let’s walk through the process together.

Identifying JWT-Based Authentication

It all started when I noticed how the website managed user sessions. After logging in, I saw that a small token was exchanged between the server and client: a JSON Web Token (JWT). JWTs are like the digital equivalent of a driver’s license—they contain the user's identity and their permissions in the system. They consist of:

  • Header: States the signing algorithm (e.g., HS256, RS256).

  • Payload: Holds the user’s data (user_id, role, etc.).

  • Signature: Verifies the token’s integrity.

Here’s a simplified example of what a JWT looks like:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzNDUiLCJyb2xlIjoidXNlciJ9.signature

This was my first clue that the application used JWTs to manage user access. Now, JWTs are great, but if not used carefully, they can be easily manipulated. This is where things started getting interesting.

Decoding the JWT Token

To dig deeper, I decoded the JWT. Remember, JWTs are encoded using Base64, so decoding isn’t "hacking"—it’s just revealing what’s already there. I used jwt.io for this purpose. When decoded, I found:

  • User ID (sub) : A unique identifier for the user.

  • User Role (role) : Indicates the user’s access level.

  • Resource ID(resource_id) : Connects to specific data within the application

At this point, I started seeing potential problems. If the application solely relies on these claims to control access, manipulating them could allow me to access unauthorized information.

Finding a File with No Access Control

Next, while poking around the application, I found a file that was accessible without any authentication. It contained sensitive information like:

  • Email address: Personal and business emails of employees.

  • Resource ID (resource_id): Unique identifiers linked to each user.

This file should have been behind some form of access control, but it wasn’t.

The resource_id was key. It suggested that the application might use it to control data access. With the right tweak, this could open a much bigger security hole.

Intercepting a URL That Uses the Resource ID

https://www.redacted.com/api/redacted-resources?populate[redacted_role][populate]=*&populate[redacted_facilities][populate]=*&filters[resourceId][$eq]=auth0|64e855fd6ab522fredacted

This confirmed that the application was using the resource_id to control access. It meant that if I could manipulate the JWT to use a different resource_id, I could potentially see data belonging to other users.

Manipulating the JWT Token

Now, it was time to test this theory. I went back to jwt.io and modified the token’s payload to include a different resource_id and altered other claims (like the user ID and role). Here's what I did:

  1. Modify the Payload: Changed the sub (user ID) and resource_id to impersonate another user, possibly with higher privileges.

  2. Sign the Token: The app was using the RS256 algorithm. During earlier investigation, I found that the server’s public key was exposed, which let me create a new, valid token.

  3. Replace the Original Token: I injected the new JWT into the request headers, replacing the original token.

Gaining Access to a Completely Different UI

With the manipulated JWT in place, I sent the request, and bingo! The server granted access to a whole new user interface meant for users with higher privileges. This confirmed that the application relied entirely on the JWT claims without additional server-side checks.

Why This Matters: This revealed a major flaw in the application’s design—blindly trusting the JWT without server-side verification. By tampering with the token, I could gain access to settings and data that were never intended for my user role.

Unearthing More Sensitive Information

The new UI provided access to more sensitive information, including employee records, internal settings, and healthcare facility data. This wasn’t an isolated issue; it showed a deeper problem with the application’s access control mechanisms.

Why Screenshots of This Step Aren’t Provided

Before we go any further, I want to point out that I won’t be sharing certain screenshots for ethical reasons:

  1. The Restricted UI: Accessing this revealed sensitive controls and data, which I can’t share without risking the application's security.

  2. The Actual Website: Identifying the website would expose it to potential exploitation and risk the privacy of its users.

  3. Additional Sensitive Information: Some information was too personal to share publicly.

I hope you understand that some things must remain private to protect those involved.

The Importance of Access Control and Data Obfuscation


Now, let's talk about what this means. This case highlights just how crucial access control and data obfuscation are. JWTs are a fantastic tool for managing user sessions, but they need to be used with caution. Here are the key lessons from this assessment:

1. Access Control: Why It’s Non-Negotiable

Access control is the cornerstone of application security. It’s what defines who can access what within your application. In this scenario, the application relied solely on the JWT's content for access control, without verifying the user’s permissions server-side. This was a critical oversight.

Why It Matters:

  • Don’t Trust the Client: Never trust data that comes from the client side (like JWT claims) without verifying it on the server. Otherwise, an attacker who can manipulate a token gains access they shouldn’t have.

  • Enforce Granular Permissions: Use role-based access control (RBAC) or attribute-based access control (ABAC) to ensure each user can only access what they’re supposed to.

2. Data Obfuscation: Minimising Data Exposure

This application exposed sensitive information like resource_id and email addresses through publicly accessible endpoints. This data was used to manipulate the token and gain unauthorised access.

Why It Matters:

  • Limit Data Exposure: Only share what’s absolutely necessary with the client. Avoid including sensitive identifiers in JWTs or public API responses.

  • Use Obfuscation Techniques: Obfuscate identifiers like resource_id to make it harder for attackers to guess or misuse them.

A Call to Developers: Building a Security-First Mindset


Alright, developers and security professionals, listen up: security is everyone’s responsibility. Here’s what you can do to build a security-first mindset:

  • Think Like an Attacker: Regularly test your own application with a hacker’s mindset. How would you try to break it? If you’re using JWTs, think about what an attacker might do if they could manipulate them.

  • Enforce Server-Side Validation: Always validate access controls server-side. Never trust what the client sends you without double-checking it.

  • Obfuscate Data: Use data obfuscation to make it harder for attackers to extract useful information. Make sure your endpoints only expose the minimal data required.

Conclusion: Security Is a Shared Responsibility


This assessment is a clear example of how small oversights can snowball into major security issues. It started with identifying JWT usage, moved through decoding and manipulating the token, and ended with unauthorised access to sensitive data.

To every developer and security team out there: Take access control seriously. Always verify data server-side, minimize data exposure, and use JWTs securely. The digital world we live in is increasingly vulnerable to attacks, and protecting user data isn’t just a technical requirement - it’s an ethical one.

By adopting a security-first mindset and continuously learning from real-world vulnerabilities, we can create applications that are not only functional but also secure and trustworthy. Every little precaution counts. Stay vigilant!

Did you find this article valuable?

Support BreachForce by becoming a sponsor. Any amount is appreciated!