Apache LocationMatch wildcard for ModSecurity on w

2019-07-01 15:15发布

I'm have mod_security installed on an Ubuntu 14.04 Apache 2.4.7 running a WordPress site. I have a handful of rules that I need to ignore, but I'm having trouble implementing some wildcard rules so that I don't have to specify each and every page..

What I have (in my site.conf file) is...

  <LocationMatch "/wp-admin/post.php">
     SecRuleRemoveById 300016
  </LocationMatch>

  <LocationMatch "/wp-admin/nav-menus.php">
     SecRuleRemoveById 300016
  </LocationMatch>

  <LocationMatch "(/wp-admin/|/wp-login.php)">
     SecRuleRemoveById 950117
     SecRuleRemoveById 950005
     SecRuleRemovebyID 981173
     SecRuleRemovebyId 960024
  </LocationMatch>

    <LocationMatch "/wp-admin/load-scripts.php">
     SecRuleRemoveById 981173
    </LocationMatch>


    <LocationMatch "/wp-admin/plugins.php">
     SecRuleRemoveById 981173
    </LocationMatch>

    <LocationMatch "/wp-admin/customize.php">
     SecRuleRemoveById 981173
    </LocationMatch>

What I want is to consolidate everything into a single rule that uses a wildcard on wp-admin and wp-login.

I've tried the following but it seems to be ignored as mod_security is throwing denials..

<LocationMatch "(/wp-admin/*|/wp-login/*)">
....

and also

<LocationMatch "(/wp-admin/*)">
....

and also

<Location "/wp-admin/*">
....

I've done some research on LocationMatch and regex but I'm not getting something here. Is what I'm waning to do possible?

EDIT: The referrer URL in the modsec_audit.log is http://www.<site>.com/wp-admin/customize.php?theme=modality

2条回答
Luminary・发光体
2楼-- · 2019-07-01 15:47

This should work:

<LocationMatch "/wp-(admin|login)/">

You don't need a wildcard here, because you just want to detect the beginning of the path and it doesn't matter, what comes after the 2nd slash.

For Location, you need a ~ to trigger the regex interpretation:

<Location ~ "/wp-(admin|login)/">

More details:

查看更多
等我变得足够好
3楼-- · 2019-07-01 15:48

While Carsten's answer is correct, it should be noted that Location and Location directives run after phase 1 ModSecurity rules. However it looks like your rules are all phase 2 anyway, so this doesn't particularly matter in this case - though I don't have access to rule 300016 so couldn't be 100% sure about that.

Anyway for this reason I don't like using Location and LocationMatch and personally prefer to do Location filtering within ModSecurity with a new rule such as this:

SecRule REQUEST_URI "@beginsWith /wp-(admin|login)/" \
   "phase:2,id:1000,nolog,pass,ctl:ruleRemoveById=300016,\
   ctl:ruleRemoveById=950117,\
   ctl:ruleRemoveById=950005
   ...etc.

That way I can be consistent in rule filtering (rather than have phase 1 rules filtered with a rule like above, and other rules filtered by location matching). You will however need one rule for each phase. Anyway, as I say, that doesn't really matter if all of these are phase 2 or above rules for now.

Another funny worth remembering is that, if you use SecRuleRemoveById you need to specify this after the rule you are removing, whereas if you use ctl:ruleRemoveById you need to specify this before the rule you are removing.

However most Wordpress attacks will be against these very URLs. So you want to be very sure that you don't need these rules. And by moving to a more generic exceptions like this, you are matching each rule against more than it needs to. For example if looks like from your original set up, /wp-login.php only needs 4 of these exceptions but you will move it having them all.

I would suggest that instead of loosening the rules to match more, you should aim to keep them tight and not make this change.

In fact you could tighten them further to only match certain arguments that are causing the need for the exception. For example if only the username field is causing you issues then you could tighten the rules to this:

<LocationMatch "(/wp-admin/|/wp-login.php)">
     SecRuleUpdateTargetById 950117 !ARGS:'username'
     SecRuleUpdateTargetById 950005 !ARGS:'username'
     SecRuleUpdateTargetById 981173 !ARGS:'username'
     SecRuleUpdateTargetById 960024 !ARGS:'username'
</LocationMatch>

or in the other format to this:

SecRule REQUEST_URI "@beginsWith /wp-(admin|login)/" \
  "phase:2,id:1000,nolog,pass,\
  ctl:ruleRemoveTargetById=950117;ARGS:username,\
  ctl:ruleRemoveTargetById=950005;ARGS:username,\
  ctl:ruleRemoveTargetById=981173;ARGS:username,\
  ctl:ruleRemoveTargetById=960024;ARGS:username

Yes this may mean extra work, and I know you came here looking to consolidate your rules to make this easer, but there is little point in running a WAF like ModSecurity if you end up disabling a lot of the rules that you are aiming to protect against and, unfortunately, Wordpress is an active target for a lot of bad people due in part to it's popularity.

So, while I didn't directly answer your question, I hope that's useful and gives you food for thought.

查看更多
登录 后发表回答