Apache2.4 htaccess - negative ifModule executes regardless - .htaccess

Consider the following Apache conf directives inside .htaccess:
ErrorDocument 403 /dbug.html
<IfModule !mod_php5.c>
Require all denied
</IfModule>
It denies access even though mod_php5 is active, but ignores the ErrorDocument
If i remove the ! it triggers the ErrorDocument 403 - which it should, but this is backwards, and wrong ..
Any answer/advice would be appreciated, thanks.

In some shared-hosting environments, live-module-version-switching (hot-switch) is available; as a result, the main module-name (module-handler) may be different than the target-module-name, but the target-module will show up as being present only when it is called by the module-handler.
The solution is to track down the name of the module-handler-name and reference that instead .. contact the hosting provider. In this case, the module-handler-name is: mod_php_null (Hetzner); so <ifModule !mod_php_null.c> will work as expected -BUT- to set directives for the target-module, use the target module-name; so then <ifModule !mod_php7.c> will work as expected.
If there is no "module-handler" for such a module, then referring the target module directly in both conditions should work as it gets loaded upon server daemon startup.
The question was also posted on Server Fault, to avoid duplication -the .htaccess code is posted there.

Related

Why my rewrite rule in htaccess is working in some case only?

I try to rewrite some of my URLs with a .htaccess file but it didn't work as expected.
This is the rewrite rule in my .htaccess file :
RewriteRule ^(index|administration)/([A-Za-z0-9-]+)(\.php)?$ index.php?c=$1&t=$2 [QSA]
When I go on www.example.com/index/main, I get a 404 error code.
So I try to change my rewrite rule to
RewriteRule ^index.php$ index.php?c=index&t=main [QSA]
Then I go to www.example.com/index.php and the webpage displays perfectly with all the datas in $_GET (c = index and t = main).
So I don't know why my first rule is not working. Let me see if you have any idea.
Is it possible that my server wants to enter the index folder, then the main folder for my first rule without taking care of my .htaccess (www.example.com/index/main) ?
You need to ensure that MultiViews (part of mod_negotiation) is disabled for this to work correctly. So, add the following at top of your .htaccess file:
Options -MultiViews
If MultiViews is enabled (it's disabled by default, but some hosts do sometimes enable this in the server config) then when you request /index/main where /index.php already exists as a physical file then mod_negotiation will make an internal request for index.php before mod_rewrite is able to process the request. (If index.html also exists, then this might be found first.)
(MultiViews essentially enables extensionless URLs by mocking up type maps and searching for files in the directory - with the same basename - that would return a response with an appropriate mime-type.)
If this happens then your mod-rewrite directive is essentially ignored (the pattern does not match, since it would need to check for index.php) and index.php is called without the URL parameters that your mod_rewrite directive would otherwise append.
it perfectly works by disabling the MultiViews Option in my .htaccess
This would ordinarily imply its your script (ie. index.php) that is triggering the 404 (perhaps due to missing URL parameters?), rather than Apache itself?
However, if you were seeing an Apache generated 404 then it would suggest either:
You also have an index.html file, which is found before index.php. .html files do not ordinarily accept path-info (ie. /main) so would trigger a 404.
OR, AcceptPathInfo Off is explicitly set elsewhere in the config, which would trigger a 404 when the request is internally rewritten to /index.php/main (by mod_negotiation).

Payment gateway blocked by mod_security when trying to request Woocommerce endpoint

my payment gateway is blocked by mod_security when trying to access Woocommerce endpoint.
receiving 403 permission denied when trying to access the "/wc-api/my_gateway_payment_callback" endpoint.
im on an Litespeed shared host.
when disabling the mod_security from .htaccess
<IfModule mod_security.c>
SecFilterEngine Off
SecFilterScanPOST Off
</IfModule>
it solves the issue but exposes Wordpress admin to attacks, so i want to be more specific.
i tried to add a LocationMatch
<LocationMatch "/wc-api/my_gateway_payment_callback">
<IfModule mod_security.c>
SecRule REQUEST_URI "#beginsWith /wc-api/my_gateway_payment_callback/" \"phase:2,id:1000,nolog,pass, allow, msg:'Update URI accessed'"
</IfModule>
</LocationMatch>
or
<IfModule mod_security.c>
SecRule REQUEST_URI "#beginsWith /my_gateway_payment_callback" \"phase:2,id:1000,nolog,pass, allow, msg:'Update URI accessed'"
</IfModule>
but they dont work and im still getting the 403 error.
I can spot multiple problems here:
<IfModule mod_security.c>
SecFilterEngine Off
SecFilterScanPOST Off
</IfModule>
Are you really using ModSecurity v1? That is VERY old and suggests you are using Apache 1 as ModSecurity v1 is not compatible with ModSecurity v1. If not this should be:
<IfModule mod_security2.c>
SecRuleEngine Off
</IfModule>
Next you say:
it solves the issue but exposes Wordpress admin to attacks
I don't see how it can solve the issue unless you are on REALLY old software, so suspect this is a red herring.
so i want to be more specific. i tried to add a LocationMatch
Good idea to be more specific. However LocationMatch runs quite late in Apache process - after ModSecurity rules will have run so this will not work. However you don’t really need LocationMatch since your rule already scopes it to that location. So let’s look at the next two pieces:
SecRule REQUEST_URI "#beginsWith /wc-api/my_gateway_payment_callback/" \"phase:2,id:1000,nolog,pass, allow, msg:'Update URI accessed'"
SecRuleRemoveById 3000
You shouldn't need to remove the rule if you allow it on the previous lines. Typically you would only do one or the other.
or
<IfModule mod_security.c>
SecRule REQUEST_URI "#beginsWith /my_gateway_payment_callback" > \
"phase:2,id:1000,nolog,pass, allow, msg:'Update URI accessed'"
</IfModule>
but they dont work and im still getting the 403 error.
You have pass (which means continue on to the next rule) and allow (which means skip all future rules). It seems to me you only want the latter and not the former. As these are conflicting, I suspect ModSecurity will action the former first hence why it is not working.
However the better way is to look at the Apache error logs to see what rule it's failing on (is it rule 3000 as per your other LocationMatch workaround?) and just disable that one rule rather than disable all rules for that route.
So all in all I'm pretty confused with your question as seems to be a lot of inconsistencies and things that are just wrong in there...

Why does this RewriteRule work for all extensions but .php?

This simple RewriteRule that I am using for practicing with .htaccess files works almost always:
RewriteEngine on
RewriteRule ^.*$ test.html
When I have the file flowers.html and I use http://localhost/flowers I get redirected to test.html, however when I rename flowers.html to flowers.php I get a 404 page with the message The requested URL /flowers was not found on this server. Does anyone know what causes this?
EDIT:
When I create an empty file called flowers it does redirect properly to test.html. What is going on here?
This does sound like a conflict with MultiViews, so try adding the following at the top of your .htaccess file to disable MultiViews:
Options -MultiViews
MultiViews is not enabled by default, so maybe this has been enabled in your server config?
When MultiViews (part of mod_negotiation) is enabled, a request for /flowers (no extension) will result in Apache searching for an appropriate file to return (based on mime-type) by trying various file extensions of files found in that directory. This is achieved with an internal subrequest before mod_rewrite runs.
However, it's not clear why this would be a problem in your case if you have no other directives? Since your directive simply rewrites everything to test.html (which should include any subrequests). (I was unable to reproduce this behaviour on my Apache 2.4 test server - hence my initial doubt.)

How to have two different custom error pages in .haccess?

1.
I have a .haccess file that requires you do be accessing from a certain IP address:
<RequireAll>
Require ip XX.XX.XX.XX.XX YY.YY.YY.YY.YY ZZ.ZZ.ZZ.ZZ.ZZ
</RequireAll>
If someone tries to access the website from a IP other then X, Y, or Z then they get an error 403 Forbidden page. I have customized it using the following:
ErrorDocument 403 /.forbidden.php
2.
If someone tries to access a restricted file in the same directory (even if they are from ip addresses X, Y, or Z) then again they prompted with the SAME custom 403 Forbidden page.
My Question
How can I have two different custom 403 Forbidden pages based on why they are forbidden from accessing? In example 1 the forbidden page would /.wrongip.php and in example 2 the forbidden page would /.restricted.php
If this is about the extent of what you are doing then it is fine but if you are going to be doing a lot of redirecting I would consider doing this in PHP, but I digress. You are going to have to use Apache (2.4) module mod_rewrite to rewrite rules and conditions for the IP restriction portion. I would leave your custom 403 Forbidden as is for handling the other cases of that status code. If you are on shared hosting this module is usually enabled by most hosting providers by default.
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^111.222.333.444$
RewriteRule ^(.*)$ /.wrongip.php [L]
You will likely avoid confusion if you keep rule rewrites up near the top of your .htaccess file. You only need the RewriteEngine On line once in your file. RewriteCond is one of the conditions for the rule immediately following. You could have multiple conditions mapped to a single rule (using [OR] flag; AND behavior is by default).
In this solution, the ^ character indicates the start of a string. Likewise, $ indicates the end. So, ^(.*)$ is a wildcard and would match any file accessed on your server. Preceded by a single space separator, the /.wrongip.php portion indicates your custom error page to be redirected to. [L] is the flag to indicate the Apache server should stop processing other rules once it matches that one. Use this unless you are using multiple rules to construct a single URL, otherwise you may cause yourself a headache.
There is an additional flag, [R], that I would suggest being aware of and trying to use when possible for easier use in maintaining good practice with HTTP response codes. These help with search rankings and I would recommend specifying a 403 response because by default it will throw a 302 error which can negatively effect ranking over time. Changing the rule to RewriteRule ^(.*)$ /.wrongip.php [R=403,L] would cause the Apache server to issue an HTTP redirect to the browser (to /.wrongip.php) and communicate a 403 Forbidden error in the header. Since my example has all pages redirecting to /.wrongip.php for non-whitelisted IPs, most likely even /.wrongip.php itself, I think in your specific case the [R] flag would result in an HTTP redirect loop where they would keep requesting /.wrongip.php. In this case you should omit the [R] flag, this will cause the Apache server to do an internal redirect.
Without the [R] flag, the client won't have any idea that this redirect went on (hence internal), so you should still emulate the error code in the header of your /.wrongip.php file using PHP.
I have not tested it, but I assume something like
<Directory /var/www/mysite>
ErrorDocument 403 /.restricted.php
<RequireAll>
Require ip XX.XX.XX.XX.XX YY.YY.YY.YY.YY ZZ.ZZ.ZZ.ZZ.ZZ
ErrorDocument 403 /.wrongip.php
</RequireAll>
</Directory>
could do the trick.
Have a look at
https://httpd.apache.org/docs/trunk/custom-error.html and https://httpd.apache.org/docs/trunk/mod/core.html#errordocument for more information on how such configurations work.

Enable mod_rewrite rules for page not managed by Joomla - 403 forbidden

I have a simple issue to resolve. Every time I access one of the URLs explicitly defined in .htaccess (used by Joomla), I'm getting 403 Forbidden message.
Details about my setup:
I'm using shared hosting
Joomla is installed in the root folder
my newly created page is located in /new/products.php
.htaccess is the default one supplied by Joomla with one additional rule: rewriterule $/new/products^ /new/products.php [R=301,L]
Options +FollowSymLinks is commented out, but switching it on doesn't change anything
Each time I access mysite.com/new/products I' getting:
Forbidden
You don't have permission to access /new/products/ on this server.
Additionally, a 404 Not Found error was encountered while trying to
use an ErrorDocument to handle the request.
Any ideas?
In the end I simply removed old site, cleared all Jooml entries in .htaccess and did RewriteBase to point to my directory. The problem is no more.

Resources