What is the ideal setup to address security concerns?

I’m aware of the requirements WP has for certain directories and files to be writable. I’m also aware that making permissions too loose can open security holes. Finally, I know that the user that (insert your server here) runs as on Linux systems can be a factor.

Security aside, I like being able to download themes and plugins to my blog, and update them when necessary. Proper permissions seem to be a bit at odds with this preference.

Read More

I’ve collected little bits of detail here and there, but I’d like to see a more definitive answer, if there is one: what is the preferred setup with a nod to security? What permissions should be in place, what user should the site run as, etc.

Related posts

Leave a Reply

2 comments

  1. If you have FTP access to your server, the most secure setup is not having your themes or plugins directory writable by your webserver and instead having WordPress update files using FTP. When you go to update a plugin, WordPress will prompt you for your FTP details.

    The FTP method is a lot slower than direct file writes, but it is a lot more secure as a rogue script won’t be able to modify your files.

  2. As @Viper007Bond noted, updating your core, plugins, and themes via the built-in update mechanisms is pretty safe, as far as file-permissions go, because they can use your actual user credentials. For maximum safety, you want to make sure that you have the SSH2 PHP extension installed. The method of installation (if possible) can vary from host-to-host, so if it’s not already there, you might need to ask the hosting service, or do some Googling.

    Many shared hosting services will use suexec in their Apache setup, so that the web service runs as the actual user. This eliminates most permission problems and helps protect your files from other users on the server. However, in cases where Apache runs as a separate user, if you want to upload files into WordPress, you have to open up permissions on the upload directory.

    In this case, you probably want your wp-content/uploads directory to have 0713 permissions, (AKA rwx--x-wx). This gives the directory owner full permissions, their group can read files if they know the full path, and others (including the web server) can read files to which they know the path and can create/write files.

    Some caching plugins also expect to have a wp-content/cache directory (or similar) available that they can write to. The same permissions advice would apply to that.

    Lastly, for pretty permalinks, WordPress needs to be able to modify the .htaccess file, unless you plan to update it manually. In this case, you’d want 0646 for the file mode. However, once you’ve settled on your permalink structure, you normally won’t need to change this again, so you could turn off the extra write permissions, and set it to 0644. Occassionally, a plugin or core upgrade might require access to it, and you could temporarily turn write permissions back on for that, then turn it back off again.

    All other files should have 0644 permissions. Directories should be 0711 if you’re extra-paranoid, but that could interfere with any plugins that need to get a list of files from a directory. In that case, or if you aren’t quite as paranoid, use 0755, which will allow others to read, but not write.

    Most of this is mainly a concern if you are on shared hosting. If you have a dedicated server (including VPS), with no other users that have ssh/ftp access, then you can relax a little more. I don’t mean that you should just make everything openly writable, but you can probably just trust the system defaults, which will probably be 0755 permissions on directories instead of 0711.

    If it is an option, get an SSL certificate installed for the site, and once you’ve tested that you can access your site via https, you can force SSL for admin logins and access by adding these lines to your wp-config.php file, just before the ‘Stop editing’ comment:

    define('FORCE_SSL_ADMIN', true);
    define('FORCE_SSL_LOGIN', true);