Cart Price Manipulation in a B2B Checkout
The B2B checkout accepted a cart update with quantity 114. The line-item total in the response was €38,646. The basket total — the figure a payment step would actually charge — was €1,057. Those two numbers should always agree.
How the discrepancy appeared
The assessment covered a B2B checkout platform used by business customers. Standard approach: walk the purchase flow with Burp, capture every request, look at every field that carries a number. The cart update endpoint accepted a product ID and quantity as JSON and returned a full cart summary including line totals, VAT, and basket total. Setting quantity to 114 on a €339 unit-price item produced the inconsistency in a single request.
The server's two calculations
The line-item total was correct: 114 × €339 = €38,646. The basket total returned €1,057 — consistent with three units, not 114. Two pricing computations, two results, one wrong. The wrong one was the figure that would flow into payment.
PUT /api/cart/update HTTP/1.1
Host: b2b.acme-lab.test
Authorization: Bearer <valid B2B session>
Content-Type: application/json
{"productId":"PROD-LAB01","quantity":114}
HTTP/1.1 200 OK
{
"items": [{ "unitPrice": 339.00, "quantity": 114, "lineTotal": 38646.00 }],
"subtotal": 38646.00,
"vat": 9278.04,
"basketTotal": 1057.40
}
The test stopped at the cart stage. Completing a checkout to confirm the payment endpoint honoured the lower figure would have processed a fraudulent order; the API response demonstrated the risk without going further.
What it enables
A business customer placing a large order would pay approximately €1,057 for €38,646 worth of goods — a ~97% discount requiring nothing beyond a valid session and a high quantity. The attack surface is the gap between two server-side computations that produce different answers for the same cart state.
Cart update and checkout endpoints captured in Burp. Every numeric field — quantity, unitPrice, lineTotal, basketTotal — identified as a candidate.
Quantity 114 → lineTotal €38,646, basketTotal €1,057. Single cart update request. Inconsistency between the two server-side calculations confirmed.
Test stopped at cart API level. No order placed, no payment initiated. Response body sufficient to evidence the finding.
Finding documented with full request/response pair. Root cause flagged for developer investigation.
Defending against it
- Recompute the basket total server-side at payment initiation from the cart record — never from a client-submitted value.
- Reject any checkout request where a submitted total differs from the server's recalculation.
- Identify and fix the root cause of the divergence in the cart update path — cache, type overflow, or discount-tier logic.
- Add a regression test asserting that line-item prices sum to the basket total on every cart state change.
The takeaway
A €38,000 order priced at €1,057 needs no payload — just a Burp proxy, a high quantity, and enough domain knowledge to notice when two numbers that should agree don't.