5

URL to Drupal.org article Preventing execution of untrusted PHP

By default .htaccess inside sites/default/files contains:

<IfModule mod_php5.c>
  php_flag engine off
</IfModule>

Adding mod_php7.c version doesn't fix.

Temporary solutions are:

ProxyPassMatch ^/(.*\.php(/.*)?)$ "fcgi://127.0.0.1:9000/var/www/drupal"

And

<FilesMatch \.php$>
   SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>

But they are not recommended and they are overrideable.

There is a Drupal Core issue for adding mod_php7.c to .htaccess, but it's only for Drupal 8 (so how is this solved in Drupal 7 then?) https://www.drupal.org/node/2455465

There is solution for Apache How to disable PHP files from being run in the sites/default/files directory? but not nginx and php7.0-fpm.

So what is the solution?

(I'm running Security Review module that reports PHPs are executable within sites/defaul/files)

Screenshots: enter image description here

Permissions:

www-data:www-data 755 for dirs / 644 for files

.htaccess:

# Turn off all options we don't need.
Options None
Options +FollowSymLinks

# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
  # Override the handler again if we're run later in the evaluation list.
  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>

# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
  php_flag engine off
</IfModule>

<IfModule mod_php7.c>
  php_flag engine off
</IfModule>

I did restart nginx and php7.0-fpm.

  • 1
    You're aware that nginx doesn't process .htaccess files, those are for Apache? – Clive Feb 8 '17 at 15:28
  • good to know, but how to solve? – user3108268 Feb 8 '17 at 18:20
  • I think the easiest solution is to change your nginx php-fpm proxy to only access files Drupal needs to operate, e.g. /index.php and /cron.php. That way any other requested file simply won't be executed as php. You also might need to configure the handler so it doesn't serve requested .php files in plain text, no point in exposing that. I don't have examples to hand, hopefully someone else will – Clive Feb 8 '17 at 21:06
0

EDIT : since Nginx doesn't use .htaccess files, you have to place all your directives into your /etc/nginx/sites-available/yoursite.tld.vhost file. To prevent executing .php files, place this snippet :

location ~ \..*/.*\.php$ {
    return 403;
}

before

location / {
    try_files $uri /index.php?$query_string; 
}

location ~ '\.php$|^/update.php|^/cron.php' {
    fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
    include fastcgi_params;
    # Block httpoxy attacks. See https://httpoxy.org/.
    fastcgi_param HTTP_PROXY "";
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_intercept_errors on;
    fastcgi_read_timeout 180;
    # PHP 7 socket location (change it to fit your config)
    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}

This regex simply means if there's a request for /anything/../file.php, it will send a 403, since php files rarely should be accessible from outside (except for index.php, update.php and maybe cron.php, defined below).

To put it all together, please refer to that full nginx vhost example

  • @user3108268 I edited answer to add some clarifications. Let me know when you got it working – Kojo Feb 10 '17 at 9:25
  • The location is clearly way too restrictive. See Gerald Melendez's answer for something that is actually correct. – jcaron Apr 25 '18 at 9:36
3

This is what works for nginx and only targets files directory:

location ~ /files/.*\.php$ {
    return 403;
}

This is more generic and wont let any php file in a directory execute directly:

location ~ /.*/.*\.php$ {
    return 403;
}

WARNING, this is posted all over the web but only works for hidden directories:

location ~ \..*/.*\.php$ {
    return 403;
}
0

How the Nginx site shows it done:

# Block access to scripts in site files directory
location ~ ^/sites/[^/]+/files/.*\.php$ {
    deny all;
}

The full reference file is here:
https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.