What's the most secure possible Devise configuration? - ruby-on-rails-3

I'm about to start setting up an employees-only Rails application at our company for working with sensitive information. There will be a firewall, physical security measures, etc. My concern right now is the login process for the application.
I'd like to use Devise for authentication. What is the most secure possible configuration for Devise?
I'm thinking I wil do the following:
Lock accounts after a small number of failed login attempts
Use config.paranoid so an attacker can't tell if they've guessed a valid email address
Maybe disable password resets by email?
Some of the specific things I'm unsure of, with quotes from devise.rb in italics:
Peppers. Devise has an option to "Setup a pepper to generate the encrypted password." My understanding is that this is a single, app-specific value that transforms a stupid password like "password123" into something like "password123K#(!#akdlwekdf" or "*%!kd39gpassword123" or whatever before hashing. This is meant to thwart rainbow table attacks, but my understanding from this article is that it's not as good as a per-password unique salt. Then again, this article and this paper say that bcrypt has salts built in. Does using a pepper with bcrypt really add anything? Can I, and is there any need to, also have a salt column?
Stretches. "For bcrypt, this is the cost for hashing the password and defaults to 10." Based on this question, I'm thinking of using a work factor of 12. Does that seem reasonable?
Password length. A longer password seems more secure in general, but I don't want it to be so hard that the user writes it on a piece of paper somewhere. Does password length matter much if we're using bcrypt?
SSL cookies. For public apps with SSL enabled, marking cookies as "this can only be transmitted over HTTPS" protects against Firesheep-style attacks. But I'm not sure how much sense it makes to have a security certificate for an internal app. Is that silly?
What else am I missing?

Peppers: yes you are correct. There is not much additional security achieved with a pepper if you are using salt.
Stretches: 12 is reasonable, however bcrypt only ensures a constant time. You should consider using the newer scrypt as it allows you to specify both a constant time and the amount of memory to use. Cryptyograhpically bcrypt and scrypt are about the same but scrypt makes brute forcing harder.
Password length: forcing any sort of password rules reduces the entropy of passwords. The only restriction should be a minimum length and numerous studies have suggested at least 8 characters.
SSL Cookies: use them if you can. Security should always be built from the start and not added later. You can never be sure who might be sniffing you internal network. Just because you assume no outsiders can sniff data, does not mean inside employees wouldn't for one reason or another. You have a responsibility to protect your employees from each other as well as external threats.

For passwords, you can checkout https://github.com/bitzesty/devise_zxcvbn which rejects passwords with weak entropy, and checks against known cracked passwords.

Related

Now that I know how to salt & hash passwords, a few more questions

