How to protect Database?

My website is programmed using PHP, and I would like advice on the best way to protect my Database and Database Settings from hackers.

Currently I have a “database_connection.php” file which contains all of my connection details (e.g. Database Host, User, Password, Name).

It is located in a directory called “secure” which has has .htaccess file in the same directory with this code…


deny from all

Anytime a script needs to access MySQL, it has this code at the top of the file…


	require_once(WEB_ROOT . 'secure/database_connection.php');

I’m not very experienced on this topic, and fear this could be my Achilles Heal?! :frowning:

Sincerely,

Debbie

If your hosting allows it you should move the file with the settings in it above the folder that the web site is in. That way it will only be accessible from PHP and not directly.

You can also place code in the file itself that tests whether it is being called or accessed directly and which disallows direct access.

You lost me on this part…

Debbie

Similar to this:

if (!is_defined('ACCEPTABLE')) exit;

Another file(s) in your script would have the following in it, thus telling your database connection file, it is being included in an approved file.

define('ACCEPTABLE', true);

However, I will say, that isn’t fool-proof. To make it better, I’d follow @felgall ; initial advice. Place the database connection file outside of your web directory and include it using an absolute path.

Sorry but I’m getting what you are trying to do.

And “Another file(s) in your script…” make no sense?! (Um, a script is a file… And what “file(s)” and “script” are you talking about??)

I have a Virual Private Server with GoDaddy.

In my config.inc.php file I have this code…


	// Physical Location (aka Document Root)
	define('WEB_ROOT', ENVIRONMENT === 'development'
					? '/Users/user1/Documents/DEV/++htdocs/06_Debbie/'
					: '/var/www/vhosts/MySite.com/httpdocs/');

	// Virtual Location
	define('BASE_URL', ENVIRONMENT === 'development'
					? 'http://local.debbie';

If I change the first constant to something like this…


	// Physical Location (aka Document Root)
	define('WEB_ROOT', ENVIRONMENT === 'development'
					? '/Users/user1/Documents/DEV/++htdocs/06_Debbie/'
					: '/var/www/vhosts/MySite.com/[b][COLOR="#FF0000"]SECRET_FOLDER_OUTSIDE_ROOT/[/COLOR][/b]');
				: 'http://www.MySite.com');

…is that what you are talking about??

Sincerely,

Debbie

Okay, assume you have an index.php, that “includes” the database connection file.

Your index.php would have the following:

define('ACCEPTABLE', true);

Your database connection file would have (should be at the top of the file):

if (!is_defined('ACCEPTABLE')) exit; 

Since index.php has defined ACCEPTABLE, the include for database_connection will complete.

