8

It has been suggested in securing PHP article that using directive as below in htaccess is more secure than hardcoding it into your app:

<VirtualHost ilia.ws>
Include /home/ilia/sql.cnf
</VirtualHost>

then declare your parameters in the sql.cnf as below:

SetEnv DB_LOGIN “login”
SetEnv DB_PASSWD “password”
SetEnv DB_DB “my_database”
SetEnv DB_HOST “127.0.0.1”

And finally access them via :

echo $_SERVER[‘DB_LOGIN’]; // login
echo getenv(“DB_LOGIN”); // login 
Alireza
  • 1,280
  • 1
  • 20
  • 26
  • 2
    SetEnv is passed to all cgi scripts for which that part of the .htaccess file is evaluated (although those scripts may also be able to access a config.php file). Furthermore, it may appear on print_r's of the _SERVER variable, such as in phpinfo(). – Legolas Apr 17 '12 at 07:34
  • Do not trust security articles that rely on Apache. – Evgeniy Chekan Jul 12 '13 at 03:45

4 Answers4

4

This is a reasonable approach. The benefit of this approach is that it avoids storing your password in the source code. This is a good thing: you should not hardcode passwords in your source code.

(Of course, with this suggestion, the database password is not stored in the .htaccess file; instead, it is stored in a separate configuration file. But the difference is inconsequential.)

Important: Make sure that sql.cnf is not stored within your web root. If it is stored in your web root, maybe anyone who knows the right path to it will be able to request it just by sending a GET request.

  • There is an additional risk with storing passwords in a sql.cnf file within your webroot, which is a bit obscure but can be easily avoided by placing the file outside of your web root. Consider: if you are editing sql.cnf using a text editor, and your connection drops while you are editing it, your editor will automatically save a copy of the sql.cnf file in some backup file: e.g., sql.cnf~ (in the same directory). Now the backup file has a different extension, so if someone tries to fetch that file, the Apache server will happily serve up a copy of the file in plaintext, revealing your database password. See 1% of CMS-Powered Sites Expose Their Database Passwords for details.

For more reading on the general principle:

D.W.
  • 98,420
  • 30
  • 267
  • 572
3

The recommendation is predicated on the fact that PHP files will be world-readable but .htaccess files / httpd.conf won't. The author rightly points out that using encryption to hide these values doesn't help - since that means the encryption key needs to be accessible to PHP code. But storing the values in the environment only avoids some issues which are also avoidable by other means. Values in an httpd.conf file will be readable by any PHP code run on the server. Moving them into a vhost defn narrows the visibility. You can keep them as PHP code within the document root by simply prepending the filename with '.ht'.

Certainly it's good practice to maintain the tokens indepently of the bulk of the code. Since

  • they will have a different lifespan than the code (i.e. may need changed independently of the code and vice versa)
  • should not be exposed via code management facilities such as the version control system
  • should vary depending on where the code is deployed (i.e. different tokens for test / stage / live)

However using the webserver config is only one way to achieve this - there are other valid approaches.

Regardless of which route you take, the security of the solution will come from considering all aspects - file permisssions / accessibility of the file, restrictions on DB connection, access controls at the DB

symcbean
  • 18,278
  • 39
  • 73
0

If you would like to store passwords in an environment variable, but you don't want other users to be able to read the password or key, you could follow the following steps (tested on Ubuntu 18.04):

  • Create a file /etc/apache2/conf-available/mysql_credentials.conf
  • Change the ownership to root sudo chown root:root /etc/apache2/conf-available/mysql_credentials.conf
  • Change the file permission, so it is only readable for root sudo chmod 600 /etc/apache2/conf-available/mysql_credentials.conf
  • Put the password or key in the file, e.g. SetEnv DB_PASSWD abcdefg12345+-987654321
  • Enable the configuration file sudo a2enconf mysql_credentials
  • Restart Apache sudo service apache2 restart

This key is accessible in PHP via $_SERVER['DB_PASSWD'].

Coanda
  • 101
  • 1
0

There are some caveats with this, first one would hope that the path: /home/ilia/sql.cnf is not located within the webroot of your website, or an attacker could simply visit the url http://ilia.ws/sql.cnf to view your database credentials.

Additionally one would hope that your website did not include various information disclosure bugs or a phpinfo page as phpinfo will dump the $_SERVER array and thus disclose your database credentials to any visitor of this page.

Further more the assumption that it would be harder for an attacker to obtain the information if it's stored in a PHP file versus environment variables is rubbish. Your example sets the environment variables for every page request. That means that a directory traversal attack which may not have permissions to read your sql.conf file will still probably have permission to read /prof/self/environ and obtain the credentials that way.

I would ensure that your database server is bound to the loopback interface, that your database credentials have the lowest possible privileges and that your web application and server software are patched in a timely manner and just store the credentials in the php file.

wireghoul
  • 5,745
  • 2
  • 17
  • 26