So, let's assume I have read every article/post about appropriately salting and hashing passwords in order to secure user credentials.
This means I am not wondering what hashing algorithm to use (SHA1 vs. SHA2 vs. PDKBF2), how to generate the salt, how to store the salt, how to append the salt, or whether I should be writing the code myself vs. leveraging well-established libraries like bcrypt. Please, avoid rambling about these issues here as I have read 50+ other pages of that already.
Just assume the following is my approach (also note I understand this is not flawless or likely sufficient for applications like financial service, I am really just wondering if this is an acceptable min bar to claim that I "do the right thing").
User comes to my amazing website (www.myamazingwebsite.com) and logs in with email and pass.
I pull her salt and hash from my database. Assume the salt is lengthy enough, unique per-user, and created using a CSPRNG upon user registration.
I prepend the salt to her input password, hash it using SHA-512, run 1,000 iterations, then compare it to the hashed value pulled from the db:
var hash = sha512(salt + password);
for (i = 0; i < 1000; i++) {
hash = sha512(salt + password + hash);
}
If they match, the user is authenticated. Otherwise, they are not.
Now, my question is how secure is my above approach. The questions I would like help answering:
Do I need to change the salt periodically? For example, perhaps I could re-compute and store a new hash using a newly created random salt after every successful login. This seems like it would be more secure but I am not sure what standard practice is here.
The request to the server will be done via https. Does that mean I can assume that I can process all of the hashing and validation logic server side? Would most folks consider this sufficient, or do I need to consider some hybrid both on client and server side?
Anything else I am overlooking or need to consider?
Thanks in advance, I appreciate the help.
1) Assuming you've done the right thing and do not store their password, you can't change the salt unless they are logging in. I suppose you could change their salt every time they do log in, but it doesn't really help (and might hurt).
Here's why: Having a unique salt on everyone simply makes it harder for an attacker that has access to your database from attempting to guess the passwords. If you've done things correctly, he would have to use a different salt for each person. He can't just start guessing passwords using a site-wide salt and see if it matches anyone. As long as you have a unique salt for each user, you are doing the best you can.
In fact, changing the salt does nothing but give an attacker with access to your database over time MORE information. Now he knows what their password looks like salted two different ways. That could (theoretically) help crack it. For this reason, it would actually be ill advised to change the salt.
2) Https is sufficient. If someone can compromise https, then any additional client side hashing or such will not help. The clients computer is compromised.
3) I think you have a fair understanding of best password practices. Don't overlook other security issues like sql-injection and cross-site scripting.
Do I need to change the salt periodically?
No. The salt is a per-user public parameter that servers two purposes. First, it ensures that an attacker cannot build an offline dictionary of passwords to hashes. Second, it ensures two users with the same password have different hashed password entries in the database.
See the Secure Password Storage Cheat Sheet and Secure Password Storage paper by John Steven of OWASP. It takes you through the entire threat model, and explains why things are done in particular ways.
The request to the server will be done via https. Does that mean I can assume that I can process all of the hashing and validation logic server side?
This is standard practice, but its a bad idea. Its a bad idea because of all the problems with SSL/TLS and PKI in practice. Though this is common, here's how it fails: the SSL/TLS channel is setup with any server that presents a certificate. The web application then puts the {username, password} on the wire in the plain text using a basic_auth scheme. Now the bad guy has the username and password.
There's lots of other problems with doing things this way. Peter Gutmann talks about this problem (and more) in his Engineering Security book. He's got a witty sense of humor, so the book is cleverly funny at times, too even though its a technical book.
Would most folks consider this sufficient, or do I need to consider some hybrid both on client and server side?
If possible, use TLS-PSK (Preshared Key) or TLS-SRP (Secure Remote Password). Both overcome the problems of basic_auth schemes, both properly bind the channel, and both provide mutual authentication. There are 80 cipher suites available for TLS-PSK and TLS-SRP, so there's no shortage of algorithms.
Anything else I am overlooking or need to consider?
Cracking is not the only threat here. More than likely, the guy trying to break into your organization is going to be using one of the top passwords from the millions of passwords gathered from the Adobe breach, the LinkedIn breach, the Last.fm breach, the <favorite here> breach.... For example:
25 most-used passwords revealed: Is yours one of them?
The 30 Most Popular Passwords Stolen From LinkedIn
Top 100 Adobe Passwords with Count
Why bother brute forcing when you have a list of thousands of top rated passwords to use?
So your FIRST best defense is to use a word list that filters a user's bad password choices. That is, don't allow user's to pick weak or known passwords in the first place.
If someone gets away with your password database, then he or she is going to use those same password lists to try and guess your user's passwords. He or she is probably not even going to bother brute forcing because he or she will have recovered so many passwords using a password list.
As I understand it, these word lists are quite small when implemented as a Bloom Filter. They are only KB in size even though there are millions of passwords. See Peter Gutmann's Engineering Security for an in depth discussion.

Salting the Password with the Password

