It’s a good idea to separate passwords from the Web pages that use them. With PHP’s include()/ include_once() and require()/require_once() functions, it’s very easy to drop in text (such as database passwords) from another file at runtime. Remember that these included files do not have to be in a PHP or Web server–enabled directory! Whenever possible, keep them somewhere outside your Web tree, such as in the directory above your Web document root or in a home directory.

Taking the database variables out of PHP files is also good for other reasons. If you have many PHP scripts using the same database, they can all use the same password file. When you suspect the password has been compromised, or when you change the password on a regular schedule, you need only alter one script for all the files to be updated.

The unavoidable downside of this technique is that the file must be readable by the Apache user. Because the Apache user and the database user are seldom the same, that means in practice the file must be world-readable. This should still be safer than keeping the database variables inside a public Web root directory .

If you have a set of database variables you use infrequently—a configuration script or the like—you can keep it in a non-Apache-readable directory and change the permissions only on the rare occasions necessary. We infrequently have to go to the trouble to delete postings from our sites’ forums. So it’s not that much more work (and much more secure) to keep this file in a non-Apache-user-owned directory, once in awhile change the permissions just long enough to delete the offending post, and then immediately change everything back.

If for whatever reason, you decide to put your database username, password, hostname, and database name into a PHP script in plaintext, this is what you can expect. If the httpd is functioning normally, the database passwords should be as safe as any file on that server—which is to say, not extremely. But if the daemon goes down, there is some chance your raw PHP (including plaintext database variables) will be delivered in a human-readable form. You can
reduce this risk by avoiding the use of the .html suffix for PHP files.

In PHP3, if database connectivity went down and you hadn’t specified silent mode, you would see something like the following:

Warning: MySQL Connection Failed: Access denied for user:
[email protected]’ (Using password: NO) in
on line 2
This constitutes a security breach, because it reveals your MySQL username and whether or not you use a password. From PHP4 forward, MySQL error messages are no longer displayed by default. Two functions, mysql_errno() and mysql_error(), allow you to opt for error codes or text warnings—but now you have to deliberately choose to ask for the information. Because, in most cases, you can opt for the more configurable die() instead or remove error messages after debugging, it’s still not a good idea to use mysql_error on a public production server unless you scrupulously send messages to error logs using the error_log() function rather than to standard output