Hi, my name is Hossam Hamada, I'm a Bug Bounty Hunter, and today I'll be sharing a vulnerability I discovered in a Bug Bounty program on HackerOne. For confidentiality reasons, I'll refer to the target as example.com throughout this article.

This write-up focuses on a business logic flaw related to subscription and plan management, which allowed me to bypass paid plan restrictions and gain access to premium features without payment. I'll walk through my thought process, the testing methodology, and how a simple observation led to a high-impact issue.

Before diving into the vulnerability, let me first give you some context about the target so everything is easier to understand.

The target offers three subscription plans:

  • Starter
  • Business
  • Enterprise

All three plans are paid plans, with the main difference between them being the features available in each tier.

When a user creates a new account, they are automatically placed on the Starter plan, which comes with a 14-day free trial. After the trial period expires, the user is required to either subscribe to the Starter plan or upgrade to a different plan by paying for it.

After creating an account, I started exploring the platform to better understand how it works. While browsing the available features, I noticed a specific feature that displayed a prompt saying something like "Upgrade to Enterprise to use this feature", along with a button that would automatically upgrade the account to the Enterprise plan.

Out of curiosity, I clicked the button and confirmed that my plan was immediately upgraded from Starter to Enterprise, and the feature became fully accessible.Interestingly, this was the only feature that provided such an option, and I wasn't entirely sure why this behavior was unique to that feature.

At this point, I decided to inspect the underlying request responsible for this plan upgrade, which looked like the following:

None

I noticed that the plan I was upgraded to was identified as rec_plans_v4_enterprise_an.

This made me curious about what would happen if I changed the plan name to a different one. I wasn't trying to exploit anything at this point — I just wanted to see how the system would react, since this kind of behavior often leads to logic bugs. I then decided to check Burp Suite's history to see if I could find responses that contained other plan names, such as the one I was originally on, or possibly even additional plans. This is something I usually do during testing, as reviewing the history often reveals useful details that aren't visible through the UI.

After that, I took the first part of the plan name I had been upgraded to — rec_plans_v4_enterprise_an — specifically the rec_plans prefix. I assumed this part was common across all plan identifiers.Based on that, I started searching through all the responses in Burp Suite's history. Eventually, I came across an API request whose response returned a large list of different plans.

The request looked like the following:

None

I started testing these plans identifiers one by one and confirmed that I was able to switch to them without any issues.

It's important to note that all of these plan changes were happening within the original 14-day free trial I received when creating the account.

Also, keep in mind that the platform officially exposes only three plans to users, as mentioned earlier. However, the plans I discovered through the API were additional plans that were not visible or selectable through the UI, and were only accessible by manipulating the API requests.

At this point, the behavior was confusing. Some of these plans were paid plans, which meant that subscribing to them normally wouldn't be considered a bug. Others were free but came with heavy limitations, making them practically useless.

Since I was still within the free trial period, the real question became: what would happen once the 14-day trial expired?

I decided to wait until the 14-day free trial ended before testing further. The reason was that while I was still within the trial period, I couldn't truly test the system — any actions taken would fall under the expected free trial behavior. Waiting ensured that any feature access or plan manipulation afterward would clearly reveal a logic flaw, rather than being part of the trial's intended functionality.

After the 14-day free trial ended, I came back and found that my plan was expired, and in order to use any feature, I was required to upgrade the plan.

I then used the saved plan-switching request and changed my plan to another plan. For example, if I was on Business plan, I switched it to the Enterprise plan.

After sending the request, the plan was successfully changed. However, my account was still marked as expired, and I was still required to pay to fully use the plan.At the same time, I noticed that some features related to the new plan were unlocked. In other words, even though the account was expired, certain features became available.

Based on this, I initially thought this was a bug and reported it. However, the report was not accepted because I still couldn't download or send projects.

Let me explain what Download and Send mean in this context.

In the target platform, you work on a project and are given access to certain features to use within that project.

Once the project is completed, the platform expects you to either send it to someone or download it.

At this point, I realized what this meant: even if all the features were unlocked and I had completed the project, I couldn't actually use it because the Send and Download options were still restricted. In other words, all the effort I put into the project was wasted unless I paid to fully access the plan.

After that, I started thinking about how I could bypass the restriction and actually download or send the project. This led me to try upgrading and switching between all the plans I had discovered, to see if any of them would unlock the Send or Download options.

For example, I would complete a project while on the Enterprise plan, then switch to another plan and check whether I could use that plan to send or download the project.

I continued switching between the different plans one by one, and that's when something unexpected happened.

While testing one of the many internal plans I had discovered, I noticed an important detail. There was a plan named dev, which appeared to be intended for developers. When I switched to this plan, I was granted an additional 14-day free trial, separate from the free trial I received when I first created the account. This behavior was unexpected and only occurred with this specific plan.

Unfortunately, the dev plan did not allow Send or Download, which made sense given that it was likely designed for development or internal use.

At this point, I wondered whether the newly granted 14-day free trial would still apply if I switched to another paid plan. To test this, I switched from the dev plan to the Enterprise plan.

The result was critical: the 14-day free trial remained active, and all Enterprise features were fully unlocked, just like during the initial trial period. This allowed me to send and download projects without paying.

As an attacker, I can continue using the platform and access all features even while my plan is expired. After finishing my project, when I decide to send or download it, I switch to the dev plan to obtain a new 14-day free trial, then switch to the Enterprise plan, where the free trial is still applied. This unlocks all Enterprise features, allowing me to send or download the project freely without paying any money. This completely breaks the platform's business model.

I intentionally kept this write-up concise despite the large amount of testing involved, focusing only on the most important details. In this scenario, the impact was real, the vulnerability was accepted, classified as Medium severity, and I received a bonus for my efforts.

None

I also asked why it was rated as Medium despite the significant business impact, and this was their response.

None

Thank you for reading — I hope you found this write-up useful.