This project explores ways to prevent CSRF attacks using request headers.
yarn
yarn start
This starts three webservers, "Alice", "Bob", and "Eve":
- Alice is your main application, running on http://localhost:9997.
- Bob is a trusted service, running on http://localhost:9998.
- Eve is an untrusted service, running on http://localhost:9999.
Open the services in your browser. Examine the server logs triggered by loading the services as well as by clicking the buttons on their pages.
Your overall goal is to preserve same-origin access by Alice while enabling CORS access by Bob and preventing CSRF attacks by Eve.
That's a mouthful. First, some terminology:
- a request succeeds if it receives an HTTP 200. If this request was made by the frontend, there should additionally be no Access-Control-Allow-Origin errors in the console.
- a request fails if it receives an HTTP 403.
Now let's break the overall goal into smaller goals:
- All API calls made by Alice's frontend should succeed.
- All API calls made by Bob's frontend should succeed. (Hint: apply cors to Alice's APIs).
- All API calls made by Eve's frontend should fail. (Hint: apply cors-gate to Alice's APIs. It may not properly handle GET requests… see the caveats below.)
- The POST call made by Alice's backend should succeed. (Hint: set the
Origin
header.) - The POST call made by Bob's backend should succeed. (Hint: set the
Origin
header.) - Make sure that you continue to satisfy the above goals when HTTPS is enabled, in case the browser
applies the Origin header differently, particularly in conjunction with
Referrer-Policy: no-referrer;
You will need to make some modifications to this harness to enable that. - Make sure that neither Chrome nor Safari nor Firefox only expose referrer information over HTTPS (if ever) and never leak referrer paths.
Firefox does not set the Origin
header on same-origin requests
nor on form POSTs (possibly tracked by https://bugzilla.mozilla.org/show_bug.cgi?id=446344). So, to
accomplish goals 1 and to in Firefox, we'll instead need to check the Referer header. But to accomplish
goal 7, you'll need to set different Referrer-Policy
headers and meta referrer
elements in the different browsers.
It is acceptable for GET requests from Eve's frontend to partially fail by returning 200s, so long as they fail CORS (with Access-Control-Allow-Origin errors in the console), and the POST requests from Eve's frontend completely fail.
It is acceptable for your solution to goals 4 and 5 to allow the POST call made by Eve's backend to succeed too. Preventing server-side request forgery is out of scope for this exercise (that can be handled using server-to-server authentication).
Document your solution in the form of automated tests on cors-gate's repo.