FS-DEMO-01 · demo-corp.test · sample
Any user can read other customers’ invoices
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Description
The endpoint GET /v2/invoices/{id} checks that the token is valid, but not that the invoice belongs to the requester. Changing the identifier is enough to read any customer’s invoices.
Impact
Exposure of every customer’s personal and tax data: name, tax ID, line items and amounts. If exploited, it is a personal data breach under the GDPR.
Remediation
router.get('/v2/invoices/:id', auth, async (req, res) => { const invoice = await Invoices.findById(req.params.id); const invoice = await Invoices.findOne({ id: req.params.id, customerId: req.user.customerId, }); if (!invoice) return res.sendStatus(404); res.json(invoice);}); Also: non-sequential identifiers and an automated object level authorisation test in continuous integration.
Evidence
GET /v2/invoices/48214 HTTP/2Host: api.demo-corp.testAuthorization: Bearer eyJhbGciOiJSUzI1NiIs… (user A)Accept: application/jsonHTTP/2 200 OKContent-Type: application/jsonCache-Control: no-store{ "id": 48214, "customer": "usr_9102", "tax_id": "B••••••••", "item": "Annual licences", "total": "€18,900.00"}curl -i https://api.demo-corp.test/v2/invoices/48214 \ -H "Authorization: Bearer $TOKEN_A" \ -H "Accept: application/json"