Arkendia Classrooms
Lesson 19 of 28 · 17 min

Business logic flaws

Most flaws we have studied come from a missing technical check. Business logic flaws are different: the code works exactly as written, yet the application can be made to do something its designers never intended. No scanner can find them reliably, because there is no “bad” input to detect. They demand something a tool does not have: an understanding of what the application is supposed to do.

Scope reminder

Logic flaws often involve money, stock, vouchers or accounts, so careless testing can have real consequences: orders placed, payments triggered, stock exhausted. Only test them in your lab, or in a real engagement where the client has explicitly agreed to such tests and explained how to avoid real transactions. The examples below are generic and fictional.

An everyday analogy

A supermarket has a rule: “each loyalty coupon can be used once”. It also has a rule: “you can return an item for a refund”. Nobody designed a flaw, yet a customer who buys with the coupon and then returns the item may get back more than they paid. Each rule alone is sensible; the combination hides a gap. Business logic testing is the hunt for such gaps.

Why logic flaws exist

  • Developers imagine the “happy path” and test it, but not unusual sequences or values.
  • The rules are implemented in several places that slowly drift apart: the front end, the API, the back-office.
  • The application trusts the client to follow the intended sequence.
  • Requirements are ambiguous, and no one defined what should happen in edge cases.

A catalogue of generic patterns

The examples that follow are fictional and illustrate categories you can look for in an authorised lab or, for instance, in a PortSwigger Academy logic lab.

1. Trusting client-side values

A shop page sends the product price in a hidden field along with the product ID. If the server uses that submitted price instead of looking it up, the buyer decides the price. Rule: the server must compute prices, totals, discounts and permissions itself.

2. Unexpected numbers

What happens when a quantity is zero, negative, extremely large or fractional? A negative quantity might reduce the total or credit the account. A very large number may overflow a counter. Limits and type checks must be applied on the server. Always test boundaries: minimum, maximum, just inside, just outside.

3. Skipping or reordering steps

A checkout has steps: basket, address, payment, confirmation. If the confirmation step only checks that a basket exists, a user may skip payment by requesting the confirmation page directly. This is the same idea as skipping the second factor in chapter 2. The server must keep track of the state of the process and verify that each step has been completed before allowing the next one.

4. Repeating one-time actions

Coupons, welcome bonuses, “refer a friend” rewards, free trials. If the server checks “has this coupon been used?” but records the usage after granting the discount, repeating the request quickly might apply it more than once. Even without speed, alternating two coupons that each check only the last one used can break the rule.

5. Race conditions

When two requests arrive at nearly the same time, the checks and the updates may interleave. Imagine a balance of 100 and two simultaneous withdrawals of 80: if both read the balance before either updates it, both succeed. Race conditions are a deep topic; for now, note that any rule of the type “only once” or “not more than X” is a candidate. Prevention involves atomic database operations and locking.

6. Abusing the interplay of features

Combining legitimate features in an unexpected order: add an item, apply a discount, then change the basket content so that the discount still applies to a different, more expensive item; or request a refund after transferring an item to another account.

7. Inconsistent rules between channels

The web page limits quantity to 5, but the API or mobile app does not. Or the limit exists only in the browser’s JavaScript. Always test the server’s behaviour by sending the request directly through the proxy.

8. Information-based abuse

Features that reveal too much: a “check if this username exists” function, a “verify this voucher code” endpoint without any rate limit that lets someone try thousands of codes. The feature works as designed, but its design allows abuse at scale.

How to approach logic testing

You cannot rely on a checklist of strings. Instead, follow a thinking process.

  1. Understand the purpose. Write in one sentence what each feature is meant to do and for whom. Use a feature description or the way the application is used.
  2. List the assumptions. “The user will complete payment before confirmation.” “A coupon will be entered only once.” “The quantity will be a positive whole number.” Each assumption is a test idea.
  3. Break the assumptions, one at a time. Skip the step, repeat it, reverse the order, change the number, use two sessions at once.
  4. Observe the final state. Not just the response, but the result: the total, the stock, the balance, the account status.
  5. Judge the impact in business terms. Financial loss, data exposure, reputation, legal consequences.
Feature: checkout
Purpose: customer pays for basket contents, then receives an order confirmation
Assumptions to test:
 - payment step cannot be skipped
 - quantities are positive whole numbers
 - total is computed on the server, not read from the request
 - coupon applies once per order
 - the same basket cannot be paid twice and delivered twice

Writing about logic flaws

Logic findings must be explained more carefully than technical ones, since the reader may not see why it is a problem. A good report includes the intended behaviour, the actual behaviour, the steps to reproduce, and the business consequence expressed in terms the owner cares about, such as “an order can be received without payment”.

Prevention

  • Specify the rules, including limits, order of steps and what happens on failure, and have them reviewed, ideally with a “how could this be abused?” session at the design stage (often called threat modelling, as described in OWASP resources).
  • Enforce every rule on the server. Treat client-side checks as convenience only.
  • Keep process state on the server and verify it at each step.
  • Use atomic operations and transactions for anything that must happen once.
  • Apply rate limits to features that can be abused at scale.
  • Write abuse-case tests alongside normal tests: negative numbers, reordering, duplicates, concurrency.
  • Monitor business metrics for anomalies: unusual refunds, voucher use, stock changes.

Tip

Ask “what would a dishonest customer try?” and “what would a careless customer do by mistake?”. Both reveal gaps. The second question often finds the more realistic problems, such as double-clicking a payment button.

Your turn: list assumptions for a feature

Take the “transfer credit to another user” feature of an imaginary app (or a similar feature in your lab). Write its purpose in one sentence, list at least six assumptions the developers might have made, and for each assumption, one test idea that breaks it.

See a solution

A possible answer:

AssumptionTest idea
The amount is positiveSend zero, negative and very large amounts
The sender has enough balanceSend an amount above the balance
The sender and the receiver differTransfer to your own account
The balance check and the debit are one atomic stepSend two simultaneous transfers that together exceed the balance
The sender in the request is the logged-in userChange the sender identifier (IDOR)
The limit applies on all channelsSend the request directly to the API without the web page

Purpose sentence: “A logged-in user moves a positive amount of their own credit to another existing user, once per request.” Everything above checks one part of that sentence.

Key takeaways

  • Business logic flaws let users do something unintended even though no technical check is missing; scanners rarely find them.
  • Typical patterns: trusting client values, extreme numbers, skipped or reordered steps, repeated one-time actions, race conditions, feature interplay and inconsistent channels.
  • Test by listing the developers’ assumptions and breaking them one at a time, then observing the final state.
  • Explain the intended versus actual behaviour and the business impact in reports.
  • Prevent with clear rules, server-side enforcement, server-held state, atomic operations, rate limits and abuse-case tests.

The last lesson of this chapter turns the server itself into an unwitting accomplice: server-side request forgery.

Advertisement
Log in to save your progress. Log in