Is Rails Devise gem truncating passwords? - ruby-on-rails

OWASP ASVS Standards
I am testing a web app against OWASP standards:
2.1.3 Verify that password truncation is not performed. However, consecutive multiple spaces may be replaced by a single space
We are using Rails, along with Devise gem for authentication. While testing whether we meet the requirements of 2.1.3, I noticed that longer passwords are truncated.
I can set the following password:
NVjEuRjiFcDGYfhm9kh9pTxUvHwKyTpNMhXqwDBHoaU3cHKv2guZJTwrUZyNN9GiJ4B8TjtiWpCWZXVsRoXmhXKEtzqJr7qnngQlfldlfdlE (108 chars)
I can sign in with the above password fine. I can also sign in with this truncated version of it, though:
NVjEuRjiFcDGYfhm9kh9pTxUvHwKyTpNMhXqwDBHoaU3cHKv2guZJTwrUZyNN9GiJ4B8Tjti
Beyond those 72 chars, I can add or remove characters, or just lop them all off, and I can still sign in. I only need the first 72 chars to be correct, the rest appears to get ignored. I haven't checked yet, but different characters might require more storage, and could shorten the length required for authentication.
Looking in the db, I can see the field is varchar(128) - 128 being the maximum length, going by OWASP:
2.1.2 Verify that passwords 64 characters or longer are permitted but may be no longer than 128 characters.
I assumed the user entered password should be up to 128 chars, but it seems the field only stores 128 chars, and 29 of them are being used by Devise for the salt. How Devise Encrypts Passwords
I have only a vague understanding of how hashing/encrypting work - I understand the encrypted password length is not necessarily the same as the user entered password length. But since my password is being truncated, it seems like Devise didn't leave enough room for a user entered password to be 128 chars.
Am I mis-reading the OWASP standards, or is this a flaw in Devise, or am I missing something?

As the article you linked to states, Devise defaults to using bcrypt to encrypt your password. It's the bcrypt algorithm that has the limitation. See:
https://en.wikipedia.org/wiki/Bcrypt#Maximum_password_length
https://security.stackexchange.com/questions/39849/does-bcrypt-have-a-maximum-password-length
I think you could say this is flaw in that devise should handle this case better. You could also see it as a known limitation of the default devise condfiguration.
If you are going to use devise with bcrypt, I think you need to validate that passwords are within this limit. It's not uncommon to see this kind of limit in web registration forms. In the devise initializer, I see an option to change the encryption algorithm. I haven't done it myself, but I think if you wanted to exceed the limitations of bcrypt, the way to do it would be to pick a different algorithm.

Related

Set password for user automatically - without Devise

I'm beginner with Rails 5, i would appreciate your help.
I have an user model, where obviously save a password for the user for a possible login.
The thing is i want to set the password automatically based on a text_field called identification_number.
Everything I've read is about doing it with Devise gem, but I'm not using it and also don't want to.
Once again, thanks for your help.
The password field is just another string field called :identification_number for your case.
But, saving password in the DB as plain strings is highly unrecommended.
There are a lot of security issues if you save the passwords as plain strings on your database.
Some of them are that:
You have full access on the passwords of your users
If someone, somehow manages to access your database they will also have full access to the passwords of your users.
In order to avoid these issues, most of the applications save the password strings as encrypted strings with some kind of salt for enhanced entropy.
With a quick google search I found some relevant blog posts that can help you build the password encryption from scratch, such as:
Without using a gem:
https://www.sitepoint.com/rails-userpassword-authentication-from-scratch-part-i/
Using some gems:
http://railscasts.com/episodes/250-authentication-from-scratch?view=asciicast
Apart from that, the password is not an identification_number. I would not use that name. The password is not used to identify the user. The id is most of the time the identification number. Better just call it :password. Also, it does not need to be a text field, it shouldn't be that long.
You can use bcrypt gem for implementing the secure password.
The bcrypt ruby gem provides you with has_secure_password method. The has_secure_password method encrypts passwords by hashing and salting the passwords and generate ‘password_digest’.
you can refer this link for more info

How devise stores and read salts/hashes?

How does it work, that devise knows salts for encrypted passwords? Where does it store these hashes and how is that safe?
This is one of the main files for creating passwords: Devise::DatabaseAuthenticatable
Salt is not stored in the database, it is a string generated by this C program that is run by the BCrypt::Engine.generate_salt() function __bc_salt:
prefix = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
__bc_salt(prefix, cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
This can be found here:
BCrypt::Engine
With some other interesting code here: BCrypt::Password
From what I can gather though, the salt itself is the 29 characters that appear after the third $ in the encrypted password. This alone cannot tell you the password though, since you also need to know the pepper which is based on your apps secret key (usually stored in your /config/initializers/secret_token.rb)
Conclusion: In order to decrypt a password, one would have to be using the right version of BCrypt, have obtained the secret token from the app, and have the encrypted password, and I think that at that point, user passwords are probably the least of your security concerns, so I think its pretty safe.

Convert password hashing from SHA to bcrypt

This questions has been answered in this Stack Overflow question already, but it's not Grails-specific and is also kind of vague.
I set my Grails app up with Spring Security, but apparently didn't get the newest version, because it defaulted to SHA-256 instead of bcrypt. Now I have production data with passwords hashed in what seems to be a less-than-ideal method.
It's a piece of cake to enable bcrypt hashing:
Config.groovy > grails.plugins.springsecurity.password.algorithm = 'bcrypt'
but now I need the app to convert the old hashes into new ones. Fundamentally, I understand that when a user logs in, I should have the app check to see if the password is an SHA-256 hash, and if so, re-hash the entered password with bcrypt. After a while, they'll all be upgraded and that code can be removed.
What is the actual code for determining if a password hash is from SHA-256 or bcrypt, though?
EDIT
That is to say, what is the actual function that I call to get a hash? How do I bcrypt(incomingpassword) to see if it matches the existing password hash?
bcrypt passwords will start with "$2a$10$" and be 60 chars long. There is no pattern for SHA-256, but it will be 64 chars long.

How to validate password strength with Devise in Ruby on Rails?

I want to force a user to choose a strong password on registration.
I know, there are many jquery password strength meters out there, and I will most probably use one of them, too. But that does not really enforce anyone to choose a strong password. The registration form must also be useable without js enabled, so one could still potentially register with a weak password.
Accounts must be most secure, because if you are logged in, you can see data of other accounts, which I do not want exposed under any circumstances. So I want to go for maximum security here, therefore I think, it is most important to only allow strong passwords.
So,
How do I set and customize requirements for validating minimum password strength? Only thing I could find in the devise config file is password length. Is there another gem that I should use for this task?
You can use the Devise Security extension, where you can define a password regexp validation (among other things) and enforce the password strength you want.
I've recently released a devise gem which uses the zxcvbn library to reject weak passwords:
https://github.com/bitzesty/devise_zxcvbn
As of this writing (2018), I'd suggest other-folk to consider the newer Devise Security fork before settling on the previously recommended Devise Security extension gem (stale as of v0.10.0 March 2016, but still OG AF mang!)
edit: This one looks more recent, but idk.

Password encryption in Delphi

I need to store database passwords in a config file. For obvious reasons, I want to encrypt them (preferably with AES). Does anyone know a Delphi implementation that is easy to introduce into an existing project with > 10,000 lines of historically grown (URGH!) source code?
Clarification: Easy means adding the unit to the project, adding max. 5 lines of code where the config file is read and be done with it. Should not take more than 15 minutes.
Another clarification: The password is needed in order to create a connection to the db, not to support a user management scheme for the application. So using hashes does not help. The db engine checks if the password is valid, not the app.
I second the recommendation for David Barton's DCPCrypt library. I've used it successfuly in several projects, and it won't take more than 15 minutes after you've read the usage examples. It uses MIT license, so you can use it freely in commercial projects and otherwise. DCPCrypt implements a number of algorithms, including Rijndael, which is AES.
There are many googlable stand-alone (single-unit) implementations too - the question is which one you trust, unless you are prepared to verify the correctedness of a particular library yourself.
For typical authentication purposes, you don't need to store the passwords, you only need to check if the password entered by the user is correct. If that's your case then you can just store a hash signature (e.g. MD5) instead and compare it with the signature of the entered password. If the two signatures match the entered password is correct.
Storing encrypted passwords may be dangerous because if someone gets your "master" password they can retrieve passwords of all your users.
If you decide to use MD5 you can use MessageDigest_5.pas which comes with Delphi (at least it's included with my copy of Delphi 2007). There are also other implementations with Delphi source code you can choose from.
I think Turbopower LockBox is an excellent library for criptography:
http://sourceforge.net/projects/tplockbox/
I don't know if it's too big for your uses but it is very easy to use and you can encrypt a string with 5 lines of code. It is all in the examples.
TOndrej has the right approach. You should never store a password using a reversible cypher. As it was correctly pointed out, if your "master" key were ever compromised, the entire system is compromised. Using a non-reversible hash, such as MD5, is much more secure and you can store the hashed value as clear text. Simply hash the entered password and then compare it with the stored hash.
I've always user Turbopower Lockbox. It works well, and very easy to use. I actually use it for exactly the same thing, storing a password in a config text file.
http://sourceforge.net/projects/tplockbox/
TurboPower LockBox 3 (http://lockbox.seanbdurkin.id.au/) uses automatic salting.
I recommend against Barton's DCPCrypt because the IV's are not salted. In some situations this is a very serious sercurity flaw.
Contrary to an earlier commment, LB3's implementation of AES is fully compliant with the standard.
I've used this library, really quick to add. But wiki shows few more solutions.
Even if you encrypt, it seems to me that your decryption key as well as the encrypted password will both be in your executable, which means that in no way is just security by obscurity. Anyone can take the decryption key and the encrypted passwords and generate the raw passwords.
What you want is a one-way hash.
Just a reminder.
If you don´t need to interoperate with others crypt libs, then DCP or LockBox would do the job.
BUT
if you need it to be fully compliant with the rinjdael specs, forget free components, they´re kinda "lousy" most of the time.
As others have pointed out, for authentication purposes you should avoid storing the passwords using reversible encryption, i.e. you should only store the password hash and check the hash of the user-supplied password against the hash you have stored. However, that approach has a drawback: it's vulnerable to rainbow table attacks, should an attacker get hold of your password store database.
What you should do is store the hashes of a pre-chosen (and secret) salt value + the password. I.e., concatenate the salt and the password, hash the result, and store this hash. When authenticating, do the same - concatenate your salt value and the user-supplied password, hash, then check for equality. This makes rainbow table attacks unfeasible.
Of course, if the user send passwords across the network (for example, if you're working on a web or client-server application), then you should not send the password in clear text across, so instead of storing hash(salt + password) you should store and check against hash(salt + hash(password)), and have your client pre-hash the user-supplied password and send that one across the network. This protects your user's password as well, should the user (as many do) re-use the same password for multiple purposes.
I reccomend using some type of salt. Do not store crypt(password) in config file, but insted of this store crypt(salt + password). As 'salt' you can use something that is required to open database, eg. db_name+user_name. For crypt function you can use some well known algortithm as AES, Idea, DES, or something as simple as xoring each byte with byte from some other string, that string will be your key. To make it more different to solve you can use some random bytes, and store them.
So to store:
init_str := 5 random bytes
new_password := salt + password // salt := db_name + user_name
crypted_password = xor_bytes(init_str + new_password, 'my keyphrase')
crypted_password := init_str + crypted_password
store crypted_password in config, as this will be bytes you can hexify or base64 it
And to connect:
split data read from config into init_str and crypted_password
new_password = xor_bytes(init_str + crypted_password, 'my keyphrase')
password := remove (db_name + user_name) from new_password
Nick is of course right - I just assume you know what you are doing when you say you want to spend all of 15 minutes on implementing a security solution. The DCPCrypt library also implements a number of hashing algorithms if you decide to go that (better) route.
A couple of solutions:
Don't store the password at all. If
the database supports integrated
authentication, use it. The process
can be set to run with a specific
identity, and be automatically
authenticated by the database
Use Windows certificate stores and a
certificate to encrypt your password.
If you store the key used to crypt
your password in your application,
you have very little security anyway,
you have to protect the key also.
You need to store it in a place where only the current user has acccess too.
Basically there are two ways to do this:
Store it in an EFS encrypted file.
Store it in the secure local storage.
Internet Explorer uses 2. But if you can get local access, you can decrypt both 1. and 2. if you have the right master key and algorithm (for instance, iepv can get at the Internet Explorer passwords).
So:
If you can, avoid storing passwords.
Look for alternatives (like Windows authentication, directory services, etc) first.
--jeroen
A simple but for most applications strong enough system is given by this Embarcadero's demo:
https://edn.embarcadero.com/article/28325

Resources