Business logic flaws abuse valid application features in unintended ways — price manipulation, workflow skipping, race conditions, and discount stacking that scanners rarely catch.
TL;DR
@ryotkak extension (Aug 2024) enables 10,000 requests in ~166 ms.A business logic flaw is a vulnerability in the application's intended workflow rather than in its input handling, parsing, or access-control plumbing. The requests look syntactically valid, pass authentication, and contain no injection payloads. The attacker is using the application exactly as designed — just in a sequence, combination, or magnitude the developers never foresaw.
The canonical examples are everywhere: applying a percentage discount after manually setting the cart price to zero, ordering a quantity=-5 item to receive a credit, navigating directly to /checkout/confirm without ever completing payment, and racing 30 concurrent requests against a max_redemptions=1 promo code to drain a $600,000 fee-free transaction window. None of these involve a payload list. Each requires understanding what the application is supposed to do, then doing the opposite.
The taxonomy has matured. The primary classification under MITRE is CWE-840 (Business Logic Errors), with sub-classes for CWE-841 (Improper Enforcement of Behavioral Workflow) and CWE-915 (Mass Assignment / Improperly Controlled Modification of Object Attributes). The OWASP Top 10 historically mapped business logic to A04:2021 Insecure Design; in OWASP Top 10:2025, this category was renumbered to A06:2025 Insecure Design and explicitly named "missing business constraint validation" as a sub-category, closing a documentation gap that previously made the OWASP framing seem limited to architectural drawings rather than runtime rule enforcement.
The biggest taxonomic event of 2025 was the publication of the first dedicated OWASP Top 10 for Business Logic Abuse (BLA) at AppSec Global EU in Barcelona on May 30, 2025, with a refreshed v2 on August 2, 2025. The framework models applications as abstract Turing machines (tape, head, states, transitions) and was validated by LLM-classifying 76,000 CVEs from 2023–2025 plus 25,000 GitHub security issues. The result is the first cross-domain taxonomy that treats business logic not as a category of bug, but as a class of system behaviour that must be reasoned about formally. Categories range from BLA1 Action Limit Overrun through BLA10 Shadow Function Abuse, and they cleanly absorb the older OWASP WSTG-BUSL-01..10 catalogue.
This page is the pillar reference. It defines the class, surveys the six attack variants you must master, summarises the state-of-the-art research from 2024–2026, and links to dedicated deep dives for each variant.
Traditional dynamic application security testing (DAST) — ZAP, Burp Scanner, Nuclei community templates — achieves close to zero detection on genuine business logic flaws. The structural reason has five components, and they compound:
amount=-1000 is only a vulnerability if the application accepts it and credits the account. Scanning for the parameter name tells you nothing about exploitability. Compare with SQL injection, where ' OR 1=1-- produces a deterministic differential signal.POST /api/checkout/confirm without a prior /api/checkout/payment call is a bug depends entirely on the checkout state machine — which a generic scanner cannot model without ingesting the application's intended workflow.The HackerOne 8th Annual Hacker-Powered Security Report (2024/2025) shows business logic flaws growing +5% year-over-year as a share of disclosed reports, and +59% YoY in API-specific attacks (27% of API attacks in 2024 were business logic, up from 17% in 2023). The crypto and blockchain sectors saw a +37% increase in BL findings between 2023 and 2024. The gap between automated scanning and real-world exploitation is widening, not closing.
A new generation of tools has emerged in 2025–2026 to attack this gap. Pynt, Escape DAST, and StackHawk Business Logic Testing (BLT) — launched on December 16, 2025 — use OpenAPI-driven smart crawling, multi-user role configuration, and feedback-driven test orchestration to detect Broken Object Level Authorization (BOLA) and Broken Function Level Authorization (BFLA) flaws automatically. They do not yet cover price manipulation, race conditions, boundary attacks, or workflow circumvention; those still require either custom YAML rules engines (the BreachVex approach), human pentesters with Burp Repeater + Turbo Intruder, or LLM-assisted specification-guided detection (GPTScan 2024, IRIS arXiv:2405.17238).
The six variants below cover the bulk of business logic findings disclosed publicly between 2020 and 2026. Each has a dedicated deep-dive page with attack walkthroughs, real CVEs, code examples, and remediation patterns.
The application accepts a client-supplied price, quantity, total, or currency without re-validating against the server-side product catalog. The attacker intercepts the cart-add or checkout request and substitutes price: 0.01 (or currency: "BTC" against a USD catalog). The server processes the order at the attacker-controlled value. PortSwigger's "Excessive Trust in Client-Side Controls" lab demonstrates this exactly. Real-world cases include CVE-2025-56426 (Bagisto CMS, April 2025, CVSS 8.1, patched in 2.2.3) and HackerOne #614523 (Eternal e-commerce — order amount manipulable via cart submission).
Read the deep dive on Price Manipulation
A specialisation of price manipulation: the attacker submits quantity: -5 (or a value that wraps via INT32/INT64 overflow, such as 2147483648). If the server multiplies unit_price * quantity without sign validation, the line-item total goes negative and reduces the cart total — sometimes below zero. CVE-2023-45854 (Shopkit 1.0, CVSS 7.5) is the textbook case: the qtd parameter accepted INT32_MAX+1 and wrapped to a negative cart total. HackerOne #364843 (Upserve/OLO) reports the exact same class against a major restaurant ordering platform.
Read the deep dive on Negative Quantity Abuse
Coupons, promo codes, and gift cards are intended for one-time use, but the deduplication logic only checks the immediately previous code (or none at all). Applying coupon A, then coupon B, then coupon A again often re-applies the discount. PortSwigger's "Flawed Enforcement of Business Rules" lab demonstrates the alternating-coupon bypass. Their "Infinite Money" lab demonstrates the gift-card cycle: buy a $10 gift card with a 10% discount → net $9 spent → redeem $10 → profit $1 per cycle, infinitely. HackerOne #59179 (Dropbox) and HackerOne #157996 (Instacart, race-condition variant) are canonical real-world cases.
Read the deep dive on Discount Stacking
A multi-step process — registration, checkout, subscription upgrade, refund — is implemented by exposing each step as its own HTTP endpoint. The attacker calls the final endpoint directly without completing the prerequisites. Classic example: POST /checkout/confirm {order_id: X} from a fresh session. If the server returns HTTP 200 with the order confirmation body, payment was bypassed. HackerOne #271176 (Lyst, 2017) skipped the payment step by crafting checkout_id in a cookie. HackerOne #92481 (Shopify) accessed payment-method addition without prerequisite checkout. The Magento2 PayPal "Bill Me Later" issue (#39145) bypassed checkout entirely via a specific API sequence. This class maps to CWE-841 and OWASP BLA2:2025 Concurrent Workflow Order Bypass (CWOB).
Read the deep dive on Workflow Step Bypass
The application enforces "one per user" or "max N per day" limits in the application layer (Python check, then database insert) without an atomic guard. Concurrent requests bypass the limit because the check runs before either insert commits. The textbook target is single-use coupons and verification tokens. HackerOne #1717650 (Stripe) — a max_redemptions=1 promotion code redeemed 30 times in parallel, yielding $600,000 in fee-free transactions (payout: $5,000). CVE-2025-31161 (CrushFTP) — race condition in authentication enabling Concurrent Workflow Order Bypass, actively exploited. The class maps to CWE-362 and OWASP BLA1:2025 Action Limit Overrun (ALO).
Read the deep dive on Limit Override
Less common but high-impact when present: an application performs floating-point arithmetic on currency values (0.1 + 0.2 != 0.3 in IEEE-754), accepts micro-amounts (0.001) that round to zero on display but accumulate in storage, or accepts multiple currencies (USD, BTC, JPY) without canonicalisation. The attacker either drains accumulated rounding error through repeated micro-transactions (Office Space attack), or exploits currency mismatches where prices in USD are charged as the same numeric value in JPY (1/100th the price). The classic discipline rule: never use floating-point for money.
Read the deep dive on Currency Rounding Abuse
The research landscape for business logic exploitation moved faster between 2023 and 2026 than in the entire prior decade. Three streams reshaped the field.
In Smashing the State Machine: The True Potential of Web Race Conditions, James Kettle (PortSwigger Research) introduced the single-packet attack: deliver all concurrent requests in a single HTTP/2 frame burst, eliminating network jitter as a confounding variable.
| Technique | Median spread | Std deviation |
|---|---|---|
| Last-byte sync (HTTP/1.1) | 4 ms | 3 ms |
| Single-packet attack (HTTP/2) | 1 ms | 0.3 ms |
The performance improvement is 4–10x over prior HTTP/1.1 last-byte synchronization. One real-world vulnerability went from "exploitable in 2+ hours" (HTTP/1.1) to "exploitable in 30 seconds" (HTTP/2 single-packet). Concurrent requests now race against the application's internal sub-states — intermediate states that exist only during single-request processing, lasting roughly 1 ms.
In August 2024, researcher @ryotkak published Beyond the Limit: Expanding single-packet race condition with a first sequence sync, which uses IP-layer fragmentation to extend the attack window from the 1,500-byte MTU to the full 65,535-byte TCP window. The result: 10,000 synchronized requests in approximately 166 milliseconds. Implementation: open-source h2spacex (Scapy-based) and Turbo Intruder with engine=Engine.BURP2.
Kettle's 2023 paper introduced four entirely new race-condition attack classes beyond the classical limit-overrun:
POST /transfer racing with GET /balance where both read the same row under different lock semantics.CVE-2022-4037 (Devise/GitLab, patched 15.7.2 on January 4, 2023) is the canonical Partial Construction case study. Two simultaneous email-change requests result in confirmation tokens sent to the wrong address while remaining valid — enabling account hijacking and OpenID identity provider takeover on GitLab installations. The race window is the gap between writing the new email and invalidating the old confirmation token.
Kettle's 2024 follow-up, Listen to the Whispers: Web Timing Attacks That Actually Work, weaponises microsecond-scale timing differentials. Key advances over 2023:
GraphQL surfaces unique BL attack vectors that REST-focused detectors miss. 50% of production GraphQL endpoints still accept introspection queries (verified across 2024–2025 surveys), revealing internal mutation names, argument types, and field structures that map directly to business logic flows. Attack categories specific to GraphQL:
createUser(role: "ADMIN") + grantPermission() may individually pass authorization but together constitute a privilege escalation.deleteUser, resetPassword, generateJWT, modifyRole — frequently missing authorization checks and callable by any authenticated user.The selection below mixes the canonical case from each variant with the most actively-exploited 2025 CVEs to illustrate the financial scale.
| Platform / Product | CVE / Report | Class | Impact |
|---|---|---|---|
| Stripe | HackerOne #1717650 | Limit override (race) | $600K fee-free transactions; 30 concurrent redemptions of max=1 promo |
| WooCommerce Stripe Gateway | CVE-2023-28121 (CVSS 9.8) | Auth bypass + price logic | Actively exploited in the wild; mass remote takeover |
| CrushFTP | CVE-2025-31161 | Race / CWOB (BLA2) | Authentication bypass via concurrent requests; actively exploited |
| Bagisto CMS 2.3.6 | CVE-2025-56426 (CVSS 8.1) | Negative quantity | Faulty arithmetic — checkout at $0; patched 2.2.3 |
| Shopizer | CVE-2020-11007 | Price manipulation | E-commerce price tampering accepted server-side |
| Sylius PayPal Plugin | CVE-2025-29788 | Workflow / payment bypass | Order confirmation without payment validation |
| Devise / GitLab | CVE-2022-4037 | Partial Construction race | Account takeover via email-change race; patched 15.7.2 |
| Shopkit 1.0 | CVE-2023-45854 (CVSS 7.5) | Boundary / INT32 overflow | qtd=2147483648 wraps to negative cart total |
| Mozilla | HackerOne #1913309 | Limit override | Race in credit-grant flow; additional credits acquired |
| Tesla (2020) | Public report | Race / limit override | Vehicle software upgrade purchased free via concurrent requests |
| HackerOne (own platform) | HackerOne #220445 | Race | Duplicate bounty payment via concurrent award requests |
| Dropbox | HackerOne #59179 | Discount stacking | Single promo code applied multiple times to Pro subscription |
The financial pattern is consistent: business logic flaws routinely command the highest payouts in bug bounty. Shopify pays $25K–$150K for checkout price manipulation, GitLab $20K–$80K for authorization workflow bypass, and Uber $10K–$50K for pricing logic abuse. The crypto and blockchain sector pays even higher — single business-logic findings against major DeFi protocols have been disclosed at $50K–$500K.
The professional manual workflow combines four tools:
race-single-packet-attack.py template with engine=Engine.BURP2, concurrentConnections=1, and gate-based synchronization.@ryotkak 65535-byte extension. Required when you need 1,000+ synchronized requests for token exhaustion or gift-card mass-redemption.The methodology: map the workflow → identify state transitions → tamper one numeric/state parameter at a time → verify state change via a follow-up GET to the appropriate balance/order/account endpoint → escalate to concurrent requests where ordering matters.
| Tool | BL coverage | Methodology | Limitation |
|---|---|---|---|
| OWASP ZAP | Minimal | Active scan rules for mass assignment only | No workflow modeling |
| Burp Suite Pro | Manual | Burp Repeater + Turbo Intruder | Not automated |
| Bright Security | Moderate | Pattern-based: races, mass assignment, ID enumeration | Limited to common patterns; no app-specific rules |
| Escape DAST | Best-in-class commercial | Feedback-driven BLST engine, API-first | Requires OpenAPI spec, limited non-API targets |
| Pynt | Moderate | Replay test traffic with tampered parameters | OpenAPI-dependent |
| AppCheck NG | Good | GoScript Flows for workflow modeling | Requires manual scripting per app |
| StackHawk BLT (Dec 2025) | BOLA / BFLA only | Multi-user role testing, OpenAPI Smart Crawl | No price/race/workflow coverage |
| XBOW | Good | Multi-agent AI coordination, proof validation | Expensive, no custom rules |
| Nuclei | Template-based | YAML templates, no state tracking | No state diff, no ordering |
The structural limitation across all of them: proof requires application-specific state verification. None of the commodity scanners build a per-finding state_before / state_after evidence dict. Generic 200 OK is not proof — confirmation requires a follow-up GET to the appropriate balance/order/inventory endpoint that demonstrates the tampered value persisted.
BreachVex detects this class via a custom YAML rules engine that encodes per-rule state-check endpoints, a post-tamper probe that compares the resource state before and after the request, and a default-deny proof model that elevates a finding to CONFIRMED only when an actual server-side state change is observed. The default ruleset covers negative transfer, zero-price product, coupon stacking, workflow skip, mass assignment, integer overflow, idempotency reuse, gift-card multiplication, and free-trial reactivation, and is auto-generated from OpenAPI specs at scan time — no human curation required for standard e-commerce or API targets.
The four principles below are the structural fixes that close every variant on this page. Code-level details are in each variant's deep-dive page; the principles themselves are uniform.
Never trust any value the client submits that affects pricing, quantity, role, status, or workflow state. Always re-fetch the canonical value server-side from the catalog, the user record, or the order state.
# BAD: price comes from the client
@router.post("/cart/add")
async def add_to_cart(item: CartItemInput):
cart.add(item.product_id, item.quantity, item.price)
# GOOD: price fetched server-side from the authoritative catalog
@router.post("/cart/add")
async def add_to_cart(item: CartItemInput):
product = await catalog.get_product(item.product_id)
cart.add(item.product_id, item.quantity, product.current_price)The client is allowed to submit product_id and quantity (with bounds validation). Everything else — price, currency, tax, shipping, role, status — is computed server-side from authoritative storage.
Every state-changing operation must run inside a single atomic transaction with explicit row-level locking. The classic mistake is "check then act" without locking the row between the check and the act — the canonical TOCTOU race.
-- BAD: SELECT then UPDATE — race window between the two statements
SELECT redeemed FROM coupons WHERE code = 'SAVE10'; -- returns false
UPDATE coupons SET redeemed = true WHERE code = 'SAVE10';
-- GOOD: SELECT FOR UPDATE locks the row for the duration of the transaction
BEGIN;
SELECT redeemed FROM coupons WHERE code = 'SAVE10' FOR UPDATE;
UPDATE coupons SET redeemed = true WHERE code = 'SAVE10' AND redeemed = false;
COMMIT;
-- BETTER: single atomic UPDATE that returns the row only on success
UPDATE coupons
SET redeemed_by_order = $1
WHERE code = $2 AND redeemed_by_order IS NULL
RETURNING amount;The RETURNING form is the cleanest defence: a single statement that succeeds at most once across all concurrent transactions, regardless of how the application code is written.
Operations that must not double-execute (transfers, charges, order placement) require an idempotency key supplied by the client and stored server-side. Replays of the same key return the cached response instead of re-executing. This is the Stripe API pattern (Idempotency-Key header) and it is the industry-standard defence against duplicate payment, double-refund, and concurrent-submission races.
@router.post("/transfer")
async def transfer(req: TransferRequest, idem_key: str = Header(...)):
cached = await cache.get(f"idem:{idem_key}")
if cached:
return cached # replay returns cached response
# execute transfer atomically
result = await db.execute_transfer(req)
await cache.set(f"idem:{idem_key}", result, ttl=86400)
return resultAny multi-step workflow — registration, checkout, refund, KYC — must be modeled as an explicit finite state machine with server-side transition validation. The state lives in the database (or Redis), not in the client cookie or hidden form field, and every transition is checked against an allow-list before being applied.
VALID_TRANSITIONS = {
"cart": ["shipping"],
"shipping": ["payment"],
"payment": ["confirm"],
"confirm": ["complete"],
}
@router.post("/checkout/{step}")
async def checkout_step(step: str, session: Session = Depends(get_session)):
current = await redis.get(f"checkout:{session.id}:state") or "cart"
if step not in VALID_TRANSITIONS.get(current, []):
raise HTTPException(400, f"Cannot transition from {current} to {step}")
# ... process step ...
await redis.set(f"checkout:{session.id}:state", step)This is the structural fix for Workflow Step Bypass and SPA Workflow Skip. Direct requests to /checkout/confirm from a fresh session fail at the transition guard — the user has no payment state to advance from.
A business logic vulnerability is a flaw in how an application enforces its intended workflow, not in how it handles input. Attackers exploit valid features in unintended sequences or magnitudes — applying a discount after setting price to zero, sending a negative quantity, or skipping payment by calling /checkout/complete directly. The class is mapped to CWE-840 and OWASP A04:2021 (renamed A06:2025 — Insecure Design in the Top 10:2025 refresh). It is also the focus of the new OWASP Top 10 for Business Logic Abuse 2025.
By understanding the intended workflow, then sending well-formed requests that violate it. Examples: replaying a one-shot coupon 30× via HTTP/2 single-packet attack (Stripe HackerOne #1849626, $600K loss), submitting qty=-1 to invert cart arithmetic (CVE-2020-11007 Shopizer), or calling POST /api/checkout/complete without a payment step (HackerOne #2170559 Cloudflare R2). No payload, no injection — every request looks legitimate to a WAF or DAST scanner.
Traditional DAST scanners (ZAP, Burp Scanner, Nuclei, Acunetix) fuzz endpoints with payloads and look for known signatures — SQL errors, XSS canaries, OOB DNS hits. Business logic bugs require modeling application state across multiple requests and recognizing that valid behavior in invalid sequences is a flaw. New tools like Pynt, Escape BLST, and StackHawk Business Logic Testing (launched December 2025) address this gap with multi-user role-based testing, but still need significant human configuration.
OWASP A06:2025 — Insecure Design is the renamed and re-prioritized version of A04:2021 in the OWASP Top 10:2025 refresh. It explicitly names 'missing business constraint validation' as a sub-category, addressing the gap that previously made A04:2021 seem limited to architectural diagrams. Combined with the dedicated OWASP Top 10 for Business Logic Abuse 2025 (validated against 76,000 CVEs), this elevates business logic to first-class status in modern threat modeling.
Discovered by James Kettle (PortSwigger Research, August 2023, 'Smashing the State Machine'), the HTTP/2 single-packet attack bundles 30 or more requests into the last frame of a single HTTP/2 connection, synchronizing them into a sub-1ms execution window from a remote host. The August 2024 @ryotkak extension (h2spacex tool) enables 10,000 requests in ~166ms. This turns remote race conditions into local ones, defeating sub-state checks like coupon redemption and quota enforcement.
CVE-2023-28121 (WooCommerce Payments, CVSS 9.8 Critical, actively exploited — header injection bypasses auth), CVE-2025-31161 (CrushFTP, CVSS 9.8, AWS4-HMAC race ~5ms window CWOB), CVE-2020-11007 (Shopizer negative quantity), CVE-2025-56426 (Bagisto cart price manipulation), CVE-2022-4037 (Devise/GitLab Partial Construction race), CVE-2025-29788 (Sylius PayPal Plugin cart-after-intent). All exploit business workflow gaps, not memory corruption or input parsing.
Five-step methodology: (1) map the workflow with Burp passive scan + sitemap exploration; (2) identify state-changing endpoints (checkout/complete, /apply-coupon, /transfer); (3) test sequence violations via Burp Repeater (replay, skip, parallel); (4) test arithmetic bounds (qty=-1, qty=0, qty=2147483648); (5) test concurrency with HTTP/2 single-packet attack via Burp Turbo Intruder or h2spacex. Specialized tools include Pynt, Escape BLST, and StackHawk BLT.
Technical vulnerabilities (SQL injection, XSS, RCE) exploit malformed inputs that the application fails to sanitize — a single payload triggers the bug, and a static signature catches it. Business logic flaws use perfectly well-formed requests in unintended sequences or combinations — applying the same coupon twice, sending qty=-1, or skipping payment. WAFs and DAST scanners cannot detect them because there is no malicious payload to match. Defense requires server-side authority, atomic state transitions, and idempotency keys.