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.
Related
I am using SQL in my app so i have created php site to manege it.
the problem is that the password required in mysqli_connect is the password to the main server (all the file maneger,mysql,etc).
what is the best way to secure my password (sending it from the app or wirte it down explicitly in the php source file).
Other suggestions?
There are many ways, but in general: put it in a file that is outside of the webroot, or a file that is otherwise unreadable from the outside. ie. a PHP file that gets executed will not expose it's source.
If you're using Apache you can store it in a file named .htsomething because Apache, by default, blocks access to any file starting with .ht*
You can store it in a file named secret.txt and block access to it by added an .htaccess RewriteRule.
For my projects I store settings in a JSON file that is outside of the webroot. One major advantage of this approach is that other applications, like a deploy or monitor tool, can read and easily generate this settings file. And it's also clean, you can't do any programming in JSON.
First up: Make a new account for your application with only the privileges required for your app!
Second: Put the in a file somewhere on your system locked down as best as possible. There are things you can do to obfuscate the password further, but in the end you will end up with a plaintext something which can be used to work your way back to the database credentials. So to be clear:
Use a database account with minimum privledges needed to run the app.
Manage security to the config file holding the password as best as possible (only the user running the service and admin should have access), keep it outside the webroot.
Just refreshed the other answer - the advice by #FritsVanCampen is also dead on.
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.
Is there a way to encrypt or enclose my code on my Linux server after deployment? I know Zend does some kind of encryption, right? Is that what people use? Is this even possible? How do I go about keeping my code secure online?
You are right, you can use Zend Encoder, Ion Cube or something like Source Guardian to encrypt your source code.
Its not really needed unless you are giving away your code and dont want people to steal it though.
What is it about your server that you think its insecure?
Periodically check the open ports on you server
Do not trust the data coming from the browser - verify it and validate it.
Periodically do an audit of the processes on your machine and who can access them
Only have files in the document root that should be accessible by the outside world. Include files etc should not exist here
Check the log files periodically to check for suspect access.
For PHP errors/warnings - find a mechanism that does not give the client (browser) any info what has gone wrong. Send that to yourself. This is true for MySql as well.
If the file-system on your server has been compromised, then all is already lost. The best you can do is restrict folders, which are writable by web-server's user.
Also keep the application code outside the DOCUMENT_ROOT. Publicly available should only be the file you actually intend to show user, or which would not show any sensitive informations: like an index.php file which contains and include ../app/bootstrap.php .
You could use Zend Guard, but this would impact owner of the code. You might not be always the one maintaining it.
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?
First time reader, first time poster (woo!)
So I've been implementing my login scripts for an informal website. Not likely to be compromised, but just to be safe, I'd like to ask if there's a security risk in having my MySQL database login stored in plaintext in the php code.
As far as I know, the code itself is parsed by Apache, so the end-user doesn't see it (just the output), which would mean it should be safe to keep... but I'd like a second opinion.
Summary:
Accessing database through mysql_connect, mysql_select_db, mysql_query. Login info stored in local variables defined at each iteration of the script, and (I think) dumped once script terminates.
Security vulnerability?
You could also consider moving the username/password combination to a seperate configuration file that lives outside the webroot. Make sure that place is not directly accessible from the webserver side.
That way, if for some reason the webserver decides not to execute PHP files anymore you don't lose the account information to the database server.
As an added bonus, if you use anything that makes a copy of the .php file (editors, SVN or whatever) in the webroot, you don't risk anyone getting around the .php execution.
That's very standard procedure for web applications that talk to a database.
I recommend taking read permissions away from the file for users other than the web server and yourself - if you have other users on your box that can spy on the file, they'll be able to access your mysql server.
Also, you should adjust the executable permission on the top directory as it'll prevent unauthorized users from even entering it.
Harden your mysql user's allowed host, so that only the boxes you need can connect to it.
Of course if your box is compromised and an attacker gains root access, there's little that will protect you.
You can add some additional layer of security by putting all your php files (except index.php of course) in a separate directory and protect them with a .htaccess file. This covers cases in which the php parser is not invoked and apache returns the files in clear text. One more thing that might be usefull: <?php defined('some_id_here') or die(); ?>. You can put this at the top of every php file except index.php (where you define some_id_here) so there is no direct access to your database-files.
Not having the bulk of the code within the webroot, where it is possible, however unlikely, is just the first line of defence that can be taken.
Your database should also be secure even if the database user and password was published - by the simple expedient of only allowing a small number of source machines to connect to the database anyway.
Defence In Depth
<?php // simplest /index.php, as the only .PHP file in the public-accessible webroot
require '../bootstrap.php';
I dont know how you connect to your MySQL database, but if you use PDO there is the possibility that the PDO constructor throws an exception.
If you dont catch this exception the Zend Engine will show a backtrace by default and reveal your connection details!
It is just normal to store the connection creds inside a php file/variable or, in that case you use PDO, in the DSN (Data Source Name). I would even suggest you to put it inside a php file, because it will gets parsed and not send plain into the web...
One step to more safety is to put the login details outside the www-root or protect it with an .htaccess file (this would make it impossible to access the file via the webserver).
However on my server it is impossible to connect not from localhost. So i dont care if someone reads my login details (it is not the case of course.).
Anybody who can login with root privileges on that web server (or possibly somewhat lower ones too) will be able to see your password -- but then, it's essentially impossible to defend against the super-user (wherever else you might keep your password, they could hack around and find it). Apart from this risk, you should be safe.
Edit: backups of the server could also be used (if unencrypted, or by somebody who can decrypt them) to recover your password if it's in-clear in your .php script. This possible attack might perhaps be mitigated (to great inconvenience/cost) by keeping the password on a different, secure location, and only sending it (securely) under highly restrictive circumstances. Is this the kind of attack you fear?