Database settings security - php

I've got a file on my site called dbSettings.php with the lines:
<?php
$host = "localhost";
$dbName = "database";
$user = "user";
$pwd = "pass";
$db = new mysqli($host, $user, $pwd, $dbName);
?>
I get this page into my main page with the require_once() function. Is there ANY way for someone who's reaching this page through the server(my domain) to get a hold of the values stored in these variables? Is this a secure way to keep the database settings?

This is a common way to keep database credentials in php applications. Generally a config file would keep those settings some good practices are
Proper file permissions to the file such as
chmod the file 640 instead of 600. Keep file ownership to your user and change group to webserver. This way, the webserver can only read and not modify it
Move file out of webroot so its not accessible directly by others
Only give needed database privileges to that database user
If user just needs to access one database only give privileges for that database and data not give Structure or Administration related privileges if not needed
If possible protect with
.htaccess
<files dbSettings.php>
order allow,deny
deny from all
</files>

If your webserver is configured properly, web clients should not be able to view the settings. When a .php file is accessed through the webserver, it executes the script, and returns what it prints to the client. The source code of the script is not sent to the client.
You can make things more secure by putting files like this outside your webroot. Then clients can't even address them, they can only be accessed by being required from another script.

From what I know of PHP security, there are a couple ways for this information to leak:
If dbSettings.php can be somehow loaded by a client, without the server processing the page. This would obviously give out the details, since they can just look at the file. Generally speaking, if you server is correctly configured, and and you have no backup files created, this shouldn't be an issue.
If dbSettings.php is loaded by the client, you want to make sure no errors could leak the information (so for instance the mysqli creation can't fail and leak the information). Since your app isn't initialized, it is possible for errors you regularly mask to appear.
As for securely storing the information, I don't believe there is a much better solution then to do as Barmar suggests, and put the configuration files somewhere the web server doesn't actually serve files. PHP can still generally access these files, but the web server won't give them out to clients. Depending upon your hosts, this may or may not be possible.

Make sure that your dbSettings.php is not accessible through URL, so php must be able to read this file, but this file should not be accessble by typing it's address in the browser (by guessing, luck, etc). But if you have properly configured www server you should be fine because php will be processed and blank page will be returned to user.
Only if you misconfigure your web server so it will not process php pages but return them to the user - the file will accessible by others to download. So again your settings must not be accessible from outside.
Besides that You should never have echo, dump, etc those values from your php code on production server and you should also catch any errors from mysql driver so they will not be printed out to the user on production server.

The most important security measure, as outlined by previous answers, is proper webserver configuration.
As you are creating a configuration file that should never be directly accessed, you can safely place it outside the server root, or in a directory for which the server is configured to not serve files. As long as the file has proper permissions, you can include() it without the webserver's help.
If for what ever reason you choose to stick with having the configuration file in an accessible location, you can use a define() trick to prevent unauthorised execution. This is done by defining a constant in the file to include the config file, prior to the actual include(), then checking for the existence of the constant in the config file itself.
example.php:
<?php
define ('my_const', 1);
include ('config.php');
echo $super_secret_data;
?>
config.php:
<?php
if (!defined ('my_const'))
die ();
$super_secret_data = 42;
?>
Of course, the only security benefit here is that executable code will not run without the constant if the page is accessed directly, and that its data will not be accessible by files that do not define the const (which is pretty bad security through obscurity, as you can probably still call getfilecontents() on the file).

Related

Can another site use my PHP script externally?

So I make some basic PHP software and have a config file. The file contains database information only, there are no user passwords etc etc. However, I declare the variables just as normal ($test = "test";), and was wondering if someone could use require/include to get the variables? I think they wouldn't be able to access the variables with file_get_contents(); due to the way PHP works. But I'm not sure about require/include. Obviously you can do it locally, but what about from other sites?
Example to clear things up:
http://example.com/config.php
$db_host
$db_user
$db_pass
$db_base
Now with http://anotherexample.com/somepage.php would they be able to use require/include to fetch the PHP script from example.com and then echo the variables?
Thanks!
If you file is a PHP file, and the configurations are PHP code, and your server is setup to correctly run .php files through the PHP processor...then, only people within the same server could potentially require or include the file. There are some basic PHP base directory configurations, etc., and some "safe mode" features that will prohibit users on shared servers from being able to do this--so long as it's setup correctly.
Other than on a shared server that's not configured to protect your directory from other users on that same server...about the only way the file can get compromised is if Apache stops recognizing the file extension and serves it to the web browser as plain text, etc...which is also a configuration issue.

PHP & MySQL connection more secure

I have a small page that contains the connection data to my MySQL DB, which I include in other pages that require it. The small code is:
[connect_DB.php]
----------------
<?php
define("HOST", "localhost");
define("USER", "myUser");
define("PASSWORD", "myPasword");
define("DATABASE", "members");
$mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
?>
A friend of mine proved to me that he can download the .PHP file, and in less than 2 min, he did. That means he got the login info for my MySQL server. And I was wondering if there existed another way of connecting with the database, without putting the password in a file, etc. He recommended me use SSL or TSL, or simply configuring the HTTPD.CONF or .HTACCES to not allow "exterior" access to the file. Is that correct or achievable?
I am actually testing this on Wamp Server (Win7), and I cannot create a .HTACCESS file because It tells me to enter a name for the file (which I am already introducing! :( ) every time I try to name it that way.
I understand that this may be a duplicate question, but believe me I read a lot of t hem but I don't understand what should I do. In advance, thank you.
I am pretty sure that your host Provider is not parsing the PHP files, because it would not be possible to download the sources if they'd pass the interpreter.
Make sure you have PHP installed, configured and activated, contact your provider's support in case of questions. The easiest way to test this is to upload a file:
test.php
<?php phpinfo(); ?>
To protect a file it's enough to put the your database config php outside of public_html, html or htdocs directory (one of these is most likely to be your document root), where you still can include(); it via PHP.
Other solution is to protect the file via .htaccess where you put something like that inside the file and upload it to your document_root:
<Files db_config.php>
deny from all
</Files>
To add a little more security,
you can protect the db_config.php by adding this on top:
if (!defined('IN_MY_PROJECT')) {
die('forbidden');
}
and put this on top of your index.php:
define('IN_MY_PROJECT', true);
Most likely, Your server is not setup correctly, meaning the PHP engine is not running, so its just sending or displaying the file contents back as say text/html and not being parsed by PHP. This is the only way that some tool like you mentioned in comment could possibly access the file, a tool like that would also not see the file if there was not a link to it somewhere, so perhaps you have Directory Indexes enabled to.
To test you have PHP enabled simply make a file and put in it:
<?php phpinfo(); ?> if it displays your php info then im stumped, if not then its proof your server is misconfigured for PHP.
Though once fixed, it is good practice to put sensitive files outside of your web root. And not a good idea to set your values in constants as a function like get_defined_constants() will give access to the sensitive values. Just put them directly in the construct arguments.
if you want to block access to a directory where only PHP can access you make a .htaccess file with deny from all in it, this will cause the server to send a 403 Forbidden.

Secure php files so only I can execute them

Currently I have a bit of a 'different' set-up. My main files are on server1; this server simply delivers the content through php and mysql. But that's just the front end. In the back, on server2 (homeserver), are alot of different scripts doing various things that could not be done on server1, since it's a shared host and thus resources are limited.
This setup works great. If server2 loses power or something the site won't be updated, but what's there is still available, and it can just catch up once back online. But here's the problem; all scripts on the homeserver are wide open for everyone to execute. As an example, my database-syncing script;
Server1 detects it's databases hasn't been synced up with the one on server2, so it initiates the syncing script.
<?php
//This initiates the script on server2, which then dumps it's database into a .sql file
file_get_contents('http://server2.x.com/backup/backup_mysql.php');
//This reads out and saves said database file locally for processing
$myresult2 = file_get_contents('http://server2.x.com/backup/backups/db-backup.sql');
file_put_contents_atomic("backups/db-backup.sql", $myresult2);
//This will delete the backup file from server2
$deleteurl = 'http://server2.x.com/backup/backup_mysql.php?delete=true';
$myresult3 = file_get_contents($deleteurl);
//This initiates bigdump for processing the sql file
include_once('bigdump.php');
?>
As you can see, this opens up some obvious security flaws. *backup_mysql.php* can be used by anyone who knows the address to server2 and even once that's fixed, someone who monitors the /backup folder can retrieve the sql backup before my script deletes it again.
How do I prevent all this from happening?
You can use Apache2 webserver directves to deny access to certain locations from all IPs except your own.
You should look into using HTTP authentication to prevent access to everything published by server 2. This way you 'd be able to lock everyone else out of server 2 with minimum hassle.
With HTTP auth in place, your file_get_contents calls would need to change to include the credentials, for example
file_get_contents(http://user:pass#server2.example.com/data.php);
If you are worried that someone might sniff the credentials from the network, then you can also move to HTTPS. Since both the server the only user will be your own applications, you can create the certificates yourself and make your scripts accept them as valid.
You can protect your files or folders through .htaccess:
Password protecting your pages with htaccess
Here's another solution besides .htaccess:
server1/index.php
server1/config.php
server2/index.php
Lets say you dont want people accessing config, use the define function. Define a unique name and check if it's defined in the config.php file before setting variables / methods.

How to make sure no scripts except those under my own domain, can include the db connection file?

I would like to ensure that any scripts that are trying to "include" my database connection file are located under my own domain. I don't want a hacker to include the database connection file to their malicious script and gain access to my database that way. My connection file's name is pretty easy to guess, it's called "connect.php". So without renaming it and taking the security through obscurity route, how can I protect it by making sure all connection requests are made by scripts residing under my own domain name? How can this be checked using PHP?
Generally speaking if someone tries to include a file on your domain, they will see the results of the execution of that file. What do you see when you load the connect.php script in your web browser? Thats what they'll see as well if they try to include a remote file.
That said, its generally a good idea to keep important files inaccessible from the outside of your public web space. So, if your website is /var/www/yoursite/ then keep your connect.php in /some/dev/dir/yoursite and include the files from your pages using require_once '/some/dev/dir/yoursite/connect.php';
thetaiko's answer addresses the fundamental issues here - but if anyone else has access to run code on the server (i.e. its a shared server) then access to the file will depend on how the server is configured.
There are lots of ways that access might be constrained - e.g. suphp, base_opendir, multiple chrooted servers. The only way to find out what's going on for sure is to casr yourself in the role of the hacker and see if you can access files outside your designated area.
C.
What do you mean by including your connection file? If a script does include "connect.php" then they can see the source code of the file, so whatever security measures you add to that file will be pointless, as it will be like:
if($notFromHostname)
{
echo "DONT LOOK AT THIS";
die();
}
define('DB_PASS',"myPassword");
...
And the "hacker" will clearly be able to see your password. You are probably better off using something like iptables to deny hosts that are not from a specific domain.
Are you on a shared server and don't want other users of the same server instance to be able to get at your files? That'd be up to your server provider, then, to provide some sort of chroot or virtual system to keep your things in. For Apache, mod_suid can accomplish this nicely, and each vhost gets its own userid and permissions set.
If you want external users to not be able to get at your files, then unless you've badly munged your code, or the server's badly misconfigured, then all they'll get when they visit http://yourserver.com/connect.php is a blank page
No other user than yourself should have access to your PHP files in any way, as Felix mentioned. However, this is how you'd check in PHP:
if($_SERVER['SERVER_NAME'] != "example.com")
die("I've been kidnapped!");

Where do you store your PHP script configurations like DB access data?

I have an config.php file where I simply make an huge array that contains all the framework configuration. Also the database source string thing like "mysql:host=localhost;dbname=mydb" (whats that called, btw?) and username + password for DB. I'm afraid this is:
stupid
not good; better solution there
not secure (?)
so how do the PHP experts do that?
If you have a www, httpdocs or public_http folder or something like that, where your php application is situated, then it is good practice to put the config file outside of that folder, and just access it like this:
include "../config.php";
Nobody can gain access to that file without FTP access, and so it's relatively safe compared to having it in the application folder.
If you don't have such a folder, you can create one, and make a .htaccess file in the root, which redirects all requests to that folder. There are many different ways to do that, but that's a different question all together.
I store it in a plain text ini style configuration file, usually above the web root so as not to allow users access to it. In the cases where it is accessible, I usually have a .htaccess file with deny from all so as to prevent all access to it.
Storing it in a PHP file accessible to users should be fine, but it isn't ideal. If the sever handles PHP files correctly, even if people can access the file, they can't access the values as they just get the output (nothing). There are of course issues with this, (see comments).
Using PHP files is the most common method with PHP projects (Both FOSS and commercial) I have used. Most of them didn't both storing them above the web root. With any stable setup, there is on the face of it very little point in storing your configuration file above the web root, although given Murphy's law it is worth doing if you can (That or use .htaccess or the equilivent for your server to deny user access to a directory)
That's how most do it, but you could also try some of these solutions:
Save the configuration file outside the web folder (this requires that the open_basedir configuration in PHP is disabled).
Restrict access to the configuration file by using .htaccess:
<Location /config.php>
Order deny,allow
Deny from all
</Location>
Use .ini files and the parse_ini_file function (this is not really a solution in itself, but could be combined with the others)
Why storing DB username & password in "config.php" is not fine? as long as i know, the data in this file can't be shown publicly.
E.G.
<?php
$DB_User = "amindzx";
$DB_Pass = "Something";
// connect to DB and so on.
?>
unless if the hacker can gain access to your FTP.
Why it's stupid to hold simple config.php file without any securities? Even if programmer finds this file he can do nothing, because, like amindzx said "this file can't be shown publicly." Or I'm wrong?
With sensitive info like database or payment gateway credentials, and when I have control over the server, I like to add lines like the following to my apache virtual host config:
SetEnv DB_USER "myuser"
SetEnv DB_PASS "mypass"
In your PHP, you can access these using $_SERVER['DB_USER']. You can make this config file readable only by root, which you can never do to a file that php accesses at run time. One caveat: Be sure you disable php_info and don't expose these variables with something silly like print_r($_SERVER). (Much of this is paraphrased or stolen from here.)
For non-sensitive configuration, I like to do a class full of constants, which is similar to your setup, but I like the OOP-ness of it.
class Application
{
const CONTACT_EMAIL = "me#mysite.com";
}
usage:
$contactEmail = Application::CONTACT_EMAIL;
I usually store settings in a config.php too, such as database connection settings, file paths etc.

Categories