gethacked.ai

LEARN

What business logic abuse is

Business logic abuse is when someone uses your product exactly as it was built and still causes damage. Here is what it looks like, why scanners miss it, and how to go looking for it.

Get Hacked AB

In short.

Business logic abuse is a flaw in the rules of your product rather than in the code that enforces them. The attacker breaks nothing. A discount code applied five hundred times, a refund for an order that never shipped, a trial that cancels itself and keeps the credits.

Every product has a set of rules about what should happen. A customer gets one active trial. A refund is allowed once. A seat belongs to one workspace. A payout happens after the invoice clears. Those rules are what the product is for.

Then there is the code that enforces them. Often the code checks the wrong thing, or checks it in one place and not another, or checks it correctly and a second feature undoes it later. When the code lets someone reach an outcome the rules forbid, you have business logic abuse.

The important word there is outcome. Nobody broke in. No secret leaked. The request was accepted and answered normally. The system did exactly what it was told to do, and what it was told to do was wrong.

Why a scanner will not find it

A scanner looks for known patterns. Missing headers. A known vulnerable library. A password field that nobody rate limits. Patterns are shared between products, so patterns can be checked automatically.

Business logic abuse is specific to your product. Whether applying the same coupon twice is wrong depends on what the coupon is for. Whether cancelling and refunding in the same minute is wrong depends on how cancellation and refund interact in your system. A scanner has no way to know any of that, and neither does a rule file written for a different product.

This is also why an automated scan is worth running and is not enough. It clears the known patterns so the human can spend the time on the part that only a human can do.

What it looks like in practice

The same handful of shapes shows up over and over, whichever product it is.

  • Discount abuse. The same code applied to several orders, or a code that was meant to be single use applied until the store rejected it.
  • Refund and credit abuse. A refund requested for an order that was never shipped, or a credit issued and then spent while the refund is still under review.
  • Trial abuse. Signing up repeatedly to collect the free tier, or cancelling a plan and keeping the credits it already granted.
  • Quota bypass. Limits counted per request instead of per account, so calling the endpoint twice gives you twice the allowance.
  • Workflow skipping. Approving, confirming or cancelling a step that was supposed to require a previous step to happen first.
  • Role abuse. Inviting yourself, or promoting a seat you control, through a path that was meant for somebody else to use.
  • Referral and affiliate abuse. Getting paid for a signup your own system made, or a referral loop that pays out on both sides.

None of those need a tool. They need somebody who read your rules and tried to break them.

Where startups carry the most risk

The risk follows the code that was written fastest and reviewed least.

  • Onboarding. New code, written once, rarely revisited, and it decides who gets in and what they start with.
  • Billing changes. Plan upgrades, downgrades, proration, credits. The most stateful part of most products, and the part with the most edge cases.
  • Admin tools. Built for internal use, often deployed with a role check in the interface and no role check on the server.
  • Integrations and webhooks. Anything that arrives from outside is an input you did not design.
  • Anything with a coupon, a referral, a credit or a quota attached to it. These are the features where the rule and the code most easily drift apart.

How to test for it

Start with the rules, not the endpoints. The endpoints are easy to enumerate. The rules are the part worth writing down.

  1. Write down what the product promises, one sentence per rule. One discount per customer. Refunds only for delivered orders. One trial per person. Credits cannot be spent after cancellation.
  2. For each rule, write the opposite. The same discount twice. The refund before delivery. The second trial from the same address.
  3. Find the code that enforces each rule and check three things. That it runs on the server rather than only in the interface. That it runs on every path that changes the state. That it cannot be skipped by going around it.
  4. Test the sequence, not the request. Most of these failures only appear when you combine two actions that are each allowed on their own.
  5. Test with the wrong account. A user with a lower role, a second workspace, a second customer on a shared plan, a user account that has been dormant for a year.

How to fix it so it stays fixed

Four habits do most of the work.

  • Enforce on the server. The interface is a convenience. It is not a security control, because the caller does not have to use it.
  • One decision point per rule. If a rule is checked in two places, it will be checked in one place after the next refactor.
  • Make money and credit paths idempotent. The same request should not be able to produce the same effect twice.
  • Write the rules where the code can read them. A constant that says one trial per customer is easier to enforce than a comment that says so.

Then write the negative test. The check with no test is the check that disappears two sprints from now.