39

My connection.php file stores the credentials to connect to the database:

<?php 
    $objConnect = mysql_connect("localhost","username","password"); 
    mysql_select_db("selectDB", $objConnect);
?>

When a page need to connect the database I just use <?php include("connection.php"); ?>.

Is this safe? Can hackers steal my credentials from that file?

Anders
  • 64,406
  • 24
  • 178
  • 215
OammieR
  • 493
  • 1
  • 4
  • 7

4 Answers4

43

My recommendation: Don't store passwords in source code.

Instead, store them in a configuration file (outside of the web root), and make sure the configuration file is not publicly accessible. The reason is that you normally don't want to keep your passwords checked into the source code repository or exposed to everyone who can view files in your web root.

There is an additional risk with storing passwords in a .php 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 connection.php using a text editor, and your connection drops while you are editing it, your editor will automatically save a copy of the connection.php file in some backup file: e.g., connection.php~ (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.

See also How do open source projects handle secure artifacts?, Open Source and how it works for secure projects?

D.W.
  • 98,420
  • 30
  • 267
  • 572
  • 2
    +1 I like this answer the most. But I need to note that places outside of web root are still accessible on websites with local file inclusion vulnerabilities. Well the hacker would still need to guess the location. – Máthé Endre-Botond Apr 02 '12 at 03:02
  • Exactly. Most of the risks are not around storing the password somewhere on disk, but around the differences in how you use/treat source code files vs. configuration files. This is something of a human problem rather than a technological one. +1 – jpmc26 Mar 15 '18 at 21:04
  • You're all suggesting to store credentials outside wwwroot. Ok, I understand the security background. But how should it be stored in version control then (sample config)? Usually wwwroot is the root of git repo, so if there is anything outside - it will be outside of VC. Imagine new developer trying to set up a local instance for development - how should he know magic like "take this file, copy it outside and fill in"? – The Godfather Aug 10 '18 at 18:18
  • 1
    @TheGodfather, that's a separate question, and should be asked separately. But do some research first (including reading the links I gave) -- I think it's been answered in a bunch of places. One approach is to put the secrets in a separate config file, and *don't store that config file in version control*. Indeed, passwords and crypto credentials should probably not be stored in version control, but should be managed in a different way. – D.W. Aug 10 '18 at 19:39
  • I did before posting a comment. If your config (or sample config) is not in VC then it's kind of "sacred knowledge" so noone really knows how to configure your app. You shoudn't store actual credentials in VC, but you *should* store config file itself. Having readme like "create file in this random place on filesystem and fill it in with values" is not really helpful here. – The Godfather Aug 10 '18 at 19:44
  • @TheGodfather, that's not the only option. There are other ways to handle key management. In any case, this comment thread isn't the place for your question. If you have a question about how to handle this case securely, please use the 'Ask Question' button to ask a new question, and provide context about your specific situation, your particular requirements, and what approaches you have already considered and why you have rejected them. – D.W. Aug 10 '18 at 20:01
11

It's reasonably safe. To get the content of the php file, a hacker needs to compromise your server, or you need to mis-configure it.

Still I recommend configuring mysql so that the user used by the script isn't accessible remotely, and use a different user for administrative remote access.

CodesInChaos
  • 11,854
  • 2
  • 40
  • 50
  • I wouldn't even allow remote admin - route access via phpmyadmin with appropriate controls (SSL + preferably running on a dedicated port) or even better only allow access via ssh then mysql client over filesystem socket. – symcbean Apr 02 '12 at 14:05
  • https://feross.org/cmsploit/ – Pacerier Jun 07 '20 at 09:52
6

The problem comes if you have a PHP script that possibly downloads the files on your server e.g download.php?=index.php.

If you check Google, you will see that this vulnerability exists within many other sites.

Limit
  • 3,191
  • 1
  • 16
  • 35
Victor Casé
  • 281
  • 1
  • 5
4

The /etc/php/N.m/apache2/php.ini already contains a section to store the MySQL username and password, if mysqli is used:

[MySQLi]
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =

This password can be easily read via php get_cfg_var method

  • echo get_cfg_var("mysqli.default_pw")

It could be an security issue if the hacker can get the php permission.

We can config the password with a customized key so hacker need to guess the key, like:

my_raldfklg_random_key_pw=top-secret-password

So in the php code we can load the password via

  • echo get_cfg_var("my_raldfklg_random_key_pw")
Happy
  • 141
  • 2
  • Is there something like this for being able to connect to MongoDB – user2402616 Sep 29 '21 at 20:46
  • 2
    @user2402616 There is no MongoDB section, well we can add a new key for mongodb in the `php.ini`'s standard section. like: `mongodb_dflkjadkfl_username=...` and `mongodb_dflkjadkfl_password=...`, then get the value via `get_cfg_var("mongodb_dflkjadkfl_username")` and `get_cfg_var("mongodb_dflkjadkfl_password")` , where `dflkjadkfl` is some random text and you can change to whatever others – Happy Oct 04 '21 at 17:14