Storing database username and password in a php-file

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Storing database username and password in a php-file

Post 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?
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post 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..

?>
User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Post 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?
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post 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...
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post 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.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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.
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Post 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.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post 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.
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Post 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.
rubberjohn
Forum Contributor
Posts: 193
Joined: Fri Feb 25, 2005 4:03 am

unset

Post 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
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Re: unset

Post 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
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Post 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 ...
?
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

Yes. :)
User avatar
hawleyjr
BeerMod
Posts: 2170
Joined: Tue Jan 13, 2004 4:58 pm
Location: Jax FL & Spokane WA USA

Post 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)
rubberjohn
Forum Contributor
Posts: 193
Joined: Fri Feb 25, 2005 4:03 am

Post by rubberjohn »

cheers, thats made that a whole lot clearer
Post Reply