June 22, 2026
π¨ Unlimited Coupon Abuse β A Critical Business Logic Flaw
Hello Everyone , My Name is Mian Hammad, And today Iβm sharing Unlimited Coupon Abuse.
Mian Hammad
3 min read
Not every critical vulnerability lives in a stack trace. Some of the most expensive ones live in a discount field that nobody thought to rate-limit.
TL;DR
A checkout flow allowed unrestricted stacking and reuse of discount coupons β across sessions, across accounts, with no usage caps at all. What initially looked like a low-severity "coupon stacking" finding turned into a fully automatable, unlimited revenue-loss vulnerability once I tested it for repeatability and scale. That escalation path β not the bug itself β is the real subject of this post.
π§ The Issue
The platform supported two coupon types:
- Percentage-based discounts (
SAVE20β 20% off) - Fixed-value discounts (
FLAT5β $5 off)
Tested in isolation, both worked exactly as intended. The problem wasn't the discount math β it was everything around it. The checkout service never enforced:
- A maximum number of coupons per order
- A per-user / per-account usage limit on any single coupon
- Any cross-session or cross-account validation of prior redemptions
In short: the backend trusted the client to behave responsibly. It didn't have to.
β‘ Proof of Concept β Unlimited Abuse
Expected behavior:
- β Only one coupon redeemable per order
- β Each coupon usable a limited number of times per user
Actual behavior:
- βοΈ Multiple coupons applied to the same cart simultaneously
- βοΈ The same coupon code reused indefinitely
- βοΈ Zero validation tying coupon usage to a session, device, or account history
Attack Steps
- Add a product to the cart β price = $100
- Apply percentage coupon
SAVE20β price drops to $80 - Apply fixed coupon
FLAT5on top β price drops to $75 - Open a new session (or spin up a throwaway account)
- Repeat steps 1β3 with the exact same coupon codes
Result: the discount was honored every single time, with no server-side memory of prior redemptions.
Request sequence (simplified, redacted):
POST /cart/add { product_id: 1001 } β $100.00
POST /cart/coupon { code: "SAVE20" } β $80.00
POST /cart/coupon { code: "FLAT5" } β $75.00
POST /checkout/confirm { ... } β order placed β
[ new session / new account ]
POST /cart/coupon { code: "SAVE20" } β $80.00 β οΈ reused, no rejection
POST /cart/coupon { code: "FLAT5" } β $75.00 β οΈ stacked again
POST /checkout/confirm { ... } β order placed β
Request sequence (simplified, redacted):
POST /cart/add { product_id: 1001 } β $100.00
POST /cart/coupon { code: "SAVE20" } β $80.00
POST /cart/coupon { code: "FLAT5" } β $75.00
POST /checkout/confirm { ... } β order placed β
[ new session / new account ]
POST /cart/coupon { code: "SAVE20" } β $80.00 β οΈ reused, no rejection
POST /cart/coupon { code: "FLAT5" } β $75.00 β οΈ stacked again
POST /checkout/confirm { ... } β order placed β
No 409 Conflict. No "coupon already redeemed" error. No throttling. Just a green light, every time.
The diagram below lays out exactly this: the same three calls, looping back in with a fresh session or account, hitting a server that never checks whether those coupons were already spent.
π Escalation β Why This Is the Critical Part
Most reports stop at "coupon stacking is possible." That alone is usually triaged as low-to-medium severity β annoying, but bounded. The real severity only shows up when you ask three follow-up questions:
- Can it be repeated? Yes β the same codes worked indefinitely, with no expiry on reuse.
- Can it be automated? Yes β the entire flow is three sequential API calls with no CAPTCHA, no device fingerprinting, and no anomaly detection.
- Can it scale across identities? Yes β new accounts could be created freely, and the coupon engine had no concept of "this user already redeemed this code."
Put together:
- Unlimited reuse of the same coupon codes
- Works across multiple accounts, defeating any naive "one redemption per user" assumption
- No rate limiting, no detection, no alerting
- Trivially scriptable β a basic loop with rotating session tokens is enough
This is the difference between a cosmetic pricing bug and a scalable financial exploit. A single attacker with a script could drive the effective price of any product toward zero, indefinitely, without ever tripping a single control.
π₯ Impact
- Direct, unbounded financial loss β every fraudulent order is real revenue the business never collects
- Fully automatable abuse β no manual effort required beyond writing a short script
- Total breakdown of pricing integrity β the "price" shown to a legitimate customer becomes meaningless if anyone can discount it arbitrarily
- Difficult to detect retroactively β without redemption logging tied to identity, there's no clean audit trail to even quantify the damage after the fact
π§© Key Insight
Most hunters stop at:
β "Coupon stacking works."
The impact that actually matters is:
βοΈ Can it be repeated?
βοΈ Can it be automated?
βοΈ Can it scale across users?
That escalation β from "this rule is bypassable" to "this rule is bypassable at unlimited scale, automatically, by anyone" β is exactly how a P2 becomes a P1. Severity isn't just about whether a control is missing; it's about the blast radius once that control is gone.
β οΈ Takeaway for Builders and Testers
If a business rule says:
"Limited discount usage β one coupon per order, capped redemptions per user."
Then validation needs to happen server-side, tied to persistent identity (not just session state), and explicitly tested for:
- Reuse β does the same code work twice, three times, a hundred times?
- Multi-account abuse β does creating a new account reset the limit?
- Parallel/stacked application β can multiple discounts be combined when the business rule says only one should apply?
Business logic flaws don't show up in a vulnerability scanner. They show up when someone asks "what happens if I justβ¦ do this again?" β and the answer is "nothing stops me."
Linkedin: https://www.linkedin.com/in/mianhammad-sec/
Stay secure, Mian Hammad
Thank You