Clouds in my coffee | Brian Hare's personal blog.

Feb/11

18

Hiding MySQL Passwords In PHP Using Apache Environment Variables

This technique assumes you are running Apache Web Server and have access to edit the Apache configuration files; this technique can be used with .htaccess files but it’s not as secure. It’s generally geared towards users who don’t like having important passwords or information in PHP files owned by Apache’s user (www-data, nobody, etc). This is especially more risky if you don’t limit where users can open files or run suPHP or similar

This technique works by including a root owned file into the public run-time environment variables of apache. using Apache directives you can control which site or even page has access to these variables.

You start off by creating a root owned file somewhere outside where any other user has access to. For example, my file is located in /home/shared/ as all my users are jailed to their home directory both in FTP and SSH. Furthermore, you must make sure only root has access to the file. The great thing about apache is that it reads any included files as root before it actually switches to it’s running owner (www-data, nobody, etc). Therefore this file can only be read by someone who actually has root-access to your server, and if that’s the case then you’re out of luck anyways.

Inside the file, you want to define the Apache Environment Variables you will be using. Even though this post is more about keeping PHP passwords safe, this can be used for anything you want to hide from users in case somehow they get apache user permissions.

I am going to keep it basic with simple commands, but you can read more about setting Apache Environment Variables  here: http://httpd.apache.org/docs/2.0/env.html

For this example I am going to name the file secret_mysql_passwords.conf located in /home/shared/

cd /home/shared/
touch secret_mysql_passwords.conf
chown root:root secret_mysql_passwords.conf
chmod 700 secret_mysql_passwords.conf

Inside the file you will put something similar to the following:

SetEnvIf Host "^www.yoursitehere.com$" secret_db_user=testusername
SetEnvIf Host "^www.yoursitehere.com$" secret_db_pass=testpassword

where www.yoursitehere.com will be whichever website you are using. For now, let’s leave testusername and testpassword as is for testing purposes, in case we mess something up we aren’t publishing our real username and password. If you don’t use the www prefix or you want the password to be visiable on all your subdomains, then use
“yoursitehere.com$” instead of  “^www.yoursitehere.com$”

The reason why I used SetEnvIf and then define the Host I want the variable to be accessed on is because by default every website you are hosting with apache will have access to this environment variables through PHP’s global $_SERVER array.

Important: If you don’t specify the exact host/website that will have access to these variables you’re doing more harm than you would in the first place by publically displaying your username and password for every user to see.

Now that you have the file created, with the correct owner and permissions, and have correctly set up the SetEnvIf or other declarations it’s time to include the file to your apache configuration. The file I am going to be using is httpd.conf which for me is located in /etc/apache2/

inside httpd.conf put:

Include "/home/shared/secret_mysql_passwords.conf"

If you have a vhost that’s specific to your website, place the include text inside the vhost; otherwise just apply it globally because the If statement in our file should only make it visible to your website.

Restart apache on your machine, for my debian system with apache2 the command is

/etc/init.d/apache2 restart

You should now test and make sure you set up everything correctly, browse to your site files and create a PHP file. Inside it put:

print $_SERVER['secret_db_user'];
print "<br>";
print $_SERVER['secret_db_pass'];

then execute it from a browser. If done correctly, you should see testusername and testpassword. This is proof that the environment variables are working for the website. Now the next thing to do is do the same thing for a website that is outside the specified host you defined above.

For example using a subdomain such as test.yoursitehere.com or a totally different website all together. If you cannot see testusername and testpassword on a different host, then we have done it correctly. If you still see our test values on a different host, then something is wrong the SetEnvIf statement.

Now that we have tested it and everything is working correctly, delete the file you made for testing so it’s not accessed anymore. Now it’s time to go and edit the test values we put and replace it with your real MySQL username and password. Restart Apache once you’ve done this and you should be all set.

Anytime you need to enter your MySQL username or password in a PHP file simple just use the appropriate $_SERVER variables instead. This can be a bit tedious but it will become beneficial in the long run, especially if you don’t run suPHP or restrict other users to their home directory.

No tags

6 comments

  • This Week in Web – MongoDB, jQuery, Unladen Swallow | Query7 · March 31, 2011 at 9:51 pm

    [...] Hare has written a tutorial showing how to hide passwords and access them with Apache environment variables. Rather than having [...]

    Reply

  • Searching every table in a database for a string | Clouds in my coffee · October 31, 2011 at 11:35 pm

    [...] user and pass for my database are server variables using the security method mention in this post: http://www.brianhare.com/wordpress/2011/02/18/hiding-mysql-passwords-in-php-using-apache-environment… Source code   <?php $config['host'] = "localhost"; [...]

    Reply

  • y3000 · January 29, 2012 at 1:32 pm

    Excellent article – answered my question and guided me on the config.

    The only issue I had was configuring my read-only httpd.conf file – but that can be fixed using:

    gksudo gedit /etc/apache2/httpd.conf

    And entering the super user (root) password…

    Reply

  • Programowanie w PHP » Blog Archive » This Week in Web – MongoDB, jQuery, Unladen Swallow · November 17, 2012 at 10:13 pm

    [...] Hare has written a tutorial showing how to hide passwords and access them with Apache environment variables. Rather than having [...]

    Reply

  • bretzel · June 26, 2013 at 12:48 pm

    As a newbie in web dev., I really appreciate your hint. For me it seems to works very well :-) I tested with a root created .conf outide of my webroot and then in PHP, tested

    echo $_SERVER['myvar']; ouput: the myvar’s value!

    I am very thanful!
    :-)

    Reply

    • bretzel · June 26, 2013 at 12:49 pm

      Sorry for some typos :-( read “I am very Thankful” :-)

      Reply

Leave a Reply

<<

>>

Clouds in my coffee

Welcome to my blog. Things will be changing a lot while I settle in.