If you had another page, let’s call it article.php, that DOES NOT define the ACCEPTABLE constant and tries to include the database connection file, the database connection file will exist at the IF check and not load the entire file (so the database connection won’t be available to article.php.

Second part:
I’m not sure what WEB_ROOT is used for, but you’d only “have” to move your database connection file outside of your httpdocs, although it doesn’t hurt to move anything that is used in an include (everything, except your index.php, articles.php – which are web facing files).

Okay, I get what you were saying, but I’m still not following how this makes things more secure?

It almost sounds like you are trying to handle a scenario where a hacker uploaded their own file or something?

Can you please explain the overall logic of this more?

It is what it says it is.

It is a constant that defines where my Web Root is on either my local dev environment or on my production environment. (I usually prepend that to relative paths so things point to “one source of truth”.

Right, and that is what I showed in my last post…

Currently, GoDaddy defines your VPS WEb Root like this…


	define('WEB_ROOT', '/var/www/vhosts/MySite.com/httpdocs/');

I asked if something like this is what you meant…


	// Physical Location (aka Document Root)
	define('WEB_ROOT', '/var/www/vhosts/MySite.com/SECRET_FOLDER_OUTSIDE_ROOT/');

Sincerely,

Debbie

Yes, it is to prevent a scenario where someone uploads a file and tries to include your database connection file (or directly access it via HTTP). Granted I’m not a huge fan of this technique myself, primarily because it isn’t nearly as protective as the other technique.

Yes, assuming httpdocs is the external facing directory inside MySite.com and MySite.com is not the external facing folder itself (so files inside MySite.com but not inside httpdocs are not accessible via http://MySite.com/.

PHP files are text files.

So generally if someone tries to go to “http://your-domain.com/secret-database-info.php” they wouldn’t see the code (just output if any.).
But if for some reason the PHP engine fails to run the file, they’ll see the text in all it’s glory.

That most likely won’t happen, but if “secret-database-info.php” is outside of the root, your site’s script can get it but a direct HTTP request for it is impossible.

The use of “DEFINE(“my-sites-file”, TRUE)” is often used so that a direct HTTP request for a “secret-database-info.php” file that is under the root will exit. And for the most part this is secure, but having the file outside of the root is more secure.

I have to re-check with GoDaddy, but I am 90% certain that MySite.com/ is my VPS’s directory and that anything inside of it is NOT outward facing. And that you have to have files inside of MySite.com/httpdocs/ for them to be outward facing.

Sincerely,

Debbie

:smiley: Sounds like you got a good handle on this now, so I think you’ll be able to implement it just fine :slight_smile:

Okay.

Let me see if I understand what you and CPRadio were talking about…

First, Mittineague, if my “database_settings.php” file was in the Web Root, would this code help to prevent it from displaying the actuals settings if some tried to load “www.MySite.com/database_settings.php”…

configuration/config.php


define('LOAD_FILE', TRUE);

database_settings.php


if !(LOAD_FILE){
	exit();
}

And as far as what CPRadio suggested, would this code work…

configuration/config.php


define('LOAD_DB_SETTINGS', TRUE);

display_member_listing.php


if !(LOAD_DB_SETTINGS){
	exit();
}

(I guess I didn’t quite get the need for is_defined…)

Sincerely,

Debbie

Except for having different CONSTANT names, those code examples look the same.

The idea is that in files you want to not be able to be HTTP requested directly, you put the check to see if the CONSTANT has been defined else exit.

In files that you want to be able to access the “sensitive” file you define the CONSTANT.

Speaking of is_defined, it’s a good idea to wrap your define in if(!is_defined) as trying to define something that already has been can cause errors.

If I move “database_settings.php” from here…


	/var/www/vhosts/MySite.com/httpdocs/configuration/');

To outside of the Web Root here…


	/var/www/vhosts/MySite.com/SECRET_FOLDER_OUTSIDE_ROOT/

…then you guys are saying that is safer because hackers won’t be able to access or display the file via HTTP, right?

If that is the case, then don’t I have to be worried about my config.php file which contains this…


	define('ENVIRONMENT', 'development');

	// Physical Location (aka Document Root)
	define('WEB_ROOT', ENVIRONMENT === 'development'
			? '/Users/user1/Documents/DEV/++htdocs/06_Debbie/'
			: '/var/www/vhosts/MySite.com/httpdocs/');

	// Virtual Location
	define('BASE_URL', ENVIRONMENT === 'development'
			? 'http://local.debbie'
			: 'http://www.MySite.com');

Isn’t that “sensitive” information too??

Sincerely,

Debbie

That’s really a question you have to answer. Think of it this way: “If someone got a hold of this, would I care? Would it give them some knowledge about my system that I don’t want them to know?” If you answer yes, then you need to protect it the best you can, otherwise, leave it be.

If my config.php in inside my Web Root and it got exposed, then hackers would know the location of my “secure_directory_outside_web_root”.

And if they knew where that directory was, then wouldn’t that make it easy to hack into that folder, thus threatening the new location of my database_settings.php file??

That is my concern…

Sincerely,

Debbie

That sounds like a very valid concern to me. So protecting that information sounds like a good plan :slight_smile:

You’re a big help sometimes!! :stuck_out_tongue:

Debbie

To me, the logic is kind of “circular”…

I need to place my Database Settings in a not_in_web_root_directory for security, but…

I need a Config file to define where my not_in_web_root_directory is at, and…

If I place the Config file in the not_in_web_root_directory location, then my scripts in the Web Root can’t see it to know where my Database Settings are at?! (:

Crazy!!!

Debbie

Your scripts should be able to locate it and use it (via an absolute path, /home/user/MySite.com/mysecretfolder/config.php). It won’t be accessible via HTTP requests though, which is a good thing.