4.1Reading any customer's orders without authorization
Critical- Severity
Critical, The standard scoring of a vulnerability's technical severity, from 0 to 10. The vector beside it says how the score was reached.: 6.5
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N- Component
GET /v1/orders/{id}onapi.example.com- Description
The API checks that the caller is authenticated, but not that the requested order belongs to them. The identifier is a sequential integer passed in the URL. An authenticated customer who replaces their own identifier with someone else's receives the full order: name, shipping address, phone, order lines and amount. The server answers 200 in both cases.
- Proof of reproduction
GET /v1/orders/4172 HTTP/1.1Host: api.example.comAuthorization: Bearer <test account token> HTTP/1.1 200 OK{"id":4172,"customer":"test account","total":"149.90", ...} GET /v1/orders/4173 HTTP/1.1Host: api.example.comAuthorization: Bearer <the same token> HTTP/1.1 200 OK{"id":4173,"customer":"another customer","total":"318.00", ...}- Impact
Impact demonstrated on reads. With sequential identifiers, enumeration is trivial and can be automated: the entire order history can be retrieved with a single legitimate customer account. The data concerned is personal data under the GDPR (article 4). A confirmed exploitation would be a breach to notify to the supervisory authority within 72 hours (article 33). No write was attempted.
- Prerequisites
A standard customer account, created freely from the site. No prior privilege escalation, no victim interaction.
- Remediation
- On the server, on this route and on every route that takes an object identifier, check that the requested object belongs to the user of the session.
- Handle access control in a shared layer rather than in each route, so the omission can no longer happen.
- Replace sequential identifiers with unguessable ones (A random identifier, 122 random bits: impossible to guess from its neighbor.). A defense-in-depth measure, not a fix on its own.
- Review the access logs for past enumeration on this route.
- Status
Fixed by the client, then verified at the retest. The retest is part of the engagement: no vulnerability is marked "fixed" until it has been checked.