I'm wondering how we could hide sensitive data (databases passwords and other passwords) from some developers for our PHP projects. We are using Subversion for our projects. Is it enough to just disallow some users to access the folders where we have the files with the passwords? Any other suggestions?
Do not store sensitive data in any code versioning system. Keep the variables empty.
After first checkout, set the variables locally.
In case of distributed/remote databases, simply create another access for that user to access that database and provide credentials.
Once you set the values, exclude these files from being updated later.
You could have a DB table that stores sensitive data, and only users with right credentials can read from it.
Each developer has to enter username and password to access a DB via some configuration file.
Also you don't need to set user and password for each developer as you can have ie 3 access levels so create just 3 users ie
DeveloperAdmin ( can change password table)
DeveloperTrustedRead (can read password table)
DeveloperNotTrusted ( no access to password table)
So you distribute same db user pass for not trusted dev.
It should be enough.
If you want to implement a cost-effective yet secure way to let different people access the same resource (the password protected one, as a database) with different levels of security, look at this answer Different ways to store a password variable in a Java web application? and implement the option 3 in this way
create multiple usernames/passwords to access the same resource - like another answer suggests a DeveloperTrustedRead, DeveloperNotTrustedRead, etc... role in the database, each with a different username and password. DeveloperNotTrustedRead (for a database) should not create procedure, alter table, drop tables, access other DBs other than the one he operates, etc..
encrypt username/password for each role with a different key in your application (i.e. option 3)
give the untrusted developer the key only to decrypt the username/password linked to the role that has less permissions, like DeveloperNotTrustedRead or DeveloperNotTrustedWrite
This way you can distribute any file in the SVN, as you will be holding the key to decrypt the credentials that matters, while the distributed key will give access to a less powerful/dangerous set of permissions.
This makes sense only if you need them to access the password-protected resource (i.e. a DB) but you are worried to give high privileges to untrusted people, so you want to minimize their permissions for the DB (or any other protected resource) and keep sharing the code easily.
Related
I am preparing a web application that runs only on local network for a small business.
I am using MYSQL and writing the front-end with PHP.
I am not sure on how to best handle users. I have roughly 20 different people accessing the app, and at least 3 different groups with different privileges.
So far I have created users and passwords in MYSQL directly, with a users table that stores personal info (name, last name, email and login info) but NOT the password.
My thought is that this way I can add a layer of security by restricting the users privileges on MYSQL (e.g. avoid that somebody access a page and calls a DELETE query).
I am worried, however, because this approach forces me to keep the password stored at all times (while using the app) in $_SESSION (because I need to connect to DB almost in every page).
Is this approach acceptable?
I wrote a web app in PHP, which is processing some secret data, placed in one database table. All fields in this table (excluding id and date of creation) are encrypted with AES, so nobody who has got access to this database can read it.
I encrypt that data with user password. There's no plain password anywhere in database, just the SHA1 sum, so I can verify it. However, I need plain password to decrypt user data when he's logged in, so I store this value in session.
Is it OK for this purpose? If not, what are the good patterns to deal with this case?
I encrypt that data with user password
If they change their password you then have to re-encrypt everything. Look into something more static for the key.
so I store this value in session.
The session should not store this type of information as anyone else with a website on the box (or any other way to access the box) may be able to read it. If your box uses something similar to suPHP or phpSuExec (ask your host) you could place this data in a directory that only your account can access. You could even store it back in the database (encrypted of course).
what are the good patterns to deal with this case?
If security is important to you, go dedicated. If you're unable to do that then at least be on a server that uses suPHP or phpSuExec or the like so that your web server processes run under a unique user so that any data related to the encryption key can be secured.
so nobody who has got access to this database can read it.
By storing your password in the session, you will have a lot of session files in your /tmp directory (or wherever they are stored...) containing users passwords.
Not only does access to your server invalidate your first statement (when you have access to the server, you have direct access to lots of passwords), but someone with server access - even a valid server admin like yourself - can see passwords he or she should never be able to see.
So no, this is not OK.
A possible solution to your problem would be to use an encryption key for the user information that is stored on a different server so that access to the database / database server alone is not enough. However, this is just a thought, you might get a better answer to that question on for example https://security.stackexchange.com/
As I have been led to believe, the vast majority of web apps use a single database login credential, typically hard-coded into the app code itself or a secured config file. Application logic and sessions take care of managing user interaction with the database; the database remains ignorant of who is doing what.
However, I would like to take advantage of MySQL's current_user() + triggers to perform certain database actions specific to the individual user. This requires that users make database connections with their unique MySQL credentials. Because the PASSWORD() hashed MySQL password cannot be used to make connections, it is required that the app (1) stores the user's MySQL pwd in clear text in a DB table or ACL file, and (2) stores it in clear text in the session, to be used when making connections. That is not ideal.
Is there a better, more secure approach for doing this?
I have a database that contains user details including sensitive data. They're not as sensitive as financial, but they are sensitive nonetheless. The passwords to the accounts are hashed and salted but the rest can only be encrypted not hashed to allow editing.
How far would you go encrypting the fields? Would you go as far as encrypting everything including generic fields like username, first name, last name, or only fields like address and phone. The first name is used frequently after the user logs in.
Can someone suggest an algorithm (with sample code if available) to encrypt the fields? I use PHP and MySQL primarily.
I wouldn't encrypt the fields at all since it's going to be a royal pain in the rear end :-)
I would instead move sensitive data to a separate table and use the security features of the DBMS itself to protect the data while still allowing access to the non-sensitive data.
In other words, have two tables (user and user_sensitive) tied together with a userID column. Let anyone peruse the user table to their hearts content but access (of any sort) to user_sensitive is restricted to admin-type bods).
And, if my DBMS didn't provide such facilities (I do not know whether MySQL does), I would move to a DBMS that did.
If you want a user to have access to their own sensitive data but not that of other users, we once implemented such a scheme in DB2 by providing a stored procedure. It retrieved all the desired rows but also checked to see which user was executing it. For rows that didn't match that user, the sensitive information was blanked out. The underlying table was fully protected from everyone except the stored procedure itself.
In order for that to work, you would have to be able to run the stored procedure under a different user from the one invoking it. Whether that's possible under MySQL, I have no idea.
I'd google for "transculent databases" - there are both printed books on the subject and some on-line resources.
There are variations of this method but basic idea is to:
encrypt only sensitive fields
encrypt with key from data only the user knows of (like login/password pair)
Password ofc must not be clearly saved in any table. Keys should be held only for session. This way the attacker doesn't have the means to decrypt information whether the database and/or the application is compromised (forgetting for a moment possibility of modifying app code and silently gathering keys).
You want to encrypt the database but still be able to access it using the application. This means that the application needs to have a way to decrypt the data. If the attacker has access to the database, it is quite likely that he will gain access to the application and figures out how to decrypt the database.
You could use transparent disk encryption. However, this only guards against physical access to the disk. It does not add much security if your server is stored somewhere safe.
I have an interesting encryption problem at hand. I do not know if it can be solved but here goes:
A database is to contain sensitive user information. As such, the user information must be encrypted (two way encryption). The user has a login / password and these may be used in the two way encryption. Now, the encryption is to be designed in such a way that even the administrator viewing the database tables should not be able to make sense of the user information.
However, the design has to take care of the cases where the user may forget her password. If the password is used for encryption, forgetting the password means the information is lost - not wanted. If the user password itself is stored in the database using a two way algorithm (instead of a one way hash) with a key hardcoded in the script, the administrator can discover the hardcoded key by looking at the script (the administrator of course has access to the script).
Does anybody know a way out of this?
PS: This is a real problem. My company is an absolute security fanatic (ISO 27001 and all) and I have been entrusted to design a system with the above mentioned functionality. By the way, I am using a PHP script and MySQL.
EDIT: Perhaps it was not clear earlier, the user needs to see / edit this user information on a day-to-day basis.
What you want is a recovery agent. Encrypt all data twice: once with the user key, once with the recovery agent (public) key; atleast the latter one needs to be asymmetric. Keep the recovery agent key in a pyhsical safe, with a formal access protocol (e.g. four eyes principle). Usually, the administrator cannot access the encrypted data, but if the user loses the key, and recovery is authorized, then the recovery key is obtained.
There are also ways to encrypt the recovery agent's key so that m-out-of-n people have to agree to use it.
Edit: One implementation strategy is to encrypt everything twice. Alternatively, for each data set that needs to be recoverable independently, create a fresh symmetric key, and encrypt only that key twice; the original data get encrypted only with the session key. That approach can extend to multiple independent readers; it requires asymmetric keys per reader (so that you can encrypt the session key with the public keys of all readers - one being the recovery agent).
I copied the terminology from Microsoft's Encrypting File System, which has that scheme implemented.
Can't be done.
In all cases, someone has to be able to recreate the key to decrypt it. Let's consider the options:
Key stored on server. Fails: administrator has access.
Key encrypted with user's password. Fails: user might forget it.
The solution is to relax the administrator having access restriction, and instead of impossible, you make it just very difficult. For example, if the data were encrypted with a key stored encrypted with the user's password, but that key were escrowed in some other system which can't be accessed in the normal course of events by the administrator (perhaps only another admin has access?) then you can still recover from a user forgetting their password (with intervention of whoever has access to escrowed keys), but the admin can't just download your database and read all the data.