Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

For a web-site I'm using what I hope is the most secure password storage scheme I can find, which boils down to having a salt and hashed password stored in a database of contacts:-

        Byte[] lPassword;
        var lRNG = new System.Security.Cryptography.RNGCryptoServiceProvider();
        var lSalt = new Byte[16];
        lRNG.GetBytes(lSalt);
        using (var lPDBGen = new Rfc2898DeriveBytes(Password, Salt, 1000)) {
            lPassword = lPDBGen.GetBytes(16);
        }
        ... Save lPassword and lSalt to the database ...

If an attacker gains access to this information they essentially have access to the protected data (I can't afford a separate secure password server).

So, using this scheme is there any purpose at all in requiring any form of complexity on the user's choice of password, down to and including an empty password?

share|improve this question
    
Think of it from the basic security point, the attacker will be able to guess the password if it is too simple with a dictionary attack. –  AdnanG Oct 7 '13 at 9:47

3 Answers 3

up vote 2 down vote accepted

Unfortunately, one cannot simply ask for password complexity.

What you really want, for password security, is that the password has a high entropy; but entropy is not a property of the password. Instead, entropy qualifies the way the password is chosen. "High entropy" means "the password could have been a lot of other values".

Usual "password checkers" cannot enter the brain of the human user, so they cannot really guess how the user chooses his passwords. Similarly, "password complexity rules" cannot ensure strong passwords; they just try to evict the user from his comfort zone, to avoid some classic weak password generation methods. But in practice, they don't work. Randomness is hard for human brains. Humans cannot make really random choices in the privacy of their minds; instead, they make witty choices. Also, they don't like to be forced to make pseudo-random choices. When password complexity rules are in force, the usual outcome is that users create witty workarounds, resulting in passwords which comply to the rules, but are not random; thus, weak passwords.

A typical case is when complexity rules mandate that a password shall have at least one digit and at least one punctuation sign: in practice, users react by systematically appending "1!" to whatever password they would have liked. So the rules make the password longer but not stronger. In fact, they even make passwords weaker because that kind of systematic suffix will still count as two characters with regards to password length. If your system enforces a minimum password length of eight characters, then people will need to choose passwords of eight characters; but if they append a systematic two-character suffix (and the attackers knows that, because the attacker is a smart guy who knows how typical users think), then they can get away with the password-length rule with only 6 actual random characters. In such a case, the password complexity rules backfire: they induce user behaviours which are detrimental to security, i.e. weaker passwords.

The only "complexity rule" which is sensible is a minimum length (typically 8 characters) because while a long password is not necessarily strong, a very short password is always weak, because there are just not enough possible 6-character passwords.


All of the above aims at explaining that user-chosen passwords will be weak, for a substantial proportion of the users. This is bad, but the point is that "password complexity rules" don't really improve the situation.

What can be done is the following:

  • Use a proper password hashing function. That's what you do with PBKDF2 (Rfc2898DeriveBytes implements PBKDF2). Salts and iterations help cope with low entropy passwords, to some extent. You may want to increase the iteration count, though: chances are that your server could sustain much more than 1000 iterations, and the higher the better.

  • Try to make the question void. Password hashing must be used because it sometimes happen that attackers gain a copy of (part of) the server database, with all the hashed passwords; SQL injection, in particular, often results in such an outcome. However, it is much better if you prevent that. Password hashing is a necessary second line of defence, but that does not mean that the first line of defence is unimportant.

  • For online dictionary attacks, where the attacker talks to your server for each password guess, apply deterrents: if too many login requests come from a single IP in too short a time, temporarily ban that IP.

  • Educate your users. A good way to make users choose strong passwords is to provide a password generator. It is important that the generator is optional, otherwise users will feel it as a constraint, and refuse to use it. A generator can rely on actual randomness (that's a computer, it has RNGCryptoServiceProvider) and thus meet a reasonable entropy target. A favourite password generation method of mine is an "aa00aa00" pattern (two letters, two digits, two letters, and then two digits). Such passwords are relatively easy to remember and to type in, and still provide a bit more than 32 bits of entropy, which is enough provided that you use PBKDF2 with a high enough iteration count.

share|improve this answer
    
I think what prompted my original question is the idea that the maximum entropy can be achieved, in theory, by allowing users to use all passwords, of any length (i.e. the maximum number of options for the field). In practice it probably means that the top 100 popular passwords should be disallowed, and nothing else, and assume that the login attack detection will prevent a login using dictionary attack. –  Richard Petheram Oct 8 '13 at 7:34
    
On a separate issue, I keep seeing confusion between database passwords and login passwords. It goes without saying that my database will, at some stage, fall into malicious hands, and needs to be protected by much more than "password1". For this I use long random strings generated by a password generator (Keypass in my case) with every character allowed by the database / server policy. I suspect there is still a lot of confusion out there that makes answers for login password and encryption password overlap. –  Richard Petheram Oct 8 '13 at 7:40

It doesn't matter how strong your password hashing algorithm is (well, it matters. But not much) when the password is stupidly weak.

Common passwords like password123 or ilovehowmileycyrustwerks will fall quickly to dictionary attacks regardless.

share|improve this answer
1  
Dictionary attacks assume direct access to the stored data, if they have that then there's nothing to protect. The round-trip time for a single guess would make a dictionary attack difficult. I should add a ban on IP addresses that try too many times though. –  Richard Petheram Oct 7 '13 at 9:59
    
@RichardPetheram Up vote for the IP block thought. It plays a basic role in any web application by preventing the attacks by locking it out based on a pre determined number of attempts made by the hacker. It is just a simple way of creating PITA for any black jack B-). Be aware that this security step also can be overcome by hackers by generating different Ip for each attempt. The more security steps you add the lesser the probability of getting hacked ! –  Ebenezar Oct 7 '13 at 10:42
4  
@RichardPetheram Hashing your passwords is precisely to protect against an attacker somehow managing to compromise your database. If you assume a magical fantasy world where your server is zero-day free and your code is flawless, you don't need to hash your passwords to protect it. –  Terry Chia Oct 7 '13 at 11:48

Tom's answer regarding "educate your users" is everything the security community has been saying for a long time. However, it hasn't worked out so well in practice. The reasons are complex, but it boils down to two core concepts: a chain is only as strong as its weakest link, and the old joke that 50% of your users are below average.

First, the chain analogy. An attacker usually doesn't care which ID they break in with. If they are given 10,000 to crack, as soon as they have even one weak password, they're in. And applying that to the below average users, that means if only one of your users is sloppy, careless, or dimwitted, the attacker is in. Training people helps reduce the exposure, but due to the chain analogy it can't stop the attacks. It can never be relied upon to stop all attacks.

This is where you need to back up your systems with the classical security strategy of defense in depth. You can't simply throw a password box in front of a site and then leave everything else as it was, because you should accept as a given that one or more of your users is careless or otherwise untrustworthy.

From the point of view of an attack mounted by a "trusted" user, many systems are less tested for security and have various flaws that permit privilege escalation. Address those first, of course. But you still need to properly secure your back end systems, too. It's expensive, but if you've ever watched a pen tester weave his way through an insecure system, you'll understand exactly why all the doors need to be shut.

After patching all your systems, you still have the insecurity of the "trusted" user, and what you legitimately allow him to do. Can he easily transfer his whole balance to a Cayman Island bank at 3AM from an IP address in Estonia? Maybe that's not such a good idea. Perhaps you add a two-factor authentication step for out of the ordinary moderate-sized transactions; something out-of-band like an SMS message or email? Maybe you require an official to contact him before approving the transfer of a large amount?

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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