Skip to content

CSRF is invalid with Stateless CSRF #59065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
smbpunt opened this issue Dec 2, 2024 · 15 comments
Closed

CSRF is invalid with Stateless CSRF #59065

smbpunt opened this issue Dec 2, 2024 · 15 comments

Comments

@smbpunt
Copy link

smbpunt commented Dec 2, 2024

Symfony version(s) affected

7.2.0

Description

Hi,

After upgrading from Symfony 7.1.6 to 7.2.0 and updating the associated recipes, I encountered a bug when submitting forms: "CSRF token is invalid".

Key Details:

  • Environment: The issue only occurs in the prod environment;
  • CSRF Token Issue: The HTML generated for the CSRF token has a value attribute that is undefined:
<input type=“hidden” id=“meeting__token” name=“meeting[_token]” data-controller=“csrf-protection” autocomplete=“off” value=“csrf-token”>

Also, I created a fresh Symfony webapp with a simple CRUD setup. The same issue occurred.

How to reproduce

https://github.com/smbpunt/bug-sf-59065

It's a simple new “webapp” with an entity and an associated crud (all generated via maker-bundle).

  • Clone
  • Install
  • Run server
  • Go to /new
  • Submit a form

Possible Solution

The only working solution/workaround was to comment out the stateless configuration in csrf.yaml :

# Enable stateless CSRF protection for forms and logins/logouts
framework:
  form:
    csrf_protection:
      token_id: submit

#    csrf_protection:
#        stateless_token_ids:
#            - submit
#            - authenticate
#            - logout

Additional Context

No response

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Dec 2, 2024

Can you please try to create a small app that'd reproduce the issue?
The instructions here are partial and it'd help to have a complete and quick reproducer.

@smbpunt
Copy link
Author

smbpunt commented Dec 2, 2024

Can you please try to create a small app that'd reproduce the issue? The instructions here are partial and it'd help to have a complete and quick reproducer.

https://github.com/smbpunt/bug-sf-59065

I versioned the sqlite database and the .env.local.php

Just clone/install and submit a form http://127.0.0.1:8000/new.

@nicolas-grekas
Copy link
Member

I didn't reproduce until I compiled assets, submitted them, then removed them.

My guess is: you tried in dev, where the JS assets are auto-compiled. Then you turned prod mode, and it failed. The reason is that the session kept track of the JS submission and now requires the JS to be loaded as an additional protection.

And the fix is on your side: run php bin/console asset-map:compile

This is suboptimal, but running this command is mandatory to get assets ready for prod mode.
Maybe this command could be turned into a cache-warmer, so that falling into this trap isn't that easy?

@nicolas-grekas
Copy link
Member

Moved to a more generic RFC: #59072

@jmsche
Copy link
Contributor

jmsche commented Dec 3, 2024

@nicolas-grekas I had the same issue yesterday, but here we use Encore instead of Asset Mapper.

@nicolas-grekas
Copy link
Member

The reason should be the same.
Any idea similar to #59072 that'd work with Encore?

@smbpunt
Copy link
Author

smbpunt commented Dec 3, 2024

Hello,

I think there's something to look into. Indeed, on the test I provided, if you compile the assets, it seems to work...
However, on the project I updated to 7.2, I was sure I had compiled the assets (because I had installed it on a server...). I went to check, re-compiled the assets to be sure, and I'm still getting the “CSRF Token is invalid”...

Is it possible that this is linked to a web server configuration?
Locally (and env prod + assets compiled) I don't encounter the bug, whereas on my server I do encounter the bug. Knowing that everything was functional before the 7.2 update...

@nicolas-grekas
Copy link
Member

Are you behind a reverse proxy? If yes, ensure you configured trusted proxy headers.

@smbpunt
Copy link
Author

smbpunt commented Dec 3, 2024

Are you behind a reverse proxy? If yes, ensure you configured trusted proxy headers.

It's now working. Thanks !

@stloc
Copy link

stloc commented Dec 4, 2024

for information :
I have the same error on production (nginx behind HAproxy).
No error in local (symfony serve, ddev Docker or platform.sh)

how to configure HAproxy or Nginx ?

@nicolas-grekas
Copy link
Member

Read the doc ?
https://symfony.com/doc/current/deployment/proxies.html

@tacman
Copy link
Contributor

tacman commented Dec 5, 2024

Alas, read the doc isn't so simple. I focus mostly on the application, our dev-ops contractor who helps manage the dokku instance on hetzner isn't available now. I know we use CloudFront, but I don't know if it's a reverse proxy. I see this, so I added the ips

image

framework:
    trusted_proxies: '127.0.0.1,5.161.107.103,5.161.112.3,REMOTE_ADDR'
    http_method_override: false
    handle_all_throwables: true
    secret: '%env(APP_SECRET)%'
    csrf_protection: true

In short, this used to work with 7.1, and doesn't with 7.2, and I've read and re-read the docs, and this excellent article https://jolicode.com/blog/symfony-reverse-proxies-and-ip-protection and I'm feeling out of my league.

Are you saying that I need to reorder when the assetmap:compile command happens? Currently it's loaded in the Procfile, common for heroku-ish deployments.

web:  vendor/bin/heroku-php-nginx -C nginx.conf  -F fpm_custom.conf public/
release: bin/console importmap:install && bin/console asset-map:compile && bin/console d:m:m -n --allow-no-migration

Any suggestions? Of course, it's particularly difficult to test as I hack something in and have to push it to the production site to see if it's working.

@nicolas-grekas
Copy link
Member

trusted_proxies: '127.0.0.1,5.161.107.103,5.161.112.3,REMOTE_ADDR'

REMOTE_ADDR should be listed only if you're sure your dokku instance is not available without getting through cloudfront

Alternatively, there full list is at https://ip-ranges.amazonaws.com/ip-ranges.json

(All this is in the doc ;) )

Then, you need to configure the trusted headers. Not sure which headers cloudfront uses, but you should be able to know by inspecting requests as seen by the app.

@nicolas-grekas
Copy link
Member

Oh, and you can still not opt-in for the stateless CSRF if you really cannot configure trusted proxies.

@smbpunt
Copy link
Author

smbpunt commented Jan 8, 2025

Are you behind a reverse proxy? If yes, ensure you configured trusted proxy headers.

It's now working. Thanks !

Hello,

I installed the application (which worked) on another server. This other server uses the same HA Proxy (and the same HA Proxy configuration).
For some reason, the same application, with the same sources/environment variables/trusted proxies doesn't work.

We're looking into it (which could be the server's configuration? php packages ? web server configuration ?), but if you have any leads, I'd love to hear it.

Edit: Okay, we've found the problem.
It was an Nginx configuration problem. It seems that there were already directives to transmit headers on this server. So there must have been a conflict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants