20

If I create a login for an app that has middle to low security risk (in other words, its not a banking app or anything), is it acceptable for me to verify a password entered by the user by just saying something like:

if(enteredPassword == verifiedPassword)
     SendToRestrictedArea();
else
     DisplayPasswordUnknownMessage();

It seems to easy to be effective, but I certainly would not mind if that was all that was required. Is a simple check on username/password combo enough?

Update: The particular project happens to be a web service, the verification is entirely server side, and it is not open-source. Does the domain change how you would deal with this?

Morgan Herlocker
  • 12,722
  • 8
  • 47
  • 78
  • 3
    it depends where validPassword comes from? if it's hardcoded you won't be able to configure/change password without changing the code. If it comes from a configuration file, it will be visible to anyone who accesses that. – Alb Feb 18 '11 at 15:44
  • 1
    "is a check on username/password combo enough" to do what? – Chris Feb 18 '11 at 15:47
  • @Chris: to ensure that only people who should get through the login actually do. – Morgan Herlocker Feb 18 '11 at 16:00
  • This will provide you with minimal security for certain. (Keep in mind that minimal is zero or even negative.) – JUST MY correct OPINION Feb 18 '11 at 16:07
  • 3
    @opinion: it seems unlikely that this is WORSE than not having a login. Please provide some reasoning for such a strong claim. – Morgan Herlocker Feb 18 '11 at 16:12
  • 1
    Your terminology is incorrect, when you're comparing a password your verifying it, not making sure its valid. [Please take the time to understand the difference.](http://www.matthewedmondson.info/2010/08/difference-between-validation-and.html) – billy.bob Feb 18 '11 at 16:19
  • If it's a web service, I highly recommend using O/Auth protocol. Once the client has been authorized and an auth token has been negotiated _for that client_, you don't need to deal with username/passwords from that point forward. – Berin Loritsch Feb 18 '11 at 17:03
  • 1
    This implies plain text password storage, which is irresponsible. It also implies alerting a user that the password was incorrect, which provides a potential attacker with too much information. You should always be ambiguous, i.e. "Login or password incorrect". – Rein Henrichs May 23 '11 at 20:46
  • Yes, if it's inside client side Javascript (joke) – Coder Jun 10 '12 at 12:35

9 Answers9

52

That would suggest, that you're keeping passwords in open text, which is a no-no, even in low security scenarios.

You should rather have:

if(hash(enteredPassword) == storedHash)

You can use simple hash as for example MD5

vartec
  • 20,760
  • 1
  • 52
  • 98
  • 22
    +1 for hashing the password. But I'd at least add some salt as well. Otherwise, since users are going to reuse usernames & passwords between systems, breaching your low security app may enable an attacker to breach a much higher security app. The recent HBGary hack, for example, managed to compromise the CMS system running their website and turn that into root access to their servers in part because the low-security CMS system wasn't adding salt to hashes http://arstechnica.com/tech-policy/news/2011/02/anonymous-speaks-the-inside-story-of-the-hbgary-hack.ars/ – Justin Cave Feb 18 '11 at 16:05
  • 1
    Agree... consider the following.. "strings JavaFile.class | grep -i password" – Bill Feb 18 '11 at 16:23
  • What is the problem with having the password in plain text if they are only used once? –  Feb 18 '11 at 16:25
  • 10
    @Tim because users *won't* use the password only once. Studies consistently show that users re-use passwords multiple times (e.g. http://www.theregister.co.uk/2011/02/10/password_re_use_study/ ) no matter how many times they're told not to. – Scott Feb 18 '11 at 16:46
  • 3
    @Tim: besides, just open your exe, dll, etc, in a text editor, and you'll likely see your password right there. – Gus Cavalcanti Feb 18 '11 at 16:53
26

Not without SSL

This is not secure if the password is sent over the network in plain text. Hashing the password on the server side is also not secure if the password is sent over the network in plain text.

Since the HTML <input type="password"/> tag sends its contents in plain text, this will be a problem no matter how you store the password on the server, unless your website uses SSL to transmit the password.

(HTTP authentication, which pops up a dialog box in the browser asking for a password, may or may not be clear text, depending on what authentication mechanisms the server and browser have in common. So that could be a way to avoid this without using SSL.)

Not if the site administrators are suspect

