After researching some hours about the topic of securing stored data I am a little bit confused of what is the best way to go now.
I have a databank for my (SSL) website where I am the only one that has access to it (hackers not counted). The login data is stored in a configuration file outside of the document root. In the database I have stuff like names and adresses from my clients and I am now worried that I need to implement all the security measures put forward by cryptography experts like in this answer (How do you Encrypt and Decrypt a PHP String?) or as asked here (Storing sensitive data securely in a database).
Since neither in my PDO/SQL and PHP seminars nor in regular posts here on stackoverflow I see these encryption and authentication methods being used or more specifically e.g. the keys when explaining PDO and PHP commands like INSERT INTO ... etc. I am unsure if it is now necessary to deploy encryption and authentication measures on every entry in my databank (is it even possible to do this afterwards?). The safety measures I have been informed about in the tutorials and articles are to use PDO's prepared statements.
If encryption and authentication is what I have to do, which is probably the case: Would it not be the most convenient and fastest way to simply use password_verify() and password_hash() for every sensitive data entry like it is done for passwords?
EDIT password_verify() and password_hash() are hashing (not encryption) methods, meaning that the data is irretrievably mangled and can only be confirmed but not read.
There are different types of database encryption, and depending on what data you want to protect, and why, you will do different things.
1) Database level encryption / Transparent data encryption
This is where your RDBMS encrypts everything for you at a file level. This means if anyone has access to the hard drive, or back-up media, they should not be able to access the data. See here for how to do it with MySQL: https://dev.mysql.com/doc/refman/5.7/en/innodb-tablespace-encryption.html (note this is not a PCI compiant solution, you'll need MySQL Enterprise Edition or another Enterprise database, or further security measures for that).
Note this does not protect your data if your application is compromised.
2) Field level encryption
You can encrypt data to be stored in any field you like. Here's a good answer that deals with that: https://stackoverflow.com/a/10945097/
The drawback of field level encryption is that you can't then query across the data. In each case you'll need to pull the data into your application, and then decrypt it one field at a time.
Note this does not protect your data if your application is compromised.
Note also the difference between 'encryption' and 'hashing' (password_verify and password_hash are about hashing)...encryption lets you secure data, store it and retrieve it. Hashing by definition does not let you retrieve the data.
In all cases the most important thing is to secure your application. Encryption of the underlying data is very much a secondary concern.
Since your web server (presumably) will have to have access to the data, it's somewhat useless to encrypt it at rest when the web server can (will have to be able to) decrypt it. Why? Because the web server is often the weak link. If an attacker can get access to it, they can do anything it can do, including decrypting the data.
Encrypting data at rest is only useful to prevent backchannel leaks, like improperly handled backups (which you're doing, right, right?) which dump the data in plaintext to a file which then inadvertently gets lost somewhere. To prevent that you should use whatever at-rest encryption your database offers transparent to the client; i.e. it's not something you should burden the application logic with if it's not integral to your application, it's something the database should worry about.
password_hash is a hash, it doesn't encrypt data, it irretrievably mangles it so it's impossible to get the original back from it. It's great for storing credentials which you need to confirm but not read; it's useless for anything else.
The main security points are to isolate your database server "physically", i.e. to not grant any access to it from anything but the web server; be very restrictive and specific about that. That then means the weak spots are at those ingress points like your web server. Ensure your web server is locked down as much as possible, exposes as little attack surface as possible (no unnecessary open ports or running services) and that your application code running on it doesn't allow any exploits (yes, that's the hard part that takes knowledge and discipline).
You can further tighten it down by segregating access to the database with different accounts which have different permission levels; i.e. some accounts only have read access to certain tables while others have read/write access to other tables. If you can split up your web server(s) into separate roles which all only need specific limited access, this further enhances security by avoiding vulnerabilities in one part enabling exploits in another.
Related
I'm creating a server(PHP) to store data from android app. With POST query store name, password and email. These data as mentioned are stored on the server (database on hosting).
But I have a lot of questions how to do it correctly:
First is the backend, how to protect data and how to encrypt them?
I know that you can transfer token of android application on the web (server). And there it checked for accuracy, but android application is easy to decompile. How to be in this case?
Also heard of RSA but examples show how the mechanism works. And when used in RSA, I have the private key stored on the server and the public in android application? But what if I we obtain encrypted data from the server on android? I need to decrypt them using the private key. But the key on the server and store the private key on Android ill (paragraph 2, decompiling).
Other...
Please leave comments. Also describe every paragraph of my question, and it is desirable for each paragraph post a link with useful information. Also, I would appreciate any HELPFUL links related to this topic, well, especially your opinion and how best to do it.
I assume that you are trying to create a basic register/login-to-use-this-app mechanism.
Read the PHP FAQ article on password saving on why and how for secure data saving server-side. Basically, to hash (to irreversibly encrypt) sensitive data before directly saving them.
Regarding your second question,
Generally, it is not a big concern on directly transmitting sensitive data between client and server, because there can be these security measures:
Use HTTPS. This will encrypt the stream of data transmission, and it is less vulnerable to the connection being eavesdropped.
You may want to directly send the hash of the password instead of the password itself in the post request, or in other words, use the hash of the user password as the password.
Client frontend
In terms of internal storage, it is not possible to prevent other installed malicious apps from reading and using data you store, unless you (I am not familiar with this) store them in a storage that is only accessible by your own app.
Server backend
There are some servers that distribute OAuth tokens to clients, such as GitHub. However, if you only expect the server login API to be used by your own apps, OAuth isn't necessary in this case, since it is mainly used as a flexible permission bearer which you don't need to concern for your own app.
Instead, the more important thing is how you handle things server-side. For the web API that I once coded for my own server, although I don't expect others to use it, I made the API designed as if it is for the public to use, and pay attention to unexpected client input. This is because clients can be fake anytime, so never trust the integrity of what clients input. (Forgive my obsession, but I even considered backend of my JavaScript on webpages as "clients" to be safe)
I have never used nor have any comprehensive knowledge on other PHP frameworks, but when I work on my website, I would create a safety layer within my own backend code. I separate my backend into two levels, namely the database level and the interface level. The database level should try not let the interface level even get the data that are not supposed to be known by (the current authentication state of) the client, so as to minimize the chance of security vulnerability.
Client-server communication
So this only leaves the problem of data transmission, which is the main point of this question.
As mentioned above, HTTPS would be good enough to encrypt data transmission.
I do not know if this concept is practical, but after initial registration, it might be, if you are obsessive enough, possible to encrypt the data with a timestamp, etc. I am not quite sure about this, but disconnected tokens inspired me on this.
But how much protection you need still depends on what kind of data you are sending. For example, if you are simply tracking user usage, you don't really need a lot of protection for it. Just make sure that the user's original password cannot be leaked by hashing it.
I am working on a fleet management system in PHP. My location tracking is GPS (SMS based): I receive an SMS that contains coordinates (Lat,Lng).
What I want is to encrypt those coordinates. When it comes to database it should be encrypted and when my web application wants it it should convert (decrypt) to its original form. I want to protect the coordinates from illegal access.
Now, how and where should I do encryption and decryption of that data? I need your opinions - I searched a lot but didn't get success.
There may be no point in encrypting these coordinates - anyone who has access to your database e.g. a database administrator will probably also have access to the decryption key on the web server (assuming you are thinking of using symmetric encryption). Thus, you should work out what kind of threat you are trying to protect against, and then see if your approach would do that.
If you are worried about hackers, the same rules apply as a rogue employee: a hacker who can steal a copy of your database may well be able to steal files off the web server.
If your location data does not need to be decrypted often, or if someone must enter a password to see it, that might be more achievable. You can encrypt the coordinates with a public key, and then only decrypt them with a password-protected private key. An attacker who gets hold of the public key will not be able to use it to decrypt.
It's worth considering also whether this data is so valuable and private that it is worth encrypting at all: you could invest the money you would spend on this project on a third-party security audit of your code instead.
Finally, if this data is regarded as private for data protection reasons, consider fuzzing the data (i.e. introducing small levels of random inaccuracy) rather than encrypting it. This is only an option if you don't need exact coordinates of your vehicles. This is a data protection technique used anonymise data in health trials, where exact location data creates a privacy risk. Of course exact location data is useful for vehicle tracking in the event of theft, so you need to decide what your priorities are here.
Further reading: you might be interested in a book called Translucent Databases, which considers encryption, hashing and fuzzing in the context of building data-protected database systems. It's a very thought-provoking read.
The suggestion that I would give is to get a HSM (Hardware Security Module) - something like YubiHSM and install it on a single server. Build an API around it to encrypt and decrypt the data.
Then, there are no keys to steal. For an attacker to decrypt the data, they would need to steal that HSM. The data is useless without the physical chip (which can't be copied).
For full security they should be encrypted befor they are send via SMS. That way nobody could try to get the SMS and read the cords in it. Second to that you could check if the encrption is done right to ensure that the data you get via SMS are valide. All of this could be done with encryption keys. But those need to be know to the sender and the resiver.
It's possible to encrypt when the data is stored in the DB aswell. But with that all the way to the DB is unsecure and could be used for attacks.
My bigest consurne would be that either someone catches the SMS that's not suposed to read it or even wore that someone sends a corrupted SMS with false data or an injection.
You can use mcrypt_encrypt function before entering coordinates in DB and use mcrypt_decrypt to decrypt them after retrieving from DB.
I'm using Zend Framework with a LAMP stack. The client has requested protection of sensitive data, email included. In this project, emails will be used in two ways: for sending automated messages and for sending newsletters.
Has anyone worked with this? What algorithms are fast, reliable and can be used with a variable encryption key? Where should I store the encryption key? What engine should the database table use?
Ok, these are my 2cent.
For data that needs to be both encrypted and decrypted on the fly, I would suggest symmetric key algorithms, and the first that comes to mind is Blowfish. It is both fast, and relatively safe.
As to the variable keys. Usually there is little to no merit in having a different key for each entry that needs to be both encrypted and decrypted. Thus, I'd recommend using a single key, that is set in config file somewhere.
If you do need to have a key for each of the users/records, I'd recommend not keeping them in the db. Save them to flat-files on the disk.
As to table engine, it should not matter which one you choose, as long as it's not memory based.
As to merit - I think there is merit, if the client specifically asks for it. Even if there is technically little reason to create this encryption, this will contribute to the clients feeling of safety. Sure, it could be a false one, but it does help keep the data a bit more safe, and lets the client sleep more soundly. Therefore, if the client asks for it, go for it!
If you really have to do this, the answer Janis Peisenieks gives is a good starting point.
As far as I know, there's no safe way of storing keys in PHP - this means that an attacker who gets a moderate level of control over your system can retrieve the key from a config file, and use that to decrypt the data.
An attacker who wanted to know the email addresses of your users would have several options to retrieve that data - as GordonM writes, if your system sends email to those users, that email is relatively easily to intercept, and whilst the body may be encrypted, to "to address" is not.
Just checking that you will be hashing (not encrypting) passwords (if your system uses these?)
How should 'sensitive' data be stored in MySQL Database?
1) Should I focus more on the security of the MySQL database and store the data as plain text?
I found a step by step tutorial on how to make a MySQL database more secure:
http://www.symantec.com/connect/articles/securing-mysql-step-step
2) Should I encrypt the data?
If yes, then how should the encryption be done?
Using MySQL aes_encrypt/aes_decrypt?
Using PHP AES functions/algorithm for encrypting/decrypting data?
How should the data be stored in MySQL?
BLOB
BINARY
VARBINARY
In my case the 'sensitive' data are payments done by individuals.
Thanks
It's a mixture of both. Two existing answers (at the time I wrote this https://stackoverflow.com/a/10718397/1015483 and https://stackoverflow.com/a/10718459/1015483) are valid - you need to look at about 5 methods of possible attack that I can think of
They get access to your DB server; so yes, secure that baby as much as is reasonable (Matt's answer)
Stand alone data hijacking (someone gets to your database data somehow else, could be a backup, could be they guess a password, could be MITM if you transfer data from one place to another). For this, you do encypt your data. You also may do a CSV dump for some reason and e-mail to someone. Whoops. But it happens. So encrypt (vlzvt's answer)
But three elements not mentioned:
They could gain access to your web server (if different from your DB server). If they have access to the webserver, all bets are off as they have your password, encyption keys the lot. So you need to make that even more secure than the DB server. (Matt might have meant that above - but just make it clear)
Similar to above, but not to be forgotten, is if someone gets access to phpMyAdmin or your management consule. Don't use plain text auth or config stored passwords for access.
Finally there's your application itself (and the hardest to lock down). You need to prevent against SQL injections that may reveal data. Encrypting the data would stop minimise problems if someone did gain access through an untrapped query - so for this, encryption is the solution.
For part 2 of your question:
Using MySQL encrypt/decrypt functions will stop someone who has access to the raw data, but not MITM or SQL injection or even CSV dumps taken for transport.
So, IMO (and it's only my opinion and the way I've done it) is to encrypt with PHP and sned the encrypted data over the wire, as that stops all methods of trapping the data, and a CSV dump will be "scrambled".
If you do that, you may as well use the varbinary / blob types as it stops you accidentally trying to read/edit in phpMyAdmin. Plus potentially saves a few bytes nominally (although this depends on indexes and other stuff - so that alone is not a winning argument).
And now the down side: searching and sorting. Anything you index or search on, if encrypted, will only match the entire, exact, case sensitive string padded to the correct length (normally a search will be case insensitive, and you can do part searches with LIKE). And if you want to ORDER BY then you need the original strings. So bear than in mind when designing the structure.
Hope that helps.
What's the worst possible scenario if an attacker gets access to the plain text data? Given that you have to decrypt data in order to make it useful and you therefore need the encryption key to be somewhere accessible too, any attacker who can get to the DB will likely be able to get to the key as well, unless this is for archiving rather than e.g. a live website. I'd focus on the DB server security, unless you're carting HDDs around full of data which might get lost, but it really depends on why you need to encrypt it.
if you need to secure the data in your possibly hacked database, you can encrypt it
with mcrypt
$key = "mykey";
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key,$data,MCRYPT_MODE_ECB,$key);
after that you can select BLOB,TEXT,MEDIUMTEXT or anything, based on the ~expected data size.
* for VARBINARY/BINARY you might need to pack it first.
The encryption operation has additional cost.
You need evaluate if in your scenario, this additional cost will be a problem, per example, if your data grow to considerable size.
The first frontier to avoid data leaks is a strong data access policy with profiles of access an so on. This has the disadvantage that you will need to manage the mysql and configurate it.
If you want care about the managment of profiles, you can encrypt the data assuming the extra cost in CPU and (depend of encyption algorithm) a extra storage space.
The security of the a system is equals to the security of more weak component, don't focus your effort only in encryptation task, this only give you the sensation of security, if the data can be decrypted, the only thing that the intruder needs is time and bruteforce to break the encryption
I read all posts on HTTP over SSL. So far, I know how to get the data securely in a Web form. But I miss the part of recover and keep the data in the same way.
I need in my Website a form to collect sensible data from customers (may be also credit cards numbers for booking, but no credit card authorization process is required) and later keep and read that data in a secure way.
Then, for a basic secure Web application I need:
a) Web site with SSL Domain Validated (DV) Certificate (I don't have fixed IP address. I use basic shared or "virtual" hosting service).
b) Develop a simple PHP & MySQL application that collect sensible data of customers, putting all the app PHP files on the SSL secure folder.
c) All the collected data is gonna be stored in the server MySQL database.
This is the questions part of my message:
1) If I enter later using phpmyadmin to take look at the database over regular hoster services (HTTP), isn't this insecure??
2) What about the hosting administrators? They could also read all sensible data if I use plain text in the database. But encryption methods for data on the server (not only in transmission over SSL) could be enough? Isn't true that the encryption encoding/decoding method could be intercepted by the hosting administrators?? (consider this: the method is inside the application in the same server).
I can't pay the convenience and security of an own server.
3) Considering those things, and assuming that they are true... really matter if I go for a database encryption?
May be I missed something or I misinterpreting some issue.
Thanks a lot for your help and patience.
These shared hosting plans are not really up to the job of collecting credit card numbers - you are betting using a payment gateway and not storing them yourself.
See some regulations on this: PCI
Yes. HTTP is insecure.
Yes, plain text in the database is insecure. Encrypted is slightly more "secure" - it'll deter someone who casually looks through - but anyone with access to the server also has access to the script doing the encrypting / decrypting.
I'd say yes. Encryption in your case won't do a thing against a dedicated attacker, but it'll prevent some sysadmin idly browsing through from immediately having the data without having to make the deliberate step to break in.
I hope you're not storing credit card or other sensitive data, particularly if covered by privacy laws in your jurisdiction. Storing that sort of stuff on a shared server will probably get you sued. If nothing else, storage of credit card data in this manner will be a violation of your merchant account - if they get wind of it, Visa and MasterCard will become unavailable to you.
1) Seeing the data with phpmyadmin over HTTP is insecure, of course.
Regarding 2), if you don't have physical security, then you can't have any security (perhaps with the exception of storing encrypted data which you encrypt and decrypt outside the hosting site).
As your hosting company has access to the computer, they can read all your data.
Having said that, in my experience hosting providers will not do that and try to keep your data safe (because that is their business), pretty much in the same way banks' business is to try to keep your money for you and safeguard it and not taking it.
3) Go for database encryption only if you keep backups. For running the live version it provides little more security (if at all) and makes things more cumbersome.
It is.
They can.
Not really but it could still be a good idea. Someone could get hold of your database and not the PHP source code. Then encryption in the database would be a good thing.
You are correct. The only way to be sure is to run your own server. Also you should know about the Payment Card Industry Data Security Standard.
I think that bobince is totally correct. Public key crypto can help you but keep in mind that you loose comfort of using PHPMyAdmin to view the data - you will see garbage that will need to be decrypted somewhere on the side. See http://www.php.net/openssl to learn more about PHP and public key crypto.
Having an encryption/decryption process entirely on the server is, as you suspect, mere obfuscation and not secure in itself. It can help in cases of a partial compromise, where an attacker gains read access to the database (typically through an SQL injection hole) but no ability to read the site scripts or run arbitrary code.
If you only need to write out sensitive data (canonically credit card numbers) that the server doesn't need to be able to read back in, you can do that with public key cryptography. Encrypt the data with your public key, then read it only on a known-secure machine that has the corresponding private key. This protects past data in the case of a greater compromise where the scripts are readable, and in the case where an attacker gains write-access to the scripts, they at least only get new incoming data leaked, and not the old stuff. Hopefully that would give you time to detect the intrusion and rebuild.
Isn't true that the encryption encoding/decoding method could be intercepted by the hosting administrators?
Yes. But then the hosts have physical access to the machine, so could bang a rootkit on it that intercepted everything the webapp was doing on the fly from day one, if they really wanted. There's no way around trusting your host, so pick a reputable one and don't run sensitive systems on shared servers.