Should sensitive data be encrypted through both script and database means? - php

I don't know too much about encryption, but is there any benefit to encrypting the already encrypted, lets say passwords? I am aware of salts, but before this is done, does it matter or not?

Encryption is 2-way thing, when hashing is 1-way. You can decrypt encrypted sting, while you can't revert hash.
One simple, but good example is using md5 hash + salt: MD5('password' + 'random_string') - no matter PHP or MySQL you use - result is the same. So what you have here - is hash of 'passwordrandom_string', which can be unlikely matched using a dictionaries.
So every time you check the password you do:
if (md5($password . 'random_string') == $hash_from_db)
Updated: but if you really concerned about security (this usually needs to be done only if your application works with very sensitive data), and say more - you have crazy paranoia and insanity about it: there are a lot of hashing methods over the Internet. Find something with random salt (so every password can have almost unlimited amount of hashes), make few changes, combine it with other hashing algorithm - problem solved.
One thing you should know - sometimes the slower hashing works - the better. That means if you somehow have a rat-hole in login-attempts counter this will really slow down bruteforce process.
One example you can take a look on - bcrypt (it uses Java for hashing). Not saying you should use it, just an example of what you should look for.

This question has some relevant discussion on the topic. There are cases in which it would be a bad idea and could potentially weaken the encryption as pointed out in the linked thread, so you wouldn't want to do this unless you're really sure of what you're getting into.
The fundamental basis for encryption is that it's easier to encrypt (polynomial time) than it is to decrypt (non-polynomial time). The only way encryption breaks is if either/both of the following is true:
There's a vulnerability in your encryption scheme which decreases the gap between the polynomial time it take you to encrypt and the non-polynomial time you expect it to take an attacker to decrypt.
Someone has sufficient computational resources to decrypt your data (in non-polynomial time).
It sounds like there are cases where double encryption could actually make issue #1 more probable, so that's dangerous. But issue #2 seems like the bigger one to me. The idea is that an attacker with sufficient computational resources will be able to decrypt my data -- an act which implies that they're willing/able to invest orders of magnitude more computational resources to decrypt my data than I was in encrypting it.
If we accept on fiat that an attacker has the vast computational resources required to decrypt my data, the thought that they could have 2x that many resources doesn't seem unreasonable at all, to me.
And realize also that if you're using the same key, then there's really no added security whatsoever -- once they crack one, they've cracked them both. Potentially there could be value in using two different encryption techniques with two different keys to encrypt something in order to protect against issue #1 popping up for either encryption scheme, but that's surely debatable.

It depends on what you mean by encryption. If you're actually encrypting information on the database using for example Microsoft's SQL Server encryption engine, then yes it does matter. You should not rely on database level encryption as it's not really secure. The key is still stored on the machine and only prevents naive attackers who do not seek out that key along with the database.
Generally, databases also support exporting data in plaintext when the database is encrypted. This means that if an attacker gets into the system, they can just do that. If they only have the hard drives (external drive is stolen), then it saves you.
Passwords should be hashed in your application and then sent to a database, generally. It's considered secure to generate a 64 byte salt and then use SHA-512(salt || password) where || denotes binary concatenation. Don't use randomized ASCII text for salts and stick with secure random number generators such as /dev/urandom or Microsoft's CryptGenRandom. This makes it so attackers cannot store pre-computed lists of hashes for reverse lookups of common passwords.
If you want to prevent the stolen backup drive scenario you need to also make sure you are backing up your database, keeping encryption on, and storing the keys in a secure environment away from the encrypted database. We call this "separating the lock from the key". Since this doesn't help you in the situation where your database is exported, you also want to do hashing as I mentioned earlier. Hashing in addition to encryption will make it so that 1.) Attackers can't get at other less sensitive information such as names and addresses and 2.) Attackers can't even begin to attempt recovery of passwords or other credentials.
The bottom line is that it depends on your threat model.