I am developing my first web app that requires a login, and it has come to the point when i must decide how to store the passwords. I have been doing a lot of reading on the proper way to hash the password and adding a salt. It occurred to me that most of the ways that are recommended would rely on some variation of information that is stored in the database with the password hash, be it some variation of using all or part of the username as a salt or some other random value.
Instead I was thinking of using the user own password as a salt on the password. Using an algorithm to jumble the password and adding it to itself in some way as the salt. Of course this to would be compromised if an attacker got access to both the stored hashes and the source code of the algorithm, but any salt would be compromised in such a situation. My application really probably does not need this level of security, but it was just something that i started to think about when reading.
I just wanted to get some feedback from some more experienced developers. Any feedback is appreciated.
If you derrive the salt from the password itself, you will loose the whole benefit of salting. You can then build a single rainbow-table to get all passwords, and equal passwords will result in equal hash-values.
The main reason to use a salt is, that an attacker cannot build one single rainbow-table, and get all the passwords stored in your database. That's why you should add a random unique salt for each password, then an attacker would have to build a rainbow table for each password separately. Building a rainbow-table for a single password makes no sense, because brute forcing is faster (why not just stop when the password was found).
Don't be afraid to do it right, often the programing environments have support to create safe hashes and will handle salting for your (e.g. password_hash() for PHP). The salt is often combined with the hash for storing, that makes it easy to store it in a single database field.
I wrote a small tutorial about securely storing passwords, maybe you want to have a look at it.
Simply duplicating the password may still be vulnerable to dictionary attacks, e.g. the password "hello" becomes "hellohello", and thus might be part of a dictionary.
Using a scrambled password as the salt enables the attacker to use a dictionary and then generate a rainbow table for all entries by adding the scambled password on every entry.
Why change a proven algorithm which can be understood by any developer? Just do it the default way and your code will be maintainable by anyone else.
"My application really probably does not need this level of security" - until that point in time it was hacked. Use a salt, it takes almost no additional effort. Do it now.
"eliminate the need of storing the password salt at all": the salt can be very small (6 bytes). It will hardly affect performance.
I just wanted to get some feedback from some more experienced developers. Any feedback is appreciated.
John Steven of OWASP performed an analysis, including threat modes, for password storage system. It explains the components and their purpose, like the hash, the iteration count, the salt, the HMACs, the HSMs, etc. See the Secure Password Storage Cheat Sheet and Secure Password Storage paper.
Cracking is not the only threat here. More than likely, the guy trying to break into your organization is going to be using one of the top passwords from the millions of passwords gathered from the Adobe breach, the LinkedIn breach, the Last.fm breach, the eHarmony breach, the <favorite here> breach.... For example:
25 most-used passwords revealed: Is yours one of them?
The 30 Most Popular Passwords Stolen From LinkedIn
Top 100 Adobe Passwords with Count
Why bother brute forcing when you have a list of thousands of top rated passwords to use?
So your FIRST best defense is to use a word list that filters a user's bad password choices. That is, don't allow user's to pick weak or known passwords in the first place.
If someone gets away with your password database, then he or she is going to use those same password lists to try and guess your user's passwords. He or she is probably not even going to bother brute forcing because he or she will have recovered so many passwords using a password list.
As I understand it, these word lists are quite small when implemented as a Bloom Filter. They are only KB in size even though there are millions of passwords. See Peter Gutmann's Engineering Security for an in depth discussion.

The proper way of implementing user login system

