问题
I'd like to harden my shared hosting webspace to prevent it from rendering PHP with faked filenames like foo.php.wrong as suggested in the TYPO3 Security Guidelines. For details see also https://stackoverflow.com/a/61760273/3946047
Since I don't have access to the Apache configuration I'd like to add the configuration to my .htaccess
file. But to make the .htaccess
file work on both, my local development environment and in production, I need to wrap the code with a <If>
condition to distinguish between production and all other environments.
But as soon as I add the condition, PHP rendering fails for all PHP files. Instead, the source code is shown. To verify it's not a problem of my huge .htaccess
file, I created a new subdomain with an empty directory and put this into the .htaccess
file:
<IfModule mod_mime.c>
RemoveType .html .htm
<FilesMatch ".+\.html?$">
AddType text/html .html
AddType text/html .htm
</FilesMatch>
RemoveType .svg .svgz
<FilesMatch ".+\.svgz?$">
AddType image/svg+xml .svg
AddType image/svg+xml .svgz
</FilesMatch>
#<If "%{HTTP_HOST} =~ /^(.+)example\.com$/">
RemoveType .php
<FilesMatch ".+\.php$">
AddType application/x-httpd-php73 .php
SetHandler application/x-httpd-php73
</FilesMatch>
#</If>
</IfModule>
This works as long as the condition is commented out. When I activate the condition, even valid PHP files like index.php only show the source code instead of being rendered.
The special type application/x-httpd-php73
is needed because my provider offers several PHP versions.
So my problem is not the configuration itself but the condition. Any ideas how I can fix this?
回答1:
#<If "%{HTTP_HOST} =~ /^(.+)example\.com$/"> RemoveType .php <FilesMatch ".+\.php$"> AddType application/x-httpd-php73 .php SetHandler application/x-httpd-php73 </FilesMatch> #</If>
This "fails" because the inner <FilesMatch>
section (inside the <If>
section), that re-enables the PHP handler is never actually processed. This has to do with the order in which sections are merged.
Surrounding the directives in an <If>
block changes the order of processing. The contents of the <If>
section are merged very late, after <Files>
(and <FilesMatch>
) sections are merged. So, it seems that at the time the <If>
section is processed, it is too late for any child <Files>
(or <FilesMatch>
) containers to be processed (since any <Files>
containers - that are to be processed - have already been processed). Although this is admittedly very counter-intuitive, and there does not appear to be any "warning" of this, as far as I can see, in the Apache docs.
This can be demonstrated with a simple example (which applies to all requests and all files):
<If true>
SetEnv IF_OUTER 1
<Files *>
SetEnv IF_INNER_FILES 1
</Files>
</If>
Without the <If>
wrapper, both the IF_OUTER
and IF_INNER_FILES
environment vars are set. However, with the <If>
wrapper (causing the block to be merged late), the IF_INNER_FILES
env var is not set. It doesn't matter what directives are used: mod_setenvif, mod_rewrite, etc. the inner <Files>
block within the <If>
section is never processed.
However, you could use an alternative method using mod_rewrite to block malicious requests of the form foo.php.wrong
. For example:
RewriteEngine on
RewriteCond %{HTTP_HOST} example\.com$
RewriteRule \.php\. - [R=404]
Any request to example.com
(strictly speaking any hostname that ends with example.com
) that contains .php.
in the URL-path will simply return a 404.
However, you may need to place this in a different part of your .htaccess
file. Preferably near the top. You don't need to repeat the RewriteEngine
directive if it's already present.
There may also be other ways you can identify your development server (or rather, the "live server"). eg. You could Define
a variable in your development server config and check for the absence of this using <IfDefine>
in .htaccess
instead.
For example, in your development server config:
Define DEVELOPMENT_SERVER
Then in .htaccess
, check that this is not defined in order to identity the live server:
<IfDefine !DEVELOPMENT_SERVER>
# Processed only on live server...
</IfDefine>
来源:https://stackoverflow.com/questions/63972645/if-condition-with-http-host-in-htaccess-breaks-php