-
-
Notifications
You must be signed in to change notification settings - Fork 467
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
migrating from devise without kicking all sessions out? #916
Comments
* see thoughtbot#916 * similar to thoughtbot#909 * also see GHSA-hrqr-hxpp-chr3 for an example of the type of attack that could be possible with an injectable cookie value * Rails provides signed cookies https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html since Rails 3 (??) which prevents tampering * using a signed cookie instead of a plain one, means the attacker cannot forge the cookie value, and therefore cannot perform timing attacks to find a valid token * another added value is that tampering with the cookie will not even hit the database * added a configuration parameter `signed_cookie` so this is optional and defaults to false for backwards compatibility (however, for better security, it might be better to issue a breaking change and default to true) * updated specs
* see thoughtbot#916 * similar to thoughtbot#909 * also see GHSA-hrqr-hxpp-chr3 for an example of the type of attack that could be possible with an injectable cookie value * Rails provides signed cookies https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html since Rails 3 (??) which prevents tampering * using a signed cookie instead of a plain one, means the attacker cannot forge the cookie value, and therefore cannot perform timing attacks to find a valid token * another added value is that tampering with the cookie will not even hit the database * added a configuration parameter `signed_cookie` so this is optional and defaults to false for backwards compatibility (however, for better security, it might be better to issue a breaking change and default to true) * changed the add_cookies_to_headers method to use ActionDispatch / Rails' cookie-handling code to set the cookie * updated specs
* see thoughtbot#916 * similar to thoughtbot#909 * also see GHSA-hrqr-hxpp-chr3 for an example of the type of attack that could be possible with an injectable cookie value * Rails provides signed cookies https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html since Rails 3 (??) which prevents tampering * using a signed cookie instead of a plain one, means the attacker cannot forge the cookie value, and therefore cannot perform timing attacks to find a valid token * another added value is that tampering with the cookie will not even hit the database * added a configuration parameter `signed_cookie` so this is optional and defaults to false for backwards compatibility (however, for better security, it might be better to issue a breaking change and default to true) * changed the add_cookies_to_headers method to use ActionDispatch / Rails' cookie-handling code to set the cookie * updated specs
Our current workaround looks something like this (added to ...
module Clearance
class Session
# monkey-patch so we can import the `remember_user_token` from devise
def current_user
if remember_token.present?
@current_user ||= user_from_remember_token(remember_token)
elsif cookies.signed[:remember_user_token].present?
@current_user ||= Clearance.configuration.user_model.find_by(:id => cookies.signed[:remember_user_token].first)
end
@current_user
end
end
end |
Hi @gingerlime thanks for opening an issue. I haven't personally done such a migration but I've added some thoughts to your questions.
Could you use Rails' prepend_before_action to ensure your migration code is run before the
I'm not sure, but your approach of finding the user via the Devise remember token and signing them in seems reasonable to me.
Thanks for opening a PR for this issue. I like the idea of using a signed cookie for the remember token as an attacker would have to guess the token and know the secret_key_base. I'll follow up further in the PR. I'd like to make sure I understand the timing attack concern correctly. The concern is that because Clearance calls The mitigation would be to use a signed cookie because without the |
Hey @eebs 👋 Thanks for getting back to me.
Yes, this seems like a great idea. I don't know why I didn't think of it first. I'll give it a try. If it works, then hopefully I can avoid monkey-patching the Session.
Yes, precisely :) you captured it perfectly. it's not a super-simple attack to execute, but certainly possible for a determined attacker. Using a signed cookie eliminates hitting the database even for more casual tampering attempts. |
Great, let me know how this goes!
Excellent, thanks. Let's move this conversation to the PR, I'll provide some thoughts shortly. |
This commit introduces signed cookies into Clearance using the signed cookies functionality provided by [ActionDispatch](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html). By using a signed cookie an attacker cannot forge the cookie value, and therefore cannot perform timing attacks to find a valid token. See [this Rack security advisory](GHSA-hrqr-hxpp-chr3) for an example of the type of attack that could be possible with an injectable cookie value. This change adds an optional configuration parameter `signed_cookie` which defaults to false for backwards compatibility and does not use a signed cookie. The other two options are `true` to use a signed cookie and `:migrate` which converts unsigned cookies to signed ones and provides a safe transition path. You can set this via `Clearance.configure` in an initializer: ```ruby # ./config/initializers/clearance.rb Clearance.configure do |config| # ... config.signed_cookie = :migrate # ... end ``` This change also switched to using Rail's `ActionDispatch` for cookie handling rather than `Rack::Utils`. See related issues and pull requests: * #916 * Similar to #909 Co-authored-by: Yoav Aner <[email protected]> Co-authored-by: Eebs Kobeissi <[email protected]>
This commit introduces signed cookies into Clearance using the signed cookies functionality provided by [ActionDispatch](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html). By using a signed cookie an attacker cannot forge the cookie value, and therefore cannot perform timing attacks to find a valid token. See [this Rack security advisory](GHSA-hrqr-hxpp-chr3) for an example of the type of attack that could be possible with an injectable cookie value. This change adds an optional configuration parameter `signed_cookie` which defaults to false for backwards compatibility and does not use a signed cookie. The other two options are `true` to use a signed cookie and `:migrate` which converts unsigned cookies to signed ones and provides a safe transition path. You can set this via `Clearance.configure` in an initializer: ```ruby # ./config/initializers/clearance.rb Clearance.configure do |config| # ... config.signed_cookie = :migrate # ... end ``` This change also switched to using Rail's `ActionDispatch` for cookie handling rather than `Rack::Utils`. See related issues and pull requests: * #916 * Similar to #909 Co-authored-by: Yoav Aner <[email protected]> Co-authored-by: Eebs Kobeissi <[email protected]>
I think this would vary too much on a case by case basis. But feel free to document such migration (pull requests with such documentation are welcome). |
Hey 👋 ! Thanks for creating clearance. It looks like a breath of fresh air!
We're currently using devise and hoping to transition to clearance. Ideally, we'd like to automatically recognize existing devise sessions and then "migrate" them to clearance on-the-fly, so users won't even notice that we switched.
I can handle the devise deciphering of cookies/sessions to find out if a user is logged-in, and then I guess we can use
sign_in(user)
in clearance to migrate. I have a couple of questions however, in case anyone has some experience with this, or maybe just ideas on the best way to do this:require_login
kicks in? also the initial request after deploying the change will have no clearance cookies set yet...remember_user_token
, whereas clearance just uses a plaintext cookie. Is this secure enough? I imagine signing cookies can eliminate hitting the database / timing attacks via brute-forcing the remember token...Would appreciate any thoughts / tips. Thank you!
The text was updated successfully, but these errors were encountered: