I'm using BCrypt to hash my passwords on the server side. Before I store it in my MySQL database, would it be overkill to encrypt my hashed-BCrypt password or would storing the hash directly in the database suffice?
This website advises to encrypt passwords after hashing them:
As long as an attacker can use a hash to check whether a password
guess is right or wrong, they can run a dictionary or brute-force
attack on the hash. The next step is to add a secret key to the hash
so that only someone who knows the key can use the hash to validate a
password. This can be accomplished two ways. Either the hash can be
encrypted using a cipher like AES, or the secret key can be included
in the hash using a keyed hash algorithm like HMAC.
EDIT: I'm coding in Java. I'm trying to gauge whether the added layer of protection vs. speed performance of read & retrieval of passwords for user logins is worth it or not.
This would indeed increase security, but it is good to know what exactly you gain with encryption.
Encrypting the password-hash can protect weak user passwords from a
dictionary attack, in the special case, where the attacker has
read-access to the database (containing the hashes) but does not have
access to the source code with the key/pepper.
This situation is not so uncommon as one would think, typical scenarios would be SQL-injection, thrown away backups, discarded servers...
To be able to brute-force for passwords one needs the server side key, which was used to encrypt the password-hashes. This means, being able to read the hashes from the database is not enough anymore, one needs additional privileges to read the key from the server. Getting privileges on the server is much more difficult than being able to read the database.
Crackstation is a good site for advice. At the end of my own tutorial about safely storing password I try to explain the details of this password-hash encryption.
Related
I am creating a database and I need to store user passwords. I am already using bcrypt to hash the passwords on the client side, but I have read that only hashing on the client side makes the hash essentially equivalent to a password as far as the database is concerned. I'd like to hash the passwords (which are now hashes) again before they are stored in the database. Do I have to use a method native to MySQL like SHA2(pwd), or is there a way to use bcrypt on the server?
Bcyrpt is a good call here, but you should be doing the hashing on the server end, not the client. The client can't know all the information it needs to produce a hash you can verify is correct, only the server has that information.
What you need to do is pass through the password securely, such as over HTTPS, and hash it there in your application layer. MySQL alone does not have the functions necessary to do proper password hashing. SHA2 is completely inadequate, it's a high-speed hash by design which makes it immediately unsuitable. Password hashing algorithms are deliberately slow to make brute-forcing passwords painfully expensive.
What is the most secure way to encrypt user passwords for phpBB or MyBB forum registrations? I don't want anyone to be able to access the user passwords, not even those who administrate the MySQL database, and also if someone manages to hack the database to not be able to view them. I want only the users who register to know their passwords.
I completely agree with the response Federico Razzoli, except for one thing. Indeed, hashing must be performed upstream, in any case not at the database level (so your question is probably off topic).
However simply using a hash function is not sufficient in terms of security. You remain vulnerable to dictionary attacks, rainbow table attacks, and some attacks by frequency analysis. It is essential to at least use a cryptographic salt.
However, the best is to use a key derivation function designed to store passwords. I suggest you to look at PBKDF2 (hash_pbkdf2 with PHP), bcrypt (password_hash with PHP, which by default uses a judicious algorithm, bcrypt currently) or scrypt.
Finally, your question suggests that you use phpBB, this forum engine should normally deal alone with the secure storage of passwords.
You can use SHA512.
I see that you used the "mysql" tag. Please, don't use the SHA2() SQL function, or any other SQL hash function. If you do so, the plain strings will be sent across the net, and probably written in some logs.
Use the PHP hash() function instead, and specify 'sha256' as first parameter.
I've been working with a clients MySQL database which has users passwords stored in plain text. As I mentioned that this is a huge potential risk we talked about hashing the passwords (not that this is a full solution since it's possible to "de-hash" relatively easily these days) and I've come across a question that I think I might know the answer but I want to be 100% sure.
This client developed a couple desktop applications that require the user to insert their user/password, all in plain-text of course.
So, if we hashed the passwords by updating each password field to its MD5 (for example) hash, would modifying the desktop apps to perform this hash on the password received/input and then compare them (and login) work?
Basically, do the login procedure as it's always been but use hashed passwords instead, being this a transparent and unnoticeable operation to the users?
Yes, this will work and should be transparent to the users.
However, it's not very secure. If someone gets a copy of the login database, they'll get the hashed passwords. And since you're sending hashed passwords over the wire, that's all they need to know -- they don't need to unhash it.
It's better to send the plaintext password over the wire, and do the hashing in the server application or database query, e.g.
SELECT *
FROM users
WHERE username = :username AND password = encryption_function(:password)
See Encryption and Compression Functions for the encryption functions available with MySQL.
This way, if someone gets your user database, they'll need to decrypt the passwords for them to be useful to break into your application.
Either way, you should make sure the passwords are transmitted over encrypted connections (e.g. SSL). If someone sniffs the traffic, either mechanism allows them to get whatever they need to login.
Yes that would work, as a given hashing function always gives the same result when presented the same input. The only ability your users would loose is password recovery by looking in the db, but that's not the end of the world.
A note however about
it's possible to "de-hash" relatively easily these days.
Choose your hashing function wisely to mitigate this risk - you can go here for some inspiration (tl;dr consider bcrypt, scrypt and pbkdf2)
A criterion that should influence your choice is the existence of ready to use, trustworthy implementations of the selected algorithm, a quick Google search for the language you're using should point you in the right direction here.
I'm creating a service that will gather user data such as username, name, email, login password. How do I securely store this data? One thing I was thinking is store it encrypted in the DB so that if anyone gets access to the DB they won't be able to use the data.
But that arises two issues - #1 - much much slower search of the DB and #2 the encryption key will still be stored in the Perl script that will encrypt the data submitted by the user so if someone gets access to the whole server they'll still be able to decrypt all data.
So I was wondering what do services such as Twitter, Facebook, Hotmail, etc. use to securely store data?
BTW: as I said I'm working with Perl/MySQL.
Thank you all nice people!
You should try and avoid encrypting everything in the database. At the very least you will have to figure out which fields are being used for searching, relations, sorting etc and leave those unencrypted. You have to consider layers of encryption based on who you are hiding the data from. It would also help if you are clear about the differences between one way hashing (MD5, SHA), symmetric encryption and asymmetric encryption.
Encrypting passwords in the database makes sense because it hides the passwords from the dba or anyone with the ability to query the db directly. Actually, passwords are not encrypted, they are hashed. This way you can never recover a password, you can only generate a new one.
Data that needs to be recovered will be encrypted, so that it can be decrypted. There are various algorithms for doing that and they have different attributes of strength and cost (in terms of processing time and memory). You should choose one which suits your purpose.
The thing here is that encryption and decryption need to be done in the application and not in the database. The reason for this is that at some point there might be an open network between the database and the application servers and any data transmitted between the application and the database could be sniffed.
In deciding between symmetric and asymmetric encryption, there are two factors. One is for how long does this information need to be kept secure. If it is a bid on an auction that is going to end in 2 days, you may use symmetric encryption, because it ideally will not matter if people figure out things after that. Credit card numbers typically do not have to be kept safe. If you are storing the expiry date and the ccv numbers of the card then those have to be kept safe, typically for years. In that case you have to use asymmetric encryption.
In encrypting the whole file system it is not the performance degradation that you have worry about mainly. As far as I have seen, it requires a person to key in the correct password when OS is booting, and that requires physical access, and persons who can be trusted to know the password staying as close to the servers as the SLA requires. In this it is like setting a bios password or a grub password. If you indeed encrypt your file system, make sure to verify this or find a way around it.
Others have pointed out that encryption will incur a slowdown. How much will depend on lots of different factors, so you'll need to benchmark your code.
But in reality the most important thing to protect is probably the password since if that is compromised then the users' accounts on other services could be compromised as well since people tend to reuse the same username/email/password combos.
Fortunately passwords are easy to secure. Use a 1-way hash like SHA1 with a salt (to protect against rainbox tables) and never store the actual password in your DB. Store the salted-hash. Then when the user logs in you can check the pw they give you against the hashed one to make sure it matches without ever having to store what their pw really is.
See my answer here. The gist of it is that you can add security, but there is no 100% foolproof way to avoid a compromise of (some of) your user information if your web application is completely broken.
Encrypting the filesystem on which the database is stored minimizes many other types of vulnerabilities. Encrypting data in the database protects you against those and also against a user breaking your DB password. Encrypting data in the database with a hardware token provides the best protection but is inconvenient.
You have a few options:
You can encrypt the data in the middle tier
You can encrypt the database
You will encounter slower searches either way. In both cases, the encryption key is not included in the backup file set.
I receive data, and use aes or blowfish to encrypt it before saving it to the database, so the encryption is done at the application level. If someone steals the database, the data will be relatively safe unless they stole the application also (where the key is stored/accessed).
I'm now looking into database encryption with libraries like ezNcrypt for MySQL, Encryption-GENERAL, or SQLCipher.
But I don't quite understand how database encryption works. If the application only passes raw unaltered data to the database, and the database decrypts the data itself somehow, wouldn't that make database-level encryption less secure if the database was stolen since 100% of the encryption component was stolen?
In my current situation, if a database is stolen, the attacker would have to steel the second component (the key which is at the application level) to decrypt the database. But with database encryption, the database itself has full responsibility of the encryption, so by stealing the database, wouldn't the attacker have everything needed to decrypt the database?
Maybe I'm not clear on how database-level decryption works.
The encryption algorithm is applied at different points in your application stack, but at the end of the day the process is exactly the same regardless if you use an application or db-layer solution. The key has to be stored somewhere and if an attacker gets both the encrypted data and the key, then they have access to the data.
So, the real question boils down to how you store your key:
Plaintext - if it's in plaintext somewhere in the filesystem then that's your weak point. Maybe it's in the application code, maybe in a config file somewhere. In any case, someone who gains administrator access to the server (or simply steals the hard drive) has what they need, and obscurity is your only protection.
Manually-entered - If you have a human user enter the key when the application/database/pc is started, then you mostly* alleviate the issue of a plaintext key. In exchange, you require a user to remember the key and you give up the ability to have a completely automated restart (bad news for a server that needs to stay up).
* I say mostly because technically the key is still available in plaintext somewhere in RAM. But that's a lot harder to get at than something stored on disk (memory swapping notwithstanding).
Regarding MySQL specifically, you might find this thread helpful.
What method do you use to authenticate your users? If the authentication method is the same in each case then encrypting in the application is not likely to be any more or less secure than in the database. The most likely vector of attack is still the same. It seems much less likely that an intruder would have an opportunity actually to steal the database rather than just gain access to it - unless you are doing something very silly.