3

I am working on a PHP website and my researches showed that it is entirely possible that the server can get hacked and the PHP files may get exposed. I store the MySQL DB Username and Password within the PHP files in the form of constants, which is then used while forming the connection string.

define("HOSTNAME","hostname.com:2086");
define("DBNAME","databasename");
define("DBUSER","databaseusername");
define("DBPASS","databasepassword!");

/* Defining DB Handler */
try{
    $DBH = new PDO("mysql:host=".HOSTNAME.";dbname=".DBNAME, DBUSER, DBPASS);
    $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $DBH->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}
catch(PDOException $e){
    echo $e->getMessage();
}

If by any case the PHP files get exposed, this would cause the database and its contents to be at risk too. Am I doing it wrong? Is there a better way to ensure the safety of the database even if the PHP files get exposed?

BlackPanther
  • 149
  • 1
  • 1
  • 5
  • possible duplicate of [Reasonable way to store encrypted passwords in a webapp's database, Linux](http://security.stackexchange.com/questions/48590/reasonable-way-to-store-encrypted-passwords-in-a-webapps-database-linux), and related to this https://security.stackexchange.com/questions/20461/how-can-i-avoid-putting-the-database-password-in-a-perl-script – Adi May 25 '15 at 15:58
  • This site has some guidance about securing PHP & MYSQL https://alias.io/2010/01/store-passwords-safely-with-php-and-mysql/ – John May 25 '15 at 14:43

4 Answers4

5

Defence in depth is the keyword: Instead of just securing the credentials, ensure that even knowing the credentials is (almost) useless for an attacker.

That means, use a dedicated user with the least required privileges (principle of least privilege) and restrict access with that user from the web server only. Then it doesn’t really matter where you keep the credentials as the only way for an attacker to exploit these credentials is from the web server, which means he/she requires code/command execution on the web server. And in that case you’re already doomed.

Gumbo
  • 2,003
  • 1
  • 13
  • 17
  • How can you use "Defense in depth" in the same awnser as "does not really matter where you keep teh credentials" Isn't part of defense in depth that you make it so the credentials will not 'leak' even if some of the security measures have failed (like the webserver starts serving raw php files instead of parsing them through php) – LvB May 25 '15 at 12:30
  • @LvB You would use a random, unique password for that database user. Then it doesn’t matter if it gets leaked as you can only use it from the web server. – Gumbo May 25 '15 at 12:31
  • My point is not that, its that its better to **NOT** reveal a username / password of a website instead of showing them but just limiting access to the local host (with the credentials I only need to 'force' (relay) access to the machine. and if I can not see the credentials I would need to get access and get some credentials somewhere (so more effort is needed). – LvB May 25 '15 at 12:34
  • 2
    My point is that securing the credentials alone is not sufficient and desirable. However, many people only focus on that (within/outside the web root, environment variable, etc.) but still expose their database to the world and connect to it with a privileged user. Then if the credentials get leaked somehow, an attacker has an easy job exploiting it. – Gumbo May 25 '15 at 12:45
  • Better to reword your answer than to reflect that ("In addition to placing the credentials outside of the webroot also limit....") ;) – LvB May 25 '15 at 14:03
  • @Gumbo Thanks for the answer. But, since LvB's answer kinda mention your answer too, I accepted that as the final answer. – BlackPanther May 25 '15 at 16:16
4

I good way to protect your keys is to put the php file with the credentials outside of the webroot. Even when the 'raw' php files are then served to a client, none of them include the database credentials. (does not protect against someone with file access on the server).

Another defensive measure you can take is limiting the connections the Database accepts connections from. (so not the whole world but just a select list of specific ip's)

Lastly you should make the account that connects with the Database only have rights on its own database, and no other!

LvB
  • 8,217
  • 1
  • 26
  • 43
  • Thanks, 'limiting the connections the Database accepts' is a great idea. I need to have a static IP though right? – BlackPanther May 25 '15 at 12:09
  • that depands on your setup, it is not required but can help – LvB Mar 27 '17 at 13:45
  • Wow, that took a while. But thanks anyway. :) It would be nice if you could explain how I could get this done without static IP. I scrubbed that idea on that premise... – BlackPanther Mar 28 '17 at 01:00
  • 1
    Well I was reviewing some old answers and thought this merited an reply ;). The truth is that in general there are to many possibilities to list them all. But if your not in a situation where you can set the IP you usually can limit access to the localhost (127.0.0.1) and only connect externally to the DB using an SSH tunnel. – LvB Mar 28 '17 at 08:41
0

What I would do, besides the measures mentioned in the other answers, is to read the username/password from a file to be retrieved from the web server and to have this file explicitly blacklisted for all but the server itself.

Martin Argerami
  • 863
  • 6
  • 6
  • why put the file in a location the webserver can read? if only php can read it and the webserver does not have the permissions to do so, even if it would be persuaed to read the file. it can't. with your solution this would be trivial. – LvB May 25 '15 at 14:05
  • True, but the assumption here is to mitigate the risk of the php source being leaked. – Martin Argerami May 25 '15 at 14:17
  • and how is that mitigated (if you asume php source can be any human readable file) – LvB May 25 '15 at 14:44
0

You can put them in environment variables.

In addition to the little security benefit, they provide multiple advantages for your development workflow, like not having to touch PHP files and insert different credentials each time you want to work on a different development environment. Instead, the environment provides this information, and you only have a single app that automatically adapts to wherever it's deployed to.

  • 2
    Placing them in environment variables makes them leak through phpinfo – wireghoul May 25 '15 at 20:45
  • @wireghoul if an attacker is able to run phpinfo or other arbitrary code he can defeat all the solutions posted here. –  May 25 '15 at 20:49
  • 2
    Plenty of sites keep a phpinfo around for debugging/etc. It does not have to be attacker controlled – wireghoul May 25 '15 at 21:22
  • "Plenty of sites" I haven't seen any serious site do that. To me that looks like irresponsible information disclosure, and I don't see how it would help debugging. Plus, you should debug your site locally, not on the production environment. –  May 26 '15 at 12:36
  • 2
    Alas, google disagrees with you: https://www.google.com/search?q=phpinfo+"This+program+makes+use+of+the+Zend+Scripting+Language+Engine%3A" gives 50k hits for public phpinfo pages. This number is very deflated as most websites don't link to their phpinfo pages or have them restricteed by robots.txt. Further more there is a historical precident for phpinfo leaking credentials, in particular apache changed the way they inhereted environment variables due to the number of websites leaking webmin credentials through phpinfo back in 2005 or so. – wireghoul May 27 '15 at 23:14
  • @wireghoul most of the sites on the first page of the results show outdated OS and/or PHP versions. So instead of having to manually discover OS and PHP versions by causing exceptions or hoping they're advertised in the server's headers, the attacker can just Google for them. Yet another reason why leaving a public phpinfo is a bad idea. –  May 27 '15 at 23:25
  • I'm not disagreeing, I'm just highlighting some edge cases that people often forget when setting database details as environment variables. And making a recomendation without warning just helps history repeat itself. I can understand that some might say it's common sense, but as the person asking the question clearly don't have the same "common knowledge" there can't be common sense. – wireghoul May 27 '15 at 23:57