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):
Sounds harmless, right?
Well, here’s what I did to trigger this bug:
site.staging.server.com
tosite-staging.ssl.server.com
).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:
wp-config.php
in the web root, a request to/wp-config.php
would have downloaded the WordPress configuration file.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 serverWordPress 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:(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 theopen_basedir
directive in your PHP configuration: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
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
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 enoughFALSE: 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 dealFALSE: 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 secureFALSE: Assuming
wp-config.php
is inhttpdocs/
, just move it to../phpdocs/
, and setopen_basedir
to include onlyhttpdocs/
andphpdocs/
. For instance:(Remember to always include
/tmp/
, or your usertmp/
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:wp-config
to prevent any user without sufficient privileges from reading the file even if they gain (limited) access to your server via SSH.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 userwp-config
, they’ve probably messed with something else.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:
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).Someone asked us to shine in, and I will reply here.
Yes, there are security benefits from isolating your wp-config.php from the root directory of your site.
1- If your PHP handler gets broken or modified in some way, your DB information will not be exposed. And yes, I saw this happen a few times on shared hosts during server updates. Yes, the site will be broken during that period, but your passwords will be intact.
2- Best practices always recommend isolating configuration files from data files. Yes, it is hard to do that with WordPress (or any web app), but moving it up does a bit of isolation.
3- Remember the PHP-CGI vulnerability, where anyone could pass the ?-s to a file and view the source. http://www.kb.cert.org/vuls/id/520827
At the end, those are small details, but they do help to minimize risk. Specially if you are on a shared environment, where anyone can access your database (all they need is a user/pass).
But don’t let small distractions (premature optimizations) get in front of what is really necessary to get a site properly secure:
1- Keep it always updated
2- Use strong passwords
3- Restrict access (via permissions). We have a post about it here:
http://blog.sucuri.net/2012/08/wordpress-security-cutting-through-the-bs.html
thanks,
Definitely YES.
When you move wp-config.php outside public directory you protect it from reading using browser when php handler gets maliciously (or accidentally!) changed.
Reading your DB login/password is possible when server is hardly infected through a fault of lame administrator. Charge the administrator a fine and get a better-tended and more reliable server host. Though that may be more expensive.
I just want to clarify, for the sake of argument, that moving your wp_config.php file does not necessarily mean you have to move it only to the parent directory. Let’s say you have a structure like /root/html, where html contains the WP installation and all of your HTML content. Instead of moving wp_config.php to /root, you could move it to something like /root/secure … which is both outside the html directory and also not in the server root directory. Of course, you would need to make sure that php can run in this secure folder as well.
Since WP cannot be configured to look for wp_config.php in a sibling folder like /root/secure, you have to take an additional step. I left the wp_config.php in /root/html, and cut out the sensitive portions (database login, salt, table prefix) and moved them to a separate file called config.php. Then you add the PHP
include
command to your wp_config.php, like this:include('/home/content/path/to/root/secure/config.php');
This is essentially what I’ve done in my setup. Now, based on the above discussion, I am still evaluating whether it is necessary or even a good idea. But I just wanted to add that the above configuration is possible. It does not expose your backups and other root files, and so long as the secure folder is not set up with its own public URL, it is not browsable.
Furthermore, you can limit access to the secure folder by creating an .htaccess file in there with:
There are a lot of bad written themes and plugins out there which allow atatckers to inject code (remember the security issue with Timthumb). If I would be a attacker, why should I search for the wp-config.php? Simply inject this code:
You can try to hide your wp-config.php. As long as WordPress make all the sensitive information global accessible, it have no benefit to hide the wp-config.php.
The bad part in wp-config.php is not that it holds sensitive data. The bad part is to define the sensitive data as a global accessible constant.
Update
I want to clearify the problems with
define()
and why it is a bad idea to define sensitive data as a global constant.There are a lot of ways to attack a website. Script injection is only one way to atack a website.
Assuming the server has a vulnerability that let an attacker access a memory dump.
The attacker will find in the memory dump all values of all variables. If you define a global accessible constant, it have to stay in memory until the script ended.
Creating a variable instead of a constant, there is a good chance that the garbage collector will overwrite (or free) the memory after the variable is not longer needed.
A better way to protect sensitive data is to delete them immediately after using it:
After using the sensitive data, the assigning to
null
will overwrite the data in memory. An attacker have to get the memory dump just in the moment when$db_con
contains the sensitive data. And that is a very short time in the example above (if the class Database_Handler do not save a copy of it).Sorry to bump an old post but is there not just an obvious solution to all this. We know there is some security benefits from moving the wp-config.php file out of the wordpress route directory. Some would argue that the benefits are minimal others would not.
On the flip side there can be some drawbacks to moving the file out of it’s default location such as breaking some plugins that do not have functionality to look for the wp-config.php file in other locations.
Most obvious thing to me is to create a secret-info.php file outside of the wordpress route directory which contains variables for all your usernames and passwords i.e.
$userName = “user”;
$databasePassword = “12345”;
Leave the wp-config.php file in the default wordpress route directory, remove the username and password values from wp-config.php but leave everything else. Then just simply reference the $userName and $databasePassword variable by requiring secret-info.php in wp-config.php i.e.
require(‘PATH-TO-FILE/secret-info.php’);
Seems the obvious thing to do, am I missing something here ?
Eternety later and wordpress still puts
wp-config.php
by default in its root directory accessable to the web without even adding .htaccess rules to prevent access to it. All the shared hosting which have a one click wordpress install most likely do the same. The result is that most of wordpress sites ae configured like that and I don’t believe I ever heard anyone saying “my site was hacked because wp-config.php was on the root directory”.To use the information contained in the file you need an access to the DB server, probably by adding scripts to some app server which if you run a VPS means that if an attacker has such an ability it is “game over” for you in any case, and on shared hosting they probably isolate access to DB based on user therefor it is not a trivial thing to do even in that setting.
The result is that the wordpress 5.2+ health info will not give a suggestion to move the file, and never heard of a security plugin that does it.
So a long term practical info shows that it is theoretically better to do it, but it is mostly a security theater.
The real problem with moving
wp-config.php
to one directory above is that it essentialy prevents other wordpress from being installed in the same directory as the first one, something that many people do. The solution is to still have yourwp-config.php
in the default location but add to it code that loads the actual configuration from a different file which is located outside of the web root and probably named in a way which is not generic but site specific.The problem with that is that many wordpress toturials do not even mention the possibility of having
wp-config.php
in another place, and people that will come after you will have a WTF moment trying to figure out how to follow instructions which asks them to add adefine
to thewp-config.php
fileApart from the security benefits, it also allows you to keep your WordPress instance under version control while keeping the core WordPress files as a submodule/external. This is how Mark Jaquith has setup his WordPress-Skeleton project. See https://github.com/markjaquith/WordPress-Skeleton#assumptions for details.