skip to Main Content

I have Ubuntu 18.10 with apache2, libapache2-mod-security2, modsecurity-crs packages with their default configuration except for enabling ModSecurity debug logging and copying modsecurity.conf-recommended and adding SecRuleEngine On.

I added a new SecRule to a separate file in /etc/modsecurity/

Content of /etc/modsecurity/sf4-modsec.conf is only one line:

SecRule RESPONSE_BODY "@rx <script" id:1000137,phase:4,deny,log,status:403

I can confirm that this rule is being loaded as it appears in debug logs with phase:1:

[02/May/2019:20:48:33 +0200] [localhost/sid#7f8e0d51a5c8][rid#7f8e108d20a0][/_profiler/empty/search/results][4] Recipe: Invoking rule 7f8e0d40d138; [file "/etc/modsecurity/sf4-modsec.conf"] [line "1"] [id "1000137"].
[02/May/2019:20:48:33 +0200] [localhost/sid#7f8e0d51a5c8][rid#7f8e108d20a0][/_profiler/empty/search/results][5] Rule 7f8e0d40d138: SecRule "RESPONSE_BODY" "@rx <script>" "phase:1,auditlog,id:1000137,deny,log,status:403"
[02/May/2019:20:48:33 +0200] [localhost/sid#7f8e0d51a5c8][rid#7f8e108d20a0][/_profiler/empty/search/results][4] Rule returned 0.
[02/May/2019:20:48:33 +0200] [localhost/sid#7f8e0d51a5c8][rid#7f8e108d20a0][/_profiler/empty/search/results][9] No match, not chained -> mode NEXT_RULE.
[02/May/2019:20:48:33 +0200] [localhost/sid#7f8e0d51a5c8][rid#7f8e108d20a0][/_profiler/empty/search/results][4] Recipe: Invoking rule 7f8e0d40f5a0; [file "/etc/modsecurity/crs/crs-setup.conf"] [line "845"] [id "900990"].

However, it doesn’t appear in the logs if specified with phase:4 (I couldn’t find a line with 1000137 in it.)

I would expect this rule to block every page with <script> inside it’s HTML, but it doesn’t, despite the <script> tag 100% being in the response.
However, the installed rules from OWASP CRS set seem to work flawlessly.

My response body handling configuration:

SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction Reject

I tried restarting Apache by sudo service apache2 restart several times.

I tried disabling all OWASP CRS rules and it still didn’t help.
Here’s my debug log with phase 4: https://pastebin.com/8aXk8hL0 (it’s pretty short)

2

Answers


  1. Chosen as BEST ANSWER

    I've spent nights trying to find out why this didn't work.

    The reason is technical limitation of ModSecurity. You can see the issue here: https://github.com/SpiderLabs/ModSecurity/issues/1658

    If you're using mod_rewrite together with apache, it is impossible to apply phase:3 or phase:4 rules and the rules from the given phases don't get executed at all.


  2. Your rules is a phase 1 rule, it needs to be a phase 4 rule to look at response bodies.

    The phases are as follows:

    1. Request Headers
    2. Request Body
    3. Response Headers
    4. Response Body
    5. Logging

    So a phase 1 rule only has access to the Request Headers and is processed before the request body is processed by Apache, and before the request is actioned by Apache and the Response is created.

    However, even if you move this to a phase 4 rule, other rules may stop this phase being run. For example OWASP CRS v2 has an optional_rules/modsecurity_crs_10_ignore_static.conf file with the following rule:

    # HTML
    SecRule REQUEST_FILENAME ".(?:(?:cs|j)s|html?)$"  "phase:2,t:none,t:lowercase,setvar:tx.text_file_extension=1,allow:phase,nolog,id:'999005',severity:'6'"
    

    Which runs in phase 2, and says any files ending in .html (and also .js and .css but probably less relevant here) are passed (so skip the rest of phase 2, and also phase 3 and phase 4 – phase 5 is a special phase that is always run). This would mean your phase 4 rule is not run for .html files.

    Rules like these are used for performance reasons as those files, if not dynamically generated, are less risky and so no need to run the full set of rules on them.

    If you really, really want to run phase 4 rules then you need to turn this rule off, either by 1) not including that file or 2) by explicitly excluding that rule with below config:

    SecRuleRemoveById 999005
    

    But then you may want to add another rule so this still works for css and js files.

    And on that note scanning outgoing bodies is expensive. Typically incoming HTTP requests are small (unless you are an upload site) but outgoing requests will often be large, hence why SecResponseBodyAccess is off by default. Are you sure you want to do this? Not sure what you are trying to achieve but there may be better ways to achieve your goal (e.g. with Content Security Policy).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search