Skip to main content
Back to all research
Business LogicSample Research WriteupOWASP Top 10 - A04:2021 Insecure Design

Detecting Business Logic Weaknesses and Concurrency Flaws in E-Commerce Workflows

Published: 2025-12-106 min readAuthor: MASKNODS

Business logic bugs evade traditional signature scanners. This paper details workflow state manipulation, parameter tampering, and race conditions in transaction flows.

#Business Logic#Race Conditions#State Machine#E-Commerce#Financial Logic

01.Overview & Architectural Context

Unlike traditional memory corruption or injection flaws, business logic vulnerabilities occur when software handles unexpected user sequences that violate business rules while remaining technically valid HTTP transactions.

02.Attack Vector & Proof of Concept

A classic instance involves multi-packet or single-packet race conditions (exploiting HTTP/2 multiplexing) to apply a single-use discount coupon multiple times simultaneously before the database transaction marks it as redeemed.

Modern distributed architectures often employ non-atomic read-then-write patterns across microservices. In the window between checking `coupon.used == false` and setting `coupon.used = true`, concurrent requests execute within the same millisecond window.

HTTP Request Transcript:
HTTP Request Payload
POST /api/v2/checkout/apply-discount HTTP/2
Host: shop.brand-retailer.com
Authorization: Bearer [CUSTOMER_TOKEN]
Content-Type: application/json

{
  "cart_id": "cart_33104",
  "coupon_code": "WELCOME-50OFF"
}
HTTP Response Transcript:
HTTP Response Payload
HTTP/2 200 OK
Content-Type: application/json

{
  "cart_id": "cart_33104",
  "discount_applied": 50.00,
  "balance_due": 0.00
}

03.Source Code Analysis

Preventing Race Conditions via Atomic DB Updates
// ❌ VULNERABLE: Non-atomic read-modify-write cycle
const coupon = await db.coupons.findById(code);
if (coupon.isRedeemed) throw new Error('Already used');
// Time-of-check to time-of-use (TOCTOU) gap occurs here!
await applyDiscount(cart, coupon.amount);
await db.coupons.update({ code }, { isRedeemed: true });

// ✅ SECURE: Atomic condition-based update with row locking
const result = await db.coupons.updateOne(
  { code, isRedeemed: false }, // Only updates if NOT redeemed
  { $set: { isRedeemed: true, redeemedAt: new Date() } }
);

if (result.modifiedCount === 0) {
  throw new Error('Coupon has already been redeemed or is invalid');
}
await applyDiscount(cart, coupon.amount);

04.Impact & Risk Assessment

Severity Assessment

Financial loss through arbitrary checkout price reduction, inventory depletion attacks, and unauthorized digital reward minting.

05.Remediation & Engineering Mitigations

  • Use atomic database operations and distributed transactional locks (e.g., Redis Redlock) during critical balance or coupon operations.
  • Implement idempotency keys for all state-changing financial transactions.
  • Validate state machine transitions strictly on the backend (e.g., Cart -> Payment -> Completed; disallow jumping states).