You do get some benefits from encrypting twice using different keys. For instance, a file encrypted with weaker ciper and subsequently encrypted again with a stronger cipher and key strength will be harder to break than just having the weak cipher alone. The analogy is putting a flimsy lock box inside of a bank's vault. But, in general, you're better of encrypting with a strong cipher than encrypting twice with a weak cipher.
There are also some instances where it is appropriate for something to be encrypted twice, such as when you cross multiple trust barriers. For instance, you might encrypt your files before sending them to a cloud provider (who you may not trust). If the cloud provider needs to send files to another offsite backup company (who the cloud provide may not trust), they might encrypt it again.
That said, for passwords, you are probably better off with using a strong hash (e.g. sha1) alongside a salt for storing passwords.

Yes. It does matter. Storing sensitive data anywhere in plaintext goes beyond bad practice. It's dangerous. Even the standard md5 hash is considered "broken" now, and shouldn't be used on its own without salting it, and perhaps using other hashing combinations in tandem with it. Just to shake things up.
$salt = 'Yh%Gg^!&ud$*';
$encryption = md5(sha1($salt.md5(md5($salt.$_POST['pwd']))));
$query = mysql_query("SELECT * FROM users WHERE name=$uname AND pass=$encryption");
Not exactly the most secure, but if anybody gets their hands on the table information, they won't be able to crack it without knowing the salt and hashing combination.
Ultimately, you need to make an educated decision based on the sensitivity of the data. If you're storing user passwords of any kind, even YOU shouldn't know what they are.

Related

Store Usernames and passwords in encrypted file instead of database

So i know you are going to say this is bad, but i really dont like using a database as it is confusing and hard at the same time. I also think storing usernames and passwords in a file is bad, but both the username and password would be encrypted using md5. I dont think this is secure enough though though because im going to make it public. If you could give me tips on how to make this better please tell me.
Also You will only have two attempts per minute ;)
Here is my idea: https://drive.google.com/file/d/0B19YDO3uT0ClaVZsYjRFRVZkUzA/view?usp=sharing
Also if you could give me examples on how and where to store the file in the webserver? i am not very good with php to be honest
Most databases can be accessed from the open web and you have to store the database password in a PHP file as well. Therefore in most configurations there is no security benefit using a database. It is just a more comfortable handling.
Hashing passwords is always a good idea and should be taken for granted. md5 is not a secure algorithm. Consider usage of password_hash() instead. Don't forget to intersperse a salt string to prevent rainbow table attacs when your hashfile gets stolen.
Any two-way-encryption would make your system insecure at all, because you would have to hold the secrets for decryption into plain text on the server an an attacker could steal everything he needs.
Limiting the login attemps is certainly not a bad idea, however, it is not as essential as you think. The main weak point is to get read access to the hashfile and then process an offline bruteforce, preferably with rainbow tables.
Here's what I would suggest. Don't use md5 because it's insecure and too fast without using iterations.
You really must have an SSL certificate for this to be secure from people seeing the password. Anything without a certificate is roughly equivalent to the user sending a raw text password. You have basically just changed what their password is.
As zaph noted, it's best practice to pin the certificate
On the client
send the password to the web server (encrypted by the certificate for you)
On the web server
Store a salt (a unique random string)
Hash the password using bcrypt or another secure hashing algorithm that also takes the salt
Store the salt and the hashed salted password
You need to use a password hashing algorithm that also takes a salt and iterates such that the hashing takes substantial time such as 100ms. Typically you can use algorithms such as PDKDF2, bcrypt, script or password_hash.
The password must be hashed on the server.
Use HTTPS for communication the password and pin the server certificate in the app, the pinning is important as it will protect against MITM attacks.
A DB may not be necessary, it is an issue of lookup time and disk I/O. You can start with a flat fine and migrate to a DB if/when the performance is needed. "Uncle Bob" Martin delayed using a DB in FitNesse and in the end found a flat-file solution was all that was needed.
Note: Essentially all simple hash methods such as SHA2, SHA3, etc. are to fast and need many iterations to increase the calculation time. The time is important so an attacker can not try hashed quickly. A random (not exactly unique) salt per password is needed to eliminate the use of rainbow tables of pre-calculated hashes.

