27

OWASP advise against storing DB credentials in plain text:

https://www.owasp.org/index.php/Password_in_Configuration_File

However, they don't provide suggestions of how to encrypt the DB access credentials, where to store keys, how to manage access to keys, etc.

Has anyone any real-world experience of implementing such a solution who can suggest an architecture on a LAMP stack (ubuntu 10, PHP 5.3)?

PS - I'm not looking for answers along the lines of "don't bother - if someone gains root access it's too late", etc.

2
  • With all my respect to OWASP this article is just a small stub with links to empty or dead pages. I wouldn't consider it truly seriously. Commented Oct 19, 2012 at 7:10
  • I know. But it's a business requirement/box ticking exercise...
    – tom
    Commented Oct 19, 2012 at 7:57

3 Answers 3

17

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.

3
  • Excellent answer. +1 for mentioning ASP.NET's optional encryption of web.config. I agree that a downvote without commentary is unhelpful. Perhaps it got down voted for the confusing paragraph beginning with "A second benefit...". Commented Oct 20, 2012 at 6:35
  • 3
    "OS decryption can be set up by the SA for the process that will access the file." - that's me! I'm the SA. How do I set this up?
    – tom
    Commented Oct 24, 2012 at 13:49
  • While there are a number of options the easiest under Ubuntu is probably to use EFS to encrypt the user's home folder that is running your process. An after the fact method is here: howtogeek.com/116032/… but it's certainly not the only option.
    – iivel
    Commented Oct 25, 2012 at 3:38
0

I have very little experience with this but I've always heard you leave it in plaintext (what's the point in encrypting if the key is right there anyways) and leave the credentials in a include file and then put very strict access control on that file.

in my experience with web stuff...there are many ways of doing things...and few ways of doing things well.

(from my phone excuse my brevity)

2
  • In a web server, leaving the credentials file out of the public root is a must.
    – Null
    Commented Oct 18, 2012 at 23:06
  • The point is so that if someone is able to dump the document root they still don't have the credentials. To be more secure I guess the key could be managed by a key server hosted on another instance, but I think that's overkill for what we need to achieve.
    – tom
    Commented Oct 19, 2012 at 8:02
0

There is little use in encrypting your database password. In case of PHP you even require crypto code to run on every request - that's just a waste of CPU time. Besides that, there is a whole bunch of other reasons why it's not a good idea:

  • Your application needs to decrypt the data. Since in PHP config files are most likely PHP files, too, someone with access to the config file most likely also has access to the file containing the decryption code/key.
  • Waste of CPU time to decrypt the password.
  • If the database is properly configured having the password does not give you any advantage - access should be restricted to localhost (or whatever host the webserver is running on) and in case tools such as phpMyAdmin are on the server they should be protected with a different password. Actually, in case of e.g. PostgreSQL running locally you might not need a password at all since you can simply grant a system user access to a certain database - so if your PHP code runs as that user you avoid storing any password for the database.

So.. what can you do that makes sense? Pretty simple, don't put more files inside the document root than absolutely necessary. Since usually good applications use clean URLs routed through a single .php file only put that file in the document root. Anything else - i.e. the other application code, config files, etc. should be outside the document root. That way a server misconfiguration (e.g. the PHP engine being disabled and thus sending plain code to the user) will only give the user access to a single PHP file that probably does not contain much more than a require call and some function call.

Also ensure that your files are not world-writable/readable (especially when you have to use shared hosting). With a properly configured server (php NOT running as www-data or a similar user but your user) you can completely disable "world" and possibly "group" access to your files.

6
  • An approach that's been suggested internally is to encrypt the password and have it readable only by apache (outside doc root, obviously). Then, create a singleton-type class that will decrypt it and set it as an environment variable. This therefore removes the per-request overhead.
    – tom
    Commented Oct 19, 2012 at 7:59
  • Environment variables will not affect other processes which are not subprocesses of the current one. So you'd need to put this into apache itself. So why not simply put the environment variable in plaintext in the apache config which could have 600/root permissions. Commented Oct 19, 2012 at 11:24
  • This assumes that the database is running on the same system as the web server itself - this is not a good idea and DISA/NIST specifically reccomend against it. Still having the configuration files in a non-world readable location is key.
    – iivel
    Commented Oct 19, 2012 at 14:31
  • @theifmaster - we'd use a singleton-type object in the PHP front controller to set the env variable after decrypting the key.
    – tom
    Commented Oct 25, 2012 at 9:21
  • That means the PHP code has access to everything needed to decrypt it. And that means any hacker with access to it can also retrieve the necessary information. Commented Oct 25, 2012 at 9:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .