I originally reported this to the security team, but they cleared it to be discussed in public.
Problem/Motivation
The routing system of Drupal Core offers a CSRF protection mechanism (mainly) for GET requests. This mechanism adds a CSRF token as a query parameter to the URL. There are two (related) problems:1. Sensitive information within URLs may be logged in various locations, including the user's browser, the web server, and any forward or reverse proxy servers between the two endpoints. URLs may also be displayed on-screen, bookmarked or emailed around by users. They may be disclosed to third parties via the Referer header when any off-site links are followed. Placing session tokens into the URL increases the risk that they will be captured by an attacker. Therefore, it is also an OWASP recommendation not to place CSRF tokens in the URL. If an attacker is able to intercept the CSRF token of the user, the attacker is able to conduct a CSRF attack on the specific user for the specific protected action.
2. GET requests should (by specification) never be used for server-side state-changing actions in the first place. Nevertheless, Core and many contributed modules do so, although even Drupal's own documentation stated that this is bad practice in the past.
CSRF tokens in GET requests are therefore not only somewhat insecure (1.), but shouldn't also never be necessary (2.) if strictly following the HTTP specification and secure coding guidelines.
Therefore, it is in my opinion questionable whether this core feature should even exist in its current form since it encourages the usage of GET requests for server-side state-changing actions. Currently, the feature only seems to exist to make a bad practice a bit (or much) "less bad".
Proposed resolution
tbd
Remaining tasks
- Discuss if this feature should still exist
- Discuss potential impact of removal of feature
- ...
Comments
Comment #2
prudloff commentedComment #3
msankhala commentedI had a security scan with Burp Suite for a Drupal 10 website and Burp suite also reported the same issue with Medium severity. Below is one sample of such issue reported by Burp suite.
Comment #4
joachim commentedI've attempted to make a way of doing this with POST instead of GET -- it uses a button which is styled to look like a link, and the CSRF token is in a hidden input value element.
Proof-of-concept module at https://github.com/joachim-n/link_csrf_post_poc. Feedback welcome!
Comment #6
prudloff commentedWhile I agree that having state-changing GET requests is not a best practice, I don't think it would be realistic to remove the existing CSRF token feature anytime soon.
I think we would need to come up with a long term plan and handle this in multiple followup issues.
Maybe something like this:
The main risk of doing this too quickly would be to have modules that keep using state-changing GET requests but simply don't protect them against CSRF (which would be way worse than the current situation).
Comment #7
gregglesI appreciate the effort here. I think the ideas from #6 are a strong proposal.