Forum Moderators: coopster

Message Too Old, No Replies

Securing/hiding the MySQL password in PHP scripts

How do you do it?

         

grahamstewart

1:41 am on May 21, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I am creating a dynamic PHP site based on content from a MySQL database.

so I have lots of code like


mysql_connect(DB_SERVER, DB_USER, DB_PASSWORD);
mysql_query( $sql );

Now I need to define DB_USER etc somewhere.
But it would be quite nice if this information wasn't lying around for everyone to see.


My first approach was to create a 'config.php' file and place it outside my document root in directory called private in my user directory.

I could then include it in scripts with

require_once 'private/config.php';
(after suitably modifying the php include path)

This at least meant that the file containing the password could never be accidentally served by the webserver if there was some kind of configuration mess up.

This seemed to work pretty well. However, there are two problems with that approach..

  • its a shared server so other users could read the file

  • it requires my user directory to be world readable and if I change it to this it gets changed back by an automated script on my webhost.

    So I contacted the webhost and asked them what they suggested. They recommended running all my scripts that require DB access as CGI.

    This involves copying them to the cgi-bin folder and adding a #!/local/bin/php line to the top of them.

    Since CGI uses suexec to run as me (instead of nobody/nobody) it has access to files that only I can read so the password can stored safely.

    I see the sense in this approach but I'm hesistant because..

  • Moving all the scripts to cgi-bin will ruin my site structure and will give me ugly looking URLs for my pages

  • I'd have to modify my own test environment to match this CGI setup (and I'm on Windows so I'm not sure how easy this will be).

  • I believe CGI is slower than the apache module approach and causes greater server load



    Any suggestions on a better approach or should I just stop worrying about it and put my password in plain view? ;)
  • DrDoc

    4:00 am on May 21, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Well, running it as CGI is a good solution (depending on the setup)...

    But I usually put all sensitive information in a file, then I just include it. Provides better portability too. The file is placed, either outside the document root, or in a password protected folder.

    $mysql_password = "mypass";

    This way I can change information in just one place, and it will affect all scripts. :)

    isorg

    5:12 am on May 21, 2003 (gmt 0)

    10+ Year Member



    the file containing the password could never be accidentally served by the webserver if there was some kind of configuration mess up

    I have often wondered about this. I put my password in a config.php file in the same folder as any .php file that may need it. Under what circumstances would the webserver serve the config.php without parsing it?

    The only thing I could think of was if I removed the "AddType application/x-httpd-php .php" from the httpd.conf file. That would be a very easy problem to spot as all the .php pages on the site would be served without parsing.

    So I've stopped worrying about it. For added security I like DrDoc's idea of putting it in a password-protected directory, so I might do that, thanks.

    BCMG_Scott

    12:12 pm on May 21, 2003 (gmt 0)

    10+ Year Member



    my "solution" to this was to create a file outside of the web doc root. I called it .db.inc

    $MYDB_USER = "some_mysql_user";
    $MYDB_PASS = "secret";

    Then I issue a

    require /somepath/notin/webroot/.db.inc

    The reason I used the . prefix is that usually ftp sessions don't show those files, so it may not be easily seen.

    Another possible option is to use a local php.ini setting. You can set values in .htaccess that will specify what user and password to use when connecting to MySQL. (See Section 4 of the PHP manual).

    Scott Geiger

    lorax

    1:57 pm on May 21, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    Normally I have my dblogin info within a PHP file (not an .inc file) and located in a seperate dir at or above the level of the website root. I call it with a require().

    Lately I've been thinking about using a homemade function to execute this. Even have gone so far as to begin planning a generic class which would contain several basic functions.

    jatar_k

    4:14 pm on May 21, 2003 (gmt 0)

    WebmasterWorld Administrator 10+ Year Member



    I have always put it below the root and given it a .php extension so that it is always parsed and wont show the contained info as would a .inc.

    its a shared server so other users could read the file

    seems to be the main problem. Do they have shell access or ftp? With shell there isn't much you could but if it is only via ftp you could do as Scott suggested and start the filename with a dot to keep them from viewing it in ftp.

    grahamstewart

    10:27 pm on May 21, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    drdoc said:
    I usually put all sensitive information in a file, then I just include it. Provides better portability too. The file is placed, either outside the document root

    BCMG_Scot said:

    my "solution" to this was to create a file outside of the web doc root

    lorax said:

    I have my dblogin info within a PHP file (not an .inc file) and located in a seperate dir at or above the level of the website root.

    Yeah, yeah and yeah... but as I said, I can't do this because my webhost forces my home directory to only be readable by me (i.e. chmod 700) so PHP can't read any files in it. :(

    The CGI version of PHP can, but it sucks for the reasons stated.

    Any other ideas?

    Under what circumstances would the webserver serve the config.php without parsing it?

    Most likely situation would be that your host upgrades their installation of Apache (or whatever) and forgets to add the PHP handling back into the configuration file (so all php gets served as plain text).

    grahamstewart

    10:29 pm on May 21, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    jatar_k: all users have shell access - but its monitored and they jump on anyone who peeks in the other users directories (I know cos it almost got me barred :))

    lorax

    1:41 pm on May 22, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    Have you thought or/tried using some form of MD5 Hash [php.net] as a way to 'hide' the dblogin information?

    figment88

    2:05 pm on May 22, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    I'd think of switching hosts. Seems to me decent shared servers give you a directory above www root for precisely this reason.

    daisho

    2:40 pm on May 22, 2003 (gmt 0)

    10+ Year Member



    I'm not sure what FTP clients that you use but all the ones I use show dot files. Though they will be hidden from shells unless you do "ls -a" without the "-a" option ls will hide all files that start with a dot.

    On a shared server there is not much you can do short of the cgi method. That's the tradeoff for speed.

    You may want to protect even further by having your include file like:

    global.php:
    <?
    ConnectToDatabase();

    function ConnectToDatabase () {
    global $conn;

    $user='xxx';
    $pass='xxx';
    $host='xxx';
    $db='xxx';

    $conn=mysql_connect($host,$user,$pass);
    mysql_select_db($db,$conn);
    }
    ?>

    This still lets you handle your database connection in one place but has the added benifit of not having global variables containing your login information. So even if another user on the server included your file they could only call the function to connect to the database. Still not great but a little better. For them to see your information they'd have to fopen the file and read it in as raw text. A little more work.

    daisho.

    DrDoc

    5:18 am on May 23, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    I'm not sure what FTP clients that you use but all the ones I use show dot files.

    It has nothing to do with the FTP program... It depends on the setting in httpd.conf (or your local .htaccess for that matter).

    grahamstewart, there are lots of options even if you can't put the file outside the document root. For example, name the file something funky (easterbunnybookshelf.php) and include() it.

    daisho

    12:40 pm on May 23, 2003 (gmt 0)

    10+ Year Member




    It has nothing to do with the FTP program... It depends on the setting in httpd.conf (or your local .htaccess for that matter)

    You are incorrect here DrDoc. Linux (and unix I beleive) shells/ls do not how files if they begin with a "." this has nothing to do with apache or httpd.conf.

    Most FTP clients will show files that start with a ".".

    daisho.

    BCMG_Scott

    12:47 pm on May 23, 2003 (gmt 0)

    10+ Year Member



    Another option, but only if you own the server, would be to write a login Zend extension in C. Compile it in with the main PHP C code and then delete the source. Of course if you ever change your password you'd have to recompile it all over again.

    Other ideas:

    1. Security by obscurity - name the include file something weird and if possible place it outside the docroot.
    2. change your password often
    3. don't make your password easy to guess
    4. BACKUP, BACKUP, BACKUP!

    and for the sysadmin - make sure the user does not have more permissions than it needs (i.e. shutdown privs)

    Scott

    grahamstewart

    10:35 pm on May 26, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Hi guys,

    Sorry to drag this one up again but I've been away for a bit and I'm still no closer to a solution.

    lorax said:

    Have you thought or/tried using some form of MD5 Hash as a way to 'hide' the dblogin information?

    Umm.. yeah.. but MD% is one-way - there is no way to un-MD5 and you need to give the

    mysql_connect
    function a plain text password.

    Even if I had some reversible encryption available I'd still have to store the password for that somewhere - so I'd just be moving the problem to another level. :(

    figment88 said:

    decent shared servers give you a directory above www root for precisely this reason

    Can't switch hosts - we're tied because my client knows the reseller. There IS a directory above www root - but the problem is that it is only readable by MY account and not by the nobody/nobody account that PHP uses. (and if try and change these permissions they get changed back automatically by the hosting company). :(

    jatar_k said:

    if it is only via ftp you could do as Scott suggested and start the filename with a dot to keep them from viewing it in ftp

    As daisho says, most ftp programs let you view . files (usually by selecting a menu option somewhere). Might stop a script kiddie but anyone with any experience at all will know to look for . files. :(

    BCMG_Scott said:

    Another option, but only if you own the server

    If I owned the server it wouldn't be a problem at all, but I don't. Its a shared server with a hosting company. :(

    DrDoc said:

    For example, name the file something funky (easterbunnybookshelf.php) and include() it.

    But whats the point if other people can read the scripts and see lines that say

    include 'easterbunnybookshelf.php';


    If I put the password in a php file could I setup .htaccess to prevent that file from ever being served externally? So it can only be include by other php scripts on the same server?

    That way I could at least prevent public attacks and I'd only have to worry about 'internal' security (i.e. other sites using the same host).

    Thats the best I can think of right now - other than giving up and using the messy cgi option.

    Thanks for everyones help,

    Graham

    daisho

    10:55 pm on May 26, 2003 (gmt 0)

    10+ Year Member



    If you do that you don't have to worry about .htaccess at all. If you put it all in a global.php file it will be server side parsed. If the client requests that page directly they will just get an empty page. No security risk there.

    daisho.

    grahamstewart

    11:23 pm on May 26, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    As I said in post #7, there is a security risk.

    The webhost might decide to upgrade its version of Apache and forget to make the neccessary changes to the new httpd.conf file to activate PHP (thus causing all php to be served as plain text).

    Might not sound very likely, but it does happen (I believe that it actually happened on this very forum before now).

    But yeah.. my main concern is from other users of the server - which this approach will not address. :(

    Still open to suggestions then...

    daisho

    11:34 pm on May 26, 2003 (gmt 0)

    10+ Year Member



    On that same note they could forget to process .htaccess files and you'd have basically the same effect.

    On a shared server I guess you just have to take those risks.

    daisho.

    jatar_k

    11:41 pm on May 26, 2003 (gmt 0)

    WebmasterWorld Administrator 10+ Year Member



    On a shared server I guess you just have to take those risks.

    I was thinking the same thing. You seem to be in a bad spot and it looks like you may have to do the best you can with what you've got.

    The only other idea I had was zend encoder but that raises a whole bunch of other issues.

    bcc1234

    11:41 pm on May 26, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Get a host that offers jailed environments. Other than that, there is nothing you can do. Shared is shared.