Wordpress - Is moving wp-config outside the web root really beneficial?
Short answer: yes
The answer to this question is yes and to say otherwise is probably irresponsible.
Long answer: a real-world example
Allow me to provide a very real example, from my very real server, where moving wp-config.php
outside the web root specifically prevented its contents from being captured.
The bug:
Take a look at this description of a bug in Plesk (fixed in 11.0.9 MU#27):
Plesk resets subdomain forwarding after syncing subscription with hosting plan (117199)
Sounds harmless, right?
Well, here's what I did to trigger this bug:
- Set up a subdomain to redirect to another URL (e.g.
site.staging.server.com
tosite-staging.ssl.server.com
). - Changed the subscription's service plan (e.g. its PHP configuration).
When I did this, Plesk reset the subdomain to defaults: serving the contents of ~/httpdocs/
, with no interpreters (e.g. PHP) active.
And I didn't notice. For weeks.
The result:
- With
wp-config.php
in the web root, a request to/wp-config.php
would have downloaded the WordPress configuration file. - With
wp-config.php
outside the web root, a request to/wp-config.php
downloaded a completely harmless file. The realwp-config.php
file could not be downloaded.
Thus, it's obvious that moving wp-config.php
outside the web root can have bona fide security benefits in the real world.
How to move wp-config.php
to any location on your server
WordPress will automatically look one directory above your WordPress installation for your wp-config.php
file, so if that's where you've moved it, you're done!
But what if you've moved it somewhere else? Easy. Create a new wp-config.php
in the WordPress directory with the following code:
<?php
/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');
/** Location of your WordPress configuration. */
require_once(ABSPATH . '../phpdocs/wp-config.php');
(Be sure to change the above path to the actual path of your relocated wp-config.php
file.)
If you run into a problem with open_basedir
, just add the new path to the open_basedir
directive in your PHP configuration:
open_basedir = "/var/www/vhosts/example.com/httpdocs/;/var/www/vhosts/example.com/phpdocs/;/tmp/"
That's it!
Addressing arguments to the contrary
Every argument against moving wp-config.php
outside the web root seems to hinge on false assumptions.
Argument 1: If PHP is disabled, they're already in
The only way someone is going to see that contents of [
wp-config.php
] is if they circumvent your servers PHP interpreter… If that happens, you're already in trouble: they have direct access to your server.
FALSE: The scenario I describe above is the result of a misconfiguration, not an intrusion.
Argument 2: Accidentally disabling PHP is rare, and therefore insignificant
If an attacker has enough access to change the PHP handler, you're already screwed. Accidental changes are very rare in my experience, and in that case it'd be easy to change the password.
FALSE: The scenario I describe above is the result of a bug in a common piece of server software, affecting a common server configuration. This is hardly "rare" (and besides, security means worrying about the rare scenario).
Changing the password after an intrusion hardly helps if sensitive information was picked up during the intrusion. Really, do we still think WordPress is only used for casual blogging, and that attackers are only interested in defacement? Let's worry about protecting our server, not just restoring it after somebody gets in.
Argument 3: Denying access to wp-config.php
is good enough
You can restrict access to the file via your virtual host config or
.htaccess
– effectively limiting outside access to the file in the same way that moving outside the document root would.
FALSE: Imagine your server defaults for a virtual host are: no PHP, no .htaccess
, allow from all
(hardly unusual in a production environment). If your configuration is somehow reset during a routine operation – like, say, a panel update – everything will revert to its default state, and you're exposed.
If your security model fails when settings are accidentally reset to defaults, you probably need more security.
Why would anybody specifically recommend fewer layers of security? Expensive cars don't just have locks; they also have alarms, immobilizers, and GPS trackers. If something's worth protecting, do it right.
Argument 4: Unauthorized access to wp-config.php
is no big deal
The database information is really the only sensitive stuff in [
wp-config.php
].
FALSE: The authentication keys and salts can be used in any number of potential hijacking attacks.
Even if database credentials were the only thing in wp-config.php
, you should be terrified of an attacker getting their hands on them.
Argument 5: Moving wp-config.php
outside the web root actually makes a server less secure
You still have to let WordPress access [
wp-config.php
], so you need to expandopen_basedir
to include the directory above the document root.
FALSE: Assuming wp-config.php
is in httpdocs/
, just move it to ../phpdocs/
, and set open_basedir
to include only httpdocs/
and phpdocs/
. For instance:
open_basedir = "/var/www/vhosts/example.com/httpdocs/;/var/www/vhosts/example.com/phpdocs/;/tmp/"
(Remember to always include /tmp/
, or your user tmp/
directory, if you have one.)
Conclusion: configuration files should always always always be located outside the web root
If you care about security, you should move wp-config.php
outside your web root.
The biggest thing is the wp-config.php
contains some sensitive information: your database username/password, etc.
So the idea: move it outside the document root, and you don't have to worry about anything. An attacker will never be able to access that file from an external source.
Here's the rub, however: wp-config.php
never actually prints anything to the screen. It only defines various constants that are used throughout your WP install. Thus the only way someone is going to see that contents of that file is if they circumvent your servers PHP interpreter -- they get .php
file to render as just plain text. If that happens, you're already in trouble: they have direct access to your server (and probably root permissions) and can do whatever they like.
I'm going to go ahead and say there's no benefit to moving wp-config
outside the document root from a security perspective -- for the reasons above and these:
- You can restrict access to the file via your virtual host config or .htaccess -- effectively limiting outside access to the file in the same way that moving outside the document root would
- You can ensure the file permissions are strict on
wp-config
to prevent any user without sufficient privileges from reading the file even if they gain (limited) access to your server via SSH. - Your sensitive information, database settings, are only used on a single site. So even if an attacker gained access to that information, the only site it would affect would be the WordPress install to which the
wp-config.php
file belongs. More importantly, that database user only has permissions to read and write to that WP install's database and and nothing else -- no access to grant other users permissions. Meaning, in otherwords, if an attacker gains access to your database, it's simply a matter of restoring from a backup (see point 4) and changing the database user - You backup often. Often being a relative term: if you post 20 article every day, you better back up every day or every few days. If you post once a week, backing up once a week is likely sufficient.
- You have your site under version control (like this), which means even if an attacker gained access, you can easily detect code changes and roll them back. If an attacker has access to
wp-config
, they've probably messed with something else. - The database information is really the only sensitive stuff in
wp-config
, and because you're careful about it (see point 3 and 4), it's not a huge deal. Salts and such can be changed any time. The only thing that happens is that it invalidates logged in users' cookies.
To me, moving wp-config
out of the document root reeks of security by obscurity -- which is very much a straw man.
I think Max's is a knowledgeable answer, and that's one side of the story. The WordPress Codex has more advise:
Also, make sure that only you (and the web server) can read this file (it generally means a 400 or 440 permission).
If you use a server with .htaccess, you can put this in that file (at the very top) to deny access to anyone surfing for it:
<files wp-config.php> order allow,deny deny from all </files>
Note that setting 400 or 440 permission on wp-config.php may prevent plugins from writing to or modifying it. A genuine case for example would be, caching plugins (W3 Total Cache, WP Super Cache, etc.) In that case, I'd go with 600 (the default permission for files in /home/user
directory).