Best Way to Store Passwords in MySQL Database

Best way to store passwords in MYSQL database

First off, md5 and sha1 have been proven to be vulnerable to collision attacks and can be rainbow tabled easily (when they see if you hash is the same in their database of common passwords).

There are currently two things that are secure enough for passwords that you can use.

The first is sha512. sha512 is a sub-version of SHA2. SHA2 has not yet been proven to be vulnerable to collision attacks and sha512 will generate a 512-bit hash. Here is an example of
how to use sha512:

<?php
hash('sha512',$password);

The other option is called bcrypt. bcrypt is famous for its secure hashes. It's probably the most secure one out there and most customizable one too.

Before you want to start using bcrypt you need to check if your sever has it enabled, Enter
this code:

<?php
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
echo "CRYPT_BLOWFISH is enabled!";
}else {
echo "CRYPT_BLOWFISH is not available";
}

If it returns that it is enabled then the next step is easy, All you need to do to bcrypt a password is (note: for more customizability you need to see this How do you use bcrypt for hashing passwords in PHP?):

crypt($password, $salt);

A salt is usually a random string that you add at the end of all your passwords when you hash them. Using a salt means if someone gets your database, they can not check the hashes for common passwords. Checking the database is called using a rainbow table. You should always use a salt when hashing!

Here are my proofs for the SHA1 and MD5 collision attack vulnerabilities:

http://www.schneier.com/blog/archives/2012/10/when_will_we_se.html, http://eprint.iacr.org/2010/413.pdf,
http://people.csail.mit.edu/yiqun/SHA1AttackProceedingVersion.pdf,
http://conf.isi.qut.edu.au/auscert/proceedings/2006/gauravaram06collision.pdf and
Understanding sha-1 collision weakness

Best practice for storing usernames & password in MySQL Databases

For the password hash use PBKDF2 it's NIST approved. You should use a random non-secret salt for each password and nontrivial (over 1000) iteration count.

For the username and email, probably not worth encrypting.

Best way to store password in database

You are correct that storing the password in a plain-text field is a horrible idea. However, as far as location goes, for most of the cases you're going to encounter (and I honestly can't think of any counter-examples) storing the representation of a password in the database is the proper thing to do. By representation I mean that you want to hash the password using a salt (which should be different for every user) and a secure 1-way algorithm and store that, throwing away the original password. Then, when you want to verify a password, you hash the value (using the same hashing algorithm and salt) and compare it to the hashed value in the database.

So, while it is a good thing you are thinking about this and it is a good question, this is actually a duplicate of these questions (at least):

  • How to best store user information and user login and password
  • Best practices for storing database passwords
  • Salting Your Password: Best Practices?
  • Is it ever ok to store password in plain text in a php variable or php constant?

To clarify a bit further on the salting bit, the danger with simply hashing a password and storing that is that if a trespasser gets a hold of your database, they can still use what are known as rainbow tables to be able to "decrypt" the password (at least those that show up in the rainbow table). To get around this, developers add a salt to passwords which, when properly done, makes rainbow attacks simply infeasible to do. Do note that a common misconception is to simply add the same unique and long string to all passwords; while this is not horrible, it is best to add unique salts to every password. Read this for more.

Storing Passwords on MySQL database: Hash vs Encryption?

I'm going to go ahead and say neither of them. You should never store a password, even encrypted. That makes you vulnerable to password stealing, either external or internal to your organization. Also, SHA2 is not deprecated per-se, and you don't specify the hash length. SHA2-512 or even SHA2-256 are still considered excellent cryptographic hashes. You could also use the more recent SHA3/Keccak crytographic hash, but from recent literature, it's not better than SHA2 as much as different. Both are still endorsed by NIST.

However, there's consensus in InfoSec that a simple crypto hash is not enough for properly storing secrets. As of 2018, it seems either PBKDF2, bcrypt or ARGON2 are widely considered the top contenders for "best" crypto hash algorithms. You can read a much more detailed explanation about passwords and cryptographic hashes on this Security StackExchange link
https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords/31846#31846

The link above doesn't explain ARGON2, which was the recent winner of the Password Hashing Competition. You can read more about it here: https://github.com/p-h-c/phc-winner-argon2

My recommendation would be to:

  • Add a fourth field to the table called salt. This should be a truly random 8+ digit alphanumeric string, stored in plaintext.
  • Store the "password" as CryptoHash(salt + 'password1234'). This protects you from rainbow tables, since it's not feasible to precalculate ALL rainbow tables for all possible salts.

Replace CryptoHash above with either PBKDF2, bcrypt or ARGON2, and you'll have a pretty good password storage mechanism.

How to store password securely in database

You hope to store your cisco switch passwords in your database in a form where you can recover the password plain text to use it for ssh connections.

Even if you encrypt the passwords in the database, your program that accesses the database will have to be able to decrypt them to use them. So the decryption key necessarily will be available to your program. That's entirely different from the kind of password-hashing mechanism available in php. Password hashing doesn't allow you to recover the password from the hash, only to compare a user-presented password with the hashed password to see if they match.

Storing decryptable passwords is not secure, and can never be secure. If somebody cracks your server, they then have access to your entire infrastructure. (Cybercreeps with access to switches and routers can really make a mess.) This is the kind of thing that shows up in https://KrebsOnSecurity.com . Don't do it. Please.

If you want more-or-less automated access to your switches via ssh, your best bet is to use ssh's key management features. The machine from which you access the switches will have a private key, and each switch will have a public key corresponding to the private key. If you configure the public keys correctly you can restrict the operations available to users who present the corresponding public keys. It's a big topic, too big for a Stack Overflow answer.

