A Note for PHP-FPM Users

php-fpmIf you are using PHP-FPM to process your PHP files in Apache, you may have a security risk.

A common way to access the PHP-FPM service is by using mod_rewrite to direct files (with the appropriate extension) to it.  This works well until you decide to protect folders on your server with an AuthType Apache directive, either in a <Directory …> section in your httpd configuration files, or using a .htaccess file.

If you browse to the folder being protected, without defining a file in the URL, then everything works as expected, and authorization is requested.  This is because Apache has to first process the URL to determine what the default file is, and that triggers the authorization protection.

But if you include a file name in that folder in the URL that’s destined for the PHP-FPM processor, mod_rewrite immediately redirects it to the PHP-FPM service without passing through the authorization process, and the page is served without hindrance.  This is correct operation of mod_rewrite, because there’s no need to do much if the user is going to be handed off the some other URL.  Let the destination do the necessary authorization or whatever.  But unfortunately the PHP-FPM processor knows nothing about how to do this, so it doesn’t happen, and the file you thought was protected isn’t.  So your sensitive web page is viewable by anyone knowing the file name.

Both the <Directory …> and .htaccess systems are bypassed in this scenario.  Although curiously not the <Location …> directive.  If the authorization requirement is put there it will work.  However, as this directive works on URLs, there may be many different URLs that server given file, so it’s not really reliable.

The solution that worked for us is to not use mod_rewrite at all, but rather the SetHandler directive.  This is a more natural way of telling Apache what do with certain file types, and all the other functionality (Alias/Directory etc.) in the httpd configuration files works as expected.  Here’s a sample of what we put in our VirtualHost entry:

<FilesMatch “.+.(php)$”>
SetHandler proxy:fcgi://127.0.0.1:9001
</FilesMatch>

Your port may differ, and you can match multiple file types by using something like:

<FilesMatch “.+.(php|php3)$”>

Searching the web for this issue, you may find some suggesting putting this in your mod-rewrite chain that accesses PHP-FPM:

RewriteCond %{LA-U:REMOTE_USER} !^$

This says to use look-ahead to work out the value of REMOTE_USER (which would be the log-in user name) and then check it’s not empty.  This works fine when pages are protected by the authorization system, but causes pages not to be directed to the PHP-FPM processor when they’re not, with disastrous consequences for your web site!  For those pages the value of REMOTE_USER is empty (by definition) and hence fails the regular-expression test, terminating the mod_rewrite chain.

(This was all tested on a CentOS V7 server with mod_proxy_fcgi installed.)