Unit 6: The browser security model · Lesson 2 of 5 · 20 min
CORS
How a server lets a named origin read its responses, and the setting that lets everyone in.
mission
- You are
- The analyst reviewing the shop's API.
- Situation
- Three API routes send CORS headers. One of them carries signed-in customers' orders.
- Goal
- Check which origins each route trusts, with and without cookies.
- Hand in
- A finding for any route that trusts every origin with credentials.
CORS as a gatekeeper's list
A route with one trusted origin
curl -sI -H 'Origin: https://status.example.com' http://127.0.0.1:8000/api/status | grep -i access-control
Access-Control-Allow-Origin: https://status.example.com
you should see Only the status site may read it.
The preflight
Before some cross-origin requests, the browser asks first with OPTIONS.
curl -si -X OPTIONS http://127.0.0.1:8000/api/status | grep -i access-control
Access-Control-Allow-Origin: https://status.example.com
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 600
you should see Allowed origin, allowed methods and how long the browser may remember the answer.
Try an unknown origin on the orders route
curl -si -H 'Origin: https://unknown.example' http://127.0.0.1:8000/api/orders | grep -i access-control
Access-Control-Allow-Origin: https://unknown.example
Access-Control-Allow-Credentials: true
you should see The route copies whatever origin it receives and allows credentials.
defender tip Reflected origin plus Allow-Credentials: true means any website a signed-in customer visits can read their orders. That is a high severity finding.
Compare with the products route
curl -si -H 'Origin: https://unknown.example' http://127.0.0.1:8000/api/products | grep -i -E 'access-control|vary'
Access-Control-Allow-Origin: https://shop.example.com
Vary: Origin
you should see A fixed origin regardless of what you send, and Vary: Origin for caches.
CORS on /api/orders
allow_origin = request.headers["Origin"] allow_credentials = true
Every origin may read signed-in data.
if origin in {"https://shop.example.com"}:
allow_origin = origin
allow_credentials = true
vary = "Origin"A fixed allowlist.
What a defender takes away
- 1CORS relaxes same origin; it never adds protection.
- 2Never reflect the Origin header together with Allow-Credentials.
- 3Use a fixed allowlist and send
Vary: Origin.
Questions
0 of 3 solved
Answer each one from what you find on your lab machine.