How to secure files folder

Events happening in the community are now at Drupal community events on www.drupal.org.
jean84's picture

hello, i want to prevent people from execute php files in the files folder of drupal here my idea but its not working after restarting nginx can you correct my code please.

location ~ ^/sites/default/files/.(php)$ {
               deny all;
}

location ~ .php$ {
fastcgi_split_path_info ^(.+.php)(/.+)$;
          fastcgi_pass   127.0.0.1:9000; # By all means use a different server for the fcgi processes if you ne$
          fastcgi_index  index.php;
          fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;   # !! <--- Another path r$
#          fastcgi_intercept_errors on;

          include        /etc/nginx/fastcgi.conf;
#          track_uploads uploads 60s;
        }

Comments

The proper way

perusio's picture

to do that is to enumerate all PHP enabled locations and add a location stanza like this at the end of the config:

## Any other attempt to access PHP files returns a 404.
location ~* ^.+.php$ {
    return 404;
}

Also drupal doesn't rely on PATHINFO so there's no need to use it.

See any of the configs indicated on the group blurb at the top of the page.

Hello, i looked into the

jean84's picture

Hello,
i looked into the configs in the blurb but i did not find anything that enumerates all php enabled locations.

Usually there would only be 2

jean84's picture

Usually there would only be 2 files beeing directly accessed by me, the administrator. All other sites would only be called from inside the server so there would be no need at all to call urls ending with .php directly from outside the server.
Do i understand it right?

i do not know much about nginx. So i also not exactly know how to format a rule that would enumerate all the locations to enable php.

There's no rule for all

perusio's picture

php files. Instead there are several rules. One corresponds to a particular location and php file. A catch all rule like ~ \.php$ is something you want to avoid for security and performance reasons.

Depending on how you run cron you should have a single file index.php. You can have others if you use modules like the ad module.

You can take a look at my config for an example of a config that enumerates all php locations and restricts php execution outside the enumerated locations. Here's a snippet:

## Restrict access to the strictly necessary PHP files. Reducing the
## scope for exploits. Handling of PHP code and the Drupal event loop.
location = /index.php {
    fastcgi_pass phpcgi;
    # To use Apache for serving PHP uncomment the line bellow and
    # comment out the above.
    #proxy_pass http://phpapache;
    # Filefield Upload progress
    # http://drupal.org/project/filefield_nginx_progress support
    # through the NgninxUploadProgress modules.
    track_uploads uploads 60s;
}

Note the = meaning that is an exact location.

settings.php

ogi's picture

When you give location = /index.php as an example, it's essential that you write about location ~* ^.+.php$ too because accessing settings.php through web server is a security hole. It's important to note some PHP files like cron.php and update.php that can be used by someone that doesn't use Drush for everything.

EDIT: I know see that you wrote about \.php$ catch-all.

Well in the config

perusio's picture

there are two files, one for running with drush and another for the drush impaired :)

Also I talk above about adding other scripts to the config. You can't have it both ways if you want the config to be fast and secure there's no way to use a catch all location for php files.

didn't notice

ogi's picture

I've only looked at drupal_boost_drush.conf and it didn't come to my mind that the other conf file is for no Drush :-)

Nice and clean configuration :-)

Nginx

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: