How to encrypt database connection credentials on a web server?

The other answers here are all correct in a couple key aspects. The file containing your connection string should not be kept in a world readable location, and as you note, you can't stop someone from getting at the key if they've compromised your server. Even so, there are other reasons to encrypt the key (or the file). Part of the reason OWASP recommends against storing in plain text are to prevent accidental disclosure of credentials to those who don't need them.

While many make the point that encrypting the connection string on the running system provides little actual value (security by obscurity) this is true primarily in the context of the live system. Assuming a traditional LAMP configuration, file based permissions would prevent read from any user other than the script user that the php/apache process is running under. Having the file outside of the root location provides slightly more potential security (in case of misconfigured MIME handlers or .htaccess) but isn't strictly necessary.

The greatest value in segregating connection settings is that authentication details and data no longer needs to be handed out to developers/testers or other individuals that may have a real need to connect to the server. By keeping the connection details out of source control, and out of general distribution, you reduce the possibility of loss or leakage.

A second benefit is the distribution and backup of the source. Certainly a best practice would be to only transfer files containing sensitive connection and account information encrypted themselves, but for many reasons, this isn't always practical. Due to this if encryption is in use, separating the key from the connectionstring and separating the connectionstring from the source is an essential action. Doing this has separated the duties and protection of the encryption keys (or configuration files) and becomes a system administrator function, rather than a developer function.

That out of the way, in Apache/php you have a number of options.

1.) Don't put the connectionstring in php code at all. You can put these values in your httpd.conf or virtual hosts file. Connection then requires no parameters when using mysql_connect() ... more detailed use is available here: http://www.php.net/manual/en/class.mysqli.php

2.) Include the configfile.php configuration file as normal, but move the connection file out of webroot if you can, and encrypt the file itself. OS decryption can be set up by the SA for the process that will access the file. Alternately use If you can't move the file out of the webroot (shared hosting) secure the file with .htaccess

<files configfile> 
     order allow,deny 
     deny from all 
</files> 

For Microsoft IIS with ASP.NET, the connection string is stored in the application.config or web.config file and the encryption used can either be a static machine key, stored in either of these files, or a key generated by IIS itself - which is not stored in an accessible location. Specifics are available on MSDN, which I won't litter this answer with since your question was specific to LAMP.

I should also note, that when possible, my preference is to avoid the issue altogether by using integrated authentication. Mapping the OS user to a db user pulls the protection requirements out of this question's context almost altogether.

Tags:

Encryption