Encryption of hashed passwords?

I came about this security discussion after reading some topics about session management in php, have a look:
https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence#title.2
Quote from Chapter: To Pepper Or Not To Pepper?
A much better solution, which is especially useful if you employ hardware separation, is to encrypt the hashes before you insert them in your database. With this safeguard in place, even if an attacker finds a way to dump all of your database tables, they first have to decrypt the hashes before they can even begin to crack them. With the PHP and the database on separate hardware, this becomes much more secure.
In this article, the link to https://github.com/defuse/php-encryption is shared...
So far, I only used password_hash() in order to store passwords in a database. Is it recommendable to encrypt the hash itself? What's your opinion?
Thanks for your ideas!
Hashing with an appropriate hash algorithm is usually enough to protect the passwords, but it is indeed more secure to encrypt (not encode) the hashes afterwards.
When you encrypt the hashes with a server-side key, an attacker must gain additional privileges on the server, to get this key (without the key, the hashes are worthless). It is much easier to get readonly access to a database, than to get privileges on a server. Examples are SQL-injection, thrown away backups, discarded servers, ... In all this cases the encryption would protect the hashes.
In this answer you can find more information, or maybe you want to have a look at the end of my tutorial about safely storing passwords.
Is it recommendable to encode the hash itself? What's your opinion?
No, password_hash() / password_verify() is sufficient. People who need spinal-tap grade security can refer to that part of the article for guidance to avoid accidentally shooting themselves in the foot trying to improve their security, but in general if you're using bcrypt in 2016 then you're fine.
Unless you have separate servers for your website and for your database, the security gain by this strategy is zero. If I can get into your database, I can almost certainly get to your file system, and recover the encryption key.
If you do have separate hardware, and you use an authenticated encryption library such as the one provided by Defuse Security, do feel free to use it. Just know that it's not necessary for most use cases, as the password hashing API provides decent security against modern password cracking.
In a later version on PHP, they'll also support Argon2. If you're going to go overboard, switch to that instead of adding complexity to your protocol.
(Also, it's encrypt, not encode.)
there's no need at all to encrypt the hashes. The attacker has to reverse the hash to find the correct plaintext (user password). This is equivalent to find out the right key for the encryption. hashing is enough. plus salt obviously otherwise your schema is susceptible to rainbow table attacks

Making a six digit pin system more secure at the back end

I'm developing a password manager which has two forms of authentication.
First the user logs in using their password. I have this working securely using bcrypt.
The next part is far more tricky. The user's saved services are stored in a JSON format like so:
{
"name":"facebook",
"login":"myemail#email.com",
"signup-email":"myemail#email.com",
"password":"121654754321",
"notes":"my security questions answer is \"blah blah blah\""
}
I plan to store this in a DB table with two fields: id, and data(the AES256 encrypted JSON).
So far my design is using a 6 digit pin with a 32 char salt (unique to each user) to encrypt this. the pin is never stored. the salt is stored in the user table.
What are the possible flaws in doing it this way? Can anyone recommend a better way to implement this?
The risk
Your systems poses a great security challenge, since it acts as a central password repository, thus making it a choice target. Your best defence is ignorance: if you can't decode it, an attacker would have a hard time doing it too. Also, you don't need access to the data stored, but the user (and only the user) does.
What you've done/intend to do is on the right track since you don't have access to the full key. But why do you use a 6-digit pin instead of a "standard" password/phrase? You're responsible for the security of over 80% of the encryption key, and you've got all of them in one single place! An attacker just needs to figure out the (quite weak) pin to add to the salt in order to read the data. Plus, if your system gets compromized, one could manage to retrieve user requests in order to extract the pins and gain access to your user's accounts.
(some) Tips
What could you do then? I'm no expert in security, but I know some tricks. I'll try to answer to the best of my abilities.
Delegate decryption to the end-user
If the decryption key never gets close to your system, the data would be way safer. In order to retrieve a user's passlist, one would need to break into this user's computer and somehow retrieve the decrypted data off the page. That's totally doable, maybe easier than breaking into your server in some case, but this would only grant access to only one account. That's quite good for your other users :D
There's a growing number of applications using this approach to acheive similar results. You often see client-side AES decryption done with JavaScript for instance. The zerobin project describes such a mechanism.
Use strong encryption keys
As said earlier, leaving the user only 6 bytes in the encryption key isn't really robust. They need to be able to add as much entropy they like. Passwords with an upper size limit are often a bad idea (I personally hate those who tell me how short my password has to be).
Have a look at key stretching
(This point is related to the previous)
Key stretching describes an operation taking a standard "human" password and transforms it into a stronger encryption key. It has many applications, and is in use in several password managers of the kind you're building.
RSA's PBKDF2 is a well-known key stretching algorithm used in many security applications.
Side notes
Of course there are several other points you need to address in order to build a secure system:
Obviously, you NEED to enforce SSL (HTTPS) communications between your server and your clients ;
Access to your server needs to be well protected in order to protect the secrets used for encryption. Client-side decryption greatly reduces the threats posed by break-ins, but that doesn't mean they shouldn't be protected. This implies fine tuned firewalls, up-to-date applications, reactivity to security fixes, etc. ;
You need to teach a thing or two to your users about security. It's well known that both ends of a channel have to be secured in order for the channel itself to be secure too.
There are probably many other concerns, but hey, this isn't a lecture on security ;-)
The pin is known and inserted only by the user? Instead of using the 6 digits pin + salt for encrypting the data you can use PBKDF2 (Password-Based Key Derivation Function) to generate a secure encryption key based on that 6 digits pin (and the salt). This way each user will have a different (and secure) encryption key. Mind that along with this you should always use a different and cryptographically secure generated IV that can be appended (or prepended) to the encrypted data.
The security flaws of your implementation are that there is the possibility of not having enough entropy generated by your pin + salt and since you didn't talk about an IV I suppose you are not using one thus exposing possible patterns in your encrypted data.
For the security flaws my implementation has instead, depends on what are your security objectives. For most people PBKDF2 (+ one of the hash_algos() algorithm as per the PHP implementation) is secure enough, even if it is more exposed to attacks using FPGA or GPU clusters. If you want to avoid them, you can use bcrypt to generate a key that is harder to attack using these technologies.
I recommend you to read this answer that gives more in-depth reasons on why bcrypt is somewhat better than PBKDF2

the best way to handle user's database name and passwords [duplicate]

I'm using Mysql and I was assuming it was better to separate out a users personal information and their login and password into two different tables and then just reference them between the two.
Note : To clarify my post, I understand the techniques of securing the password (hash, salt, etc). I just know that if I'm following practices from other parts of my life (investing, data backup, even personal storage) that in the worst case scenario (comprised table or fire) that having information split among tables provides the potential to protect your additional data.
Don't store passwords. If it's ever sitting on a disk, it can be stolen. Instead, store password hashes. Use the right hashing algorithm, like bcrypt (which includes a salt).
EDIT: The OP has responded that he understands the above issue.
There's no need to store the password in a physically different table from the login. If one database table is compromised, it's not a large leap to access another table in that same database.
If you're sufficiently concerned about security and security-in-depth, you might consider storing the user credentials in a completely separate data store from your domain data. One approach, commonly done, is to store credentials in an LDAP directory server. This might also help with any single-sign-on work you do later.
The passwords should be stored as a cryptographic hash, which is a non-reversible operation that prevents reading the plain text. When authenticating users, the password input is subjected to the same hashing process and the hashes compared.
Avoid the use of a fast and cheap hash such as MD5 or SHA1; the objective is to make it expensive for an attacker to compute rainbow tables (based on hash collisions); a fast hash counteracts this. Use of an expensive hash is not a problem for authentication scenarios, since it will have no effect on a single run of the hash.
In addition to hashing, salt the hash with a randomly generated value; a nonce, which is then stored in the database and concatenated with the data prior to hashing. This increases the number of possible combinations which have to be generated when computing collisions, and thus increases the overall time complexity of generating rainbow tables.
Your password hash column can be a fixed length; your cryptographic hash should output values which can be encoded into a fixed length, which will be the same for all hashes.
Wherever possible, avoid rolling your own password authentication mechanism; use an existing solution, such as bcrypt.
An excellent explanation of how to handle passwords, and what you need to concern yourself with, can be found at http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes.
As a final note, please remember that if an attacker obtains access to your database, then your immediate concern should probably be with any sensitive or personally-identifying information they may have access to, and any damage they may have done.
There's nothing wrong with putting them in the same table. In fact, it would be much faster, so I'd highly recommend it. I don't know why you'd want to split it up.
I'll attempt to answer your original question. Having it all in one table is fine unless you just have a lot of personal information to gather. In that case it may make sense to split it up. That decision should be made based on the amount of personal information you're dealing with and how often it needs to be accessed.
I'd say most of the time I'd do something like this in a single table:
UserID, FirstName, LastName, Email, Password, TempPassword
But... if you're gathering much more than that. Say you're gathering phone, fax, birth date, biography, etc, etc. And if most of that information is rarely accessed then I'd probably put that in its own table and connect it with a one-to-one relationship. After all, the fewer columns you have on a table, the faster your queries against that table will be. And sometimes it makes sense to simplify the tables that are most accessed. There is a performance hit with the JOIN though whenever you do need to access that personal information, so that's something you'll have to consider.
EDIT -- You know what, I just thought of something. If you create an index on the username or email field (whichever you prefer), it'll almost completely eliminate the performance drawback of creating so many columns in a user table. I say that because whenever you login the WHERE clause will actually be extremely quick to find the username if it has an index and it won't matter if you have 100 columns in that table. So I've changed my opinion. I'd put it all in one table. ;)
In either case, since security seems to be a popular topic, the password should be a hash value. I'd suggest SHA1 (or SHA256 if you're really concerned about it). TempPassword should also use a hash and it's only there for the forgot password functionality. Obviously with a hash you can't decrypt and send the user their original password. So instead you generate a temporary password they can login with, and then force them to change their password again after login.
Will all of this data always have a 1:1 relationship with the user? If you can forsee allowing users to have multiple addresses, phone numbers, etc, then you may want to break out the personal info into a separate table.
First, to state the (hopefully) obvious, if you can in any way at all avoid storing usernames and passwords do so; it's a big responsibility and if your credential store is breached it may provide access to many other places for the same users (due to password sharing).
If you must store credentials:
Don't store a reversible form; store a hash using a recognized algorithm like SHA-256. Use cryptographic software from a reputable trustworthy source - DO NOT ATTEMPT TO ROLL YOUR OWN, YOU WILL LIKELY GET IT WRONG.
For each credential set, store a salt along with the hashed data; this is used to "prime" the hash such that two identical passwords do not produce the same hash - since that gives away that the passwords are the same.
Use a secure random generator. Weak randomness is the number one cause of encryption related security failures, not cipher algorithms.
If you must store reversible credentials:
Choose a good encryption algorithm - AES-256, 3DES (dated), or a public key cipher. Use cryptographic software from a reputable trustworthy source - DO NOT ATTEMPT TO ROLL YOUR OWN, YOU WILL LIKELY GET IT WRONG.
For each credential set, store a salt (unencrypted) along with the encrypted data; this is used to "prime" the encryption cipher such that two identical passwords do not produce the same cipher text - since that gives away that the passwords are the same.
Use a secure random generator. Weak randomness is the number one cause of encryption related security failures, not cipher algorithms.
Store the encryption/decryption key(s) separately from your database, in an O/S secured file, accessible only to your applications runtime profile. That way, if your DB is breached (e.g. through SQL injection) your key is not automatically vulnerable, since that would require access to to the HDD in general. If your O/S supports file encryption tied to a profile, use it - it can only help and it's generally transparent (e.g. NTFS encryption).
If practical, store the keys themselves encrypted with a primary password. This usually means your app. will need that password keyed in at startup - it does no good to supply it in a parameter from a script since if your HDD is breached you must assume that both the key file and the script can be viewed.
If the username is not necessary to locate the account record encrypt both the username and password.
In my personal experience, storing the personal information and the login information in individual databases is the best practice in this case. The reason being should an SQL injection take place, it is limited (unless the infiltrator knows the inner layout of your database(s)) to the table that the data pertains to, as opposed to providing access to the whole conglomerate of data.
However, do note that this may come at the expense of needing to perform more queries, hence a performance hit.
You ought to store them in the same table, and use one-way encryption. MD5 will work, but is weak, so you might consider something like SHA1 or another method. There's no benefit to storing the 2 items in seperate tables.

