diff --git a/htaccess.txt b/htaccess.txt
index b5aa0ade..63a7854b 100644
--- a/htaccess.txt
+++ b/htaccess.txt
@@ -1,22 +1,65 @@
#################################################################################################
# START PROCESSWIRE HTACCESS DIRECTIVES
# @version 3.0
-# @indexVersion 300
+# @htaccessVersion 301
#################################################################################################
+# Upgrading htaccess (or index) version 300 to 301
# -----------------------------------------------------------------------------------------------
-# 1. Don't show directory indexes, but do follow symbolic links
-# 500 NOTE: Some cloud hosting companies don't allow +FollowSymLinks.
-# Uncomment +SymLinksifOwnerMatch and comment +FollowSymLinks if you have 500 errors.
-# If that doesn't resolve the error, then set it back to +FollowSymLinks.
+# If your htaccess/index version is 300, upgrade to this version by replacing all of section #15
+# (Access Restrictions). Also take a look at section #9, which you might also consider replacing
+# if using HTTPS, though it is not required. Following that, optionally review the rest of the
+# file to see if there are any other changes you also want to apply. When finished, add a line
+# at the top identical to the "htaccessVersion 301" that you see at the top of this file. This
+# tells ProcessWire your .htaccess file is up-to-date. If you never customized your original
+# .htaccess file, then of course you can also just replace it with this one.
+#
+# Resolving 500 errors
+# -----------------------------------------------------------------------------------------------
+# Depending on your server, some htaccess rules may not be compatible and result in a 500 error.
+# If you experience this, find all instances of the term "(500)" in this file for suggestions on
+# things you can change to resolve 500 errors.
+#
+# Optional features
+# -----------------------------------------------------------------------------------------------
+# Many of the rules in this .htaccess file are optional and commented out by default. While the
+# defaults are okay for many, you may want to review each section in this .htaccess file for
+# optional rules that you can enable to increase security, speed or best practices. To quickly
+# locate all optional rules, search this file for all instances of "(O)".
+#
+# If using a load balancer
+# -----------------------------------------------------------------------------------------------
+# If using a load balancer (like those available from AWS) some htaccess rules will need to
+# change. Search this file for instances of "(L)" for details.
+#
+
+# -----------------------------------------------------------------------------------------------
+# 1. Apache Options
+#
+# Note: If you experience a (500) error, it may indicate your host does not allow setting one or
+# more of these options. First try replacing the +FollowSymLinks with +SymLinksifOwnerMatch.
+# If that does not work, try commenting them all out, then uncommenting one at a time to
+# determine which one is the source of the 500 error.
# -----------------------------------------------------------------------------------------------
+# Do not show directory indexes (strongly recommended)
Options -Indexes
+
+# Do not use multiviews
+Options -MultiViews
+
+# Do follow symbolic links
Options +FollowSymLinks
# Options +SymLinksifOwnerMatch
+# Character encoding: Serve text/html or text/plain as UTF-8
+AddDefaultCharset UTF-8
+
# -----------------------------------------------------------------------------------------------
-# 2. Let ProcessWire handle 404s
+# 2. ErrorDocument settings: Have ProcessWire handle 404s
+#
+# For options and optimizations, see: (O)
+# https://processwire.com/blog/posts/optimizing-404s-in-processwire/
# -----------------------------------------------------------------------------------------------
ErrorDocument 404 /index.php
@@ -42,15 +85,18 @@ ErrorDocument 404 /index.php
# you will need to remove this one if you want to allow external iframes
Header always append X-Frame-Options SAMEORIGIN
- # to prevent cross site scripting (IE8+ proprietary)
+ # To prevent cross site scripting (IE8+ proprietary)
Header set X-XSS-Protection "1; mode=block"
- # prevent mime-based attacks via content sniffing (IE+Chrome)
+ # Optionally (O) prevent mime-based attacks via content sniffing (IE+Chrome)
# Header set X-Content-Type-Options "nosniff"
# -----------------------------------------------------------------------------------------------
-# 5. Protect ProcessWire system files
+# 5. Prevent access to various types of files
+#
+# Note that some of these rules are duplicated by RewriteRules or other .htaccess files, as we
+# try to maintain two layers of protection when/where possible.
# -----------------------------------------------------------------------------------------------
@@ -62,9 +108,18 @@ ErrorDocument 404 /index.php
+
+
+ Require all denied
+
+
+ Order allow,deny
+
+
+
# -----------------------------------------------------------------------------------------------
# 6. Override a few PHP settings that can't be changed at runtime (not required)
-# 500 NOTE: Try commenting out this entire section below if getting Apache 500 errors.
+# Note: try commenting out this entire section below if getting Apache (500) errors.
# -----------------------------------------------------------------------------------------------
@@ -80,60 +135,125 @@ ErrorDocument 404 /index.php
DirectoryIndex index.php index.html index.htm
# -----------------------------------------------------------------------------------------------
-# 8. ProcessWire requires mod_rewrite
+# 8. Enable Apache mod_rewrite (required)
# -----------------------------------------------------------------------------------------------
RewriteEngine On
- AddDefaultCharset UTF-8
-
- # -----------------------------------------------------------------------------------------------
- # 9. If you only want to allow HTTPS, uncomment the RewriteCond and RewriteRule lines below.
- # -----------------------------------------------------------------------------------------------
- # RewriteCond %{HTTPS} off
- # RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
- # If using an AWS load balancer, use these two lines below instead of those above:
- # RewriteCond %{HTTP:X-Forwarded-Proto} =http
- # RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+ # 8A. Optionally (O) set a rewrite base if rewrites are not working properly on your server.
+ # -----------------------------------------------------------------------------------------------
+ # In addition, if your site directory starts with a "~" you will most likely have to use this.
+ # https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase
+
+ # Examples of RewriteBase (root and subdirectories):
+ # RewriteBase /
+ # RewriteBase /pw/
+ # RewriteBase /~user/
+
+ # 8B. Set an environment variable so the installer can detect that mod_rewrite is active.
# -----------------------------------------------------------------------------------------------
- # 10. Set an environment variable so the installer can detect that mod_rewrite is active.
- # Note that some web hosts don't support this. If you get a 500 error, you might try
- # commenting out this SetEnv line below.
- # -----------------------------------------------------------------------------------------------
+ # Note that some web hosts don't support this. If you get a (500) error, try commenting out this
+ # SetEnv line below. It is okay to remove these lines after ProcessWire installation.
SetEnv HTTP_MOD_REWRITE On
- # -----------------------------------------------------------------------------------------------
- # 11. OPTIONAL: Set a rewrite base if rewrites aren't working properly on your server.
- # And if your site directory starts with a "~" you will most likely have to use this.
- # -----------------------------------------------------------------------------------------------
-
- # RewriteBase /
- # RewriteBase /pw/
- # RewriteBase /~user/
# -----------------------------------------------------------------------------------------------
- # 12. Access Restrictions: Keep web users out of dirs that begin with a period,
+ # 9. Optionally Force HTTPS (O)
+ # -----------------------------------------------------------------------------------------------
+
+ # 9A. To redirect HTTP requests to HTTPS, uncomment the lines below:
+ # -----------------------------------------------------------------------------------------------
+ # RewriteCond %{HTTPS} !=on
+ # RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+
+ # 9B. If using load balancer/AWS, use the following rather than 9A above: (L)
+ # -----------------------------------------------------------------------------------------------
+ # RewriteCond %{HTTP:X-Forwarded-Proto} =http
+ # RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+
+ # 9C. If using cPanel AutoSSL or Let's Encrypt webroot you may need to MOVE one of the below
+ # lines after the first RewriteCond in 9A or 9B to allow certificate validation:
+ # -----------------------------------------------------------------------------------------------
+ # RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
+ # RewriteCond %{REQUEST_URI} !^/\.well-known/cpanel-dcv/[\w-]+$
+ # RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
+
+
+ # 9D. Store current scheme in a 'proto' environment variable for later use in this file
+ # -----------------------------------------------------------------------------------------------
+ RewriteCond %{HTTPS} =on
+ RewriteRule ^ - [env=proto:https]
+ RewriteCond %{HTTPS} !=on
+ RewriteRule ^ - [env=proto:http]
+
+
+ # 9E. If using Load balancer/AWS- Use lines below rather than 9D: (L)
+ # -----------------------------------------------------------------------------------------------
+ # RewriteCond %{HTTP:X-Forwarded-Proto} =https
+ # RewriteRule ^ - [env=proto:https]
+ # RewriteCond %{HTTP:X-Forwarded-Proto} =http
+ # RewriteRule ^ - [env=proto:http]
+
+
+ # 9F. Optionally (O) tell web browsers to only allow access via Strict-Transport-Security (HSTS)
+ # -----------------------------------------------------------------------------------------------
+ # This forces client-side SSL redirection. Before enabling be absolutely certain you can
+ # always serve via HTTPS because it becomes non-revokable for the duration of your max-age.
+ # See link below for details and options (note 'max-age=31536000' is 1-year):
+ # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
+
+
+ # Uncomment one (1) line below & adjust as needed to enable Strict-Transport-Security (HSTS):
+ # Header always set Strict-Transport-Security "max-age=31536000;"
+ # Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains"
+ # Header always set Strict-Transport-Security "max-age=31536000; preload"
+ # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
+
+
+ # Sections 10 and 11 intentionally omitted
+
+ # -----------------------------------------------------------------------------------------------
+ # 12. Access Restrictions: Keep web users out of dirs or files that begin with a period,
# but let services like Lets Encrypt use the webroot authentication method.
# -----------------------------------------------------------------------------------------------
RewriteRule "(^|/)\.(?!well-known)" - [F]
+
# -----------------------------------------------------------------------------------------------
- # 13. OPTIONAL: Redirect users to the 'www.' version of the site (uncomment to enable).
- # For example: http://processwire.com/ would be redirected to http://www.processwire.com/
+ # 13. Optional domain redirects (O)
+ #
+ # Redirect domain.com to www.domain.com redirect (or www to domain.com redirect).
+ # If using then uncomment either 13A or 13B, do NOT uncomment both of them or nothing will work.
# -----------------------------------------------------------------------------------------------
+ # 13A. Redirect domain.com and *.domain.com to www.domain.com (do not combine with 13B):
+ # -----------------------------------------------------------------------------------------------
# RewriteCond %{HTTP_HOST} !^www\. [NC]
- # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+ # RewriteCond %{SERVER_ADDR} !=127.0.0.1
+ # RewriteCond %{SERVER_ADDR} !=::1
+ # RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+
+ # 13B. Redirect www.domain.com to domain.com (do not combine with 13A):
+ # -----------------------------------------------------------------------------------------------
+ # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
+ # RewriteRule ^ %{ENV:PROTO}://%1%{REQUEST_URI} [R=301,L]
+
# -----------------------------------------------------------------------------------------------
- # 14. OPTIONAL: Send URLs with non-ASCII name-format characters to 404 page (optimization)
+ # 14. Optionally send URLs with non-ASCII name-format characters to 404 page (optimization).
+ #
+ # This ensures that ProcessWire does not spend time processing URLs that we know ahead of time
+ # are going to result in 404s. Uncomment lines below to enable. (O)
# -----------------------------------------------------------------------------------------------
# RewriteCond %{REQUEST_URI} "[^-_.a-zA-Z0-9/~]"
@@ -141,49 +261,73 @@ DirectoryIndex index.php index.html index.htm
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule ^(.*)$ index.php?it=/http404/ [L,QSA]
+
# -----------------------------------------------------------------------------------------------
- # 15. Access Restrictions: Protect ProcessWire system files
+ # 15. Access Restrictions: Keep users out of some files and directories
# -----------------------------------------------------------------------------------------------
- # Allow screenshot files (for install.php only: this 1 line below may be removed after install)
- RewriteCond %{REQUEST_URI} !(^|/)site-[^/]+/install/[^/]+\.(jpg|jpeg|png|gif)$
+ # Prevent all the following rules from blocking images in site install directories
+ RewriteCond %{REQUEST_URI} !(^|/)site-[^/]+/install/[^/]+\.(jpg|jpeg|png|gif|webp|svg)$
+
# Block access to any htaccess files
- RewriteCond %{REQUEST_URI} (^|/)\.htaccess$ [NC,OR]
- # Block access to protected assets directories
- RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) [OR]
- # Block acceess to the /site/install/ directory
- RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/install($|/.*$) [OR]
- # Block dirs in /site/assets/ dirs that start with a hyphen
- RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets.*/-.+/.* [OR]
- # Block access to /wire/config.php, /site/config.php, /site/config-dev.php, and /wire/index.config.php
- RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ [OR]
- # Block access to any PHP-based files in /templates-admin/
- RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ [OR]
- # Block access to any PHP or markup files in /site/templates/
- RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ [OR]
- # Block access to any PHP files in /site/assets/
- RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets($|/|/.*\.php)$ [OR]
- # Block access to any PHP files in core or core module directories
- RewriteCond %{REQUEST_URI} (^|/)wire/(core|modules)/.*\.(php|inc|tpl|module|info\.json)$ [OR]
- # Block access to any PHP files in /site/modules/
- RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module|info\.json)$ [OR]
- # Block access to any software identifying txt files
- RewriteCond %{REQUEST_URI} (^|/)(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md|textile)$ [OR]
+ RewriteCond %{REQUEST_URI} (^|/)(\.htaccess|htaccess\..*)$ [NC,OR]
+
+ # Block access to various assets directories
+ RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) [NC,OR]
+
+ # Block access to the /site/install/ directories
+ RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/install($|/.*$) [NC,OR]
+
+ # Block dirs in /site/assets/dirs that start with a hyphen (see config.pagefileSecure)
+ RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets.*/-.+/.* [NC,OR]
+
+ # Block access to /wire/config.php, /site/config.php, /site/config-dev.php, /wire/index.config.php, etc.
+ RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ [NC,OR]
+
+ # Block access to any PHP-based files in /site/templates-admin/ or /wire/templates-admin/
+ RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ [NC,OR]
+
+ # Block access to any PHP or markup files in /site/templates/ or /site-*/templates/
+ RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ [NC,OR]
+
+ # Block access to any PHP files within /site/assets/ and further
+ RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets($|/|/.*\.php)$ [NC,OR]
+
+ # Block access to any PHP, module, inc or info files in core or core modules directories
+ RewriteCond %{REQUEST_URI} (^|/)wire/(core|modules)/.*\.(php|inc|tpl|module|info\.json)$ [NC,OR]
+
+ # Block access to any PHP, tpl or info.json files in /site/modules/ or /site-*/modules/
+ RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module|info\.json)$ [NC,OR]
+
+ # Block access to any software identifying txt, markdown or textile files
+ RewriteCond %{REQUEST_URI} (^|/)(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md|textile)$ [NC,OR]
+
+ # Block potential arbitrary backup files within site directories for things like config
+ RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/(config[^/]*/?|[^/]+\.php.*)$ [NC,OR]
+
+ # Block access throughout to temporary files ending with tilde created by certain editors
+ RewriteCond %{REQUEST_URI} \.(html?|inc|json|lock|module|php|py|rb|sh|sql|tpl|tmpl|twig)~$ [NC,OR]
+
+ # Block access to names of potential backup file extensions within wire or site directories
+ RewriteCond %{REQUEST_URI} (^|/)(wire/|site[-/]).+\.(bak|old|sql|sw[op]|(bak|php|sql)[./]+.*)[\d.]*$ [NC,OR]
+
# Block all http access to the default/uninstalled site-default directory
RewriteCond %{REQUEST_URI} (^|/)site-default/
+
# If any conditions above match, issue a 403 forbidden
RewriteRule ^.*$ - [F,L]
+
# PW-PAGENAME
# -----------------------------------------------------------------------------------------------
- # 16a. Ensure that the URL follows the name-format specification required by PW
+ # 16A. Ensure that the URL follows the name-format specification required by PW
# See also directive 16b below, you should choose and use either 16a or 16b.
# -----------------------------------------------------------------------------------------------
RewriteCond %{REQUEST_URI} "^/~?[-_.a-zA-Z0-9/]*$"
# -----------------------------------------------------------------------------------------------
- # 16b. Alternative name-format specification for UTF8 page name support.
+ # 16B. Alternative name-format specification for UTF8 page name support. (O)
# If used, comment out section 16a above and uncomment the directive below. If you have updated
# your $config->pageNameWhitelist make the characters below consistent with that.
# -----------------------------------------------------------------------------------------------
@@ -201,7 +345,7 @@ DirectoryIndex index.php index.html index.htm
RewriteCond %{REQUEST_FILENAME} !(favicon\.ico|robots\.txt)
# -----------------------------------------------------------------------------------------------
- # 18. OPTIONAL: Prevent ProcessWire from attempting to serve images or anything in /site/assets/.
+ # 18. Optionally (O) prevent PW from attempting to serve images or anything in /site/assets/.
# Both of these lines are optional, but can help to reduce server load. However, they
# are not compatible with the $config->pagefileSecure option (if enabled) and they
# may produce an Apache 404 rather than your regular 404. You may uncomment the two lines
@@ -211,18 +355,20 @@ DirectoryIndex index.php index.html index.htm
# section #2 above that makes ProcessWire the 404 handler.
# -----------------------------------------------------------------------------------------------
- # RewriteCond %{REQUEST_FILENAME} !\.(jpg|jpeg|gif|png|ico)$ [NC]
+ # RewriteCond %{REQUEST_FILENAME} !\.(jpg|jpeg|gif|png|ico|webp|svg)$ [NC]
# RewriteCond %{REQUEST_FILENAME} !(^|/)site/assets/
# -----------------------------------------------------------------------------------------------
# 19. Pass control to ProcessWire if all the above directives allow us to this point.
# For regular VirtualHosts (most installs)
# -----------------------------------------------------------------------------------------------
+
RewriteRule ^(.*)$ index.php?it=$1 [L,QSA]
# -----------------------------------------------------------------------------------------------
- # 20. If using VirtualDocumentRoot (500 NOTE): comment out the one above and use this one instead
+ # 20. If using VirtualDocumentRoot (500): comment out the one above and use this one instead
# -----------------------------------------------------------------------------------------------
+
# RewriteRule ^(.*)$ /index.php?it=$1 [L,QSA]
diff --git a/site-default/htaccess.txt b/site-default/htaccess.txt
new file mode 100644
index 00000000..e9b1f081
--- /dev/null
+++ b/site-default/htaccess.txt
@@ -0,0 +1,10 @@
+# ProcessWire: Block any PHP files from direct access
+
+
+ Require all denied
+
+
+ Order allow,deny
+ Deny from all
+
+
\ No newline at end of file
diff --git a/wire/core/ProcessWire.php b/wire/core/ProcessWire.php
index 061c3945..97844ddc 100644
--- a/wire/core/ProcessWire.php
+++ b/wire/core/ProcessWire.php
@@ -62,7 +62,7 @@ class ProcessWire extends Wire {
* Minimum required .htaccess file version
*
*/
- const htaccessVersion = 300;
+ const htaccessVersion = 301;
/**
* Status when system is booting
diff --git a/wire/modules/Process/ProcessLogin/ProcessLogin.module b/wire/modules/Process/ProcessLogin/ProcessLogin.module
index 6ed7f326..e145067d 100644
--- a/wire/modules/Process/ProcessLogin/ProcessLogin.module
+++ b/wire/modules/Process/ProcessLogin/ProcessLogin.module
@@ -397,11 +397,11 @@ class ProcessLogin extends Process implements ConfigurableModule {
$htaccessFile = $this->wire('config')->paths->root . '.htaccess';
if(is_readable($htaccessFile)) {
$htaccessData = file_get_contents($htaccessFile);
- if(!preg_match('/@(?:index|htaccess)Version\s+(\d+)\b/', $htaccessData, $matches) || ((int) $matches[1]) < $htaccessVersion) {
+ if(!preg_match('/@htaccessVersion\s+(\d+)\b/', $htaccessData, $matches) || ((int) $matches[1]) < $htaccessVersion) {
$this->warning(
- "Not urgent, but note that your root .htaccess file is not up-to-date with this ProcessWire version - please update it when possible.
" .
- "To ignore this warning, replace or add the following in the top of your existing .htaccess file: " .
- "# @indexVersion $htaccessVersion", Notice::log | Notice::allowMarkup
+ "Please note that your root .htaccess file is not up-to-date with this ProcessWire version - update it when possible.
" .
+ "To suppress this warning, replace or add the following in the top of your existing .htaccess file: " .
+ "# @htaccessVersion $htaccessVersion", Notice::log | Notice::allowMarkup
);
}
}