Now, supposing you're using HTTPS to do the web site, this could be secure if you trust your site administrators (who can read plain text passwords), and other people who have access to the machine to behave properly. Now, it may be obvious that they can do anything they want with your website (since they administer it), but if they can read the password, the may also be able to use the stolen login/password pairs on other people's sites.

A way that keeps passwords safe from the administrator

One secure way to store and check passwords is as follows:

def change_password user, new_password
  salt = random(65536).to_s(16) #will be 4 characters long
  password_hash = salt + hash(salt + new_password)
  store(user,password_hash)
end

def does_password_match? user, entered_password
  correct_password_hash = retrieve(user)
  salt = correct_password_hash[0...4]
  entered_password_hash = salt + hash(salt + entered_password)
  return correct_password_hash == entered_password_hash
end

For the hash function, try to use something strong, and something that doesn't have good rainbow tables in the wild yet. You can change the length of the salt if necessary work around rainbow tables.

Depending on the environment you're in, the variability in your network latency, and whether user names are meant to be publically known, you may want to have another code path compute hash('0000'+entered_password) if the user doesn't exist, in order to prevent attackers from determining which usernames are valid based on the time it takes determine that the password is incorrect.

Ken Bloom
  • 2,384
  • 16
  • 20
  • 1
    Good advices :) Regarding SSL, we were required to design something that would work *in the wild*, and simply used asymetric cryptography to encode the password (requires Javascript) and then decode it on the server. The salt+hash then occurs normally. Also, since the public key is sent with the web-page, it can change arbitrarily often. – Matthieu M. Feb 18 '11 at 18:19
  • 1
    @Matthieu M.: When someone can fake your webpage, he can also change the public key there to one where he himself knows the corresponding private key. So your idea does help only against passive read-attacks, not against man-in-the-middle. – Paŭlo Ebermann Feb 18 '11 at 23:04
  • @Paulo: yes, I agree that SSL is not only about encryption, but also about certificate, unfortunately I don't call the shots here, and when people say they want to use the webpage with a regular `http://` connection... it's frustrating :/ – Matthieu M. Feb 19 '11 at 11:33
  • @Matthieu: Does that mean you're sending public_key as part of the the public web page, computing `encrypt(entered_password, public_key)` on the client, and sending that result to the server, which performs `does_password_match?(user, decrypt(encrypted_password, private_key))`? – Ken Bloom Feb 20 '11 at 03:17
  • @Ken: more or less, you got the encryption right. For matching the password it's more `does_password_match(user, salt, decrypt(encrypted, key))`, with the salt depending on the user. As I said, the obvious issue is the lack of man-in-the-middle protection. – Matthieu M. Feb 20 '11 at 11:16
  • @Matthieu: my `does_password_match?` function is finding the appropriate salt *inside* the function, so we're really describing the same thing. – Ken Bloom Feb 20 '11 at 17:27
14

I concur with those who suggest hashing, but there is also a wheel you are reinventing here. Depending on the platform you can probably find a role/user management tool that covers all of the user management stuff safely and securely without needing too much intervention on your part.

glenatron
  • 8,729
  • 3
  • 29
  • 43
  • I only just discovered ASP.Net Membership Providers but I was looking at them thinking "how many times have I wasted my time implementing something like this?" – glenatron Feb 18 '11 at 16:23
8

Security is a very touchy subject, particularly because there needs to be a balance between inconveniencing your users and making sure their information is safe. Typically, the formula for how much security you need is a function of the importance of the data. In short:

isSecuritySufficient = effortToBreak > rewardForBreaking

A common misunderstanding about people who do bad things is what they are after. Most of them are out to destroy trust. You should always do everything you can to protect your users' trust. Part of that is doing your due diligence to make sure their identity is safe. They may care less about the data they store, but they do care about their identity--even at the lowest threshold of security.

There's a number of low cost (to implement and impact to the user) options available. One of those is hashing the password at a bare minimum. Any service that stores something as sensitive as a password in plain text deserves the embarrassment of being hacked.

General Principles for Password Protection

  • Never store passwords in plain text
  • Hash using a secure hash function like SHA-1 or even SHA-512 (even MD5 is too easy to find a matching hash)
  • Use an application salt value. The salt is random bytes either added to a password to make it more difficult to guess. The salt should be generated at run time and using information about the machine as a seed value rather than stored and referenced in any way.
  • Use a user specific salt value. Use this in conjunction with your application salt.
  • Encrypt all authentication requests that go over a network. That means use SSL for web applications.

