2

I'm using mod_security on various websites, some WordPress and some not.

I notice that on a non WordPress website the following:

https://test-site.com/?exec=/bin/bash

returns a 403 forbidden error code, along with the Apache "forbidden" error page. The mod_security error is written to the log.

However, on a WordPress install, bizzarely, the following:

https://wordpress-test-site.com/?exec=/bin/bash

returns a 403 forbidden error code and writes the error to the log, however it dispays the contents of the homepage, rather than the Apache "forbidden" error page.

I note that it behaves correctly on any other page, other than the homepage:

https://wordpress-test-site.com/some-page/?exec=/bin/bash

The above works as expected, and returns the Apache error page.

I can only assume this is some conflict with WordPress's mod_rewrite rule which is as follows:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Is there something I'm missing here? I don't want to display the homepage content when a mod_security rule is matched via the homepage.

MrCarrot
  • 345
  • 1
  • 4
  • 13
  • On the "non WordPress website" do you also have an `index.php` (or _DirectoryIndex_) file in the document root? – MrWhite Oct 09 '20 at 17:04
  • Yes I do. Interestingly, https://wordpress-test-site.com/index.php?exec=/bin/bash works as expected (403 error page) but https://wordpress-test-site.com/?exec=/bin/bash does not, unless I comment out the mod_rewrite rules. – MrCarrot Oct 09 '20 at 17:56

2 Answers2

1

I can only assume this is some conflict with WordPress's mod_rewrite rule

It actually looks like the opposite is happening. Only when you request https://wordpress-test-site.com/<something> do the mod_rewrite directives actually do anything. When you request the document root, then the mod_rewrite directives simply don't match and instead the request is rewritten to index.php by mod_dir as an internal subrequest (the DirectoryIndex document).

However, I would expect the same behaviour from the non-WordPress test site as well, assuming you have a DirectoryIndex document present?!

Having said that, I would have expected the mod_security rule to have taken priority here?

To test this theory, you could try changing your WordPress .htaccess to the following: (I assume you are using .htaccess since the mod_rewrite directives as posted are intended to be used in a directory context.)

DirectoryIndex disabled

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.php [L]
</IfModule>

UPDATE: Note the 2 changes from the original directives. The RewriteRule pattern is now ^, not . and the RewriteCond directive that checks whether the request maps to a directory is commented out.

This forces requests for the document root to also be processed by the mod_rewrite directives (marginally less efficient). Since we have commented out the directory filesystem check it means that directories will not be accessible (although that is rarely a requirement).

MrWhite
  • 11,643
  • 4
  • 25
  • 40
  • Thanks for your reply. DirectoryIndex is already disabled for all virtualhosts. I added it to the .htaccess file just to double check, but the outcome is the same. There is an index.php file present on both the WordPress and non-WordPress website. When I remove the mod_rewrite rules from the .htaccess file entirely, it behaves as expected. – MrCarrot Oct 09 '20 at 17:50
  • "DirectoryIndex is already disabled for all virtualhosts" - if `DirectoryIndex` is disabled (with the original mod_rewrite directives) then your homepage would not work?! Are you sure you don't mean `Options -Indexes` - which disables the autogenerated directory listings (aka directory indexes)? – MrWhite Oct 09 '20 at 17:55
  • Sorry that's correct, Options -Indexes is turned off for all virtualhosts. I did however add `DirectoryIndex disabled` to the .htaccess file, but it made no difference. Interestingly, `wordpress-test-site.com/index.php?exec=/bin/bash` works as expected (403 error page) but `wordpress-test-site.com/?exec=/bin/bash` does not, unless I comment out the mod_rewrite rules – MrCarrot Oct 09 '20 at 17:58
  • "I did however add DirectoryIndex disabled to the .htaccess file" - you would also need to make the two other changes to the mod_rewrite directives as noted above (otherwise the homepage would not work). – MrWhite Oct 09 '20 at 18:01
  • Thanks, have made those changes, exactly as above, but the issue remains the same. Could it be the order in which the modules are loaded? It's a Centos server and I notice mod_rewrite is loaded from `00-base.conf` and mod_security is loaded from `10-mod_security.conf` – MrCarrot Oct 09 '20 at 18:04
  • `wordpress-test-site.com/index.php` - That would essentially bypass mod_rewrite _and_ mod_dir. – MrWhite Oct 09 '20 at 18:05
  • Well, this is certainly odd behaviour. The only time mod_rewrite really does anything is when requesting a URL of the form `wordpress-test-site.com/`, when `` does not map to a file or directory. Yet, from what you say, this request works OK with regards to the mod_security response. So, it's kind of backward!? It's almost like there is something else going on (yet, removing the mod_rewrite directives "fixes" the mod_security response). – MrWhite Oct 09 '20 at 18:10
  • 1
    To confirm, is this the _default_ 403 Apache response, it's not a custom 403 `ErrorDocument`? – MrWhite Oct 09 '20 at 18:13
  • 1
    I've just discovered a file called `welcome.conf` which appears to be a standard confguration file, but it has `` along with `ErrorDocument 403 /.noindex.html`. The comment at the top says `This configuration file enables the default "Welcome" page if there is no default index page present for the root URL. To disable the Welcome page, comment out all the lines below.` If I comment out the lines, it starts working as expected! – MrCarrot Oct 09 '20 at 18:28
  • 1
    Ah ha! Hhmm, it "enables the default _Welcome_ page" by overriding the default Apache 403 response for the document root only. Does a `.noindex.html` file exist? If not, then the call for the error document itself (internal subrequest) would trigger a 404. – MrWhite Oct 09 '20 at 18:38
  • Looks like .noindex.html doesnt exist. But why would triggering a 404 load the homepage? Actually, the more I think about it, the more I realise why – MrCarrot Oct 09 '20 at 18:58
  • 1
    Well, not necessarily the 404 itself, but the subrequest for `.noindex.html` would be routed through WordPress - by the mod_rewrite directives. Except that WP uses the `REQUEST_URI` variable to route URLs. `REQUEST_URI` is still `/` - the document root - so from WP it's not a 404 and the homepage is served. (Although I'm still a bit puzzled why the initial 403 doesn't "win" in this situation.) – MrWhite Oct 09 '20 at 19:45
  • Thanks for your help getting to the bottom of it :-) – MrCarrot Oct 09 '20 at 19:56
1

Thanks to @MrWhite in the comments, on Centos I discovered a file called /etc/httpd/conf.d/welcome.conf which contains:

<LocationMatch "^/+$">
    Options -Indexes
    ErrorDocument 403 /.noindex.html
</LocationMatch>

Since there is no file called .noindex.html the 403 error document itself was triggering an internal 404 error.

Commenting out the lines above fixed the issue.

MrCarrot
  • 345
  • 1
  • 4
  • 13