Drupal adds tokens to forms for cross-site request forgery protection, but unconditionally skips doing so for anonymous users.
In most cases this does not matter (because if an anonymous user can submit a form, a potential attacker can just submit it themselves anyway), but in some cases where sites are displaying pages differently to different anonymous users (based on IP address or session information), it can matter, and it would be useful to have the option to add a form token in those cases.
This issue was discussed internally in the Drupal Security Team first, and we felt it could be a public issue due to its unusual nature and limited impact.
As for possible solutions, Heine, for example (who originally reported the issue related to this) suggested that if caching is disabled, that would be one case where we could easily add the token even if the form is being viewed by an anonymous user.
| Comment | File | Size | Author |
|---|---|---|---|
| #18 | 1803712.patch | 2.77 KB | drumm |
| #16 | 1803712.patch | 2.7 KB | drumm |
Comments
Comment #1
gregglesAn alternate solution would be to use the stateless csrf protection concept described here: http://appsandsecurity.blogspot.de/2012/01/stateless-csrf-protection.html
Comment #2
klausiWe might also consider a simpler approach with HTTP Origin or Referrer header checks as described on https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Pr... . That way we would have a stateless CSRF protection for anonymous users. Not sure about browser support for the Origin header.
Comment #3
klausiThe seckit module already does some Origin checks: http://cgit.drupalcode.org/seckit/tree/seckit.module#n327
So we could do something similar in the appropriate Form API places for anonymous users.
I'm still researching browser support. http://caniuse.com/cors seems to be only about CORS, which does not say anything about the Origin header alone.
Comment #4
klausiI was experimenting a bit with Origin header checks today, but it seems that Firefox does not send it on POST requests https://stackoverflow.com/questions/29034776/why-does-firefox-not-always...
Comment #6
fgmReferer information is increasingly not being sent either, so that's one less source of information (which was unreliable anyway).
Comment #7
alexpottComment #13
handkerchiefA security scan from one of our customers has reported this as a major security issue:
Same for:
https://example.com/user/password and others.
Question:
Is this really such a vulnerability? And how we can solve this?
We have already installed https://www.drupal.org/project/seckit but maybe with the wrong settings?
Comment #14
mcdruid commented@handkerchief Drupal already uses anti-CSRF tokens in forms for authenticated users (such as the administrator in the report text that you quoted).
This issue is about adding CSRF protection for anonymous users, who would typically not have access to forms such as the one to create / modify other user accounts.
For details of the built-in CSRF protection, see for example:
https://www.drupal.org/docs/7/security/writing-secure-code/create-forms-...
For Drupal 8 you can see some of the code which handles CSRF tokens in, for example:
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21Fo...
Comment #15
handkerchiefthx @mcdruid for your response. I'll do that.
Comment #16
drummSome anonymous forms, like the login form, would benefit from CSRF hardening - https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forger...
Attached is a D7 proof-of-concept. It could use some documentation and tests, if it is potentially a good approach.
anonymous_forms_with_tokenallows configuring specific forms to get an anonymous token. When one is generated,$_SESSIONis used to stash when it was generated.Since form tokens work as long as the form cache is there, these sessions are cleaned up once that expiration has passed, in
drupal_session_commit(). This allows anonymous sessions to be deleted if they are used to make requests, without generating form tokens, for some time. They are also cleaned up on login bydrupal_session_regenerate().Comment #18
drummFixing the PHP notice.
Comment #20
kmkelmor commentedMy apologies if this is an incorrect way for using the comment feature. Since Detectify has declared the login-csrf vulnerability a medium level issue, I have to be able to fix this on my D7 site. Seckit didn't fix it, so I was trying this patch. Unfortunately it throws an undeclared _Session value in line 358 of session.inc
I'm at a loss as to what to try next. Any and all help is greatly appreciated. Thanks! kmkelmor
Comment #22
avpadernoThe existing patches are for Drupal 7.x. I am not sure which is the correct status between Active and Needs work.
I would use the latter, since the existing patch needs to be re-rolled for Drupal 8.x. Please change the status if it's not correct.
Comment #29
mxr576RE #1
Stateless CSRF technique is now supported by Symfony:
https://symfony.com/blog/new-in-symfony-7-2-stateless-csrf
https://github.com/symfony/symfony/commit/27d8a31d105ed53a043e4e21321279...
Comment #30
abarrioAccording to #29 I made a test project and integrated the Symfony security-csrf library. It has worked perfect on anonymous and logged in users.
Maybe we can make the csrf token generation in Drupal to be made with this component.
Here is the example service that I used: