How to securely store sql files apache server - php

So, I'm writing a php script which will be tied to a cron job that will backup my site's db on a regular basis. The db will get saved to a new sql file daily just incase anything unfortunate should happen to the live version. I am aware of how bad it would be for someone to be able to get a hold of one of these files, exposing both the db structure and user email addresses (passwords are encrypted).
I am not extraordinarily security savvy, and this is one of those things you HAVE to get right the first time around. I'm not to prideful to admit when it's best to ask for help so I figured I'd inquire with the trusted Stack Overflow community. (I realize it's likely there is a question similar to this somewhere, but I have been unable to find it).
What steps do I need to take to make sure these files can't be accessed? Note, it is an Apache server. Is it enough to store them in a directory outside of the root which is limited to group read/write (no public read)? Or is it necessary to password protect the directory or even encrypt the actual files? I'd really rather not if I don't have to (encrypt the files), it would just make it more of a pain to use them, but if it's needed...
Also relevant, access to these files is NOT being built into an application interface. I don't need or want to have them accessible by an http request. FTP only. So my question isn't regarding any password protection of a UI.
Thank you all so much for your time!

Storing on the server
If you must, store them outside of the web root and download them with something like rsync over ssh.
Best option (assuming you're running MySQL)
Don't store them on the server, but rather run a cron on your local machine and use ssh and MySQL to do the dump to your local system. That way there is no ominous file someone can have that contains all of your data (unless of course your local network is compromised).
Another option (again another example with MySQL)
You might also look into doing database replication with your local machine by setting up a local MySQL server.

Related

Securing database connection information

I know that the question How do I secure my database connection credentials? has been asked and answered multiple times (e.g. How to secure database passwords in PHP?).
A commonly accepted answer to that question is to store the details outside of the web root. But I'm curious as to why this really makes much difference.
From what I understand, a person cannot download the source of the PHP file via HTTP (unless your web sever is not configured properly, but you would know about that right away). So you won't be able to see the credentials unless you have access to the source of the PHP file anyways. Correct me if I'm wrong, but doesn't this basically mean that you would need shell access? And if you have shell access, can't you just get to the file outside the web root anyways?
If the answer to that question is that the include file might have special permissions that don't allow anyone but the web server user to read it, then (considering that I have shell access), couldn't I just write (or modify) any PHP file to just echo out those credentials?
So the question is, does it really make any difference whether you store the credentials directly in the PHP script vs. in a file outside the web root?
Suppose, due to a error in the webserver, the webserver no longer processes php files, but treats them as html files.
In that case something like http://mysite.com/config.php would simple reveal the credentials of your database.
So the answer is: Yes, it does really matter, where and how you store the database credentials.
The main issue is that the web server might break down later on. E.g. after a software update php might not work properly anymore and the server falls back to delivering the files directly. Or again after a software update the configuration might be reset, so PHP is no longer registered for the file extension. Or the server breaks down under heavy load and also starts delivering files plainly.
Many things can happen and it's rather easy to mess up the config at some point. Better be safe and keep it outside the document root.
Create an O/S user for your application, such as 'UserForMyApp'
For that user, create an O/S user environment variable 'MY_APP_DATABASE_PASSWORD', and set the value
Run your app as 'UserForMyApp'
In MyApp, read the O/S user environment variable 'MY_APP_DATABASE_PASSWORD' and use that to login to the database
Other non-root users cannot read an O/S user environment variable for another user. This is default. You don't have to set anything, unlike w file permissions.
There is no chance of storing the password in source control by accident.
If db and app are on same machine could just let db trust local access without password.

PHP: Securing database connection credentials

Just to make sure everyone is on the same page these are the credentials I'm talking about...
$user = 'user';// not actual user, not root either
$pass = 'pass';// not actual password
$server = 'localhost';
$database = mysqli_connect($server,$user,$pass,true|false);
So I'm talking about the passwords used to connect to the database, not the passwords in the database (which for clarification I have hashed with salt and pepper).
I have not read anything that I think remotely suggests you can have 100% foolproof security since obviously the server needs to connect to the database and get the content for visitors 24/7; if I am mistaken I would love to hear how this would be possible.
So let's presume a hacker has root access (or if that does not imply access to the PHP code let's just say then have access to all the PHP source code) and they (in this circumstance) desire to access/modify/etc databases. If we can not prevent them should they have access to the PHP source then we want to slow them down as much as possible. I can keep each site/database connection password in separate files (can as in I'm a few weeks from finishing multi-domain support) for each site and not inside of public_html (obviously). I use serialize and unserialize to store certain variables to ensure certain level of fault tolerance for when the database becomes unavailable on shared hosting (preventing site A from looking and acting like site B and vice-versa) as the database can sometimes become unavailable numerous times a day (my database error logs are written to when the SQL service becomes available again and catches these "away" errors). One thought that has crossed my mind is determining a way to store the passwords in one hash and un-hashing them to be used to connect to the database by PHP though I'd like some opinions about this as well please.
If someone has a suggestion from the database perspective (e.g. having the ability to restrict users to SELECT, INSERT, DELETE, UPDATE, etc and not allowing DROP and TRUNCATE as examples) my primary concern is making sure I am SQL neutral as I plan to eventually migrate from MySQL to PostgreSQL (this may or may not be relevant though if it is better to mention it). I currently use phpMyAdmin and cPanel and phpMyAdmin shows the connected user is not the same as the site's database user names so in that regard I can still use certain commands (DROP and TRUNCATE as examples again) with that user and restrict the SITE user permissions unless I am mistaken for some reason?
Is there a way to configure the context of where the connection credentials are accepted? For clarification a hacker with access to the source code would not be accessing the site the same way legitimate users would.
Another idea that crossed my mind is system based encryption, is there a near-universal (as in on every or almost every LAMP web host setup) web-hosting technique where the system can read/write the file through Apache that would introduce a new layer that a hacker would have to determine a way to circumvent?
I am using different passwords for each user of course.
I currently am on shared hosting though hopefully my setup will scale upwards to dedicated hosting eventually.
So what are the thoughts on my security concepts and what other concepts could I try out to make my database connection credentials more secure?
Clarification: I am looking for ideas that I can pursue. If there is disagreement with any of the suggestions please ask for clarification and explain your concern in place of debating a given approach as I may or may not have even considered let alone begun to pursue a given concept. Thanks!
There is little to be gained from trying to slow down an intruder that already has root access to your system. Even if you manage to hide the credentials well enough to discourage them, they already have access to your system and can wreak havoc in a million ways including modifying the code to do whatever they wish.
Your best bet is to focus on preventing the baddies from ever penetrating your outer defenses, worry about the rest only after you've made sure you did everything you can to keep them at the gates.
Having said that, restricting database user accounts to only a certain subset of privileges is definitely not a bad thing to do if your architecture allows it.
As code_burgar says, once your box gives root, it's too late. That being said, I have had to implement additional security mesures on a project I was involved with a while back. The solution to store config files in an encrypted partition so that people with direct access to the machine can't pull the passwords off by connecting the drive to another PC. Of course this was in addition to file system permissions so people can't read the file from inside the OS itself.
Another detail worth bringing up, if you are really paranoid on security:
$user = 'user';// not actual user, not root either
$pass = 'pass';// not actual password
$server = 'localhost';
$database = mysql_connect($server,$user,$pass,true|false);
unset($user, $pass, $server); // Flush from memory.
You can unset the critical variables after use, ensuring they cannot be var_dumped or retrieved from memory.
Good-luck, hope that helps.
You want to approach security in layers. Yes, if an attacker has root access, you're in a very bad place - but that doesn't mean you shouldn't protect yourself against lower levels of penetration. Most of these recommendations may be hard to do on shared hosting...
Assuming you're using a decent hosting provider, and recent versions of LAMP, the effort required to gain root access is substantial - unless you're a very lucrative target, it's not your biggest worry.
I'll assume you harden your server and infrastructure appropriately, and check they're configured correctly. You also need to switch off services you don't need - e.g. if you have an FTP server running, an attacker who can brute force a password doesn't need root to get in.
The first thing you should probably do is make sure that the application code has no vulnerabilities, and that you have a strong password policy. Most "hacks" are not the result of evil geniuses worrying away at your server for months until they have "root" - they are the result of silly mistakes (e.g. SQL injection), or weak password ("admin/admin" anyone?).
Next, you want to make sure that if your webserver is compromised - but not at "root" level - you can prevent the attacker from executing arbitrary SQL scripts. This means restricting the permissions of your web server to "read and execute" if at all possible so they can't upload new PHP files. It also means removing things like CPanel and phpMyAdmin - an attacker who can compromise your production server could compromise those apps, and steal passwords from you (run them on a different server if you need them).
It's definitely worth looking at the way your database permissions are set up - though this can be hard, and may not yield much additional security. At the very least, create a "web user" for each client, and grant that user only "insert, update and delete" on their own database.
I have found a solution for PHP(Linux) On the root create a directory say db and create a class and define all the database connection variables and access methods in a class say DBConnection.php now your website is example.com you are storing your files in public_html directory create a php file under this directory to connect and do all database operations and include DBConnection.php file using following statement
require('../db/DBConnection.php');
this file cannot be accessed using 'www.example.com/db/DBConnection.php'
you can try this on your web site.

Downloading PHP content from another domain (safe way)?

So, if this question has been asked before, I'm sorry. I'm not exactly sure what to search for.
Introduction:
All the domains I maintain now are hosted on my server, so I have not ran into this problem yet.
I have created a structure, similar to WordPress, for uploading and editing images.
I regularly create changes in the functions and upload them to a single folder. When the user logs in, the contents are automatically downloaded into their folder.
What I am wanting to do:
Now, say I have a user that is not hosted on my server. I cannot use copy(), but is there a safe and secure way to echo the contents of each php file (obviously, I can echo) into another file on the users server?
For example:
Currently I can copy from jasonleodurbin.com to geodun.com (same server), but say I want to copy jasonleodurbin.com/test.php to somedomain.com/test.php.
I had some thoughts like give each user a private key and send that to a file like echo.php. echo.php will grab the contents of every file (that has been modified recently) and echo that to the screen. The requesting server would take that content and copy that into it's respective .php file.
I assume I could send the key through GET, but since I have never dabbled into the security implications of anything (I am a hobbyist), I don't know how secure this is.
Are there any suggestions or directions that someone could send me?
I appreciate the help!
I'm assuming this is sensitive data. If that's the case, then I would suggest encrypting the file using PGP keys. Either way, you need a method to send the file from your server to their server. I can't recall how I did it, but I used to send encrypted data file from our remote server to a server in house. We used PGP keys to encrypt and decrypt once it arrived in house. As for the method we used to send the file across the web, I believe we used SCP (you need shell access on the server).
You could use FTP, but how about setting it up so that they only have access to a particular directory so they can't touch anything else. You'll need a script to grab the file from the FTP location and storing it in the appropriate directory per user?
Just thought of something, store the file in a protected folder. Have the user download the file using curl. I believe you can specify username/password with curl.
Several options:
Upload the newest version of test.php as test.phps (PHP Source file, will be displayed instead of run) in a location know to the client. It is then up to them to download this file and install it on their web server.
pros: not much effort required on your part, no keys or encryption required.
cons: everyone can view the contents of your PHP file if they know where to look, no guarantee that clients will actually get updated versions of the file.
Copy the file to clients web server. Use scp, ftp, or some such method to update test.php on the clients web server whenever you change it.
pros: file will always be updated. Reasonably secure if you use scp
cons: extra step required for you, you will have to remember to do this each time you change test.php. You will need to have access to the clients web server for this to work
Automated copy at a timed interval. Set up a cron script that syncs test.php to the clients web server at a certain time each hour/day/week/whatever
pros: Not much repeated effort required on the part of either party. Reasonably secure if you use scp
cons: could break if something changes and you're not emailing when an error occurs. You will still also need access to the clients machine for this to work.
There's probably a lot more different ways to do this as well, but this is just a few to get you started
Use a version control system, such as subversion. Just check in your code to the repository each time you make some changes you want to push, and run an update from the clients. If you're already using a version control system, create a production-branch where you commit your changes when they're ready to be pushed to clients.
It can be done from the clients in pure php (slightly experimental) with library from here or here, with a PHP extension, or with a wrapper to the native svn client.
This gives you security, as each user can have their own password, which you can retract if you so please. Can also do encryption by running through a ssh tunnel (limits your library choices to the wrapper I think), but really, wouldn't worry too much about encryption, who's going to be looking at the traffic between the servers? Unless you're doing top secret type stuff.
It also gives you automatic change detection, you don't have to roll your own way of keeping track of which files are updated as this is done when you commit your new changes.
It's a proven way of doing code bases up to date, so I don't see why you would implement your own. It also gives you the extra advantage of being able to roll back changes if (when) there's a problem with the code update.

Is DB logging more secure than file logging for my PHP web app?

I would like to log errors/informational and warning messages from within my web application to a log. I was initially thinking of logging all of these onto a text file.
However, my PHP web app will need write access to the log files and the folder housing this log file may also need write access if log file rotation is desired which my web app currently does not have. The alternative is for me to log the messages to the MySQL database since my web app is already using the MySQL database for all its data storage needs.
However, this got me thinking that going with the MySQL option is much better than the file option since I already have a configuration file with the database access information protected using file system permissions. If I now go with the log file option I need to tinker the file and folder access permissions and this will only make my application less secure and defeats the whole purpose of logging.
Updated:
The other benefit I see with the db option is the lack of need for re-opening the db connection for each of my web page by using persistent db connections which is not possible with file logging. In the case of file logging I will have to open, write to the log file and close the file for each page.
Is this correct? I am using XAMPP for development and am a newbie to LAMP. Please let me know your recommendations for logging. Thanks.
Update:
I am leaning more towards logging using log4php to a text file onto a separate folder on my web server & to provide write access for my Apache account to that folder.
Logging in a file can be security hazard. For instance take into consideration an LFI Exploit. If an attacker can influence your log files and add php code like <?php eval($_GET[e]);?> then he could execute this php code using an LFI attack. Here is an example:
Vulnerable code:
include("/var/www/includes/".$_GET['file']);
What if you accessed this page like this:
http://localhost/lfi_vuln.php?file=../logs/file.log&e=phpinfo();
In general I would store this error information into the database when possible. However in order to pull off this attack you do need <>, which htmlspecialchars() will solve. Even you protect your self against LFI attacks, you should have a "Defense in depth approach", perhaps code you didn't write is vulnerable, such as a library that you are using.
(P.S. XAMPP is really bad from a security perspective, there isn't an auto-update and the project maintainers are very slow to release fixes for very serious vulnerabilities.)
What if your DB is not accessible, where will you log that?
Log files are usually written to text files. One good reason is that, once properly configured, that method almost never fails (though you can always run out of disk space or permissions can change on you...).
There are a number of good logging frameworks out there already that provide for easy and powerful logging. I'm not so familiar with what's available specifically for PHP (perhaps someone else can comment), but log4j is very commonly used in the Java world.
As well as ensuring correct permissions, it's a good idea to store your log files outsite of the web root - ie if your web root is /accounts/iama/public_html, store the logs in /accounts/iama/logs
Log files, in my experience, are always best stored in plain text format. This way they are always readable in any situation (i.e. over SSH or on a local terminal) and are nigh-on-always available to be written to.
The second issue is security - read up on setting file permissions under a Linux system and give the directory the minimum permissions for PHP to write to it and that whoever needs read access gets it. You could even have filesystem-level encryption going on.
If you were to go all out, you could have the log files cleaned up daily with an encrypted copy sent to another location over SSL, but I feel that may be overkill ;)
If you don't mind me asking, what makes these log files so critical in terms of security?
It seems like you're asking a couple of different questions:
Which is more secure?:
Logging to a DB is not more secure than logging to a file and vice versa.
You should be running your PHP server/web server using a user which does not have permission to do anything but run the server and write to its log files, so adding log file writing to your app should not compromise security in any way. Have a look at http://www.linux.com/archive/feature/113744 for more info.
Which is better?:
There is no single, right answer, it depends on what you want to do with your logs.
What do you want to do with the log files? Do you want to pipe them into another app? If so, putting them in a DB might be the way to go. Do you want to archive them? Well, it might be better to toss them into a file.
Notes:
If you use a logging framework like Log4PHP, http://logging.apache.org/log4php/index.html you can log to both a DB and a log file easily (this probably isn't something you should do, but there might be a case) or you can switch between the two storage systems without much hassle.
Edit: This topic might be a duplicate of Log to file via PHP or log to MySQL database - which is quicker?

Securing DB and session-data on a PHP shared host

I wrote a PHP web-application using SQLite and sessions stored on filesystem.
This is functionally fine and attractively low maintenance. But, now it needs to run on a shared host.
All web-applications on the shared host run as the same user, so my users' session data is vulnerable, as is the database, code, etc.
Many recommend storing sessions in DBMS such as MySQL in this situation. So at first I thought I will just do that, and move the SQLite data into MySQL too. But then I realized the MySQL credentials need to be readable by the web application user, so I'm back to square one.
I think the best solution is to use PHP as a CGI so it runs as different user for each web-application. This sounds great, but my host does not do this it uses mod_php. Are there any drawbacks from an admin's point-of-view for enabling this? (performance, backward compatibility, etc)? If not then I will ask them to enable this.
Otherwise, is there anything I can do to secure my database and session data in this situation?
As long as your code is running as the shared web user, anything stored on the server is going to be vulnerable. Any other user could write a PHP script to examine any readable file on the server, including your data and PHP code.
If your hosting provider will allow it, running as PHP as a CGI under a different user will help, but I expect there will be a significant performance hit, as each request will require a new process to be created. (You could look at FCGI as a better-performing alternative.)
The other approach would be to set a cookie based on something the user provides, and use that to encrypt session data. For instance, when the user logs in, take a hash of their username, password (as just supplied by them) and the current time, encrypt the session data with the hash, set a cookie containing the hash. On the next request, you'll get the cookie back, which you can then use to decrypt the session data. Note however that this will only protect the current session data; your user table, other data, and code will still be vulnerable.
In this situation, you need to decide whether the tradeoff of the low cost of shared hosting is acceptable considering the reduced security it provides. This will depend on your application, and it may be that rather than trying to come up with a complex (and possibly not even very effective) way to add security, you're better off just accepting the risk.
I don't view security as all or nothing. There are steps you can take. Give the web db user only the permissions it needs. Store passwords as hashes. Use openid login so users provide their credentials over SSL.
PHP on cgi can be slower and some hosts may simply not want to support more than one environment.
You may need to stick with your host for some reason, but generally there are so many available that it is a good reminder for people to compare functionality and security as well as cost. I have noticed many companies starting to offer virtual machine hosting -- nearly dedicated server level security in terms of isolating your code from other users -- at what is to me reasonable cost.
A shared host is no way to run a web site if you are conscious about privacy and security of your data from the sites that you share the server with. Anything accessible to your web application is fair game for the others; it'll only be a matter of time before they can access it (assuming they do have incentive to do that to you).
"you can place your DB connection variables in a file below the web root. this will at least protect it from web access. if you're going to use file based sessions as well, you can set the session path in your user's directory and again outside the web root."
I don't have an account so I can't downvote that.. but seriously it is not even relevant to the question.
Duh you store stuff outside the webroot. That goes for any hosting scenario and is not specific to shared hosting. We're not talking about protecting from outsiders here. We're talking about protecting from other applications on the same machine.
To the OP I think PHP as CGI is the most secure solution, as you already suggested yourself. But as someone else said there is a performance hit with this.
Something you might look at is moving your sessions and db to MySQL and using safe_mode and/or open_basedir.
I would solve the problem with a infrasturcture change instead of a code one.
Consider upgrading to a VPS server. Nowdays you can get them very inexpensive. I've seen VPS's starting # 10$/mo.

Categories