6

The remember_user_token cookie token generated by the Ruby Devise authentication component reveals part of a bcrypt salted credential when decoded.

For example:
remember_user_token=W1sxNF0sIiQyYSQxMSRtSHhGeWd3VkFNdzdxd3VmUE04MWdPIiwiMTUyMTA4NjEzMy4wOTU3Il0%3D--96341f2abb8e9fa777d9ad5199b2231f3d22e1d7

Decodes to:

[[14],"$2a$11$mHxFygwVAMw7qwufPM81gO","1521086133.0957"]

The second part of this tuple is the bcrypt cred up to the salt.
As the hashed password portion is omitted, I believe recovering the password would not be feasible. However, this does not seem like good practice and I am not clear on why this function has been designed to reveal even a part of the user's hashed credentials.

What are some scenarios where this information may help an attacker gain unauthorised access to the application?

Source code below:

http://www.rubydoc.info/github/plataformatec/devise/Devise%2FModels%2FRememberable%2FClassMethods%3Aserialize_into_cookie

http://www.rubydoc.info/github/plataformatec/devise/Devise/Models/Rememberable#rememberable_value-instance_method

  • 1
    The salt should be considered non-secret information and as such doesn't pose a significant risk. The salt is used to a) make the usage of pre-computed hash values more difficult, and b) ensure that two users with the same password don't also have the same stored hash value. Neither of these cases are compromised by storing the salt on the end user's machine. That said, there are alternatives in writing your own salting function / changing the configuration config.use_salt_as_remember_token. – Dave Satchell May 7 at 6:51
1

The "rememberable" Devise strategy is used to re-authenticate a user from the value stored in a persistent cookie (the remember_user_token that you decoded) with the following format:

[[<user_id>], "<user_salt>", "<cookie_generated_at_UTC_time>"]]

The cookie is signed to prevent tampering of the cookie values (the signature is the blob you can find after the "--" in the cookie).

The application you are testing uses the default implementation of "rememberable", which does away with the need of having a database column to store the per-user "remember tokens"; instead it uses the user id + password salt as the key to uniquely identify the user. When the application receives back the signed id+salt cookie, it looks up a user with the matching id and if the salt matches that of the cookie, it successfully authenticates the user and continues the processing.

The use of the salt as unique identifier avoids having to store "remember tokens" on the server side; as a trade-off it reveals the salt. Giving an attacker access to the bcrypt salt without the actual hashed password is useless (the salt is only used to avoid pre-computed hash attacks, forcing an attacker to bruteforce each hashed secret separately). If an attacker gains access to the user password they will also get access to the salt, so the security of the "rememberable" strategy is not compromised by the sharing the salt.

I would personally be more concerned by the sharing of the user ID (the first field in the cookie), e.g. it may be later re-used in direct object reference attacks.

If you are not comfortable exposing the user password salt you can implement your own remember_token method in your Devise user class, see the rememberable model, e.g. for instance creating random tokens and storing them on the user database table.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.