Opened 5 years ago

Last modified 2 weeks ago

#31823 assigned New feature

Add Support for Fetch Metadata Request Headers

Reported by: meggles711 Owned by: meggles711
Component: CSRF Version: dev
Severity: Normal Keywords: CSRF, Fetch, headers
Cc: Triage Stage: Someday/Maybe
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I would like to implement Fetch Metadata Request Headers as a new security feature in Django.

What are Fetch Metadata Request Headers?

Fetch metadata request headers are a relatively new security feature used to protect against cross-origin request attacks like CSRF. Browsers that support them provide request origin information to the web server inside headers with every request. This information includes what site is making the request, the mode or type of the request, and the destination of the request. The information provided in the fetch metadata request headers can be used to create a resource isolation policy that protects web application users from cross-origin attacks.

Proposed Changes to Django

New checks should be added to the CSRF middleware. Currently the middleware will check the referer header as one method of determining request validity. When the fetch metadata request headers are set, these should be used for resource isolation checks instead. Otherwise, the policy will fallback on validating with the referer header.

If the fetch metadata headers are set, this resource isolation policy is followed:

Same-site and browser-initiated requests are allowed
Top level navigation (HTTP GET) is allowed
Developer defined endpoints that are meant to serve cross-site traffic are allowed
Reject all other requests

After this policy is followed CSRF processing will continue as normal.

Please provide me some feedback on this implementation plan and let me know if you would like to see this new security feature in Django.

Change History (5)

comment:1 by meggles711, 5 years ago

Owner: changed from nobody to meggles711
Status: newassigned

comment:2 by Mariusz Felisiak, 5 years ago

Triage Stage: UnreviewedSomeday/Maybe

Fetch metadata request headers are still on an early and experimental stage and may change at any moment. Moreover browsers don't support them (e.g. Firefox and Safari). We can reconsider this ticket when the specification becomes more mature and stable.

comment:3 by Felipe Rosa de Almeida, 3 weeks ago

Fetch metadata headers are widely supported now. More specifically, the Sec-Fetch-Site which can be used to protect against CSRF is supported by by 97.63% of all tracked browsers on Can I Use.
Recently, Go introduced a CSRF protection middleware that uses Fetch Metadata and Origin headers to protect against CSRF, without relying on tokens. The author research for developing the algorithm is shown here: https://words.filippo.io/csrf/. Google recommends Fetch Metadata for CSRF prevention and OWASP will follow as well.

It seems that supporting the Sec-Fetch-Site header would be a great fit for Django CSRF protection. Today the first check on the CsrfViewMiddleware for a valid request is the Origin header. My suggestion is to add a check before that. If the Sec-Fetch-Site header is set, and it's value is either same-origin or none (user-initiated), the request is accepted, otherwise it can be rejected. If the header is not set, the following checks continue (Origin, Referer and token).

I can take a stab at implementing this if that's OK.

In the future (probably as part of a separate ticket), a setting can be added to select the CSRF protection strategy. As using Fetch metadata and Origin headers are sufficient protection against CSRF in modern browsers, the user could opt out of the token strategy which adds more complexity for the frontend.

comment:4 by Jacob Walls, 3 weeks ago

Felipe, could I ask you to open an issue at django/new-features? That's our more contemporary spot for gathering +1's for ideas.

in reply to:  4 comment:5 by Felipe Rosa de Almeida, 2 weeks ago

Replying to Jacob Walls:

Felipe, could I ask you to open an issue at django/new-features? That's our more contemporary spot for gathering +1's for ideas.

Sure, will do.

Note: See TracTickets for help on using tickets.
Back to Top