77

I have a web service. Right now, I have passwords stored in plain text in a MySQL table on my server. I know this isn't the best practice, and that is why I am working on it.

Why should passwords be encrypted if they are being stored in a secure database? I realize that if someone hacks in to my database they will get everyone's password. But I have other problems if someone gets in my database, for example, deleting data.

The scenario I can think of is that you are hacked. You restore a database from a couple of hours ago and everything is well. However, if your passwords are plaintext... The thief has all the passwords and you have to reset them all. Hassle to your users.

If the passwords were encrypted, you could just restore to previous database. Is this correct thinking?

5
  • 130
    I would go one step further. It's not enough to encrypt it. You'd want to hash it. That way, not even you should be able to know what your users' plaintext passwords are.
    – Santa
    Jan 30, 2014 at 0:36
  • 68
    @Santa Hashing the password is not enough. You have to add some salt to make the recipe good enough...
    – Bakuriu
    Jan 30, 2014 at 10:15
  • 17
    Please please have a look at this relevant Security.StackExchange post: How to securely hash passwords?
    – Adi
    Jan 30, 2014 at 12:10
  • 12
    Disgrunted DBA says... select * from user, and then sells that list for severence pay. Nothing is ever secure.
    – Jon Raynor
    Jan 30, 2014 at 19:50
  • 1

15 Answers 15

197

First up, you should be more free with read-only access rights than read-write. It might be possible that a hacker has access to your data but isn't able to edit it.

But, much more importantly, this is not about you. The fact that you might be screwed if someone has full access to your database is irrelevant. Much more important is your user's data.

If you recover your database, the hacker still has access to your user's account.

And who knows what else? What if they use the same password at Google? Or PayPal? What if that gives a hacker access to their mother's maiden name, or the last 4 digits of their credit card?

What if that gets them into other accounts? Don't put it past a hacker to go through a user support system and get more info.

Just ... just don't. That's your user's private information and you don't need to be able to see it. It's also your reputation. Encrypt it.

EDIT: One extra comment, to save any future reader from reading every answer and comment ...

If you're going to encrypt (in the strictest sense) then you need to use a public / private key pair, which is fine but makes life a little bit more difficult for both you and your user.

A simpler, and just as effective, solution is to random-salt and hash the password. Hashing alone is not enough; if your user uses a common password, it will appear in reverse-hashing tables, which are readily available with a simple internet search.

20
  • 89
    Or better, hash it!
    – Blorgbeard
    Jan 30, 2014 at 0:31
  • 30
    This. "I have other problems if someone gets in my database". It's your database, you expect to have problems if it gets hacked. But by storing plaintext passwords you give all your users problems with, potentially, all their other accounts. How many people do you think really use a different password on every single website? Jan 30, 2014 at 0:33
  • 14
    Please follow Blorgbeard's advice, maybe read this. Encrypting passwords does not provide protection when your web server has been compromised. The key to decrypt the passwords must be stored somewhere on the server. Hashing the passwords means that even in the event that someone has full access to the machine, they cannot recover the passwords easily.
    – Slicedpan
    Jan 30, 2014 at 10:16
  • 8
    Why would you ever need to encrypt passwords if it provides no value to your system? At what point in time will you have to decrypt passwords, other than for comparison? @pdr, you shouldn't be telling the OP to encrypt, you should be telling him to salt and hash. Jan 30, 2014 at 16:09
  • 5
    Hashing the password (along with salting) is not "just as effective" as encrypting, it's the only way passwords should be stored. At no point should your program ever work with plain-text (i.e. decrypted) passwords, or even have the possibility to do it. You should emphasize the problems with encryption, instead of suggesting it's the preferred approach.
    – vgru
    Jan 31, 2014 at 8:36
66

If you get hacked you can restore the site from backups and fix it. But the hacker still has passwords for everyone's accounts! There are documented real world examples of this happening (Sony, Linked-in), where if the password tables had been properly hashed and salted, securing and restoring the sevice quickly would have been much easier.

