Key takeaways
- A business logic flaw is made of valid requests, so the finding is a sequence and an outcome rather than a payload.
- Model the rules before you touch the application. Every promise the business makes is a claim you can attack, and each one becomes an abuse case with an expected refusal.
- Logic and access control overlap but route differently: authorisation is a check on an endpoint, a logic rule is a condition inside a workflow.
- The retest is a rerun of the abuse case against the fixed build, and the abuse case belongs in the application's own test suite afterwards.
A logic flaw is a rule the application states but never enforces
An injection flaw breaks an application by sending it something it cannot parse. A business logic flaw does the opposite. Every request is well formed, authenticated, inside the schema and handled exactly as the developers built it. What is wrong is the order, the combination or the number, and none of that shows up as a signature. The OWASP Web Security Testing Guide gives the class its own testing chapter for that reason, and it is the same reason the class is thin on the ground in an unattended scan, which what a web application pentest covers sets out in more detail.
Keep the boundary with access control clear while you test. Authorisation asks whether this identity may act on this object. Logic asks whether a sequence of actions the identity is entitled to perform should be allowed to end where it ends. The two meet in places like an approval a user can grant to their own request. A tester who conflates them writes findings a developer cannot route, because one is a check on an endpoint and the other is a condition in a workflow, and they are usually owned by different people.
Write the rules down before you open the application
The test starts on paper. Ask the product owner what the application guarantees, then collect the same promises from the documentation, the terms shown at checkout and the messages the interface prints when it refuses something. Each promise is a rule, and each rule is a claim you can attack. Where the answer is that the interface does not offer the action at all, write the rule down anyway: a control that lives in the front end is a suggestion, and the request can be sent without it.
Turn every rule into an abuse case with a defined expected refusal, so the result is a pass or a fail rather than an impression. The table below is a constructed example rather than any real system, and it is the shape the list takes: the rule in the business's own words, the sequence that tests it, and what a correct application does. Testing authorisation role by role produces a matrix of identities against objects. This list is its sibling, a matrix of promises against sequences.
Written this way, the finding names the rule that broke. 'The application allowed a purchase order to be approved by the account that raised it' is a sentence a business owner can act on and a developer can locate. A severity label on its own is neither.
| Rule the application states | Abuse case | What a passing application does |
|---|---|---|
| A refund above AED 10,000 needs a second approver | Approve from the account that raised it, then replay the approval call | Refuses both: the approver identity is compared to the raiser server side |
| A discount code applies once per account | Send two checkout requests carrying the same code at the same moment | One succeeds and one is refused, because the code is consumed under a lock |
| Quantity must be between 1 and 20 | Post a quantity of -3, then 21, then 20.0001 | Refuses all three at the server, not only in the form |
| A document is submitted, then reviewed, then paid | Call the payment step with a document that was never reviewed | Refuses: the state is read from the stored record, not from the request |
Model, attack, prove
A logic test runs in three passes. You model the rules and the state machine behind them: every state a record can hold, and every transition the application says is allowed. You attack, running each abuse case with the accounts you were given. Then you prove, which is the pass that separates a suspicious response from a finding, by showing a demonstrated outcome together with the request chain that produced it and the state the record was left in. NIST's SP 800-115 sets out that discipline for technical testing in general, and logic work is where it bites hardest, because the evidence is a sequence and not a single response.
Those passes are where the manual days go in a web application pentest, and they feed each other. A rule that turned out to be unenforced in the refund path is worth re-testing in the adjustment path, the cancellation path and the service interface behind both, so the list grows during the test rather than before it. Time-box it deliberately: model early, attack the rules protecting money and personal data first, and keep the last part of the window for proving what you found rather than collecting more of it.
Model
Collect the rules
Product owner, documentation, and what the interface promises
Draw the state machine
Every state a record holds and every transition allowed
Attack
Run the abuse cases
Skip a step, replay it, reorder it, change the number
Change the actor
The same sequence from a second and a third account
Prove
Show the outcome
A record changed or a value moved, not a suspicious response
Record the chain
Every call in order, so a developer can replay it
Each proven flaw suggests the next rule to test
One chain, from a valid order to committed funds
Here is a worked example, constructed to be generic. A procurement portal states that a purchase order above a threshold needs a second approver. Any buyer may raise an order. Approval sets a flag on the record, and the ordering service writes the order to the ledger once that flag is set. Nothing in that design is unusual, and nothing in the chain below sends the application a single malformed value.
The buyer raises an order below the threshold, which needs no second approver at that value, and then changes the total through an endpoint the form stops showing after submission. The approval flag is not cleared when the amount changes, so the service writes a large order carrying an approval that was granted for a small one. The weakness is one missing line: a transition that changes the total does not invalidate the state that depended on it. A scanner sees two authenticated requests from a user entitled to make both.
Write the finding as the rule, the sequence and the amount, in that order. The same endpoints usually exist as a service interface as well, and the rule has to hold on both, which is why an API pentest tests the same promises from the other side of the browser.
- Internal buyer → Ordering service
Raises an order below the approval threshold
Allowed by design: any buyer may create an order
- Internal buyer → Ordering service
Replays the edit call with a larger total
The form hides the field, the endpoint still accepts it
- Ordering service
Vulnerability
Keeps the approval granted at the smaller total
Changing the amount does not invalidate the state
- Ordering service → Ledger
Writes the order as approved at the new value
- Ledger → Internal buyer
Objective reached
Funds committed with no second approver
A logic fix is a rule change, so the retest is a rerun
There is no patch level to check here. The fix is a code change inside a workflow, and the only verification worth anything is running the abuse case again, in the same order, with the same accounts, against the fixed build. Ask for the abuse case to be added to the application's own test suite under the name of the rule it protects, so a later release cannot quietly restore the behaviour. OWASP's Application Security Verification Standard states business logic requirements in a chapter of their own, which gives a developer wording to write that test against.
Then look at what the application recorded while the chain ran. Logic abuse is built from valid requests, so it is invisible to anything watching for malformed input: the decision itself has to be logged as a decision, with the identity, the record, and the value before and after. That is one of the things your monitoring should catch during a web app pentest, and the test window is when you find out whether it does.
What a logic flaw means for a regulated business in Dubai and Abu Dhabi
A logic flaw tends to land in exactly the part of an application a regulator has an opinion about: a payment journey, a claims workflow, a customer onboarding step, an approval that separates two duties. Four regimes name security testing in the UAE. Banks and finance companies answer to the Central Bank, Dubai government entities and their suppliers answer to the Dubai Electronic Security Center, Abu Dhabi healthcare providers answer to ADHICS, and the Information Assurance Standard applies federally. Segregation of duties and transaction integrity appear across those control sets, and a business logic finding is a direct failure of that kind of control rather than a technical defect somebody has to translate into one.
That changes how the finding should be written for a reader in either emirate. A report that names the rule, the sequence and the amount can be mapped onto a control statement by an assessor, while a severity score on its own cannot. Free zone status does not remove the obligation either: a company licensed in a Dubai free zone that sells a platform into an Abu Dhabi government supply chain inherits its customer's requirements alongside its own. Which regime asks for the test, and how often, is set out in the UAE rules that ask for a web application pentest. Decide before the test which rules in the application carry regulatory weight, and spend the modelling pass on those first.
Frequently asked questions
What is a business logic vulnerability in a web application?
It is a rule the application states but does not enforce, exploited through requests that are all valid on their own. A user skips a step, replays an action, reorders two calls or changes a value the interface no longer shows, and the application accepts the result because each individual request was legitimate. The defect is in what the workflow permits, not in how it parses input.
Can a vulnerability scanner find business logic flaws?
Not on its own. A scanner compares responses against patterns for known classes, and a logic flaw produces a normal response to a well formed request. Finding one requires knowing what the application is for: that an approval should have been invalidated when the amount changed, or that a discount was meant to apply once. That knowledge comes from the business, not from the traffic.
Is a business logic flaw the same as broken access control?
They overlap but they are not the same, and they get fixed in different places. Broken access control is an identity acting on an object it should not reach, which is a check missing from an endpoint. A logic flaw is an entitled identity reaching an outcome the business never intended, which is a condition missing from a workflow. Some findings, such as approving your own request, are both.
What does a tester need in order to test business logic?
An account for every role, a written description of the rules the application is meant to enforce, and an environment where a transaction can be completed rather than abandoned at the last step. Proof of a logic flaw is the outcome, so a tester stopped short of it can only report a suspicion. Agree in advance which actions may be carried through and how the resulting records are cleaned up.





