rwf2 / Rocket

A web framework for Rust.
https://rocket.rs
Other
23.59k stars 1.52k forks source link

Add (more) CSRF protection #14

Open SergioBenitez opened 7 years ago

SergioBenitez commented 7 years ago

CSRF is a thing. Protect against it automatically in forms.

ejmg commented 3 years ago

Since Rocket doesn't have built in CSRF support yet and this hasn't been mentioned in the comments yet, it's worth noting that a ready-to-go fairing already exists with Plume's csrf_rocket. It can auto-inject CSRF tokens for you into all routes (along with blacklisting, etc) and can handle CSRF verification for you - alternatively, you can use the fairing just for it's CSRF guard and do the injection yourself.

I currently have a private fork of my own that relies on the checking mechanism while updating the crypto -- I accidentally converged on Plume's solution after realizing the tradeoff between using Rocket's built in form support and defining my own data guard for CSRF -- but the fairing as it exists is very good and should work as a stopgap until Rocket has built in CSRF utilities.

trinity-1686a commented 3 years ago

As the main developer of rocket_csrf, I'd recommend against using the auto-injecting feature, while it works most of the time, it has history of corrupting content. It is fixed as far as I know, but still quite fragile.

MorezMartin commented 3 years ago

Hi all, I am trying rust & and rocket. It is the first time i try to develop an REST API. I try to make it secure (xss, csrf) and i don"t use templates. I use cookies in order to store User id (uuid / nanoid) when user log in. I use crsf_token in a get function/route in order to get token (not implemented yet but we'd say that user must be login, not difficult to do just add cookie guard). I ask for this csrf_token for POST operations like update / delete User. For very sensitive changes like password / email, i also check the request have a correct password.

Is this a good way of doing ? I thought about use this API with Zola static website builder, i think i can create a form template, with a hidden field csrf_token, which can be filled with a GET request, is this ok ?

Thanks in advance, Sorry for my poor english and being a newbie, Martin

elibroftw commented 1 year ago

This is long past due. Rocket.rs claims to be ready for production. There's two libraries for CSRF protection so far. I'm hesitant to use both since I'm making a youtube tutorial on how to use templates and forms in Rocket.rs and the last thing I want to do is give people improper information.

kotovalexarian/rocket_csrf says the project may not be ready for production due to a simple implementation and Trinitiy's Plume-org/rocket_csrf is undocumented.

The way I see it, Rocket explicitly refers to Flask and even support Tera which is inspired from Jinaj2. flask_wtf supports csrf protection for its forms as well as agnostic uses. They support agnostic cases by automatically injecting a csrf_token function into the template context. The function implementation can be seen here https://github.com/wtforms/flask-wtf/blob/main/src/flask_wtf/csrf.py#L23 which makes use of https://github.com/pallets/itsdangerous/blob/aa7e016aae5ddc66517b37b64377352b88d0bcb3/src/itsdangerous/url_safe.py#L76

I really hope someone can implement the Rocket csrf library without a disclaimer. If the implementation might take only a couple days I might try my hand at it.

I also found https://www.stackhawk.com/blog/rust-csrf-protection-guide-examples-and-how-to-enable-it/ but it's so maybe there might not be a need to create a new library.

SergioBenitez commented 1 year ago

This is long past due. Rocket.rs claims to be ready for production. There's two libraries for CSRF protection so far. I'm hesitant to use both since I'm making a youtube tutorial on how to use templates and forms in Rocket.rs and the last thing I want to do is give people improper information.

Note that Rocket readily and automatically leverages the SameSite cookie attribute, which as of today means that 95%+ of your users are automatically protected against CSRF. I do agree that Rocket should still implement token-based CSRF countermeasures, but it is important to note that for the vast majority of cases and users, Rocket already automatically protects your application and its users.

SergioBenitez commented 4 weeks ago

I've made some progress on this issue and have implemented the bulk of an advanced CSRF token mechanism for Rocket. As far as I can tell, it offers a level of security and usability unmatched by other frameworks. You can get an idea of how things are shaping up by reading the docstring in csrf/lib.rs.

Please note that this is still incomplete and cannot yet be used by Rocket applications. What's implemented so far are the core cryptographic operations and mechanisms. What's left is to tie that to Rocket. Furthermore, I would like to thoroughly review the cryptography and security-sensitive components before publishing this.

DemiMarie commented 4 weeks ago

Basic recommendation on AEADs: instead of using a randomly-generated nonce, generate a per-process subkey (using HMAC or Blake2b) and then use an incrementing nonce for AEAD encryption. That allows the key to be shared across many machines without needing to synchronize state. Alternatively, it is safe to use XChaCha20-Poly1305, which uses a 192-bit nonce that can be randomly generated each time.

SergioBenitez commented 3 weeks ago

Basic recommendation on AEADs: instead of using a randomly-generated nonce, generate a per-process subkey (using HMAC or Blake2b) and then use an incrementing nonce for AEAD encryption. That allows the key to be shared across many machines without needing to synchronize state. Alternatively, it is safe to use XChaCha20-Poly1305, which uses a 192-bit nonce that can be randomly generated each time.

The key used for the AEAD encryption for CSRF sessions uses the secret_key configuration parameter (thus you can share it as you wish) coupled with a nonce and a timestamp.

DemiMarie commented 3 weeks ago

Basic recommendation on AEADs: instead of using a randomly-generated nonce, generate a per-process subkey (using HMAC or Blake2b) and then use an incrementing nonce for AEAD encryption. That allows the key to be shared across many machines without needing to synchronize state. Alternatively, it is safe to use XChaCha20-Poly1305, which uses a 192-bit nonce that can be randomly generated each time.

The key used for the AEAD encryption for CSRF sessions uses the secret_key configuration parameter (thus you can share it as you wish) coupled with a nonce and a timestamp.

How long is the nonce? 96 bits isn’t enough for a random nonce, but 192 bits is.

SergioBenitez commented 3 weeks ago

The recommended length of the nonce is determined by the underlying algorithm, in our case AES-256-GCM, which recommends a 96-bit nonce. The RustCrypto libraries enforce using a nonce of this size, so no other option is available to us.

Irrespective, we could improve our use of AEAD by using a more nonce-resistant algorithm, like AES-256-GCM-SIV, adding a deterministically increasing component to the nonce, or both. Or switching the algorithm to XChaCha20-Poly1305 which as you suggest, gives us a 192-bit nonce. But there are trade-offs at every juncture.

Finally note that none of this happens in Rocket or as part of this CSRF mechanism but rather in cookie. Perhaps the idea would be to extend cookie such that it is generic to the underlying AEAD algorithm.

DemiMarie commented 3 weeks ago

This makes AES-256-GCM unsuitable for this application, unless subkey derivation is used: generate a new AES-256-GCM key on each machine, using a KDF and a per-machine high-entropy nonce. I’m inclined to declare this a vulnerability in cookie, or at least a flaw that makes cookie unsuitable for multi-node deployments without sticky sessions.

SergioBenitez commented 3 weeks ago

This makes AES-256-GCM unsuitable for this application, unless subkey derivation is used: generate a new AES-256-GCM key on each machine, using a KDF and a per-machine high-entropy nonce.

This is exactly what is done.