It's probably a good idea to assume you will be hacked, and design your backup strategy and encrypt any sensitive data with this assumption in mind. And it's not just hackers you need to protect against. Disgruntled, dishonest, or just clueless employees could give away plain-text passwords.

Without hashing you will have to disable access for everyone until they change their password (which, even if possible, will be a huge headache for everyone). If the passwords had been hashed and salted you could restore the web service and it would be much harder for an attacker to gain access to people's accounts.

A properly hashed and salted password is basically one-way. You can't easily guess the password from the hashed password. Even you, as the service provider won't be able to guess it, you can only reset it.

Also, as Elin said, don't try and roll your own hashing (or encryption). Use a standard library.

9
  • 2
  • 14
    +1 for mentioning disgruntled employees. It's easy to overlook when you're a one-man shop or a small company, but eventually you'll have people working with the data that you haven't personally vetted.
    – user25946
    Jan 30, 2014 at 5:43
  • 2
    Writing the foreach to loop through a list of users and then hash their passwords is the work of a few minutes and frankly 4000 is hardly anything. php.net/manual/en/function.hash.php
    – Elin
    Jan 30, 2014 at 13:21
  • 3
    You keep switching between the terms "encrypt" with "hash and salt" @david25272. Don't confuse the two, which are entirely different. Now the OP is looking for an encryption algorithm, and not a hash algorithm. Also, it's "salt and hash", not "hash and salt". You can't salt after you hash. Jan 30, 2014 at 16:16
  • 1
    Also @phpmysqlguy, read my answer for suggestions on salting and hash algorithms. Jan 30, 2014 at 16:20
36

But I have other problems if someone gets in my database, i.e. deleting data.

It's not about the problems you have, it's about the problems it might cause for all your other users. It's about removing temptation (or even worse, potential liability) for people working on the site to abuse data that's stored there.

See, even though people should use different passwords on different systems, the reality is that don't.

...and since it's so easy to hash passwords, you have no excuses for not following industry best practices.

2
  • 9
    You make what I believe to be the most important point: YOU and your workers should not have access to the user's password. Who cares about the hacker, it's the people holding the data that concerns users.
    – Adam Davis
    Jan 30, 2014 at 19:06
  • 1
    +1 for the fact that as a developer/admin you should not have access to your users' passwords. That in itself is reason enough.
    – Matt
    Feb 4, 2014 at 20:51
22

Noticeable attacks like deleting data are usually the stuff of amateurs, and are the least of your worries. One of the first things an experienced attacker will do is attempt to gain legitimate access, so even if you patch the original vulnerability he used, he will still be able to get in. He will do everything possible to avoid drawing attention to himself until he accomplishes what he desires. By leaving passwords unhashed, you just potentially made his job a lot easier. You also made it harder to detect and isolate his future malicious behavior.

Also, not all compromises give you full shell access. What if the vulnerability an attacker used is just a read-only SQL injection on the users table? Leaving passwords unhashed just gave him pretty much full access.

That's in addition to the reasons given by other answers about your responsibility to safeguard your users' data. My point is, it's not just your users who have something to lose.

19

I have to post an answer here on a fallacy in the question itself. You are asking if passwords should be encrypted. No one encrypts passwords; no one, with the exception of services and programs like Firefox Sync and Roboform, whose sole purpose is to encrypt passwords.

Let's take a look at the definitions:

In cryptography, encryption is the process of encoding messages (or information) in such a way that only authorized parties can read it.

And hashing:

A hash function is any algorithm that maps data of arbitrary length to data of a fixed length.

In other words, encryption is a two-way conversion and hashing is a one-way conversion, so unless you are decrypting to view them later, this is not encryption.

Also, don't just hash, salt! Read this entire page before you hash your passwords.

