Skip to main content

The Ghost in the Shopping Cart: Exploring Logic Flaws in a Retail Giant

· 8 min read
Bandana Kaur
APISec Research Labs

Modern e-commerce platforms increasingly rely on distributed API architectures to power web and mobile applications. But as architectures shift toward interconnected microservices, the most dangerous bugs are found in the way data flows in the applications.

Recently, we conducted a structured security evaluation of a large-scale e-commerce API ecosystem. Rather than focusing on isolated vulnerabilities, the research aims to identify systemic patterns of failure across authentication flows, parameter handling, and microservice interactions.

Our mission: to see if we could break the business rules of a production environment using nothing but an interception proxy and a bit of creative curiosity.

The findings reveal recurring weaknesses in:

  • Authentication enforcement
  • Object-level authorization (IDOR / BOLA)
  • Session binding
  • Concurrency handling
  • Client-side parameter trust

Although some issues are mitigated by secondary validation layers, the underlying architectural gaps persist, highlighting risks that could become exploitable under evolving system conditions.


Authorization Drift in Data Retrieval APIs​

Missing Authentication + IDOR (Insecure Direct Object Reference)​

Authorization must be enforced at every layer of the stack, not just the UI. A common architectural assumption is that if the frontend hides something, the backend need not protect it. In our research, this assumption proved false in a production environment. A major retail platform's APIs exposed internal promotional data without verifying whether the requester was authorized to access it. By iterating numeric identifiers, it was possible to retrieve:

  • Hidden or inactive discount codes
  • Internal campaign configurations
  • Usage metrics for promotions

So, while the frontend showed:

frontend

The API response exposed the whole promotional data on iterating through the IDs On another endpoint,

endpoint

And just like that, we have working coupon codes to test for stacking via race conditions.

Even if no direct exploitation occurs, this creates:

  • Financial risk: Early discovery and abuse of promotional logic
  • Competitive intelligence leakage: Exposure of marketing strategies and campaign performance
  • Automation risk: Enables large-scale scraping of incentive systemsBy iterating object identifiers, it was possible to reconstruct:

By iterating identifier parameters on another endpoint, internal seller records could be retrieved without authentication, including:

  • System-level identifiers Sytem level
  • Metadata such as timestamps
  • Configuration structures
  • Contact-related fields

The value of an identifier is not in what it reveals directly, but in where it can be reused. Once obtained, these identifiers may unlock access in other endpoints, bypass weak authorization checks, or enable correlation across services

These findings reflect a pattern of authorization drift: where authorization is enforced at the application layer (e.g., UI), but not consistently at the API layer.

The system assumes that if the frontend hides it, the backend need not protect it. As demonstrated, this assumption does not always hold true.

Non-Atomic Operations in Coupon Validation​

Distributed systems often split validation and state updates across separate steps. When these steps are not atomic, a timing gap opens that attackers can exploit, known as a Race Condition or TOCTOU (Time-of-Check to Time-of-Use).

In practice, this means a check (e.g., "has this coupon been used?") and the action (e.g., "mark it as used") happen in two separate operations, creating a window of inconsistency which we can test. In our research on this platform's coupon flows, parallel requests using the same coupon resulted in multiple successful responses, indicating:

  • Validation and state update occur in separate steps
  • Temporary inconsistency exists across services

However, the final system state correctly enforced a single-use constraint.

Although no immediate exploitation was achieved in this case, it reveals synchronization gaps in distributed systems and creates risk for future exploitation if combined with other logic flaws.

Weak Binding Between Identity and Session in OTP flows​

Authentication actually doesn't end at login. Identity must be continuously enforced across every step of a flow for it to be effective and robust. When it isn't, systems fall into a pattern called Improper Session Binding: actions can be performed in the context of one user but take effect on another. In our testing, the OTP resend functionality demonstrated this gap. We thus observed that it was possible to:

  • Initiate an OTP request for one account
  • Modify the identifier, or add multiple identifiers in a resend request
  • Trigger OTP delivery to a different account

