Business Logic Vulnerability Testing: Finding Flaws Scanners Miss
Business logic vulnerabilities are the flaws that emerge when an application's intended workflow can be manipulated to do something the developers never intended — but which the code permits. They're distinct from technical vulnerabilities like SQL injection in that there's no malformed input signature to detect. The request looks completely valid. The problem is in how the application's rules interact with each other.
No automated scanner can reliably find all business logic flaws because finding them requires understanding the application's intent. That said, a systematic methodology — combined with tooling for manipulation and repeatability — gets you most of the way there.
What Business Logic Vulnerabilities Look Like
Business logic flaws tend to cluster around a handful of patterns:
- Price and quantity manipulation — submitting negative quantities, modifying prices in client-side state, applying discounts beyond their intended scope
- Workflow bypass — skipping steps in a multi-stage process, accessing step N without completing step N-1
- State confusion — reusing tokens, replaying completed actions, or making the application reach an inconsistent state
- Account and privilege abuse — exploiting feature combinations, trust levels, or role boundaries in unexpected ways
- Race conditions — executing concurrent operations that the application assumed would be sequential
Price Manipulation
Cart and Checkout Tampering
When an application stores pricing logic on the client side (in JavaScript variables, hidden form fields, or localStorage) or trusts price values submitted with purchase requests, the price can be altered before submission.
# Original checkout request (captured in Burp Suite)
POST /checkout/confirm HTTP/1.1
Host: shop.target.com
Content-Type: application/json
{
"items": [{"id": "PROD-123", "quantity": 1, "price": 99.99}],
"total": 99.99
}
# Modified request — price set to $0.01
{
"items": [{"id": "PROD-123", "quantity": 1, "price": 0.01}],
"total": 0.01
}
Also test negative quantities and negative prices — some order processing systems will apply these as credits:
{
"items": [
{"id": "PROD-123", "quantity": 1, "price": 99.99},
{"id": "PROD-456", "quantity": -1, "price": 50.00}
],
"total": 49.99
}
Coupon and Discount Abuse
- Apply the same coupon code multiple times in a single order
- Stack multiple coupon codes when only one should apply
- Apply a coupon intended for one product category to another
- Apply percentage discounts to items already at zero price
- Use a referral code on your own account
- Replay an expired coupon (reuse after the validity window has closed)
# Test: stack multiple coupons
POST /cart/apply-coupon
{"code": "SAVE20"}
POST /cart/apply-coupon
{"code": "WELCOME10"}
GET /cart/total
# Does it apply both? One? Neither?
Workflow Bypass
Multi-Step Process Skipping
Many workflows assume users complete steps in order: account verification → payment info → order confirmation. If step completion isn't enforced server-side, steps can be skipped.
# Normal flow: /checkout/step1 → /checkout/step2 → /checkout/step3 → /confirm
# Test: jump directly to step3 or /confirm without completing prior steps
GET /checkout/step3
POST /checkout/confirm
{"skipPayment": false, "confirmed": true}
Common targets for workflow bypass:
- Email verification — can you access features reserved for verified accounts without verifying?
- Payment — can you reach an order confirmation page without completing payment?
- 2FA — can you bypass the second factor by directly hitting the post-2FA endpoint?
- Age verification or terms acceptance — can you use the service without completing them?
State Machine Abuse
Applications often have implicit state machines — an order moves from pending to processing to shipped to delivered. Test whether transitions can be forced out of order:
# Can you cancel an already-shipped order?
PATCH /orders/ORD-7890
{"status": "cancelled"}
# Can you mark an order as delivered without it being shipped?
PATCH /orders/ORD-7890
{"status": "delivered"}
# Can you request a refund before an order is fulfilled?
POST /orders/ORD-7890/refund
Account and Privilege Abuse
Horizontal Privilege Escalation via Predictable IDs
If resource IDs are sequential or guessable and the server doesn't verify ownership, you can access other users' data by iterating IDs. This is an Insecure Direct Object Reference (IDOR) — a form of business logic failure, not a technical injection.
# Your order
GET /orders/10041
# Other users' orders
GET /orders/10040
GET /orders/10039
GET /orders/10038
Feature Flag and Plan Boundary Testing
Subscription-gated features are frequent targets. If the plan tier is stored in a client-side parameter, JWT claim, or cookie, test whether you can upgrade yourself:
# JWT payload (base64 decoded)
{"sub": "user-123", "plan": "free", "exp": 9999999999}
# Forge claim:
{"sub": "user-123", "plan": "enterprise", "exp": 9999999999}
# Or directly call premium endpoints as a free-tier user
GET /api/advanced-export
POST /api/bulk-action
Account Takeover via Logic Flaws
Password reset flows are particularly vulnerable to business logic issues:
- Token for wrong account: request a reset token for your account, then submit it with the victim's email address in the same request
- Token not invalidated: use a reset link, then reuse the same token link again later
- No rate limiting on token guessing: if the reset token is short or predictable
- Password set for unauthenticated account: can you set a password for an account that hasn't verified its email?
# Test: submit a reset token with a different email than the one that requested it
POST /auth/reset-password
{
"token": "YOUR_VALID_RESET_TOKEN",
"email": "victim@target.com",
"newPassword": "attacker_controlled"
}
Race Conditions
Race conditions occur when two or more concurrent requests interact with shared state in a way that produces an unintended result. The classic example: redeeming a gift card or applying a one-time discount with concurrent requests before the server has processed the first one.
# Turbo intruder script (Burp Suite) for race condition testing
import queue
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=30,
requestsPerConnection=100,
pipeline=True)
for i in range(30):
engine.queue(target.req, target.baseInput)
def handleResponse(req, interesting):
table.add(req)
Or with curl in parallel:
# Fire 20 concurrent requests to redeem a one-time voucher
for i in $(seq 1 20); do
curl -s -X POST https://target.com/voucher/redeem \
-H "Authorization: Bearer $TOKEN" \
-d '{"code":"ONCE123"}' &
done
wait
Also test race conditions on:
- Withdrawal / transfer limits ("I can only withdraw $100/day" — send 10 concurrent $100 requests)
- One-time use referral bonuses
- Concurrent account upgrades with free trial limits
- Like / vote counters with per-user limits
Testing Methodology: What to Map First
Before testing, understand the application's business model well enough to know what would be valuable to exploit. Ask yourself:
- What does the application charge for? What's the monetization mechanism — those flows are the highest value targets.
- What multi-step workflows exist? Any process with steps 1→2→3 is a workflow bypass candidate.
- What are the access control tiers? Free vs paid, user vs admin, verified vs unverified.
- What shared resources exist? Anything that can be over-consumed or exhausted (credits, API calls, concurrent sessions).
- What one-time actions exist? Email verification, referral bonuses, coupons, trial periods — anywhere the system assumes "this only happens once."
Tooling
| Tool | Use Case |
|---|---|
| Burp Suite Repeater | Replaying and modifying individual requests |
| Burp Suite Intruder / Turbo Intruder | Race condition testing, parameter fuzzing |
| Burp Suite Match-and-Replace | Automatically modifying parameters in real browsing sessions |
| curl + bash parallelism | Lightweight race condition testing without Burp |
| Postman / Insomnia | API request sequencing for workflow bypass tests |
| JWT.io / jwt_tool | Modifying and forging JWT claims |
Documenting Business Logic Findings
Business logic vulnerabilities require particularly clear documentation because the severity isn't always obvious to developers who built the feature. For each finding, document:
- The intended behavior: what the developer designed the feature to do
- The observed behavior: what actually happens when the logic is manipulated
- A reproducible test case: the exact requests, in order, that demonstrate the issue
- Business impact: financial loss, unauthorized access, account compromise — be concrete
- Root cause: client-side trust, missing server-side state check, lack of idempotency, no rate limiting
Ironimo automates the detection of business logic vulnerabilities that pattern-matching tools miss — including IDOR, price parameter manipulation, workflow state enforcement gaps, and rate limiting issues — using active testing techniques on your live application.
Scans run on your schedule, against your authenticated application, with findings that include reproduction steps and remediation guidance.
Start free scan