As for hashing algorithms, which the OP is now looking into, I would suggest any of the high-end SHA-2 varients, such as SHA-384 or SHA-512.

Optionally, you can use multiple rounds of hashing.

Consider reading this page to secure your login process more.

Second, your database can never be secure enough. There will always be security holes and ever-evolving risks. You should follow Murphy's Law and always prepare for the worst eventuality.

The other points pdr makes are exactly what else I would say: people who use the same password for every website, hackers using social engineering to gain more information, etc. etc.

6
  • +1 for hash plus salt. Cracking hashes without salts is sooo easy. Jan 30, 2014 at 16:27
  • 3
    You know what's on the other side of a rainbow table @CodeMaverick? A pot of gold. Jan 30, 2014 at 16:36
  • In the context of password hashing MD5 has no known vulnerabilities beyond being fast, and that applies to SHA-2 as well. Using a slow, iterated construction is far more important than choosing SHA-2 over MD5. Jan 31, 2014 at 14:06
  • 4
    "Read this entire page before you hash your passwords" - that page mentions that you should not use rounds of hashing, but a hashing method that has been specifically designed to be as slow as necessary, such as PBKDF2.
    – jhominal
    Apr 13, 2014 at 10:13
  • 2
    Use SCrypt or PBKDF2, both of which are designed to be very expensive to perform in terms of either memory or CPU. Use a randomly generated Salt that you store on the user record. Do not perform multiple rounds of hashing, that just leads to collision issues. Apr 14, 2014 at 14:54
14

There is an important principle at stake here. There is only one person who has any business knowing a users password. That's the user. Not their wife/husband, their doctor or even their priest.

It definitely does not include the programmer, database administrator or system technician responsible the the service they are using. That creates a challenge, as the programmer does have a responsibility to receive prove that the user actually knows the password, which is a non trivial problem to solve in a pure way.

The pure solution is to have a mechanism where the user is challenged with some new and unpredictable data, and then has to return a response that is based on this data and their password. One implementation of this would be to ask the user to digitally sign some newly generated data with their digital signature, and we could mathematically prove that they used the same cryptographic key pair that they used to originally create the account.

In practice, the pure solutions require substantial client side infrastructure and processing, and for many websites, this is often not appropriate for the data being protected.

A more common solution would be:

At the point where a password is first received in the application, the password is passed to hashing function, along with you application's random 'salt' value into the hash function.

The original string is then overwritten in memory, and from this point on, the salted hash is stored in the database or compared with the database record.

The key aspects that provide security here are:

  1. Knowledge of the hash does not directly provide authentication.
  2. Reverse calculation of the password from the hash is impractical.
  3. The use of rainbow tables (long lists of passwords and their calculated hashes) is made more challenging because the resulting hash is dependent on both username and password.
