Good way to encrypt data in MySQL table? - php

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.

Related

Security for storing Data with PHP/PDO

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.

Security in data transmission

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.

Encrypting user data for automatic login to third party system

I find myself in a situation where I have a set of users on a site who all have stored usernames and passwords that allow them to automatically access third party services via SOAP. The idea is that each user should only need to log in to the main site to gain access to multiple services, using their respective stored user info for each service. I feel like such data should be encrypted in my database when stored and then automatically decrypted when it's passed to the php/SOAP function when the user needs to access a given service. What would be the best way to accomplish this?
I've had a look at AES_ENCRYPT, but it seems as though the encryption and decryption makes use of a key that would have to be stored in my code, in plain text...which doesn't seem like the brightest thing to do. Anyway, this is my first time out on something like this (if you couldn't tell); if you could give me some pointers on how I should approach this, I'd really appreciate it.
Many thanks in advance
You stumbled over the biggest problem with encrypting data in the database:
➽ Where to store the key?
Encryption cannot solve the problem of securing data, it can only "concentrate" it to a key. Wherever you store the key, your application must be able to decrypt the data, so can do an attacker. There are two possible solutions to this problem i know of:
Place the key in a place as secure as you can. That means, it should surely be placed outside of the www-root directory in an inaccessible directory on the server. Depending on the importance of the data, you can also consider to outsource encryption to another dedicated server.
Don't store a key at all and derive it from the user password. This is the only really safe way, because not even the server can decrypt the data then. The cons are of course, that the user needs to enter the password every time he uses your service. If the user changes the password, you need to re-encrypt all data. If the user forgets the password, the data is lost.
P.S. I would recommend to encrypt the data before storing it to the database, because MySQL AES_ENCRYPT uses the ECB mode without an IV. This allows to search for a certain value, but is less secure (i'm pretty sure that you don't want to search by password).

PHP plain text encryption - keeping key safe

In a typical web scenario, a website user will come along, use a website, fill out a form, and transmit the data to the server for storage in the database. Now let's say we needed to ensure their address was encrypted as it was top secret, and only those with access to the back end of the website should be able to see what that address was - this is reasonably easy to achieve right? We would just store an encryption key server-side which would be used to generate the encrypted data, store the data in the DB, and we would just use the key again to decrypt it.
Now supposing someone at the hosting company were to browse the files on your server - they could very easily get access to this encryption key, and then use it to decrypt any data they wanted, since all addresses in the database have been encrypted with the same key!
I am just trying to cover every base with the new security model, and in a "trust no one" policy I am looking at ways of stopping the hosting company from getting at the data too.
So does anyone have any suggestions to prevent those with server access from obtaining the key and decrypting data? Would password salting help in any way, or would they still be able to decrypt data quite easily.
I can't think of a way around the issue. Does anyone have any suggestions to solve this particular problem?
Encrypt and decrypt in the browser everything sent to the host. Use a passphrase entered on the client to do the cryptography, and never send the passphrase to the host. There's a fuller description at Host-proof Hosting
I guess that's a risk when it comes to shared hostings. I'm using amazon aws for most of my projects and linode for my personal blog. Both solutions are in the model "you are your own sysadmin" and nobody peeks in your machines.
If I was in your shoes, I'd use mcrypt with a variable key. For example, whe username field of the same row. This way, for the data to be compromised, the intruder would need to get access to both your database and source code to figure out how to decrypt the data. At that point your problem would be far worse than a mere information leak.
Well mostly hosting companies have access to all databases and files that is bad really bad.
Few years ago I did some experimenting with encryption and decryption.
The best way would be to have personal servers, but that isn't cheap.
Example RC4 encryption requires key to crypt data. Now tricky part is to make that key also encrypted with some other encryption like BASE 64 , ATOM 128. This wont make it be 100% secure
But It will be really hard to decrypt data.
I hope you can understand me.
Cheers :)
btw point is there is no 100% secure data.
If you don't need to be able to decrypt the data online, this is an ideal situation for public-key cryptography. In particular, a sealing API. For example, using libsodium (PHP 7.2):
Encryption
$store_me = sodium_crypto_box_seal($plaintext, $box_publickey);
sodium_memzero($plaintext);
Decryption
$plaintext = sodium_crypto_box_seal_open($stored_msg, $box_keypair);
If, however, you do need to be able to decrypt the data from the webserver, then anyone who accesses the webserver can just pilfer the keys and decrypt your data. No cryptography algorithm can stop someone with the keys from decrypting messages.
Always start with a threat model.

Store 'sensitive' data in MySQL DB

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

Categories