Page 1 of 1

Storing database username and password in a php-file

Posted: Mon Jan 09, 2006 5:39 am
by StumpDK
I have a site which use a database class. The php-file containing the database-class also contains the username and password to the database.
These informations is used in a connect-function i the class.
But is this secure? And can I create a class that can connect to a mysql-database without having the username and password stored in the file?

Posted: Mon Jan 09, 2006 5:50 am
by Jenk
This has cropped up many times, one of the best solutions:

keep the file that contains the username and password above the document root.

e.g.(/var/www is the docroot):
/var/password.inc.php

Code: Select all

<?php

define('MYSQL_USERNAME', 'dbuser');
define('MYSQL_PASSWORD', 'dbpass');
define('MYSQL_HOST', '127.0.0.1');

?>
/var/www/includes/mysqldb.class.php:

Code: Select all

<?php
class MySQLDB
{
    var $dbhost;
    var $dbuser;
    var $dbpass;
    var $dblink;

    function connect($host, $user, $pass)
    {
        $this->dbhost = $host;
        $this->dbuser = $user;
        $this->dbpass = $pass;

        $this->dblink = mysql_connect($this->dbhost, $this->dbuser, $this->dbpass);
    }
  //etc..
}
?>
/var/www/index.php:

Code: Select all

<?php

include_once('../password.inc.php');
include_once('./includes/mysqldb.class.php');

$db = new MySQLClass();

$db->connect(MYSQL_HOST, MYSQL_USERNAME, MYSQL_PASSWORD);

//etc..

?>

Posted: Mon Jan 09, 2006 7:22 am
by jayshields
Yeah that's the best way to do it, but I never understood "putting files below the document root", if I put files below the accessible folder, then (obviously?) I can't access it.

Do you need to change some settings in Apache or something?

Posted: Mon Jan 09, 2006 7:27 am
by Maugrim_The_Reaper
The credentials have to be stored somewhere...

Its generally safer to put them above the docroot - see above. You could also make then environmental variables (something Chris Shiflett seems to love) and access them via $_SERVER['DB_USER'], etc.

If you're on a shared host - the first option is more likely.

One thing always to remember is to be certain that whatever DB user you have - only grant that user whatever priveleges they require for the application to work (and no more). By definition that often means never use your root user (whichever base user is attached to your shared host account). Create others as required. Then if one db user is compromised, at least a hacker cannot run havoc across your entire database system...

Posted: Mon Jan 09, 2006 8:44 am
by Jenk
jayshields wrote:Yeah that's the best way to do it, but I never understood "putting files below the document root", if I put files below the accessible folder, then (obviously?) I can't access it.

Do you need to change some settings in Apache or something?
As a user with a user-agent, no, you can't. Which is exactly what you want!

However, the file will be available to the PHP engine as a server side include.

Posted: Mon Jan 09, 2006 9:10 am
by feyd
storage as a define isn't a good idea. Why? Because if someone is able to add code to the system, either by plugin or whatever, they can just show all defines. Instead, use a standard variable. After the database connections are made, unset() the variables.

Posted: Mon Jan 09, 2006 10:33 am
by matthijs
feyd, could you elaborate on what you say about using a define as storage not being safe. I was convinced about the opposite. I thought that using a variable to store db username and password would be less safe because constants cannot be overwritten once defined, while variables can be overwritten (maybe due to some leak somewhere else.... )

Thanks.

Posted: Mon Jan 09, 2006 10:59 am
by Maugrim_The_Reaper
What feyd is saying is that if you expect to allow 3rd parties add something like...plugins...to your base source code, those 3rd party script will access to PHP on your system, hence they can read your database credentials, and hence they could conceivably send them to someone else - unless you peer review those plugins before adding them to your system.

So adding as constants makes them available to all 3rd party add-ons on your system. Variables are as bad sometimes - depends where initialised, what they're scope is etc. The safest route is to use them once and discard as quickly - unset().

Nothing is foolproof however when you're talking about PHP on your own system - so my usual steps are to leave the credential settings file away from webroot, include them once (in whatever form), and destroy the holding variables as soon as possible. That limits the risk of revealing credentials. 3rd party code could still include them again, etc. if they were knowledgeable enough about your system and application.

Then always use a limited db user to start with - limit the risk of compromising your entire database system. This is even more important in my view - do not use the root/shared host account owner credentials.

I'm rambling again, aren't I?

1. Create a new user for each database, with priveleges for that database only. (If an app needs two databases, well what you can't help you can't help...)

2. Put credential above the webroot. This prevents an http request reading that file by accident. Or set as environmental variables (not very common - esp. on shared hosts). Unset any variables holding credentials after use.

3. Where 3rd party plugins/modules/other code involved. Well, the lesson is not to let any user add PHP to your application until you are absolutely certain its clean. People can be very trusting of 3rd party modules for other applications - its prefereable to look for code reviewed by the original developers, or use a trusworthy source. Unreviewed code can be dangerous.

Posted: Mon Jan 09, 2006 11:57 am
by matthijs
I'm rambling again, aren't I?
:) But useful rambling, that is!

I understand the reasoning better now. Indeed, every method has its possible weak points.

The more I learn here, the more I start to see how limited most/some (cheaper) shared hostings are. Not being able to put anything above webroot, not being able to grant the level of prevelage to db users, not being able to change ini settings, etc etc

But back to the subject: unsetting variables is a good suggestion. Thanks.
1. On my shared hosting accounts I'm the only user for 1 database.
2. Not possible on my host, but I'll remember this tip (I've read it in other places as well)
3. I agree. That's one of the reasons I'm learning stuff here. To be able to review other's code or write it myself.

unset

Posted: Tue Jan 24, 2006 1:53 pm
by rubberjohn
hiya,

excuse me if this is an obvious one but if you store your db connect file above the doc root, to unset them is is just a case of using the unset function after you have finished with the database or at the end of each page where a db has been connected?

thanks

rj

Re: unset

Posted: Tue Jan 24, 2006 6:54 pm
by John Cartwright
rubberjohn wrote:hiya,

excuse me if this is an obvious one but if you store your db connect file above the doc root, to unset them is is just a case of using the unset function after you have finished with the database or at the end of each page where a db has been connected?

thanks

rj
Once you have made the connection, get rid of them :P

Posted: Wed Jan 25, 2006 2:30 am
by matthijs
Something like:
/var/password.inc.php

Code: Select all

<?php
$mysql_username = 'dbuser';
$mysql_pass =  'dbpass';
$mysql_host =  '127.0.0.1'; 
?>
/www/somepage.php

Code: Select all

include_once('../password.inc.php');
include_once('./includes/mysqldb.class.php');

$db = new MySQLClass();

$db->connect($mysql_host, $mysql_username, $mysql_pass);

unset($mysql_host, $mysql_username, $mysql_pass);

// continu script ...
?

Posted: Wed Jan 25, 2006 3:31 am
by Jenk
Yes. :)

Posted: Wed Jan 25, 2006 8:44 am
by hawleyjr
Check out the "Authentication Data Storage" (Page 8) section of the following document, it goes into some detail and has some examples.

(PDF) http://dev.mysql.com/tech-resources/art ... ty-ch3.pdf (PDF)

Posted: Wed Jan 25, 2006 12:53 pm
by rubberjohn
cheers, thats made that a whole lot clearer