6
  • 6
    In general it's preferred to use a random salt instead of the username. Jan 30, 2014 at 11:24
  • Wow, great catch @CodesInChaos. I didn't notice that on my first read-through of the question. Yes, your salt should be randomly generated. It doesn't have to be some crazy blob stored in MySQL (and that would be bad because then it wouldn't be portable). Otherwise, +1 for saying that only the user should know the user's password. Jan 30, 2014 at 16:43
  • Okay, updated answer to suggest the application has its own random salt value. Jan 30, 2014 at 17:07
  • 4
    No, the application doesn't have a salt value either. There should be a different, strongly random, salt value for each stored hash. (You store the salt alongside that hash.) That's what protects against statistical attacks. If you used the same hash for the entire application, then the same plaintext hashes to the same value. That's far worse than using the username as the hash.
    – Ben Voigt
    Jan 31, 2014 at 0:00
  • It's not a web service, but SSH keypair authentication does use the 'pure' solution, where the server stores a public key and the user authenticates with a private key.
    – cpast
    Jan 31, 2014 at 17:31
10

You need to "encrypt" (actually, "hash", for a proper notion of hashing) the passwords as a second layer of defence: this is meant to prevent an attacker, who got a read-only glimpse of the database, from escalating that into read-write access and, precisely, begin to alter the data. Read-only partial breaches happen in the real world, e.g. through some SQL injection attack from an account with read-only access, or by retrieving a discarded hard disk or old backup tape from a dumpster. I have written at length on this subject there.

As for the proper ways to hash passwords, see this answer. This involves salts, iterations, and, most of all, not inventing your own algorithms (homemade cryptography is a sure recipe for disaster).

1
  • +1 for knowing the difference between encryption and hashing. Jan 30, 2014 at 16:48
8

I won't repeat what other people have said, but assuming you have PHP 5.3.8 or better, you should be using the PHP native bcrypt to store your passwords. This is built into PHP. If you have PHP 5.5 you can use the best available password constant. You can also use a library to make 5.3.8 or better behave like 5.5.

Stack Overflow question How do you use bcrypt for hashing passwords in PHP? explains it, and the other replies there explain more. Please don't mess around trying to do this yourself.

6
  • 2
    Unfortunately, I'm using PHP 5.3.3 so your suggestions won't apply Jan 30, 2014 at 2:40
  • 4
    is 5.3.3 to 5.3.8 much of an upgrade?
    – gbjbaanb
    Jan 30, 2014 at 9:39
  • Any chance you are on Red Hat? Because they have backported the fix to bcrypt. If not, then use SHA256 instead of brcypt.
    – Elin
    Jan 30, 2014 at 13:00
  • 1
    Encryption and hashing are different things. Hash passwords, don't encrypt them. You never need to know them. You only need the user to be able to use the password to prove who he/she is. Hashing (with salt) allows this. Encryption, esp. symmetric encryption is wrong as it allows passwords to be recovered. Jan 30, 2014 at 22:38
  • The one thing I'll add is that the good thing about the password_hash() function in php 5.5+ is that it handles the salting and so on sanely by default. Earlier than that you need to go ahead and use something like ircmaxell's library that backports it (he wrote the 5.5 implementation). Do not assume you can generate a random salt by yourself. It is very very hard and best left to experts; it is really easy to get random but not uniform results which are exploitable.
    – Elin
    Jan 30, 2014 at 23:24
7

I agree with the answer from pdr, for the reasons stated in that answer.

I would add the following: you should do it because it is easy to do and generally accepted as best practice for any application. More specifically, passwords should always be salted and hashed before writing to any persistent storage. Here is a good reference on the importance of salting and choosing a good cryptographic hash (that also provides free source code in several popular languages): https://crackstation.net/hashing-security.htm

The small amount of extra development time is well worth the protection it provides your users, and to your reputation as a developer.

1
  • +1 for mentioning both salting, and hashing, as well as not mentioning encryption, which doesn't even belong in this question. Jan 30, 2014 at 16:49
3

The scenario I can think of is that you are hacked.

Another scenario you need to think of: someone slipped your DBA (or whoever else can run select queries on your DB) $100, to give them the users' passwords. Or social engineers some intern to do that.

Then they use those passwords to log in to user's Gmail... or commerce site... (because people are ... less than smart shall we say - and use the same password across sites).

Then the irate user sues your company for exposing their password.


NOBODY (including people in your company) should be able to read plain text password. Ever. There's no legitimate business or technical need for that.

2

For one, even database administrators should not see the users' passwords. Hashing them will prevent this in case the administrator decides to look at a password and login into their users' account.

2
  • 1
    this does not add anything worthy to what was already posted in prior answers
    – gnat
    Jan 30, 2014 at 8:54
  • 3
    +1. He actually said "hashing", instead of encryption like many others are. Also, he directly contradicted the OP who said he wanted the passwords plaintext to log into other users' accounts. Jan 30, 2014 at 16:24
0

Well, it's surprising no one has mentioned this, yet, but what about PHYSICAL security of your database?

You may have the best IT security in the world set up, but that doesn't stop anyone who can gain physical access to your storage media. What happens when your team wins the Superbowl this afternoon, and a small riot erupts in your city's downtown area where your office / hosting provider is? (Given that it's Seattle vs. Denver, two large IT areas in the US, I don't think that's unreasonable). The mob smashes in to your building and while the authorities are overwhelmed, someone grabs some of your hardware with a DB on it that contains clear-text passwords?

What happens when the Feds show up and seize your equipment because some high-level exec was using his position in the company to execute illegal stock trades? Then the Feds use those passwords to investigate your customers, although they did nothing wrong. Then they realize it was YOU that left them vulnerable.

What happens when your IT department forgets to wipe the old RAID drives that held your DB when they do scheduled replacements before "handing out" the old drives to interns, and then their dorm roommates find what was left behind, and figure out they can "sell" it and never have it traced back to them?

What happens when your DB Server blows a motherboard, IT restores an image to your new server, and the "carcass" of the old server gets thrown in the recycling heap? Those drives are still good, and that data is still there.

Any decent architect knows that security isn't something you "bolt on" later with firewalls and operations policies. Security has to be a fundamental part of the design from the very beginning, and that means passwords are one-way hashed, NEVER transmitted with out encryption (even inside your own datacenters), and never recoverable. Anything that can be retrieved can be compromised.

0

By encrypting, I'm assuming you're referring to password hashing, which is a one way process whose virtue is that it is hard to reverse.

Indeed, there is no value in hashing passwords under these conditions:

  • We have some sort of guarantee that the users are not reusing the passwords for multiple sites.

  • We have some sort of guarantee that the passwords themselves do not contain personal information (unrelated to their role as security credentials).

These conditions are not met if the users are random individuals from the general public; therefore, the standard practice is to hash passwords.

Regarding the first point, if plain-text passwords leak which are re-used for accounts on other sites, those who obtain the leaked password have instant access to those accounts. Even if a bulletin about the breach is put out which reaches all users, and they all act on it, they will probably not act in time. If the passwords are hashed, it takes time to obtain access; the passwords must be cracked first, and only weak passwords (e.g. dictionary words) will succumb to that more or less instantly. Users with reasonably strong passwords who react to the breach bulletin have a fighting chance to log in to the other sites and change their reused passwords.

Regarding the second point, suppose that, oh, someone living in a country where being homosexual is criminalized uses the password i-am-gay, and a leak of that password gets associated with their e-mail address or other identifying information. Users can put actual personal secrets into passwords, and so we should protect passwords as if they were actual personal secrets.

There is no way to ensure these conditions in practice if the users are coming from the general public, so we encrypt passwords.

Could the conditions be met? If, say, five expert hackers are running a site for themselves, such that they are the only users, then sure, they can store their passwords in plain text. They understand security and know what they are doing. They do not use those passwords, or similar passwords, for any other system, and don't imbue any personal secret into the passwords. Thus the passwords have zero value to an attacker. If the attacker has access to the password, the system is already compromised, and the passwords themselves are not a gateway to anything else.

-1

Why:

  1. Because your secure database isn’t secure and hackers can break in and get my password.

  2. Because you can read my passwords and you should never, ever be able to read my passwords.

  3. Because you can be accused of reading and abusing my passwords.

  4. Because if this is ever found out, the xxxx hits the fan.

-2

Furthermore, I would add this:

"Software subsystems" should never authenticate to each other using "passwords." You should be using centrally-managed technologies such as LDAP ("OpenDirectory") and digital certificates. Any database which expects to receive connections only from internal subsystems should – first of all – be firewalled-away from any other requests, but also should be relying on non-password authentication strategies.

Every "internal actor" should be identified, both by its IP address and then by unique cryptographic credentials that only it possesses.

"Passwords" should be accepted only from external users, and they should be authenticated by the external application, not by the database engine.

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