Reputation: 4723
When a PHP application makes a database connection it of course generally needs to pass a login and password. If I'm using a single, minimum-permission login for my application, then the PHP needs to know that login and password somewhere. What is the best way to secure that password? It seems like just writing it in the PHP code isn't a good idea.
Upvotes: 445
Views: 253828
Reputation: 2852
Many wrote correctly that storing you credentials outside a php in a configuration file and keep this file secure is the best way. This is a practical example how to do that.
Create a file config.ini
(or any name you like) with this contents
[db]
server = localhost
name = dbname
user = username
password = 'password'
Reading this file is easy by doing this.
$settings = parse_ini_file( '/config.ini', true);
try {
$dsn = sprintf(
'mysql:host=%s;dbname=%s',
$settings['db']['server'],
$settings['db']['name']);
$db = new \PDO(
$dsn,
$settings['db']['user'],
$settings['db']['password']
);
} catch ( \PDOException $e ) {
exit( $e->getMessage() );
}
In Apache make sure ini files will never be served with this .htaccess file
<FilesMatch "\.(htaccess|ini)$">
Order allow,deny
Deny from all
</FilesMatch>
$settings
globalSince PHP > 7.0.0 it is possible to define array constant. $settings
is an array so we could do this:
$settings = parse_ini_file( '/config.ini', true );
define( 'SETTINGS', $settings );
unset( $settings ); // we don't need this anymore
/* some where else */
$db = new \PDO(
"mysql:host={SETTINGS['db']['server']};dbname={SETTINGS['db']['name']}"
SETTINGS['db']['user'],
SETTINGS['db']['password'],
Constants are global so now we can use it everywhere. Of course you have to make sure this constant is not exposed somewhere in your project.
Upvotes: 1
Reputation: 303
Actually, the best practice is to store your database crendentials in environment variables because :
How to use them ?
$_ENV['MYVAR'] = $myvar
echo $_ENV["MYVAR"]
putenv("MYVAR=$myvar");
getenv('MYVAR');
You can easily drop a file such as envvars.php with all environment variables inside and execute it (php envvars.php
) and delete it. It's a bit old school, but it still work and you don't have any file with your credentials in the server, and no credentials in your code. Since it's a bit laborious, frameworks do it better.
Example with Symfony (ok its not only PHP) The modern frameworks such as Symfony recommends using environment variables, and store them in a .env not commited file or directly in command lines which means you wether can do :
symfony var:set FOO=bar --env-level
Documentation :
Upvotes: 3
Reputation: 29917
if it is possible to create the database connection in the same file where the credentials are stored. Inline the credentials in the connect statement.
mysql_connect("localhost", "me", "mypass");
Otherwise it is best to unset the credentials after the connect statement, because credentials that are not in memory, can't be read from memory ;)
include("/outside-webroot/db_settings.php");
mysql_connect("localhost", $db_user, $db_pass);
unset ($db_user, $db_pass);
Upvotes: 11
Reputation: 4014
Previously we stored DB user/pass in a configuration file, but have since hit paranoid mode -- adopting a policy of Defence in Depth.
If your application is compromised, the user will have read access to your configuration file and so there is potential for a cracker to read this information. Configuration files can also get caught up in version control, or copied around servers.
We have switched to storing user/pass in environment variables set in the Apache VirtualHost. This configuration is only readable by root -- hopefully your Apache user is not running as root.
The con with this is that now the password is in a Global PHP variable.
To mitigate this risk we have the following precautions:
phpinfo()
is disabled. PHPInfo is an easy target to get an overview of everything, including environment variables.Upvotes: 10
Reputation: 81
We have solved it in this way:
Upvotes: 7
Reputation: 48287
This solution is general, in that it is useful for both open and closed source applications.
Advantages:
This method is suggested by Heroku, who are very successful.
Upvotes: 16
Reputation: 2096
Just putting it into a config file somewhere is the way it's usually done. Just make sure you:
Upvotes: 4
Reputation: 6393
The most secure way is to not have the information specified in your PHP code at all.
If you're using Apache that means to set the connection details in your httpd.conf or virtual hosts file file. If you do that you can call mysql_connect() with no parameters, which means PHP will never ever output your information.
This is how you specify these values in those files:
php_value mysql.default.user myusername
php_value mysql.default.password mypassword
php_value mysql.default.host server
Then you open your mysql connection like this:
<?php
$db = mysqli_connect();
Or like this:
<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
ini_get("mysql.default.password"),
ini_get("mysql.default.host"));
Upvotes: 57
Reputation: 9343
Several people misread this as a question about how to store passwords in a database. That is wrong. It is about how to store the password that lets you get to the database.
The usual solution is to move the password out of source-code into a configuration file. Then leave administration and securing that configuration file up to your system administrators. That way developers do not need to know anything about the production passwords, and there is no record of the password in your source-control.
Upvotes: 265
Reputation: 7133
If you're hosting on someone else's server and don't have access outside your webroot, you can always put your password and/or database connection in a file and then lock the file using a .htaccess:
<files mypasswdfile>
order allow,deny
deny from all
</files>
Upvotes: 104
Reputation: 13112
Best way is to not store the password at all!
For instance, if you're on a Windows system, and connecting to SQL Server, you can use Integrated Authentication to connect to the database without a password, using the current process's identity.
If you do need to connect with a password, first encrypt it, using strong encryption (e.g. using AES-256, and then protect the encryption key, or using asymmetric encryption and have the OS protect the cert), and then store it in a configuration file (outside of the web directory) with strong ACLs.
Upvotes: 2
Reputation: 3211
For extremely secure systems we encrypt the database password in a configuration file (which itself is secured by the system administrator). On application/server startup the application then prompts the system administrator for the decryption key. The database password is then read from the config file, decrypted, and stored in memory for future use. Still not 100% secure since it is stored in memory decrypted, but you have to call it 'secure enough' at some point!
Upvotes: 40
Reputation: 597311
An additional trick is to use a PHP separate configuration file that looks like that :
<?php exit() ?>
[...]
Plain text data including password
This does not prevent you from setting access rules properly. But in the case your web site is hacked, a "require" or an "include" will just exit the script at the first line so it's even harder to get the data.
Nevertheless, do not ever let configuration files in a directory that can be accessed through the web. You should have a "Web" folder containing your controler code, css, pictures and js. That's all. Anything else goes in offline folders.
Upvotes: 4
Reputation: 73966
If you are using PostgreSQL, then it looks in ~/.pgpass
for passwords automatically. See the manual for more information.
Upvotes: 10
Reputation: 3007
Your choices are kind of limited as as you say you need the password to access the database. One general approach is to store the username and password in a seperate configuration file rather than the main script. Then be sure to store that outside the main web tree. That was if there is a web configuration problem that leaves your php files being simply displayed as text rather than being executed you haven't exposed the password.
Other than that you are on the right lines with minimal access for the account being used. Add to that
Peter
Upvotes: 9
Reputation: 933
If you're talking about the database password, as opposed to the password coming from a browser, the standard practice seems to be to put the database password in a PHP config file on the server.
You just need to be sure that the php file containing the password has appropriate permissions on it. I.e. it should be readable only by the web server and by your user account.
Upvotes: 4
Reputation: 4966
Put the database password in a file, make it read-only to the user serving the files.
Unless you have some means of only allowing the php server process to access the database, this is pretty much all you can do.
Upvotes: 4