Hi, let me introduce myself — I'm Kanishka Khandelwal. I'm currently working as an Associate Security Engineer, and apart from my day job, I spend most of my time doing bug bounty. I enjoy testing different applications, understanding how they work behind the scenes, and finding those small things that don't look right at first. Most of the time, it feels like there's nothing there… but I just keep digging until something finally clicks.

I was testing a SaaS platform that had a Responsible Disclosure Program. Let's call it example.com.

The platform offered multiple subscription tiers, including a paid Enterprise plan, which unlocked advanced features and integrations.

Initial Observation

I created a normal account and logged in.

As expected:

  • My account had a trial plan
  • I was restricted from accessing premium features

Everything looked properly implemented at first.

So I tried the usual things:

  • Parameter tampering
  • Changing request values
  • Exploring hidden endpoints

But honestly… nothing worked. At this point, I was stuck.

The Turning Point

Instead of blindly sending payloads, I opened Burp Suite and started analyzing the application flow more carefully.

While navigating through the app, I found an API endpoint:

GET /api/plan HTTP/2
Host: api.example.com

Excessive Data Exposure

The response of this API was interesting:

HTTP/2 200 OK

{
  "status": true,
  "plans": [
    {
      "displayName": "Trial",
      "price": 0,
      "features": [
                   "xx",
                   "xx",
                   "xx",
                   "xx"
                  ]
    },
    {
      "displayName": "Enterprise",
      "price": xxx,
      "features": [
                   "xx",
                   "xx",
                   "xx",
                   "xx"
                  ]
    },
    {
      "displayName": "xxxxx",
      "price": xxx,
      "features": [
                   "xx",
                   "xx",
                   "xx",
                   "xx"
                  ]
    },
    {
      "displayName": "xxxx",
      "price": xxx,
      "features": [
                   "xx",
                   "xx",
                   "xx",
                   "xx"
                  ]
    }
  ]
}

This endpoint exposed:

  • All subscription plans
  • Internal plan structure
  • Features of each plan

This was clearly an Excessive Data Exposure [Information disclosure] issue.

At this point, I had a thought: If the frontend is getting all plan data… maybe it's trusting it too..??

Digging Deeper

I logged out, then logged in again with interception enabled in Burp Suite.

While forwarding requests step-by-step, the request handing the plan appeared :

GET /api/initial-data HTTP/2
Host: api.example.com

This time, I intercepted the response instead of the request.

Original Response (Simplified)

{
  "user": {
    "plan": {
      "displayName": "Trial",
      "features": ["basic_feature_1","basic_feature_2"]
    }
  },
  "featureFlags": ["basic_feature_1","basic_feature_2"]
}

Exploitation

Inside Burp Suite, I modified the response before forwarding it.

Step 1: Replace Plan Data

I replaced the trial plan with enterprise plan data (copied from exposed API):

"plan": {
  "displayName": "Enterprise",
  "price": xxx,
  "features": ["xx","xx","xx","xx"]
}

Step 2: Modify Feature Flags

Then I added enterprise-level features inside feature flags:

"featureFlags": [
  "basic_feature_1",
  "basic_feature_2",
  "advanced_feature_1",
  "advanced_feature_2",
  "enterprise_only_feature"
]

Final Step

  • Forwarded the modified response
  • Turned off interception

What Happened Next

The UI refreshed…

And just like that — my account was now showing Enterprise Plan.

No payment. No upgrade request. No backend validation.

Impact

With this unauthorized upgrade, I was able to:

  • Access enterprise-only features
  • Enable restricted integrations
  • Use premium functionalities
  • Bypass payment completely

All of this:

  • Without paying
  • Without server-side validation

Root Cause

The issue exists because:

  • The application trusts client-side modified responses
  • No server-side validation for plan enforcement
  • Authorization logic depends on frontend state
  • Feature flags are controlled via response data

Why This is Critical

This is not just a small bug.

It leads to:

  • Revenue loss
  • Privilege escalation
  • Broken access control

This falls under:

  • Business Logic Vulnerability
  • Broken Access Control (OWASP Top 10)

Recommended Fix

  • Never trust client-side data (including responses)
  • Enforce plan validation strictly on the backend
  • Implement server-side authorization checks
  • Do not rely on feature flags from client responses

Final Thoughts

This bug taught me something important:

Sometimes the vulnerability is not in the request you send… It's in the response you decide to trust.

Bonus Insight

When you feel stuck:

  • Stop sending payloads blindly
  • Observe HTTP history in Burp Suite
  • Understand how the application behaves

Because sometimes… the application itself tells you where it's broken.

Reward…???

Interestingly, this issue wasn't limited to just one platform. I've seen similar behavior across multiple SaaS applications and responsibly disclosed them.

In many cases, the impact was somewhat limited — for example, refreshing the page would revert the plan back to its original state, indicating weak client-side enforcement but no persistence.

However, in this particular case, the behavior was different.

The changes made through response manipulation were persisted in the application state:

  • The upgraded plan remained active even after page refresh
  • Features continued to work without reverting
  • Repeating the same interception during login would restore the manipulated state again

This indicates a deeper trust issue, where the application not only relied on client-side responses but also failed to properly revalidate state across sessions.

Despite this, such issues are often treated as "functional bugs" rather than security vulnerabilities — which highlights how underestimated business logic flaws and client-side trust issues still are in many real-world applications.

Thank you for reading. Feel free to share your thoughts in the comments or connect with me on LinkedIn: https://www.linkedin.com/in/kanishka-khandelwal-a49050263/