In this post, I describe how to troubleshoot and fix an issue with some shared webhosting plans, which causes PHP to return a 403 Forbidden or 404 Not Found error for files that are actually present and readable by all users.
I ran into this issue while setting up a wiki for a client on their shared webhosting. The plan was to upgrade an existing wiki install by backing it up, removing the files and replacing them with the latest release, and then going through the wiki’s inbuilt upgrade procedure. It failed at pretty much the first hurdle. I removed the old files and unzipped the new version. When I opened the update page in my browser, I was confronted by a 404 Not Found error message.
At first I thought the problem was due to some weird .htaccess settings, as the wiki was installed in a subfolder inside a WordPress site that someone else set up. A quick investigation showed that all was as expected there though. I then decided to create a simple test script containing
<?php phpinfo(); to help me diagnose things further. Opening this file also resulted in a 404 Not Found error, which was a real surprise as I had just created the file, and it was in the WordPress root directory, and WordPress was working fine!
A closer look revealed one key difference between the new script and the existing WordPress files: the new file had
rw-rw-r-- permissions, while the other files had
rw-r--r-- permissions. This turned out to be the root cause: the webhosting was set up to use suEXEC, which won’t run files that are group writable. On top of that, someone had set a custom ErrorDocument handler so that 403 (Forbidden) files actually showed a 404 (Not Found) error message, presumably to avoid revealing the presence of protected files.
With this information, it was easy to fix the problem: a simple
chown -R g-w wiki/ corrected the permissions and the wiki then loaded normally. To prevent the problem recurring, I added the line
umask 0022 to the account’s login profile, which means that new files will not be group writable by default. It seems that the problem came up because the hosting provider was using suEXEC to keep customer accounts separate, but many Linux distros these days set the default umask to 0002, i.e. group writable by default. If your hosting provider uses a similar setup and hasn’t correctly set the default umask, I hope this post will help you...