Is moving wp-config outside the web root really beneficial?

One of the most common security best practices these days seems to be moving wp-config.php one directory higher than the vhost’s document root. I’ve never really found a good explanation for that, but I’m assuming it’s to minimize the risk of a malicious or infected script within the webroot from reading the database password.

But, you still have to let WordPress access it, so you need to expand open_basedir to include the directory above the document root. Doesn’t that just defeat the entire purpose, and also potentially expose server logs, backups, etc to attackers?

Or is the technique only trying to prevent a situation where wp-config.php would be shown as plain-text to anyone requesting http://example.com/wp-config.php, instead of being parsed by the PHP engine? That seems like a very rare occurance, and it wouldn’t outweigh the downsides of exposing logs/backups/etc to HTTP requests.

Maybe it’s possible to move it outside the document root in some hosting setups without exposing other files, but not in other setups?


Conclusion:
After a lot of back-and-forth on this issue, two answers have emerged that I think should be considered the authoritative ones. Aaron Adams makes a good case in favor of moving wp-config, and chrisguitarguymakes a good case against it. Those are the two answers you should read if you’re new to the thread and don’t want to read the entire thing. The other answers are either redundant or inaccurate.

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:

  1. Set up a subdomain to redirect to another URL (e.g. site.staging.server.com to site-staging.ssl.server.com).
  2. 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 real wp-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__) . "https://wordpress.stackexchange.com/");

/** 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 expand open_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.

Leave a Comment