rails-authentication-from-scratch icon indicating copy to clipboard operation
rails-authentication-from-scratch copied to clipboard

Single point of failure when using signed IDs

Open ayushn21 opened this issue 3 years ago • 5 comments

Using Rails signed IDs is certainly an elegant way to go about account activations and password resets and 99.9% of the time I reckon they're fine in terms of security. However, it creates a single point of failure in the secret_key_base. Signed IDs are generated using the MessageVerifier API which is also used to generate signed cookies. Please see this blog post to understand what's going on under the hood:

https://binarysolo.chapter24.blog/demystifying-cookies-in-rails-6/#signed_cookies

If an app's secret_key_base becomes compromised due to whatever reason, it'll allow an attacker with access to this key to forge signed IDs and use them to reset the password for any account. (I'm also making an assumption the the salt hasn't been changed from the default but I can't imagine this is changed for the vast majority of Rails apps).

I'm not a security expert by any stretch of the imagination so I don't know how severe this risk is. I'd estimate it to be pretty low risk. However, just to avoid a single point of failure, I personally prefer to use a token stored securely using has_secure_password and then use the MessageVerifier API to generate the user facing token instead of using a bog standard signed ID.

This isn't to say the signed ID approach is "wrong" or "insecure" by any means. I'm just opening this issue to raise this potential flaw and have a chat about it :)

ayushn21 avatar Jan 09 '22 17:01 ayushn21

Also worth mentioning is that the same flaw exists if the session_token and remember_token are stored in plain text in the database. Again I'm assuming that an attacker has access to the database and secret_key_base. If somehow they do, then they can forge sessions and impersonate any user.

If those tokens are also stored with has_secure_password then the above loophole is closed as they won't have the plain text tokens they need to put into their forged cookie.

ayushn21 avatar Jan 09 '22 17:01 ayushn21

@ayushn21 thank you for taking the time to post this since I think it's valuable information. Since the API mentions that using a singed_id is "... particularly useful for things like password reset or email verification", I'm not too concerned. If the secret_key_base becomes compromised I'd imagine that the application would be vulnerable to multiple attacks.

However, I do think it's worth keeping this issue open to raise awareness and keep the conversation going. Thanks again!

stevepolitodesign avatar Jan 10 '22 10:01 stevepolitodesign

particularly useful for things like password reset or email verification", I'm not too concerned

Yeah absolutely. In 99.9%, or even 99.99% of cases I'm sure it'd be totally fine!

If the secret_key_base becomes compromised I'd imagine that the application would be vulnerable to multiple attacks.

For sure. The app would be at serious risk if the key base was compromised. My aim with this issue was to suggest a method to minimise the exposure until a new key base can be deployed. Again making some serious assumptions about the attacker having access to sensitive information so this is all pretty low-risk "worst case scenario" stuff so just worth a chat about I reckon :)

ayushn21 avatar Jan 10 '22 12:01 ayushn21

I appreciate you taking the time to highlight this though. I'm learning a lot!

stevepolitodesign avatar Jan 12 '22 02:01 stevepolitodesign

Happy to help! :)

ayushn21 avatar Jan 12 '22 10:01 ayushn21