Since you would be using SSL for the authentication, at a minimum you want to encrypt all the pages that deal with the user's account as well. This allows as much of a user's identity to be protected as possible.

A note about password management: Users will forget their password from time to time. The absolute worst thing you can do is to send them their password in an email. If you implement the principles outlined above, you won't be able to do that anyway. It is much better to provide a way to reset their password using a link sent to their registered email address. That reset link will have a one-time use code to ensure the person accessing the page is them.

Berin Loritsch
  • 45,784
  • 7
  • 87
  • 160
  • 1
    At first I was really struck by the idea of application salt + user salt, but the more I think about it, the less convinced I am. If you used, say, 4 characters of application salt and 4 of user salt, then the difference between that and 8 characters of user salt is just that half the salt would be identical for every user. It would seem that it would be more secure to just increase the size of the user salt, rather than have application salt. Also, if the application salt is based on the hardware then you can't upgrade or change the hardware without invalidating all the passwords. – David Conrad Mar 14 '11 at 01:39
  • The problem is that the user salt is included in the database row with the user password. If a bad person knows what a salt is for (and they do), and they see it in the database, then they know how to completely crack it. By including a part in the application that is calculated (the same way every time mind you) instead of stored, it makes it that much harder to crack the user tables. Of course you can go one step further and make a 1 part pure random salt and a 1 part calculated salt with both being user specific. – Berin Loritsch Mar 14 '11 at 10:16
  • Ah, I see, keep part of the salt out of the database. That does make sense. Thank you. – David Conrad Mar 24 '11 at 02:22
  • I don't see a problem storing the salt per-row, as long as its unique per row. Here's a hash: "fd84235a55bbfeb1585a3dd069d48127989c9753058b51b6ba2056fd6c5a0a91" (SHA256), here's the salt: "671254bdf7944f8fa88e6c9913b948ee". Think you can get the password? There's no rainbow table for that salt (even if you're given the salt), you're stuck brute-forcing it. – Bryan Boettcher Jul 09 '12 at 21:45
3

That's fine unless the password is used for anything else. There's still a risk that the user decides that he can re-use the password, so it would be even better with:

if(hash(enteredPassword) == hashOfValidPassword)

If it's for yourself or someone who is aware that the password is stored in plain-text, then it's fine.

  • 1
    As in Justin Cave's comment to vartec's answer, use salt, so `if (hash (enteredPassword + salt) == hashOfValidSaltedPassword)` - and note that the `+` is probably concatenation, not addition. This really hinders the use of rainbow tables, which are tables of hashes of likely passwords. – David Thornley Feb 18 '11 at 17:10
  • if all you are checking for is a hash, could they not just run through a loop of possible strings until one generates the same hash as the stored hash? There are many strings that could correspond to the same hash, after all. – Morgan Herlocker Feb 21 '11 at 18:20
  • @Prof Plum: It is very difficult to find collisions if the hashing algorithm is good. This is the basis of modern cryptography: they are essentially one-way functions. –  Feb 22 '11 at 08:58
3

Is the source code available? Even if not, I'm quite sure the password could be found in the machine instructions in case the binary is available. I would recommend doing a checksum and comparing that instead.

Never overlook security even if it isn't very important in your opinion.

Anto
  • 11,157
  • 13
  • 67
  • 103
1

Absolutely not. Have a read of this, it describes how hackers hacked a security web site. You plan would have you as the weakest link in the chain.

dave
  • 2,466
  • 15
  • 21
0

It has been noted in a couple of answers that you should not store the password itself, but a hash - and you should use SSL.

You may say, what is the big deal? If my application gets hacked, that is of little concern. Well it is a quite common pattern for users to reuse the same password on all sites. Was a hacker to hack your site and gain access to user's passwords, the hacker would be able to impersonate a lot of those users on other sites of greater importance to those users. So hacking your site could be the first step for a hacker to gain access to banking information for the users.

And just hashing the password is not enough. You need to hash it with a salt. Hackers have reverse hash lookup tables, so for a given hash, they can find a matching password.

If you choose not to implement these feature, you should inform the users of of this lack of security, encouraging them not to use the same password that they use elsewhere.

Pete
  • 8,916
  • 3
  • 41
  • 53
-2

As long as this is server side.. Then yes.

If you want a bit more security go for https and encrypt\hash the password in the DB.

Morons
  • 14,674
  • 4
  • 37
  • 73