I am building a small application for a real estate company which needs to store sensitive information such as bank statements, tax returns, etc. Right now i have the upload form as just a standard html upload form using php $_FILES to move the file to the desired folder. This works fine but there is no level of security to protect this sensitive information. I have two questions?
First, what is best practice (as of 2017) for storing sensitive documents like bank statements, tax returns, etc? I have tried to search for best practices online but everything im finding is 5-10 years old information or deprecated php functions. Is there specific php function I should be using/researching?
Second, are there any tutorials or books available that would help me understand secure file storage, file encryption, etc., in php?
My ultimate goal is just to make sure these files are secure and don't fall into the wrong hands. My question is specific to file uploads. I do understand that the rest of my site has to be secure as well. My question is simply about protecting files.
Thanks for any help or guidance.
First, what is best practice (as of 2017) for storing sensitive documents like bank statements, tax returns, etc?
The literal answer to this is simply to keep them ENTIRELY OFFINE (on a remote hard disk, if needing to keep them digital at all) and store them in a good quality safe with only one -or maximum two- verifiable keyholder(s).
Read https://security.stackexchange.com
Read https://crypto.stackexchange.com
Read, download and use the Defuse PHP Encryption Library. My reading up on the same topic last year persistently showed this library (and all of Defuses stuff) was very high if not market leading in this arena. This encryption library can en/decrypt files.
Also research Halite. Which is a High-level cryptography interface powered by libsodium, which can encrypt and decrypt files.
Also please read my answer here for MySQL best practise for securing data storage (string or blobs etc.).
If using a database it is paramount that the database and the file server are different servers (and depending on the value of your data they should be in very different physical locations), and the database contains an encrypted key needed for the fileserver decryption, so that if when one server is compromised, the data is still secured.
Use your own server(s). Don't use the "cloud". (To have proper online data security is not really cheap)
Related
I need to implement a simple (not ultra-secure) but fast file en/decryption using PHP, so files are encrypted on upload and decrypted on download. Files are mainly images (jpg) and videos (mp4), and some videos are up to 30 MB, so my idea is to encrypt only the first X bytes of each file, just to avoid anyone that could have access to the server (ie. support people) to open the files from users.
I am new to this subject and after almost 6 hours researching found only old examples, using deprecated Mcrypt.
Please, can anyone give me tips to start? Is there any native method from PHP that I can use, or maybe an open-source library? Does Mcrypt would be an option, even if deprecated (I am using PHP 5.6). Do you think encrypting only the first X bytes of the file is a good approach in my case?
Thanks!
Here is a PHP encryption library: https://github.com/defuse/php-encryption
I found this just by googling, I can't vouch for it's reliability or security. There are documentation and examples on that page.
However I really would ask you to take a step back and consider what the purpose of this is and what the wider security considerations are. In order to do this successfully then there will need to be some security secret, either a key or a password, that will need to be kept hidden from the people that you don't want to be able to decipher the data. I can imagine that would be difficult if those people are the support staff. If you made the password the users login password you are setting yourself up for widespread data loss when a user forgets their password. Also at some point it will need to be unencrypted and you will need to think about making sure that is not leaked at this point. And then you need to think about who has access to the source code that handles the file access, and the key/password code. What about server logs and caches? Etc etc
Furthermore if you are only encrypting the first X number of bytes and don't need to make it 'ultra-secure' then I wonder why you are attempting to do it this way at all? I'm not sure what problem it is you are trying to solve.
Given that doing encryption properly is not simple (not to mention costly in terms of computing resources), but if you don't do it properly it isn't much good then I can't help suspect you will probably be much better off spending the effort making sure that untrusted persons only access information on a need-to-know basis and all access is logged in order to keep people honest.
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.
i started learning a bit about mysql and while i was reading i was thinking that the security vulnerabilities on mysql are pretty immense and can't be well covered if someone doesn't truly understand pretty much everything about mysql.
if i have a website that will store not a very big volume of information, would it be bad to store it in .php files?
what are the implications and vulnerabilities of this?
it seems to me that the risk is far smaller because if the .php file doesn't have an echo statement, if you try to access it all you get is a blank page, and if you are unable to 'send code' by user input and send files to the website it should be secure as far as the website is concerned (obviously that if the server itself is hacked the attacker pretty much has the control of everything but that's not the point on this matter)
update to the question.
it seems that what i've written above isn't producing the kind of answers that i expect and so i will try to simplify.
what i'm looking for here is why are databases more secure than flat files without bias because most people i've read stuff about on this subject will just say databases are more secure but can't say why. yes they're faster and it's easier to manipulate the data especially if it's complex or with multiple users and there is a lot of info. about that and it's easy to understand why.
the fact is that when i started reading about mysql a few days ago i saw that if your php is compromised most likely so are the databases so writing good secure php code is probably the first and most important line of defense to your mysql databases.
if your php is uncompromised so is the information you stored in php files so if you write good secure php, the security of plain php files will be good.
having databases also makes you use php functions that usually you wouldn't use and some of them possess real security holes that have to be "patched up" so writing good secure php code to work with databases is more complex than writing equally secure code to work with plain files.
also when you have apache/php/mysql installed you have 3 things that may have entry points for hackers if they're not correctly configured and maintained, if you cut mysql loose you only have 2, you won't have to bother with sql injection for example because with no databases that's impossible to happen, you may inject all sql you want but you will get nothing.
so for managing small amounts of data, plain files seem to me like a secure, a bit more complicated to work with the data, slower but not relevant considering that it's a small amount of data we are talking about.
why may these deductions be wrong is the information i'm looking for with this.
Apples and oranges.
You can go to a drag race with a Hummer and complete the race but you will surely be in last compared to a Bugatti. Take a Bugatti off-road and it will definitely fall behind the Hummer.
PHP is a server side scripting language. Data storage and retrieval is not the primary consideration in PHP.
mySQL is a relational database management system. It's design is 100% purposed for data storage, retrieval, and security.
What's your plan for data storage and retrieval in PHP? It seems like will have to do a lot of unnecessary work re-inventing the wheel to achieve this. Why would you?
Without understanding what security concerns you are specifically worried about in mySQL there isn't much more to add.
Edit: An article calling out the general differences.
These two points will cover most security issues:
1)Learn PDO and the prepared statement protocol. This will take care of most if not all SQL injection issues. Do not send raw SQL to a database.
2)Sanitize all your GET and POST data that comes into PHP. This will take care of most XSS.
Many frameworks in other languages do this for you, but the PHP newbie will just use bare PHP and open himself up to all kinds of attacks. That is why PHP is "unsafe."
Read up on security, and try to implement some of the pointers that you feel are important. No language, framework, platform, etc is 100% secure. Just like everything else in life, you take as many steps as possible to minimize the risk.
I've done a bit of web programming (using PHP and MySQL), but nothing too large in scale. I've been thinking about how someone would create a social networking type of site and I've ran into some problems.
How would you safely and securely store passwords in MySQL? What kinds of encryption would you use?
If users were allowed to upload pictures, would it be better to store them in the database or have them uploaded directly to the server?
What open source web applications (such as WordPress) would you recommend I read and study (preferably something simple but well written)?
Anything taught in class or written in books just don't seem to translate well into real production code. They just seem like very basic examples.
Thanks!
Regarding password storage: use one-way salted hashing for security. Here's an article on why.
Store a salted hash. I would personally move away from md5 and using something like sha instead. sha1 + salt will hold out for a while =]
If you store the images as blobs in the db, you'll probably have an easier time in the future backing them up (along w/the db, fetching them, etc). But really, they'll be damn fast on the file system too, but I'd prefer them in the database as I have lots of code that interfaces w/the db and I'm comfortable working in that area. That's up to you.
I'm not sure that wordpress will help you to build a social networking site...but its still good to read other's code. I'd take a look at some books on amazon on architecture just to get your mind thinking large scale. Also, take a look at some design pattern books.
I'd also look into something like the Zend Framework or CakePHP. Cake will probably get you up and running rather fast, but I prefer Zend, as its very powerful and doesn't force you to code a certain style. CakePHP is kinda of like rails for PHP.
You'll also want to get decent at security, both server and client side, watching for stuff like session hijacking, sql injection, xss, brute force attempts, remote includes, uploaded file exploits, etc.
Social sites offer many attack vectors to crackers.
Resources:
http://www.amazon.com/Pro-PHP-Security-Chris-Snyder/dp/1590595084/ref=sr_1_1?
http://www.amazon.com/PHP-Objects-Patterns-Practice-Second/dp/1590599098/ref=sr_1_3?ie=UTF8&s=books&qid=1265662237&sr=1-3ie=UTF8&s=books&qid=1265662204&sr=8-1
http://www.amazon.com/Building-Scalable-Web-Sites-Applications/dp/0596102356/ref=sr_1_1?ie=UTF8&s=books&qid=1265662256&sr=1-1
And your local PHP mailing list / meetup.
For the image storing, I always used to store them on the hard disk, but using a very hard image validation script to make sure the images don't contain malicious code.
I'm also used to apply URL rewriting so users can't find the real path to the images.
Don't you have a strange feeling storing images into databases ? The mysql database can grow very fast, and you will always need a PHP script to show up the images, which means it makes your server slower.
As for the password storage, use salting as the others replied.
Last, for the documentation, I really love to see how Wordpress is structured.
I have spent hours watching it's source code and reading it's documentations. It's just a terribly good example of how to organize any website.
Apply a hash function to the password (such as sha1 or md5). Then add extra "salt" to it by taking like the first 5 characters of md5("social") or something. It's up to you, but this is intended so that if a hacker gains access to your database, he/she won't be able to run your hashed passwords through a rainbow table and get the actual password.
I am running a website that allows users to upload pictures. The pictures are organized in bins (that is, 1,000 pictures per bin) just to keep it organized (and you can only have so many files per folder before you run into problems). The location of the pictures is stored in the database as well as other info (like picture id, file extension, bin location, etc). Another table in the database links the picture ids to a user. Also, the picture's filename once its uploaded is something like
{bin}/{userId}_{pictureId}_{token}_{variant}.{fileExt}
Not sure about web applications, but you should definitely make use of some built-in PHP classes such as the PDO database abstraction layer.
For password storage, I suggest using MD5 with a salt. MD5 is impossible to decrypt, but its possible to crack using rainbow tables. For example: Here is a MD5 lookup site I've coded
I would personally upload them directly to the server, however, you need to make sure only valid image files can be uploaded. Don't want someone uploading a rootshell.
Question 3: I would suggest studying one of the modern Rails-style frameworks (my favorite is Symfony) rather than an app like Wordpress or Gallery. They are both excellent, but they've evolved from simple hacks and aren't necessarily the way I would start anything if I was starting from scratch.
Also, for question 2, I hate binary blobs in databases. Filesystems work great for that.
And question 1: one-way hash, as others have said. Mysql's password() function is probably fine.
All these questions have been answered before.
How would you safely and securely store passwords in MySQL? What kinds of encryption would you use?
See https://stackoverflow.com/search?q=password+hash+database+php
If users were allowed to upload pictures, would it be better to store them in the database or have them uploaded directly to the server?
See https://stackoverflow.com/search?q=store+images+database+php
What open source web applications (such as WordPress) would you recommend I read and study (preferably something simple but well written)?
See https://stackoverflow.com/search?q=social+network+php
You should also take into account that running and managing a social network site is more than just coding it. Are you sure you want to build one from scratch? Consider if you would be equally happy with something like Ning, where everyone can start their own community with no programming whatsoever?
I understand the mantra of "don't roll your own" when it comes to site security frameworks.
For most cases anyway.
I'm going to be collaborating on a site that integrates text-messaging into the system.
I'd like to use an existing, well-tested security framework to protect the users data, but I need it to also protect a users phone number as well.
I wouldn't want to be the one responsible for a list of users cell phone numbers getting jacked and spammed.
What suggestions can the community offer?
Note that techniques applied to passwords aren't applicable here. You can store a password salted and hashed (although the value of doing so can be disputed), but that doesn't work for phone numbers.
If someone jacks your server, they can do anything the server can. This must include recovering the phone number, but doesn't include recovering the password if it's hashed well. So the phone number is just a particular case of protecting confidential data.
If phone nos truly are the only sensitive data in the app, then you could look at walling off the part of the app that sends the texts, and asymmetrically encrypting the phone nos. In a different process (or on a different machine) run an app that has the key to decrypt phone nos. This app's interface would have maybe one function taking an encrypted no and the message to send. Keep this app simple, and test and audit the snot out of it. Either hide it from the outside world, or use authentication to prove the request really came from your main app, or both.
Neither the db nor the main part of the app is capable of decrypting phone nos (so for example you can't search on them), but they can encrypt them for addition to the db.
The general technique is called "Privilege separation", the above is just one example.
Note that phone nos would generally need to be padded with random data before encryption (like salting a hashed password). Otherwise it's possible to answer the question "is the encrypted phone number X?", without knowing the private key. That may not be a problem from the POV of spammers stealing your distribution list, but it is a problem from the POV of claiming that your phone numbers are securely stored, since it means a brute force attack becomes feasible: there are only a few billion phone nos, and it may be possible to narrow that down massively for a given user.
Sorry this doesn't directly answer your question: I don't know whether there's a PHP framework which will help implement privilege separation.
[Edit to add: in fact, it occurs to me that under the heading of 'keep the privileged app simple', you might not want to use a framework at all. It sort of depends whether you think you're more or less likely leave bugs in the small amount of code you really need, than the framework authors are to have left bugs in the much larger (but more widely used) amount of code they've written. But that's a huge over-simplification.]
Since you need to be able to retrieve the phone numbers, the only thing you can really do to protect them (beyond the normal things you would do to protecting your db) is encrypt them. This means that you need to:
Make sure the key doesn't leak when you inadvertently leak a database dump.
Make sure your system doesn't helpfully decrypt the phone numbers when someone manages to SQL inject your system.
Of course the recommendation of not rolling your own still applies, use AES or some other well respected cipher with a reasonable key length.
I’m pleased to announce the release of hole-security system for PHP
This project stands for bring to PHP the kind of security that is provided in Java by Spring Security the formerly Acegi Security System for Spring. It’s designed to be attractive to Spring Security users because the philosophy is the same. It’s an unobtrusive way to add security to a PHP site. The configuration is made using substrate IoC/DI as Spring Security use Spring IoC/DI.
An example configuration ship with the framework and can be used like this:
$context = new substrate_Context(
'./path/to/hole-security/hole-security-config.php'
);
$context->execute();
$hole_Security = $context->get('hole_FilterChainProxy' );
$hole_Security->doFilter();
Just be sure that the bootstrap code of the framework is executed before the bootstrap of the MVC of your choice.
WebSite:
http://code.google.com/p/hole-security/
Documentation:
For the moment you can use reference documentation of Spring Security where it’s apply. You can get a general idea using the Acegi Security reference documentation because hole-security use the same way of configuration, but keep in mind that it’s based on Spring Security.
License:
It’s released under Apache License Version 2.0.
Features:
hole-security brings an pluggable security system where you can adopt the security requirement of your environment. Currently there is a very simple security system because it’s on the first release but with the base foundation that it brings you could suggest or request for new features to be added to the project.
Currently Features:
In memory dao authentication as a proof of concept, you can switch to your preferred dao or implementation that get’s user data from database or wherever you store it. In futures release an PDO based implementation will be created.
Configured filters for be applied to url patterns. Url path matcher can be plugged to, currently it ship with a ant styles path matcher.
Authorization Manager can be used in your application to decide wherever or not do something, always obtaining the reference from the substrate context.
Shared Security Context accessible from any code of your application if hole_HttpSessionContextIntegrationFilter is applied. You can use this context to save information related to the session without use the session object directly.
You can use a custom login page and customize it according to the hole_AuthenticationProcessingFilter configuration, or customize hole_AuthenticationProcessingFilter according to your custom login page.
The default password encoder is plain text, without encoding. Futures releases will have implementations for MD5, Sha based, Base64 and others related encoding. You can create your own password encoder and get configured.
All the objects are loaded as required, if something like a filter it’s not used for a request would not be loaded. This increase the performance of the application
There are others features related that hole-security have.