How to Restrict WordPress File Permissions
The WordPress Security Learning Center
How to Restrict WordPress File Permissions

2.5: How to Restrict WordPress File Permissions

Advanced
Updated September 30, 2024

File permissions are actually one of the most important ways to secure your website. At Wordfence, we’ve cleaned malware out of many sites and often times these sites are running the most up-to-date versions of WordPress, their plugins and their themes, but the site was still compromised. If everything is up-to-date and secured, how does this happen? More often then not, it’s because there’s another website running on the same server with out-of-date versions of WordPress (sometimes even 1.x or 2.x versions of WordPress), or out-of-date plugins or themes.

This vulnerable site is an easy target where an attacker gains access to either run PHP code, or shell commands. Once the attacker can do this, they can begin spreading the infection to other websites on the same server. This is where file permissions play an important role. The attacker will try to locate any world-readable wp-config.php files for other websites running on the same server. If they can read the contents of this file, they can see the database credentials needed to connect to your WordPress database. Now that they can connect to the database, they create an admin account in WordPress and compromise your site from there.

Setting Defensive File Permissions

The above scenario is common in most shared hosting environments. The reason why the attacker needs to look for world-readable files is because the first compromised site is likely running as a different user. This is done through something like suPHP or suEXEC which will run PHP under a user configured in the site’s virtual host. In order to protect our site from other users on the same server, we need to make sure any files containing sensitive data are readable (and writable) only by our user and group. Let’s assume we’re the wordfence-web user in the wordfence group.

suPHP/suEXEC Environment File Permissions

To lock down permissions for our WordPress install, we need to change the permissions for each directory within the document root of the site to 750 (rwxr-x—) and verify those files are also owned by our wordfence user.

chown -R wordfence-web:wordfence /path/to/your/wordpress/install/
find /path/to/your/wordpress/install/ -type d -exec chmod 750 {} \;

This permissions scheme ensures that all directories cannot be read or listed by other users on the server. We’ll do the same for files using 640 (rw-r—–).

find /path/to/your/wordpress/install/ -type f -exec chmod 640 {} \;

Note: Depending on whether you would like WordPress (the PHP user) to be able to write to files on the server, you can toggle the user-writable bit for each of these permissions: 550 (r-xr-x—) for directories and 440 (r–r—–) for files.

mod_php Environment File Permissions (or where an FTP user will have ownership)

In some setups such as VPS’s, suPHP or suEXEC isn’t used and there’s an FTP user used to push files to the website, and also the web server user *possibly* writing to the files as well. This is best suited for servers where there’s only one site running. We’ll need to change the permissions for each directory to 750 (rwxr-x—) and change the user to our FTP user (wordfence-ftp) and the group to the web servers user (www-data).

chown -R wordfence-ftp:www-data /path/to/your/wordpress/install/
find /path/to/your/wordpress/install/ -type d -exec chmod 770 {} \;

This permissions scheme ensures that all directories can only be read or listed by the FTP user and the web servers group. We’ll do the same for files using 660 (rw-rw—-).

find /path/to/your/wordpress/install/ -type f -exec chmod 660 {} \;

Note: Depending on whether you would like WordPress (the web server user) to be able to write to files on the server, you can toggle the group-writable bit for each of these permissions: 750 (rwxr-x—) for directories and 640 (rw-r—–) for files.

Securing Your Own Sites

This same method of spreading the infection can happen within the same account if there are multiple sites running as our user. If we have our live site (wordfence.com) fully up-to-date, but another development site (dev.wordfence.com) running outdated plugins or themes, we need to make sure both are kept up to date. The file permissions we’ve setup here are to protect our user, but since our outdated dev.wordfence.com runs as our user, the file permissions won’t prevent wordfence.com from being compromised once dev.wordfence.com is. If at all possible, run each site as a different user, and be diligent about keeping up with plugin and theme updates.

Further Hardening

For the paranoid and more hands on approach, you can always prevent the web site from being able to write to its own files. There were a few “notes” included after each environment’s permissions setup, which will remove the ability for the site to write to its own files. This will effectively disable a number of core functions WordPress offers:

  • Modifying your .htaccess file to add permalink rules.
  • Auto upgrading core and plugins with security updates.
  • Upgrading anything via the web interface.*
  • Editing theme files from the admin interface.*
  • Uploading media will be disabled.

* It’s still possible to upload plugins by entering FTP credentials at the prompt

The security benefit to this is that even if the attacker gains access to the database, they won’t be able to use the admin account to upload a malicious plugin or use the theme/plugins editor to run their own code. It adds another layer of protection, but at the expense of added time and cost of administration. It also does not guarantee the infection cannot spread, just adds another obstacle the attacker must overcome. There are advantages and disadvantages to both, weigh the options and decide which works for you.

Did you enjoy this post? Share it!

The WordPress Security Learning Center

From WordPress security fundamentals to expert developer resources, this learning center is meant for every skill level. Get serious about WordPress Security, start right here.