As usual, Digital Ocean's writeup of this topic is useful. https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server

What's the safer way to store a password in MySQL database?

Well, apart from the obvious, not storing, hashing etc...
I'd say don't use the regular {MD5, SHA1, SHA256, SHA512, SHA-3, etc} if you can, even if you can salt them. Reasons for this can be found at:

http://codahale.com/how-to-safely-store-a-password

Simply put: use bcrypt

You might want to read up on this topic on

Password hashing, salt and storage of hashed values

http://dustwell.com/how-to-handle-passwords-bcrypt.html

https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet

What's the best way to store sensitive data in MySQL?

Seriously, DON'T USE MySQL's aes_encrypt() It is the the most insecure method of using a block cipher. It is using ECB mode, and I can give a simple example demonstration why this is a serious mistake.

Plain text message:

alt text

The same message encrypted with ECB mode (doesn't matter what cipher you use):
alt text

The EXACT same message using CBC mode (again, it doesn't matter what cipher you use):
alt text

There are even more reasons not to use mysql's aes_encrypt, most notably every single query you send will also have the aes key that you use. If the database is compromised the attacker will enable logging and just get your aes key and decrypt the entire database.

So what should you use? I like this class for the time being. Its using CBC mode with a String2Key function and an IV. You can use the primary key as your IV, each message must have a unique IV. Its okay if the attacker knows the IV, and if they are sequential, so long as the block cipher implementation is secure. Reuse of an IV made WEP much less secure.

Is it safe to store usernames and passwords in the database?

The process for storing passwords with a basic measure of security is fairly simple:

  • Hash the passwords with salt
  • Use a different salt for each user/password
  • Store the salt with the hashed password in the DB
  • When they try to log in, run what the attempted PW thru the same method; compare the result.

If they entered the correct password, the hashed PWs will match. Hashing protects the users from attacks as well as the janitor walking by a screen with the members table on display.

Creating Salt and Hashing the PW

' salt size is 32 (0-31
Private Const SaltSize As Integer = 31
...

Dim dbPW As String = TextBox1.Text
Dim dbSalt = CreateNewSalt(SaltSize)
' eg: "dsEGWpJpwfAOvdRZyUo9rA=="

Dim SaltedPWHash As String = GetSaltedHash(dbPW, dbSalt)
' examples:
' using SHA256: bbKN8wYYgoZmNaG3IsQ2DPS2ZPIOnenl6i5NwUmrGmo=
' using SHA512:
' 0vqZWBIbOlyzL25l9iWk51CxxJTiEM6QUZEH1ph+/aNp+lk4Yf8NYv8RLhYtbqCNpOqO3y8BmM+0YWtbAhE+RA=="

Store the PW hash and the salt as part of the user's record. The salt is not secret, but change it when/if the user changes their password.

Comparing a Login attempt

' check if PW entered equals DB
Dim pwTry = TextBox2.Text
' hash the login attempt using the salt stored in the DB
Dim pwLogin = GetSaltedHash(pwTry, dbSalt)

' compare the hash of what they entered to whats in the DB:
If String.Compare(SaltedPWHash, pwLogin, False) = 0 Then
' okay!
Console.Beep()
End If

If the user enters the same PW, it should result in the same hash, it is as simple as that. The hashing code is not all that complicated:

Hash Methods

Private Function GetSaltedHash(pw As String, salt As String) As String
Dim tmp As String = pw & salt

' or SHA512Managed
Using hash As HashAlgorithm = New SHA256Managed()
' convert pw+salt to bytes:
Dim saltyPW = Encoding.UTF8.GetBytes(tmp)
' hash the pw+salt bytes:
Dim hBytes = hash.ComputeHash(saltyPW)
' return a B64 string so it can be saved as text
Return Convert.ToBase64String(hBytes)
End Using

End Function

Private Function CreateNewSalt(size As Integer) As String
' use the crypto random number generator to create
' a new random salt
Using rng As New RNGCryptoServiceProvider
' dont allow very small salt
Dim data(If(size < 7, 7, size)) As Byte
' fill the array
rng.GetBytes(data)
' convert to B64 for saving as text
Return Convert.ToBase64String(data)
End Using
End Function
  • It is tempting to use something like a GUID (System.Guid.NewGuid.ToString) as the salt, but it just isn't all that hard to use the cryptographic random number generator.
  • As with the hashed password, the return string is longer due to the encoding.
  • Create a new salt every time the user changes their password. Don't use a global salt, it defeats the purpose.
  • You can also hash the PW multiple times. Part of the key is to make it take a long time to try all various combinations if/when attacked.
  • The functions are ideal candidates for Shared / static class members.

Note also, the article linked to by Kenneth is well worth reading.


Note that the article mentions The salt should be stored in the user account table alongside the hash This doesn't mean you must have a Salt column in the DB. You can see the following being done in the linked article:

Dim dbPW As String = TextBox1.Text
Dim dbSalt = CreateNewSalt(SaltSize)

' get the salted PW hash
Dim SaltedPWHash As String = GetSaltedHash(dbPW, dbSalt)
' store salt with the hash:
SaltedPWHash = String.Format("{0}:{1}", dbSalt, dbPW)
' salt + ":" + hashed PW now ready to store in the db

To split the salt from the hashed password:

Dim SaltAndPWHash = rdr.Item("PWHash").ToString()

Dim split = SaltAndPWHash.Split(":"c) ' split on ":"
Dim Salt = split(0) ' element(0) == salt
Dim StoredPWHash = split(1) ' element(1) == hashed PW

You need both parts: after you hash the attempted log in PW, compare it to split(1).



Related Topics



Leave a reply



Submit