Back to scan results
Check 38 of 45

Business Logic Flaws

We review the public page's advertised forms, fields, links, and browser-storage usage for trust boundaries that commonly lead to price manipulation, workflow bypass, unauthorized object access, and unsafe state changes.

What this check reviews

The check inspects same-origin public forms and links for hidden or GET-submitted fields representing price, amount, total, discount, coupon, balance, role, approval, payment state, workflow stage, ownership, and record identifiers. Quantity controls with incomplete browser minimum and maximum hints are also reported for server-side review.

It flags state-changing-looking actions exposed through GET routes, public business-authority query parameters, numeric identifiers in links to orders, invoices, receipts, accounts, statements, transactions, profiles, or users, and scripts that store financial or authority flags in localStorage or sessionStorage.

These indicators produce warnings for manual validation, not confirmed failures. Hidden fields, numeric identifiers, and browser storage can be safe when the server ignores untrusted authority data, recalculates every value, authorizes each object, and enforces a valid workflow transition.

The scanner does not visit checkout, cart, order, coupon, transfer, refund, or account actions. It does not submit forms, change values, guess record IDs, place orders, reserve stock, redeem discounts, initiate payments, authenticate, replay requests, or send concurrent traffic. Authenticated workflows, race conditions, multi-step abuse, and server-side invariants require authorized manual testing.

Why this matters for PCI DSS

Business-logic weaknesses can let an attacker alter prices or quantities, skip required approval or payment steps, reuse a discount, access another customer's records, or perform the same one-time action more than once. The result can be fraud, data exposure, inventory errors, and unauthorized payment activity.

PCI DSS secure-development and access-control requirements expect applications to define abuse cases, validate business rules on the server, authorize every request and object, protect payment workflows, log significant actions, and handle concurrent updates safely.

How to fix it

Accept identifiers and user choices, then derive authoritative values on the server. Do not bind a browser-supplied price, total, discount, owner, role, approval, or paid flag into the domain model:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SubmitOrder(OrderInput input)
{
    Product product = products.FindForSale(input.ProductId);
    if (product == null || input.Quantity < 1 ||
        input.Quantity > product.MaximumOrderQuantity)
        throw new HttpException(400, "Invalid order.");

    decimal subtotal = checked(product.UnitPrice * input.Quantity);
    decimal discount = coupons.CalculateAuthorizedDiscount(
        User.Identity.Name, input.CouponCode, subtotal);

    orders.Create(User.Identity.Name, product.Id,
        input.Quantity, subtotal - discount);
    return RedirectToAction("Review");
}

Model the workflow as explicit server-side states and allow only named transitions. Recheck authorization, ownership, inventory, limits, payment state, and current record version inside the same transaction immediately before committing. Never rely on a disabled button, hidden input, URL sequence, JavaScript condition, or previously completed step.

Make GET and HEAD routes read-only. Require an anti-forgery token and an idempotency key for important writes, and enforce one-time coupon, refund, transfer, and payment rules with database uniqueness constraints. Use optimistic concurrency tokens or appropriate locking around balances, inventory, quotas, and redemption counters.

Authorize every referenced object against the current identity rather than trusting a customer, account, user, order, or invoice ID. Opaque identifiers reduce guessing but do not replace object-level authorization. Keep browser storage and request fields informational only; the server must derive roles, entitlements, totals, and workflow status from trusted records.

Document normal and abusive sequences, test boundary values and repeated/concurrent requests in an authorized staging environment, record security-relevant decisions, and alert on rejected transitions, repeated idempotency keys, coupon abuse, quantity anomalies, and cross-account access attempts.

Fixed it? Re-run the scan to confirm.

Run scan again