Skip to content

Business Logic Flaws

These aren’t implementation bugs like XSS or SQLi: the code works “as written,” but the business rules are badly designed or not validated server-side. The attacker injects nothing; they use the application in ways the designer didn’t foresee —skipping steps, repeating actions, feeding out-of-range values, combining legitimate functions— to get something they shouldn’t. They’re invisible to scanners because every response is “valid.”

The root error is trusting the client to enforce a rule: the front validates the price, the step order, the quantity limit, or the state, and the server accepts whatever arrives. The attacker talks straight to the API, skips the UI, and the implicit assumptions (“nobody would send a negative quantity,” “they always go through step 2 before 3”) break.

  • Price/quantity manipulation: negative quantity that lowers the total, client-supplied price, stackable discounts, rounding in your favor.
  • Skipping flow steps: go straight to /checkout/confirm without paying; reach /step3 without completing step1/step2 (broken flow).
  • Coupon/discount abuse: apply the same coupon N times, combine exclusive ones, reuse single-use coupons (see also race conditions).
  • Limits not enforced server-side: exceed the max attempts, units, transfers.
  • Trust in hidden parameters: hidden fields, cookies, or unverified JWTs that set role/price/state.
  • Inconsistent validation: front validates, back doesn’t; or two endpoints validate differently.
  • Map the full business flow (purchase, registration, transfer, subscription) and note every assumption: what happens if I skip this step, repeat that one, send the opposite value?
  • Intercept with Burp and tamper with every parameter: prices, quantities, state IDs, flags.
  • Compare what the front (JS) validates with what the back validates (talk straight to the API).
# negative quantity to flip the total
POST /cart/add {"item":"TV","qty":-3} -> total drops
# client-controlled price
POST /checkout {"item":"TV","price":1}
# skip payment
POST /order/confirm {"orderId":123} # without going through /pay
# reuse single-use coupon
POST /cart/coupon {"code":"SAVE50"} x N
# change state directly
POST /order/update {"id":123,"status":"PAID"}

The pattern: what the server should decide is sent by the client, and the server doesn’t recompute or re-validate it.

  • Burp Suite — Repeater/Intruder to tamper and replay steps; the bulk is manual.
  • Flow diagrams (state machine) to find unforeseen transitions.

Direct financial loss (buy free/cheap, over-withdraw), coupon/points fraud, access to premium features without paying, corruption of business data.

  • Orders with anomalous totals, negative quantities, states reached without the prior event.
  • Same single-use coupon/resource applied multiple times.
  • State transitions impossible per the state machine.

Log every business state transition with its actor and values; alert on totals ≤ 0, step skips, and reuses.

  • Validate and recompute server-side everything that matters: price from the catalog, total from the items, discounts against rules; never trust client values.
  • Model the flow as a state machine and reject disallowed transitions (no confirm without pay).
  • Enforce limits and uniqueness server-side (and in the database for race conditions).
  • Strict ranges and types (no negative quantities, no client prices).
  • Abuse-case testing in design (“what if…”) and logic review, not just a scanner.

Reconcile fraudulent transactions, add the missing server-side validations, review history for the same abuse pattern.

  • Most are not CVEs: they live in bug bounties (HackerOne/Bugcrowd) because they’re app-specific.
  • Starbucks / points platforms — balance duplication via logic + race.
  • Many e-commerce sites — manipulated-price purchases from trusting the client price.
  • OWASP WSTG and PortSwigger document patterns and reproducible labs (business logic vulnerabilities).
  • Does the server recompute price/total/discount or trust the client?
  • Can a flow step (pay, verify) be skipped?
  • Are negative or out-of-range quantities accepted?
  • Are limits (attempts, units, coupons) enforced server-side?
  • Can state be changed directly (status=PAID)?
  • Are there hidden parameters (hidden/cookie/JWT) that decide role/price?
  • Do front and back validate the same? (talk straight to the API)