I'm working on a CMDB like application, where I have to store our security credentials (servers usernames & passwords, ...).
I'm looking for the best way to store them securely with those constraints :
Most users will NOT have access to all credentials (depending on user role)
We don't want all passwords being encrypted with the same key (already tried : when a user leave the company, it's a pain to change the key...)
Indeed, we don't want any private key to be hard written in app source, or even stored anywhere (in our previous version, private key was stored between our ears...)
We need to realize passwords strength audits (ie. parse decrypted passwords from a script)
There must not be any case where we can not access our credentials anymore (lost key, ...) => we don't want unauthorized persons to look at them but we don't want to loose them either => solution for this constraint could be regular export into a physical locker...
I'm not asking about application (https, ...) or database (no public access, ...) security concerns themselves but only about the storage side (could even NOT be in a database...? encrypted files or something...) : Is it possible to prevent someone, even having access to app code or database content (worst case scenario), to be able to read decrypted credentials ?
I'm aware that I'm asking for some magic solution, but I want to know it if it exists ;o)
The general case of what you're asking to do is not possible. All types of modern cryptography are mechanical advantage. That is, they use a small secret to guard a larger secret. If you can't keep the small secret safe, there is no safety. If you want the ability to give passwords on a password by password basis to someone, you are effectively giving them the secret -- the passwords -- that they would need to gain access to the items in question.
This very problem is why federated identity systems (Kerberos/Active Directory/etc.) systems exist -- to allow a central machine to authenticate users without exposing secrets to said users. But using a federated identity system requires cooperation between the system-to-be-logged-in-to and the identity service.
Related
I have a Web base System and I'm using Xampp on it, my database has a password and I'm accessing it through phpMyAdmin.
I have some people working on the same machine where the Web base System is running, we're using the System for specific task.
One thing I'm afraid of is if they can get or find out the password of database (these not include overriding or resetting the password).
Since they are physically accessing the Server, is is possible to get or lets say decrypt the current password? if so, what are the possible ways?
I want to be aware of it and I want to improve the security of the System base on the method that they can do.
There are several layers of security here.
I believe the correct answer to your question is "no, this isn't a risk," but a thorough answer will address all the possible means of exposure.
System accounts
Your operating system has user accounts. This is how you, other users, and various system services (such as the MySQL server itself) authenticate to the operating system. It's a good practice to not share user accounts. These passwords are stored in a salted and hashed form on the server and are not recoverable or reversible (at least, for the purposes of this discussion). There is essentially little danger in this information being compromised by other users on the machine.
MySQL user accounts
MySQL has individual user accounts. These are how individual MySQL users authenticate to the database server and generally should not be shared between users, applications, or services. Like system accounts, these passwords are stored in a hashed form that makes it relatively secure so that there is again little danger in other users looking at the hashed password.
Application passwords
This is the difficult one. Many applications create a user table within the application database in MySQL. This can be incredibly simple; such as a username and plain text password, or can be quite elaborate and secure. Applications such as WordPress, Joomla, phpBB, and virtually everything else implement their own application-level password methods. This may be properly hashed and secure, or it may be plain-text. Without knowing the details of the application, we can't say with certainty. You can get some hint by looking at the password field in the database itself, but this doesn't make it immediately obvious if the password is salted, or hashed with a weak algorithm. Therefore, this is a possible attack vector with which you should probably be concerned.
Another interesting aspect here is network sniffing; an attacker could sniff network traffic to determine a user's MySQL password. A simple workaround is to enforce only SSL-encrypted communications for the users to connect to the MySQL server, and/or only use the socket connection method.
I think that covers on a relatively high level all the possible attack vectors here. I've taken some liberties for the sake of simplifying things; for instance there are some older operating systems that use weakened hashing methods which mean mean those hashes aren't cryptographically secure, and any user with access can probably escalate their privileges (for instance, a user with physical access to the server can restart with another bootable drive, reset the root system password, install whatever keylogger they wish, and restore things. Similar warnings would apply to a user without physical access but with administrative privileges. Depending on your attack vector, these aspects may or may not be of concern to you.
Sure it is possible....
All I would need to do is open up the phpMyAdmin configuration file and have a look at the database access information as it is unencrypted there. Basically any configuration setting which is itself not encrypted will be a security issue.
(Once I have DB access which will probably be System Admin (sa) access I could reverse engineer the users and passwords in the system given enough time as I would have access to the salt in the DB as well)
Other scenarios (I don't know your exact setup) would be:
Checking logs
Sniffing network traffic for any unsecure DB access. Say you aren't using TLS for instance
As I also have physical access to the machine I could also crack the OS users and passwords or even add one for my own use for later on
Short answer is that when people have access to the physical machine your attack surface goes up exponentially.
If you are worried about the system (OS) passwords, they are all hashed with the salt method. Read full here which takes too long to decrypt.
https://en.wikipedia.org/wiki/Salt_(cryptography)
But if it's related to phpMyAdmin, that is totally related how you store user's passwords. You might need to store the hash of the passwords, although the phpMyAdmin admins can override their own hashes and access to user's data.
I wanted to kow if it is save to store my hashed password inside a table, that resides next to the rest of my other data(tables) in the same database?
For example imagine the following (simplified) structure (with a lot of other data-tables):
authentication user
-------------- -----------
auth_id {PK} user_id {PK}
username realname
passwordhash auth_id {FK}
Is it safe to store a users authentication/password like this, or should it be stored differntly, maybe in an extra database or such?
I suggest reviewing this article by Sophos, as it really nicely describes the rationale and the secure design.
Article argues to have a separate password server, so that no one role can have access to the passwords.
Many enterprise systems compartmentize passwords away from other credentials.
It all depends.
In general, if an attacker can read one database, it's likely they can read another, so if your application would simply open a SQL connection to the other database, you'll get no significant benefit.
Also, if they can access your database, they can probably read the traffic to and from the database, including username/password combinations.
So, I would suggest storing the authentication data in a separate database alone isn't a huge improvement in security; you'd be better off spending your time and energy on other security matters such as key management (you are salting your hashes, right?).
However...if you can set up physically separate infrastructure, and expose the authentication features as a service to the front end, using e.g. OAuth, you would create a significant barrier to the attacker. They would have to compromise this alternative database, and as the integration would be at the front end, they can't rely on sniffing traffic to your database.
The first & accepted answer on this question about passwords management suggests to encrypt the user identifiers in DB.
The good point is that if anyone gets a password, he has to know how to decrypt the user login to get the full login/password pair.
Some disadvantages I see, for example:
you have to decrypt user logins every time you want to display them
if you want to do a 'begins with' search on user login to find users, you cannot simply use LIKE '...%'
ORDER BY on login field may be quite difficult too...
What would you recommend (encrypt user identifiers or not)?
As usual, the answer is "it depends".
In general, I'd say that if an attacker has access to your database, your security situation is so badly compromised that encrypting the passwords will likely do you no favours. This is different to using a one-way hash - it's likely that an attacker who has access to your database also has access to your decryption key, whereas one-way hashes, by definition, are one way.
As you already say, it's likely that you will need regular access to the userIDs (esp. if you use email addresses as user IDs); in that case, again, an attacker who can read your database likely can intercept the unencrypted data.
So, if you work for a bank, the government, or any other place where data security has to be at the very top of the list, this additional protection may just be worth it, especially if you have a strong key management system.
For other uses, I'd consider the additional security too small to merit the additional pain.
Encryption is considered to be a lesser form of secret storage than message digest functions. In fact, storing an encrypted password is a clear violation of CWE-257.
But why not hash the username? When the login the application will have the plain text. Depending on your application, you might not need to display a list of users. this would be an added layer of security, as both hashes have to be broken before the attacker can login.
That being said, if you have a plain text list of every username it will be trivial to perform a dictionary attack against any recovered hash. Further more user names are not created to be difficult to guess, often times users choose goofy names of birds or silly games like chess so that they are easy to remember.
I have a web service using HMAC to verify signed requests. In this scenario there is a key (password) assigned to each caller of my service. The user of course gets that key, but I also need to store the key in my database so that my service can verify the signature of each request coming in.
So this is a case where I really do need to store passwords in the database in a form that I can retrieve and use them. I can't use the best practice of only storing a salted hash of the password in the database.
I could encrypt the keys but then I need to store the encryption key somewhere. This is a fairly common scenario for secured RESTful web services, so the likes of Amazon (AWS) and Microsoft (Azure) have to deal with this problem.
What are best practices in this situation?
The only time password should be stored in a database is if the password is needed to connect to some other system. If one merely needs to check the credentials supplied by some other entity, one should store a hash of the password.
Even if it's necessary to use a password to connect with another party, if some other credentials are needed for you to perform such access (e.g. someone logs into your system, and then you log into another system on their behalf) it's desirable when practical to store the external password encrypted with a hash of the supplied password (but NOT the same hash as the one stored in the database!). If there are multiple credentials which could be used to log into your server, store a separate copy of the encryption key for the remote password, encrypted using each acceptable credential.
If you really need the password (in order to connect to another system, for example), I would recommend putting in somewhere far away from the other information. Perhaps another database, an encrypted file on the file system, etc. This is so if someone gets your main database, they are not guaranteed to also get the passwords in question.
It may be obvious but you want the location of the passwords to be encrypted with another key (to make it less likely that someone who somehow gained access to the primary data source will also gain access to the password data store).
It sounds like the best practice for your scenario would be to use public key cryptography.
I've heard quite a few reasons for storing hashed passwords in a database. However, there are almost always options in authentications APIs to store passwords as plain text or encrypted.
Is there ever a reason you would want to store a password as plain text or encrypted in a database?
Note To be clear I know that storing non-hashed passwords are almost always bad.(as far as I know anyway) My question is why do most authentication APIs include options to store passwords as encrypted or plain text.
The only real reason I can think of is when the database belongs to a system that is itself targetting the real application. Like when you have programs that log into something for you (email clients, instant messaging clients etc.). All those have to store the password in a recoverable way to get access, because the target application won't decide between real user and user via a tool. Exactly at this point OAuth and alikes however are made to save the user's password.
One reason I can think of is to allow a password recovery option. There's no way to recover a password that the system doesn't know.
Of course the alternative is for the system to just reset the password to something new and send you the new password.
Maybe you're a hacker, and want to use or sell them?
Even if you are quite certain of the security of your database, your users' passwords are still accessible to all administrators.
It is vitally important to understand that password encryption will not protect your website, it can protect your passwords only.
If your website does not have sufficient protection, password encryption will not make it safe from cracking. If your system has been cracked, a hacker can inflict a irreparable damage to it and also gain an access to confidential information, including passwords database. But if you store this information encrypted, hackers practically cannot make use of it. Cracking an encrypted password takes a large amount of time and processing power, even on today's computers.
1) Most of Challenge-Response authentication protocols require server to know plaintext password. There are exceptions, but they are unpopular and hard to implement.
2) Storing passwords allow password recovery.
I have encountered the following argument a few times:
Storing plaintext passwords allows you to detect when a user changes their password to something close to an old password i.e. by incrementing a number, adding a '1', or by some other low-conditional-entropy updating method.
No one should take that argument as a good reason for storing plaintext passwords - it is misguided for several reasons.
Of course, you could store all passwords as plain text in your storage (e.g. database). But it's not recommended. If someone manages to hack your server and gets your data from the database he also got every password. Even just storing a password hashed with common methods like md5 is not quite save in this case. Because there are rainbow-tables (search google for this), to lookup passwords.
So I recommend to store salted passwords. I don't know why you ever would store your passwords as plain text. I wouldn't do it :)
The only 'good' reason I can think of is that the customer paying you to develop the app or your manager insists on it. I cant think of any technical reasons for it.
One reason could be to auto-reuse the password for another, external service.
If i configure my gmail account to retrieve my e-mail from other non-google e-mail provider i have to give google my password and google has to have this password in clear to get my mails into my gmail account.
That is obviously not the same password as for the primary service, but it is "of type password" anyway.