Here, OTP-related flows allowed actions to be performed on identifiers not strictly bound to the initiating session. While this did not directly enable account takeover, it introduces the potential risks of:

  • Targeted SMS abuse
  • Denial-of-service via OTP flooding
  • This reflects a deeper issue where identity is validated at initiation, but not enforced throughout the lifecycle of an interaction. Front End

Client-Controlled Parameter Reflection (Mass Assignment Risk)​

APIs should never trust the client to supply values that the server owns. When they do, it's called Mass Assignment, and it occurs when APIs accept user input for fields that should be controlled internally. In our research, we shifted focus to endpoints responsible for delivery and logistics, an area where business logic tends to be deeply embedded but at times, inconsistently enforced.

We discovered that on endpoints handling shipment logistical attributes, modifying internal parameters (e.g., price values) resulted in those values being reflected in API responses. These included boolean parameters such as whether an item is classified as high value or fragile, as well as pricing-related fields, which the system accepted and reflected in its response as well. Imagine labelling a completely ordinary item as fragile, the digital equivalent of shipping a brick as if it were fine glassware!

It is important to note that final price calculations were validated server-side and thus, no direct financial manipulation was achieved.

However, this indicates that:

  • The API is listening to client-supplied values it should ignore
  • Future endpoints could mistakenly trust these values
  • Verification of mass assignment vulnerabilities requires contextual analysis

So, the risk here is latent: the system is accepting inputs it shouldn't, and future code changes may weaponize that trust. If a future feature relies on these parameters without strict validation, reuses the same request structure and assumes upstream sanitization, the system could become instantly vulnerable.

Key Takeaways & Recommendations​

Our findings with this e-commerce application reflect patterns seen broadly across API-driven systems. We suggest the following for teams building or auditing similar architectures:

  • Avoid sequential numeric identifiers for resource indexing: Predictable resource identifiers increase the impact of authorization failures by enabling enumeration. Prefer opaque external identifiers (UUIDs/ULIDs) for public APIs, while still enforcing object-level authorization on every request.
  • Enforce authorization at the API layer, not just the UI: Never assume that hiding something in the frontend is sufficient protection. Every API endpoint should independently verify that the requester is authorized to access the specific resource being requested, regardless of how the request arrived.
  • Make validation and state updates atomic: Any operation where correctness depends on a check followed by a state change (coupon use, inventory reservation, payment confirmation) should guarantee consistency through transactions, optimistic locking, idempotency controls, or equivalent concurrency-safe mechanisms.
  • Bind identity throughout a flow, not just at initiation: For multi-step flows like OTP, password reset, or checkout, the identity validated at step one must remain securely bound to later steps through signed state, server-side session context, or equivalent integrity controls. Re-validate that the acting session matches the target identity at each transition.
  • Audit which parameters your API reflects back in responses: Unexpected parameters accepted and reflected may indicate overly permissive input handling or future mass-assignment risk. Treat them as signals for deeper review rather than completely benign or proof of exploitable weakness.

Conclusion​

What this assessment ultimately reinforces is a simple truth: in distributed environments, authorization drift, weak session binding, and over-trusted client parameters can exist even when every individual component appears “secure enough” in isolation. The shopping cart may look polished on the surface, while a few ghosts still move around in the backend.

That is also why modern security testing must evolve beyond checking for only traditional flaws. Logic abuse, object-level authorization issues, and workflow weaknesses require multi-step, scenario-based testing that reflects how real attackers interact with APIs across multiple states.

Tools that automate this kind of validation can help teams identify these gaps earlier in the development lifecycle. Platforms capable of BOLA testing, scenario generation, and business logic analysis, such as those on the APIsec platform, are designed to surface issues before a curious researcher (or less friendly visitor) adds unexpected items to the cart.