I want to make a user login system for the purpose of learning. I have several questions.
I did some research and found that the proper way of implementing a user login system is to store the user name/id and the encrypted/hashed version of the password in the database. When a user logs in, the password is encrypted client side (MD5, SHA-1 etc.) and sent to the server where it is compared with the one in database. If they match, the user log in successfully.
This implementation prevents DBAs or programmers seeing the cleartext of the password in the database. It can also prevent hackers intercepting the real password in transit.
Here is where I'm confused:
What if the hackers know the hash/encrypted version of password (by hacking the database) or DBAs, programmers get the hashed version of the password by just simply reading the text in the database. They could then easily make a program that sends this hashed version of the password to the server allowing them to successfully log in. If they can do that, encrypting the password doesn't seem very useful. I think I misunderstanding something here.
Is this (the way I described above) the most popular way to implement user login functionality? Does it follow current best practices? Do I have to do everything manually or does some database have the built-in ability to do the same thing? Is there a most common way/method of doing this for a website or a web app? If so, please provide me with details.
My former company used couchDB to store user login info including passwords. They did not do too much with the encryption side of things. They said couchDB will automatically encrypt the password and store it in the documents. I am not sure if this is a safe way. If so, then it is pretty convenient for programmers because it saves lots of work.
Is this way (point 3) secure enough for normal use? Do other database system such as mySQL have this kind of ability that can do the same thing? If so, does it mean that using mySQL built-in method is secure enough?
I am not looking for a very super secure way of implementing user login functionality. I am rather looking for a way that is popular, easy-to-implement, proper, secure enough for most web applications. Please give me some advice. Details provided will be really appreciated.
When a user login, client side code will encrypt the password by MD5 or SHA-1 or something like that, and then send this encrypted password to server side and then compare it with the one in database. If they are matched, the user log in successfully.
No, no, the client needs to send the unhashed password over. If you hash the password on the client side then that hash is effectively the password. This would nullify the security of the cryptographic hashing. The hashing has to be done on the server side.
To secure the plaintext password in transit it needs to be sent over a secure channel, such as an encrypted TLS (SSL) connection.
Passwords should be salted with a piece of extra data that is different for each account. Salting inhibits rainbow table attacks by eliminating the direct correlation between plaintext and hash. Salts do not need to be secret, nor do they need to be extremely large. Even 4 random bytes of salt will increase the complexity of a rainbow table attack by a factor of 4 billion.
The industry gold standard right now is Bcrypt. In addition to salting, bcrypt adds further security by designing in a slowdown factor.
Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.... Cryptotheoretically, this is no stronger than the standard Blowfish key schedule, but the number of rekeying rounds is configurable; this process can therefore be made arbitrarily slow, which helps deter brute-force attacks upon the hash or salt.
A few clarifications:
Don't use MD5. It's considered broken. Use SHA but I'd recommend something a little better than SHA1. - https://en.wikipedia.org/wiki/MD5
You don't mention anything about salting the password. This is essential to protect against Rainbow tables. - https://en.wikipedia.org/wiki/Rainbow_tables
The idea of salting/hashing passwords isn't really to protect your own application. It's because most users have a few passwords that they use for a multitude of sites. Hashing/salting prevents anyone who gains access to your database from learning what these passwords are and using them to log into their banking application or something similar. Once someone gains direct access to the database your application's security has already been fully compromised. - http://nakedsecurity.sophos.com/2013/04/23/users-same-password-most-websites/
Don't use the database's built in security to handle your logins. It's hacky and gives them way more application access than they should have. Use a table.
You don't mention anything about SSL. Even a well designed authentication system is useless if the passwords are sent across the wire in plain text. There are other approaches like Challenge/Response but unfortunately the password still has to be sent in plain text to the server when the user registers or changes their password. SSL is the best way to prevent this.

SHA1-hashing for web authentication in place of Blowfish

