Skip to content

Commit

Permalink
Wrap handler settings in a FilesMatch directive.
Browse files Browse the repository at this point in the history
FilesMatch directives override Directory settings, see also:
https://httpd.apache.org/docs/current/sections.html#merging
  • Loading branch information
blueimp committed May 15, 2020
1 parent e3b5260 commit a532992
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 36 deletions.
60 changes: 39 additions & 21 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ In some cases this can be acceptable, but for most projects you will want to
extend the sample upload handlers to integrate user authentication, or implement
your own.

It is also up to you to configure your Webserver to securely serve the uploaded
It is also up to you to configure your web server to securely serve the uploaded
files, e.g. using the
[sample server configurations](#secure-file-upload-serving-configurations).

Expand All @@ -69,7 +69,7 @@ uploaded files as static content.

The recommended way to do this is to configure the upload directory path to
point outside of the web application root.
Then the Webserver can be configured to serve files from the upload directory
Then the web server can be configured to serve files from the upload directory
with their default static files handler only.

Limiting file uploads to a whitelist of safe file types (e.g. image files) also
Expand Down Expand Up @@ -122,36 +122,54 @@ understand what they are doing and that you have implemented them correctly.
> Always test your own setup and make sure that it is secure!
e.g. try uploading PHP scripts (as "example.php", "example.php.png" and
"example.png") to see if they get executed by your Webserver.
"example.png") to see if they get executed by your web server, e.g. the content
of the following sample:

```php
GIF89ad <?php echo mime_content_type(__FILE__); phpinfo();
```

### Apache config

Add the following directive to the Apache config, replacing the directory path
with the absolute path to the upload directory:
Add the following directive to the Apache config (e.g.
/etc/apache2/apache2.conf), replacing the directory path with the absolute path
to the upload directory:

```ApacheConf
<Directory "/path/to/project/server/php/files">
# To enable the Headers module, execute the following command and reload Apache:
# Some of the directives require the Apache Headers module. If it is not
# already enabled, please execute the following command and reload Apache:
# sudo a2enmod headers
#
# Please note that the order of directives across configuration files matters,
# see also:
# https://httpd.apache.org/docs/current/sections.html#merging
# The following directive matches all files and forces them to be handled as
# static content, which prevents the server from parsing and executing files
# that are associated with a dynamic runtime, e.g. PHP files.
# It also forces their Content-Type header to "application/octet-stream" and
# adds a "Content-Disposition: attachment" header to force a download dialog,
# which prevents browsers from interpreting files in the context of the
# web server, e.g. HTML files containing JavaScript.
# Lastly it also prevents browsers from MIME-sniffing the Content-Type,
# preventing them from interpreting a file as a different Content-Type than
# the one sent by the webserver.
<FilesMatch ".*">
SetHandler default-handler
ForceType application/octet-stream
Header set Content-Disposition attachment
Header set X-Content-Type-Options nosniff
</FilesMatch>
# The following directives prevent the execution of script files
# in the context of the website.
# They also force the content-type application/octet-stream and
# force browsers to display a download dialog for non-image files.
SetHandler default-handler
ForceType application/octet-stream
Header set Content-Disposition attachment
# The following unsets the forced type and Content-Disposition headers
# for known image files:
<FilesMatch "(?i)\.(gif|jpe?g|png)$">
# The following directive matches known image files and unsets the forced
# Content-Type so they can be served with their original mime type.
# It also unsets the Content-Disposition header to allow displaying them
# inline in the browser.
<FilesMatch ".+\.(?i:(gif|jpe?g|png))$">
ForceType none
Header unset Content-Disposition
</FilesMatch>
# The following directive prevents browsers from MIME-sniffing the content-type.
# This is an important complement to the ForceType directive above:
Header set X-Content-Type-Options nosniff
</Directory>
```

Expand Down
54 changes: 39 additions & 15 deletions server/php/files/.htaccess
Original file line number Diff line number Diff line change
@@ -1,25 +1,49 @@
# To enable the Headers module, execute the following command and reload Apache:
# If you have not done so already, please first read SECURITY.md in the root
# directory of this project or online:
# https://github.com/blueimp/jQuery-File-Upload/blob/master/SECURITY.md
#
# The settings in this file require Apache to support configuration overrides
# in .htaccess files, which is disabled by default since Apache v2.3.9 and needs
# to be enabled for the directives in this file to have any effect, see also:
# https://httpd.apache.org/docs/current/mod/core.html#allowoverride
#
# If you have full control over the web server, it is preferrable to define the
# settings in the Apache configuration (e.g. /etc/apache2/apache2.conf) itself.
#
# Some of the directives require the Apache Headers module. If it is not
# already enabled, please execute the following command and reload Apache:
# sudo a2enmod headers
#
# Please note that the order of directives across configuration files matters,
# see also:
# https://httpd.apache.org/docs/current/sections.html#merging

# The following directives prevent the execution of script files
# in the context of the website.
# They also force the content-type application/octet-stream and
# force browsers to display a download dialog for non-image files.
SetHandler default-handler
ForceType application/octet-stream
Header set Content-Disposition attachment
# The following directive matches all files and forces them to be handled as
# static content, which prevents the server from parsing and executing files
# that are associated with a dynamic runtime, e.g. PHP files.
# It also forces their Content-Type header to "application/octet-stream" and
# adds a "Content-Disposition: attachment" header to force a download dialog,
# which prevents browsers from interpreting files in the context of the
# web server, e.g. HTML files containing JavaScript.
# Lastly it also prevents browsers from MIME-sniffing the Content-Type,
# preventing them from interpreting a file as a different Content-Type than
# the one sent by the webserver.
<FilesMatch ".*">
SetHandler default-handler
ForceType application/octet-stream
Header set Content-Disposition attachment
Header set X-Content-Type-Options nosniff
</FilesMatch>

# The following unsets the forced type and Content-Disposition headers
# for known image files:
<FilesMatch "(?i)\.(gif|jpe?g|png)$">
# The following directive matches known image files and unsets the forced
# Content-Type so they can be served with their original mime type.
# It also unsets the Content-Disposition header to allow displaying them
# inline in the browser.
<FilesMatch ".+\.(?i:(gif|jpe?g|png))$">
ForceType none
Header unset Content-Disposition
</FilesMatch>

# The following directive prevents browsers from MIME-sniffing the content-type.
# This is an important complement to the ForceType directive above:
Header set X-Content-Type-Options nosniff

# Uncomment the following lines to prevent unauthorized download of files:
#AuthName "Authorization required"
#AuthType Basic
Expand Down

0 comments on commit a532992

Please sign in to comment.