We just installed our PHP website (WordPress, Joomla, phpBB or anything else) and we're populating it with contents, including uploaded images and files. Until we realize that any file we're uploading via the website built-in CMS engine - be it an image, a video, a pdf or anything else - doesn't show up or isn't available at all. All the images seems to be broken - with the typical "invalid URL" icon - and any other file URL just gives an abrupt 500 - Internal Server Error response.
To be more specific, looking at the Event Viewer log, we can clearly see that we're talking about a 500.19 error - The requested page cannot be accessed because the related configuration data for the page is invalid, meaning that the problem is most likely due to an improper IIS configuration.
Except that everything there seems to be ok. Anonymous access? Allowed. Folder authorization rules properly configured? Yes. IIS users added with correct read & execute permissions? Checked. Hey... wait a minute! The folder have them set, but the actual files don't. Despite any given inheritance.
Why is that so? And how can we fix that?
To fully understand our scenario we need to take into consideration the whole PHP file upload mechanism. For the sake of the readers we'll cut it to the very basics: at the start of the upload process, the files are stored into a temporary folder - the one specified in the upload_tmp_dir value of the php.ini configuration file. This folder, unless manually changed, is usually C:\Windows\Temp and is the root source of our issue. Take a look at its permissions, cause that's what our uploaded files will also get. If you're getting the 500.19 error, you're also most likely missing the read & execute permissions for the IIS and/or Application Pool users there.
The (improper) workaround
Now that we found the source, the fix seems to be obvious: we just add read & execute permissions to IUSR and IIS_IUSRS users to C:\Windows\Temp and we're done. Right?
Well, no. While this workaround undoubtely works, giving these extra permissions to C:\Windows\Temp is hardly a good move and will make you server less secure. That folder is often used by the system to store installation executables and scripts, software updates and various kinds of temp data... it just isn't meant to be accessible to IIS users.
The (proper) fix
A better and more robust way to get the job done is to create a brand new folder for PHP to use instead of C:\Windows\Temp . If you learned the lesson, you already know that you should avoid putting it into a system-controlled folder in order to avoid any unwanted inheritances. Just create something like C:\php\upload_dir\ and just add the IUSR and IIS_IUSRS permissions you need. Also remember to change the php.ini file accordingly.
The fix we'll obtain this way will give the same results of the above workaround without raising any security concerns, which is indeed a good thing.