Being unable to locate a working php/javascript implementation of blowfish, I'm now considering using SHA1 hashing to implement web-based authentication, but the lack of knowledge in this particular field makes me unsure of whether the chosen method is secure enough.
The planned roadmap:
User's password is stored on the server as an MD5 hash.
Server issues a public key (MD5 hash of current time in milliseconds)
Client javascript function takes user password as input, and calculates its MD5 hash
Client then concatenates public key and password hash from above, and calculates SHA1 of the resulting string
Client sends SHA1 hash to the server, where similar calculations are performed with public key and user's password MD5 hash
Server compares the hashes, a match indicates successful authentication.
A mismatch indicates authentication failure, and server issues a new public key, effectively expiring the one already used.
Now, the problematic part is about concatenating two keys before SHA1, could that be prone to some kind of statistical or other attacks?
Is there any specific order in which keys should be concatenated to improve the overall quality (i.e. higher bits being more important to reliability of encryption)?
Thank you in advance.
If you're only using the 'public key' (which isn't actually a public key, it's a nonce, and should really be random, unless you really want it to be usable over a certain timeframe, in which case make sure you use HMAC with a secret key to generate it so an adversary cannot predict the nonce) to prevent replay attacks, and it's a fixed size, then concatenation might not be a problem.
That said, I'm a bit concerned that you might not have a well-thought-out security model. What attack is this trying to prevent, anyway? The user's password hash is unsalted, so a break of your password database will reveal plaintext passwords easily enough anyway, and although having a time-limited nonce will mitigate replay attacks from a passive sniffer, such a passive sniffer could just steal the user's session key anyway. Speaking of which, why not just use the session key as the nonce instead of a timestamp-based system?
But really, why not just use SSL? Cryptography is really hard to get right, and people much smarter than you or I have spent decades reviewing SSL's security to get it right.
Edit: If you're worried about MITM attacks, then nothing short of SSL will save you. Period. Mallory can just replace your super-secure login form with one that sends the password in plaintext to him. Game over. And even a passive attacker can see everything going over the wire - including your session cookie. Once Eve has the session cookie, she just injects it into her browser and is already logged in. Game over.
If you say you can't use SSL, you need to take a very hard look at exactly what you're trying to protect, and what kinds of attacks you will mitigate. You're going to probably need to implement a desktop application of some sort to do the cryptography - if MITMs are going around, then you cannot trust ANY of your HTML or Javascript - Mallory can replace them at will. Of course, your desktop app will need to implement key exchange, encryption and authentication on the data stream, plus authentication of the remote host - which is exactly what SSL does. And you'll probably use pretty much the same algorithms as SSL to do it, if you do it right.
If you decide MITMs aren't in scope, but you want to protect against passive attacks, you'll probably need to implement some serious cryptography in Javascript - we're talking about a Diffie-Hellman exchange to generate a session key that is never sent across the wire (HTML5 Web storage, etc), AES in Javascript to protect the key, etc. And at this point you've basically implemented half of SSL in Javascript, only chances are there are more bugs in it - not least of which is the problem that it's quite hard to get secure random numbers in Javascript.
Basically, you have the choice between:
Not implementing any real cryptographic security (apparently not a choice, since you're implementing all these complex authentication protocols)
Implementing something that looks an awful lot like SSL, only probably not as good
Using SSL.
In short - if security matters, use SSL. If you don't have SSL, get it installed. Every platform that I know of that can run JS can also handle SSL, so there's really no excuse.
bdonlan is absolutely correct. As pointed out, an adversary only needs to replace your Javascript form with evil code, which will be trivial over HTTP. Then it's game over.
I would also suggest looking at moving your passwords to SHA-2 with salts, generated using a suitable cryptographic random number generator (i.e. NOT seeded using the server's clock). Also, perform the hash multiple times. See http://www.jasypt.org/howtoencryptuserpasswords.html sections 2 and 3.
MD5 is broken. Do not use MD5.
Your secure scheme needs to be similar to the following:
Everything happens on SSL. The authentication form, the server-side script that verifies the form, the images, etc. Nothing fancy needs to be done here, because SSL does all the hard work for you. Just a simple HTML form that submits the username/password in "plaintext" is all that is really needed, since SSL will encrypt everything.
User creates new password: you generate a random salt (NOT based off the server time, but from good crypto random source). Hash the salt + the new password many times, and store the salt & resulting hash in your database.
Verify password: your script looks up salt for the user, and hashes the salt + entered password many times. Check for match in database.
The only thing that should be stored in your database is the salt and the hash/digest.
Assuming you have a database of MD5 hashes that you need to support, then the solution might be to add database columns for new SHA-2 hashes & salts. When the user logs in, you check against the MD5 hash as you have been doing. If it works, then follow the steps in "user creates new password" to convert it to SHA-2 & salt, and then delete the old MD5 hash. User won't know what happened.
Anything that really deviates from this is probably going to have some security flaws.

What algorithm should I use for encrypting and embedding a password for an application?

What algorithm should I use for encrypting and embedding a password for an application?
It obviously is not bullet proof, but it should be good enough to thwart someone scanning the database with a hex editor, or make it hard for someone who has the skills to use a debugger to trace the code to work out, either by scanning for the encrypted password, or using a debugger to run through the decryption code.
Object Pascal would be nice.
Major Edit
I think I did not explain myself well enough. The password needs to be decrypted back into its original form and applied. The application itself uses a local SQL database and a local webserver, and the password is fixed and can't be changed by the end users. It is to ensure that changes to be made only from within the app itself. The user passwords are only to allow access to the app itself, rather than the database
/vfclists
If you want an easy solution just stick with a good hashing algorithm like MD5 and store just the hash inside your application. Then whenever the user inserts the password you will calculate the hash of the password and check if it's equal to the one stored.
Of course this approach is a simple solution that doesn't allow you to retrieve the password if it's lost but it should work quite fine if you just need some protection..
EDIT: I mentioned MD5 that was fair good but not anymore, of course you can choose any other stronger function like SHA-2 (512/384) that is more robust. I just wanted to explain an approach more than using a specific hashing algorithm.
SHA should be ok for you, best with salt.
I don't know Object Pascal very well, but probably this will help you:
http://sourceforge.net/projects/op-crypt/
When an application has to do password checking only, it is best to save a hash. An hash can not be decrypted, but it can be checked whether the password the user enters has the same hash.
If you want to save the password so that it can be recovered, it is best to encrypt it first, using some crypto library.
I would suggest SHA1, its one way encryption, i've used it before and by far no one has decrypted it!
If you need more information on sha1 visit http://en.wikipedia.org/wiki/Secure_Hash_Algorithm and http://www.openssl.org/docs/crypto/sha.html.
PS: If you're using php you can simply encrypt with SHA1 using the sha1(); function!
I suspect that what you're aiming for is not storing passwords in the application, but trying to prevent the application itself from being run without the password, as a form of DRM. If that's the case, and you're looking to stymie people with debuggers, I think you're well into the realm of needing either a hardware dongle, or a network-based lock. Off the top of my head, I know SafeNet carry products that do this (and I've had some exposure to them in the past, they seem decent), but I don't know how well they compare to the rest of the market.
If you want as much real security as is possible in the scenario you're describing, you should require that when the system is installed an "administrator" enters the database password and his own administrator password; the application should then store a salted hash of the administrator's password, and it should store the database password encrypted with a differently-salted hash of the administrator's password. The database password (or information sufficient to reconstruct it) will be kept in memory while the program is running, but absent the administrator password there would be no way to retrieve when the program isn't running, even with full knowledge of the system.
If it's necessary to allow multiple users to access the database, an "add user" button could allow the addition of a user account. When the user types his password, use it to store hashed/encrypted data as with the administrator.
Any user with a debugger would be able to leverage his knowledge of a valid user account and password into knowledge of the database password, but someone who didn't have knowledge of a valid account password wouldn't be able to do anything.
If I am interpreting your question right, then you want to basically distribute your application to users, allow them to run it, and have the application update your database. At the same time, you want to prevent that person from being able to log in to the database and use it themselves directly.
If your program can be decompiled (like java, but I don't know about other languages like C, C++), then the person who has your application will be able to see the source code. Once they have that, there will most certainly be some way they can discover the user name and password. Even if your source code has stored the password using a reversible encryption algorithm, the person who holds your source code will be able to write similar code as yours to reverse the encryption and discover the password.
Even if your application cannot be decompiled, the user may be able to capture the network packets it sends to the database and determine the password from that. I don't know if you can communicate with the database over SSL.
Instead, I believe you need to split your application into client and server applications. You can write a restful web application, or use a messaging service (like JMS for example), and write a client application that uses it.
In that case, you may or may not want to have user accounts that are managed by your server side application. Let me be clear here, I am not talking about database accounts, but accounts that your application manages, and whose details happen to be stored in the database. If you do create user accounts, you can follow the pattern in my original answer shown below.
============== Hashing Approach, my original answer ============
As others have already mentioned, it's best to add salt to the password and use a digest algorithm before you store the password in your database. However, I think a little more detail is in order.
Using SHA1 or SHA2 with a salt value may be pretty strong, but there are even stronger methods. I highly recommend that you read this section of the spring security manual. I don't think you are using spring or java, but that section covers the concepts involved very well. Allow me to paraphrase:
Use at least an 8 byte salt value, up to 16 bytes would be great. The salt value should be different for every account, if it is the same then a cracker will only need to produce one rainbow table! It should be randomly generated. The documentation doesn't say this, but I also recommend using a secure random number generator, don't use a random number seed that produces a consistent sequence of numbers.
You should hash the password multiple times because it will cause brute force password hacking attempts to take increasingly more time. Indeed, you may want a slow password encoding algorithm instead of a fast one.
Store the raw salt value in the database along with the password, you can even store it in the same field/column. This is required so passwords can be verified in the future.
The BCryptPasswordEncoder is a good example of this.
===============
One alternative approach that may or may not solve your problem is to create a database account that has limited privileges. For example, you could create a database account that can only select, update, insert, and delete on specific tables in your database. You may not find this acceptable, because you may not want to let people do those operations directly, while you may want to let the application do those operations. It depends on your specific situation.