What are the best practices to encrypt passwords stored in MySql using PhP?

I am seeking advice on how to securely store passwords in MySQL using PHP.
Overlooking the limitations of PHP itself, I want to know more about salting, hashing, and encrypting these bad boys.
Obviously people will continue to use weak passwords unless forced to do otherwise, but it's how I am storing them that is important to me. My user's passwords are far more important to me than the database itself, and as such I want to keep them in such a way that it will be painstaking and monotonous for any script kiddie trying reverse. Obviously with due diligence just about anything can be defeated, but I wouldn't mind making this particularly bothersome.
There are two scenarios we are looking at.
The kiddie has a complete copy of the database.
The kiddie has a complete copy of the PHP used to craft the password, and the database.
Any and all advice on this topic is graciously appreciated.
Use bcrypt. If someone has the user table of your database, then they can use brute force/rainbow tables/etc to their heart's content. Even with salt, if you're using MD5 or some other fast-hashing algorithm (which aren't designed to solve this problem, by the way); it's just a matter of time before it can be cracked.
Any well-known and widely-supported hashing algorithm is going to have this same basic "flaw" (if you can call it that; it's really by definition). The difference is that bcrypt is slow as molasses when performing the hashing operation, rendering a brute force attack much less effective.
For an absolutely great discussion on the merits of bcrypt, the dangers of other approaches, and the difficulty of password security in general, read this thread. It has lots of comments by many people that are much more knowledgeable about this sort of thing than I am, and it should hopefully help you understand more of the issues at stake.
Assuming you're using username and password as authentication tokens you can safely store the following to ensure the data can't be compromised.
Username (in plaintext)
Salt (random string)
Salted Hash (sha1(username + salt + password))
Using the scheme, an attacker cannot use rainbow tables against you and the passwords are not recoverable by any (reasonable) means. (That is, as long as your attacker isn't the government)
Even though the attacker has the salt and hash pairs it's not possible to use rainbow tables because all the possible hashes will need to be computed anyway, using the salt that they've been given, so it's a brand new brute force attack for each user.
Even with the source code and attacker won't be able to get hold of the passwords because the strength/security is in the hashing algorithm, not your code.
Combine this with using bcrypt as per Donut's answer and you're really quite safe. That is:
Username (in plaintext)
Salt (random string)
Salted Hash (bcrypt(username + salt + password))
Taking advice from here, for added fun you can dynamically change your salt as well. For example, use different salts for usernames of different length, use the user's registration date as the salt. This makes it that even if someone DOES get to your database, they can't just re-generate the hash, they have to calculate a hash table for each salt that you used.
If your users are over the internet, OpenId would be one of your best options. http://openid.net/
If your users are on your network, can you do Integrated Security?
In other words.. do not store their passwords.
Usually "salted" passwords (like with bcrypt) mean that not the password itself is stored, but only something like
salt
hash(salt with password appended)
Now if the kiddie has your database (and of course, the code - there is no point in keeping the code secret), he/she can only guess passwords, calculate the salted hash, and compare. If the hash function is expensive (like bcrypt is), than guessing is expensive too.
It's simple
store(sha256("somesalt" + password));
And nobody will be able to reverse it :)
See also: https://stackoverflow.com/questions/3897434/password-security-sha1-sha256-or-sha512

Categories