34

/////////////////////////////// Updated Post Below ////////////////////////////

This question has received a lot of hits, more than I ever thought it would have on such a basic topic. So, I thought I would update people on what I am doing. Also I keep reading in the comments that I am storing passwords as plain text. Just to clarify I am not.

My updated validation function :

public function is_password($str) {
        if (strlen($str) < 10) { // Less then 10
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (strlen($str) > 100) { // Greater then 100
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (!preg_match("#[0-9]+#", $str)) { // At least 1 number
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (!preg_match("#[a-z]+#", $str)) { // At least 1 letter
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (!preg_match("#[A-Z]+#", $str)) { // At least 1 capital
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (!preg_match("#\W+#", $str)) { // At least 1 symbol
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } else {
            return TRUE; // No errors
        }     
    }

Each time it returns FALSE, I always tell them the entire password need.

Just to answer some of the questions as to why it is so long :

Why not so long? People at my job that I talk to use sentences. Very long ones at that.

How am I hashing my passwords? / Why use 100 characters? -> just use better hashing algorithm

For PHP, I am using the best there is for this language. I am using this library which is the PHP 5.5 equivalence of the new password hashing API created by Anthony Ferrara. My reasoning for this hashing use is simple, very high demand on the CPU (if you ever test it out on a Linux/Windows box CPU usage is at 100%). Also, the algorithm is very scalable due to the cost factor the higher the cost the more grueling the task is for the CPU to log a person in. Last I "Tested", I put the cost to 24. An entire hour passed for me to try and login and I got a PHP time out error before I even got past the login screen (this was a foolish cost factor). A study done by Jeremi Gosney (THIS IS THE PDF DOWNLOAD OF THE REPORT) which tested the strength of this function compared to other more popular ones (yes, more popular) concluded that even with 25 - GPUs, while using bcrypt at a cost of 5, password hashing is the last of your concerns. I use a cost of 17...

My function if any one is interested (The parts that pertain to this subject at least) :

public function create_user($value) {
        $this -> CI = get_instance();
        $this -> CI -> load -> library('bcrypt');

        foreach ($value as $k => $v) {// add PDO place holder to the keys
            $vals[":$k"] = $v;
        }
        $vals[":password"] = $this -> CI -> bcrypt -> password_hash($vals[":password"], PASSWORD_BCRYPT, array("cost" => 17)); // Take old $vals[":password"] and run it through bcrypt to come up with the new $vals[":password"] 

Hopefully this question helps others out there.

/////////////////////////////// Original Post Below ////////////////////////////

I'm currently working on a new project, and an issue struck me.

Is it it safe to disclose your password requirements? If so, why is it safe?

I have a function that does validation on a password and each step shows the user why validation does not work.

Here is my function:

public function is_password($str) {
    if (strlen($str) < 10) {
        $this -> set_message('is_password', 'Password too short.');
        return FALSE;
    } elseif (strlen($str) > 100) {
        $this -> set_message('is_password', 'Password is too long.');
        return FALSE;
    } elseif (!preg_match("#[0-9]+#", $str)) {
        $this -> set_message('is_password', 'Password must include at least one number.');
        return FALSE;
    } elseif (!preg_match("#[a-z]+#", $str)) {
        $this -> set_message('is_password', 'Password must contain at least one letter.');
        return FALSE;
    } elseif (!preg_match("#[A-Z]+#", $str)) {
        $this -> set_message('is_password', 'Password must contain at least one capital letter.');
        return FALSE;
    } elseif (!preg_match("#\W+#", $pwd)) {
        $this -> set_message('is_password', 'Password must include at least one symbol.');
        return FALSE;
    } else {
        return TRUE;
    }
}

My thought on this is, if we let the "user" / attacker know what my passwords consist of wouldn't it be easier for the attacker to know? I know security through obscurity is not a best practice, but could it be a strong argument in this situation?

I would like to know if I am going about this in the right way. Any help would be great.

Simon
  • 3,182
  • 4
  • 26
  • 38
Rixhers Ajazi
  • 489
  • 4
  • 9
  • 31
    Personally I don't like having such rules at all. I'd rather estimate the password complexity. Even dumb estimates are better than such annoying rules. – CodesInChaos Aug 13 '13 at 18:33
  • 81
    You might want to revise your checking for a better experience. Lets say I enter a password `woot`. That will fail because its too short. Then I do `wootwootwoot`. Now it fails because it has no numbers. Then `w00twootwoot`, fails no capital. Then `W00twootwoot`, fails no symbol. At which point unless I have to log into your application to do my job I'm going to throw a fit and go do something else. Revise your checking to tell me *all* of the password requirements up front and make the validation tell me all of the missing requirements if I don't hit them. – Freiheit Aug 13 '13 at 21:33
  • 2
    You know @Freiheit I was actually thinking that, what if my users go down the list (for the 6 checks). I am actually doing that right now. I would be utterly pissed off especially in my register form, because I also have security question, and the answes to those questions reset if goof up happens :P – Rixhers Ajazi Aug 13 '13 at 21:36
  • 29
    Out of curiosity, why a "Too long" constraint? My limited understanding says that once you hash the password, it should be irrelevant – Akash Aug 14 '13 at 05:01
  • I would vote to close this question on basis of not much can be said. Firstly because of the requirements themselves http://xkcd.com/936/ you should not force a human being to suffer entering stupid non sense assword just because you deem them safe. And secondly, why would you want to further torture a person not telling them your insane requirement? Is it even a question you should ask? Sorry reason why I squirm at registrations – Quillion Aug 14 '13 at 19:39
  • 2
    @Quillion The fact that is somehow an [XY problem](http://meta.stackexchange.com/q/66377/146482) (asking about showing password restrictions asserting such restrictions were actually a incontestably good idea; and fortunately most answers here address that issue as well) is not a reason for closing the question - on the contrary, anyone else asking this should find the answers here pretty enlightening. You may however downvote the question at will since you obviously deem it "not useful" – Tobias Kienzler Aug 16 '13 at 10:17
  • i let my users enter any password they want, with only a 3 character minimum. if they want to enter a bad password, that's entirely on them. why would i care ? – user428517 Dec 02 '14 at 21:41

4 Answers4

101

If you do not divulge your "password requirements" then your users will hate you. Some will not succeed in finding an "acceptable password" and will call the helpdesk. Or, worse, if the users are customers then they will go buy elsewhere. A great way to kill your own business !

On the other hand, if divulging your "password requirements" really help attackers in a non-negligible way, then your password requirements are awfully bad: not only do they antagonize users, but they also restrain the users into a too small set of possible passwords.

Note that attackers can usually guess quite well what your "password requirements" are, e.g. by trying to register themselves.

In any case, "password requirements" are counter-productive and decrease security, save for a "minimum length" which can be rationally justified. So just don't do that. Key to password security is user education, possibly helped with some tools (e.g. a random generator for strong passwords). Enforcing constraints does not help; and enforcing hidden constraints is just worse. For instance, if your rules call for at least one digit and one symbol, then a surprisingly high proportion of users will just append "1." at the end of their password; attackers know that. The extra suffix will not add much to the password entropy (i.e. the number of potential passwords the attacker has to try for a successful break) but will use up some of the scarce resource known as "user patience": users will prefer shorter passwords, since they have to add the "1." suffix to appease your server.

Tom Leek
  • 168,808
  • 28
  • 337
  • 475
  • 2
    Very good answer, and yes your absolutely right, they will hate me... even more then they hate me atm :P Alright, you answered my main question : The attacker can try to register them selves and find what my PW requirements are exactly. – Rixhers Ajazi Aug 13 '13 at 21:23
  • @Tom Leek - do you have any suggestions on how to combine a random generator with a signup form? I'm thinking Google's app-specific authentication would be similar but perhaps you had another idea... – Jedidja Aug 14 '13 at 00:02
  • 15
    Just wanted to support the claim of user hate. Where I work the password requirements are hidden, and it generally takes me at least 5-10 minutes to create a password the system will actually let me use. If the requirements are hidden failed attempts will quickly lead to user rage. – Daniel Aug 14 '13 at 01:29
  • Good answer but one suggestion: user education doesn't really work. Instead, security needs to be as transparent as possible, and needs no naturally guide good decisions. Users don't want to learn a whole new field just to get their day job done. They just want to get their day job done. – atk Aug 14 '13 at 05:21
  • 1
    @Jedidja: for a password generator, provide it as a button on the same page as the login form. If the button is pressed, then a new random password is generated and displayed. Don't autofill the password entry field, though: the user still has to _remember_ the password, and making him enter it twice is a good start for that (so you should display it _as a picture_, not as text which can be copied & pasted with a mouse). – Tom Leek Aug 14 '13 at 10:41
  • @TomLeek at which point your sites accounts are only as secure as the email address they provided for the account recovery process. Or rather, the fraction of acounts belonging users who didn't rage quit over an impossible to remember password. – Dan Is Fiddling By Firelight Aug 14 '13 at 14:01
  • 3
    @DanNeely: that's why I advocate for a _non-mandatory_ password generator. It is important that it is optional; it _must not_ be forced unto users, otherwise they will rebel, and that's the last thing we want. The password generator is a helpful tool which _complements_ the normal process of "users thinks of the new password by himself". – Tom Leek Aug 14 '13 at 15:13
  • @RixhersAjazi So are you going to show these (with all due respect, ridiculous) requirements or simply drop them? Note that if you're using proper salted password hashing there is no justifiable need for `len<100`. – Tobias Kienzler Aug 16 '13 at 10:12
  • @TobiasKienzler Updated my OP. – Rixhers Ajazi Aug 16 '13 at 13:03
  • 1
    @DanielCook Called power company, they asked for password. Gave password, was told it was wrong. Knowing I'd altered my preferred PW to fit them, asked for PW requirements. Rep refused to disclose. Explained that I'm not asking them to tell me what part of the password I gave was wrong; I just want to know what all requirements are. Went in circles, till I said "If I were a new customer, creating a new password, what requirements would you give me?" Rep finally gave PW requirements. I immediately gave them the correct PW. Turns out, preferred PW is 1 character too short. Added "1" to the end. – Dan Henderson Sep 29 '15 at 16:17
  • I could not agree more. I wanted to change my password for my account on another website once and all I was getting was "_Invalid Data". How useful is that? I thought there was a problem with the server since I did not know why I was getting it so I contacted customer services. I tried to change again after a month, still got the same error. Turns out its because of a symbol! What site doesn't allow symbols in passwords? – iProgram Jan 26 '16 at 18:32
  • I agree. When you start making up "password requirements" other than the minimum length, users will start using `Password!1" and your security will be worse than without such requirements. That has mixed case, a special character, a number and it is 10 character long so it's safe, right? – Mikko Rantalainen Jun 15 '21 at 09:21
27

If you don't tell the user exactly what's needed in his password to go through the validation of your function, how would he know what to add or modify to make it valid?

Giving such information could result in making a bruteforce attack easier. However, considering your requirements, it doesn't help the attacker at all because there are too many password possibilities to make an attack worthwhile.

Simon
  • 3,182
  • 4
  • 26
  • 38
  • Just note that it'd be better to simply not enforce such requirements, since it encourages users to write down their overcomplicated password close to their PC. Or they'll simply equal "forgot password == login button" – Tobias Kienzler Aug 16 '13 at 10:13
  • @TobiasKienzler I most certainty hope that doesn't happen. None the less if they need to use forgot password I shall be just fine to. I love your input to this question! – Rixhers Ajazi Aug 16 '13 at 13:07
  • @RixhersAjazi You're welcome, thanks for the added info. Good thing you decided to show the info now at least after the first attempt, that's something I _could_ bear with if the service was interesting enough ;) And good to hear you use bcrypt - but why limit the password to 100 characters? It's sure enough a more sensible limit than, say, 20, though... Nonetheless please reconsider [Tom Leek's comment](http://security.stackexchange.com/questions/40564/is-it-safe-to-show-users-why-their-password-is-not-allowed/40565?noredirect=1#comment64654_40569) about users rebelling if you _enforce_ this – Tobias Kienzler Aug 16 '13 at 18:24
  • @TobiasKienzler I sort of can't not enforce this =\ I completely agree with you all on this is pretty crazy, but on the other hand, my IT department at the school I attend (I'm still a student I don't even work for the IT department) will have "hissy-fits". For this program to ever be used I got to sell it to the IT department. Hell if you think this password requirements are crazy you should have a look at my security questions :P Its just the line of work I am in. This application is going to hold a lot of important information on students (my information included). – Rixhers Ajazi Aug 16 '13 at 22:29
  • @TobiasKienzler Oh and not trying toot my own horn here but the service will be very interesting... a million times more interesting then the cruddy VB Access Database that only one user can use at a time. My last application I created for the office has earned me recommendations from the VP of the College (WOOT WOOT) – Rixhers Ajazi Aug 16 '13 at 23:05
  • @RixhersAjazi Please tell me the security questions can be self-defined instead of ["You mother's maiden name?"](http://security.stackexchange.com/q/29806/3272)... Maybe you should send your IT department to this site, unless they are bearded elders back from the punchcard days too proud to learn something new - btw there's also http://workplace.stackexchange.com/ where you could ask "How to inform my employers about their unwise decisions without insulting them" ;) – Tobias Kienzler Aug 17 '13 at 06:20
  • @RixhersAjazi btw concerning security questions: [What's a good alternative to security questions?](http://stackoverflow.com/q/104592/321973) – Tobias Kienzler Aug 17 '13 at 06:25
  • I've been thinking of actually letting users create their own questions. I encrypt the questions, and Bcrypt over the answers, but the fear I have is if a user has a question like : when did you graduate high school. I can google that. A big belief I have is if you give users freedom you already lose the cat and mouse game we like to call "Security" I can also do SMS... which is pretty easy... – Rixhers Ajazi Aug 17 '13 at 13:39
17

Users/customers will most likely restrain from using your service once their third attempt at entering a valid password failed. Hackers in contrast will try to register arbitrarily often to figure out your password requirements as precise as possible.

To counter this, validate the user first via the usual means (email, captcha etc) and send them a password token. This already reduces the amount of fake valid users, and by blocking too many password changes in a specific time you make hackers' life harder. However you should still disclose all password requirements no later than after the first attempt of entering an invalid one.

But better yet, I recommend not forcing users to choose an arbitrarily complex password that they will simply end up writing down on a post-it next to their monitor (or having them reset their password as simplified "login"). Instead, let them know that their password is weak, tell them what a good yet memorable password is (e.g. use a pass- phrase instead) and allow them to proceed anyway after clicking a "Yeah, I understood my password is not very secure, let me proceed anyway" - it's their fault if the account gets hacked then and you should not be liable after this explicit warning. Assuming you did use a proper and established password hashing instead of homebrew-crap or, worse, plaintext.

Tobias Kienzler
  • 7,578
  • 10
  • 43
  • 66
  • 3
    Also - the 20 character lower case password is more secure (~94b) then 8 character password having lower and upper case letters, symbols and numbers (~52b) if both are perfectly random - yet the former will not be allowed while latter will be. – Maciej Piechotka Aug 14 '13 at 10:21
  • 2
    [Precisely.](http://xkcd.com/936/) Ultimately all _enforced_ password constraints yield failure, it should be up to the user to wager whether the respective access shouldn't be secured via e.g. a KeePass generated password in that case... – Tobias Kienzler Aug 14 '13 at 10:24
8

Think about the scenario -- how does the attacker get the requirements? Most likely because they can register themselves. In which case it is trivial to reverse engineer your requirements unless they are too complex to use without an explanation. So, yes, it's safe to let the user know what your requirements are.

But a better approach is to not require a password at all, OpenID if at all possible. It's almost certainly going to be at least as secure as whatever you use for gathering and storing passwords. And for anyone with a gmail or yahoo account, it's definitely going to be easier.

jmoreno
  • 496
  • 2
  • 9
  • 1
    Though using OpenID means you're relying on an external service. Which *might* (depending on requirements) work for a web-based application that users interact with, but won't work as well for a web service (computer-to-computer communications), or for a locally installed application that must be able to run without network access, or if the OpenID service is ever unavailable for any other reason. – user Aug 15 '13 at 09:20
  • 1
    @MichaelKjörling: For computer-to-computer interaction something like OAuth token is probably a better way then password. – Maciej Piechotka Aug 15 '13 at 14:14
  • @MaciejPiechotka Possibly, but the answer talked specifically about using "OpenID if at all possible". – user Aug 15 '13 at 14:17