Backport early blocking feature

Resolves: rhbz#2115313
This commit is contained in:
Tomas Korbar 2022-08-04 15:17:29 +02:00
parent eff83675d7
commit 5ac54f1ac0
3 changed files with 431 additions and 1352 deletions

View File

@ -0,0 +1,424 @@
commit 8acabc1806d3c9be5f781da978a7684639b257d8
Author: Tomas Korbar <tkorbar@redhat.com>
Date: Thu Aug 4 12:13:03 2022 +0200
Add early blocking feature
diff --git a/crs-setup.conf.example b/crs-setup.conf.example
index 6e18996..08c719e 100644
--- a/crs-setup.conf.example
+++ b/crs-setup.conf.example
@@ -233,7 +233,7 @@ SecDefaultAction "phase:2,log,auditlog,pass"
#
-# -- [[ Anomaly Mode Severity Levels ]] ----------------------------------------
+# -- [[ Anomaly Scoring Mode Severity Levels ]] --------------------------------
#
# Each rule in the CRS has an associated severity level.
# These are the default scoring points for each severity level.
@@ -269,7 +269,7 @@ SecDefaultAction "phase:2,log,auditlog,pass"
#
-# -- [[ Anomaly Mode Blocking Threshold Levels ]] ------------------------------
+# -- [[ Anomaly Scoring Mode Blocking Threshold Levels ]] ----------------------
#
# Here, you can specify at which cumulative anomaly score an inbound request,
# or outbound response, gets blocked.
@@ -318,6 +318,35 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# setvar:tx.outbound_anomaly_score_threshold=4"
#
+# -- [[ Early Anomaly Scoring Mode Blocking ]] ------------------------------
+#
+# The anomaly scores for the request and the responses are generally summed up
+# and evaluated at the end of phase:2 and at the end of phase:4 respectively.
+# However, it is possible to enable an early evaluation of these anomaly scores
+# at the end of phase:1 and at the end of phase:3.
+#
+# If a request (or a response) hits the anomaly threshold in this early
+# evaluation, then blocking happens immediately (if blocking is enabled) and
+# the phase 2 (and phase 4 respectively) will no longer be executed.
+#
+# Enable the rule 900120 that sets the variable tx.blocking_early to 1 in order
+# to enable early blocking. The variable tx.blocking_early is set to 0 by
+# default. Early blocking is thus disabled by default.
+#
+# Please note that blocking early will hide potential alerts from you. This
+# means that a payload that would appear in an alert in phase 2 (or phase 4)
+# does not get evaluated if the request is being blocked early. So when you
+# disabled blocking early again at some point in the future, then new alerts
+# from phase 2 might pop up.
+#SecAction \
+# "id:900120,\
+# phase:1,\
+# nolog,\
+# pass,\
+# t:none,\
+# setvar:tx.blocking_early=1"
+
+
# -- [[ Application Specific Rule Exclusions ]] ----------------------------------------
#
# Some well-known applications may undertake actions that appear to be
diff --git a/rules/REQUEST-901-INITIALIZATION.conf b/rules/REQUEST-901-INITIALIZATION.conf
index 2a6f74e..b279829 100644
--- a/rules/REQUEST-901-INITIALIZATION.conf
+++ b/rules/REQUEST-901-INITIALIZATION.conf
@@ -88,6 +88,15 @@ SecRule &TX:outbound_anomaly_score_threshold "@eq 0" \
ver:'OWASP_CRS/3.3.0',\
setvar:'tx.outbound_anomaly_score_threshold=4'"
+# Default Blocking Early (rule 900120 in setup.conf)
+SecRule &TX:blocking_early "@eq 0" \
+ "id:901115,\
+ phase:1,\
+ pass,\
+ nolog,\
+ ver:'OWASP_CRS/3.3.0',\
+ setvar:'tx.blocking_early=0'"
+
# Default Paranoia Level (rule 900000 in setup.conf)
SecRule &TX:paranoia_level "@eq 0" \
"id:901120,\
diff --git a/rules/REQUEST-949-BLOCKING-EVALUATION.conf b/rules/REQUEST-949-BLOCKING-EVALUATION.conf
index 5f370a1..338ce88 100644
--- a/rules/REQUEST-949-BLOCKING-EVALUATION.conf
+++ b/rules/REQUEST-949-BLOCKING-EVALUATION.conf
@@ -11,7 +11,66 @@
# -= Paranoia Level 0 (empty) =- (apply unconditionally)
#
-# Summing up the anomaly score.
+# Skipping early blocking
+
+SecRule TX:BLOCKING_EARLY "!@eq 1" \
+ "id:949050,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ skipAfter:BLOCKING_EARLY_ANOMALY_SCORING"
+
+SecRule TX:BLOCKING_EARLY "!@eq 1" \
+ "id:949051,\
+ phase:2,\
+ pass,\
+ t:none,\
+ nolog,\
+ skipAfter:BLOCKING_EARLY_ANOMALY_SCORING"
+
+# Summing up the anomaly score for early blocking
+
+SecRule TX:PARANOIA_LEVEL "@ge 1" \
+ "id:949052,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=+%{tx.anomaly_score_pl1}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 2" \
+ "id:949053,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=+%{tx.anomaly_score_pl2}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 3" \
+ "id:949054,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=+%{tx.anomaly_score_pl3}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 4" \
+ "id:949055,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=+%{tx.anomaly_score_pl4}'"
+
+SecAction "id:949059,\
+ phase:2,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=0'"
+
+SecMarker BLOCKING_EARLY_ANOMALY_SCORING
# NOTE: tx.anomaly_score should not be set initially, but masking would lead to difficult bugs.
# So we add to it.
@@ -92,6 +151,21 @@ SecRule TX:ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" \
severity:'CRITICAL',\
setvar:'tx.inbound_anomaly_score=%{tx.anomaly_score}'"
+SecRule TX:BLOCKING_EARLY "@eq 1" \
+ "id:949111,\
+ phase:1,\
+ deny,\
+ t:none,\
+ msg:'Inbound Anomaly Score Exceeded in phase 1 (Total Score: %{TX.ANOMALY_SCORE})',\
+ tag:'application-multi',\
+ tag:'language-multi',\
+ tag:'platform-multi',\
+ tag:'attack-generic',\
+ ver:'OWASP_CRS/3.3.0',\
+ severity:'CRITICAL',\
+ chain"
+ SecRule TX:ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" \
+ "setvar:'tx.inbound_anomaly_score=%{tx.anomaly_score}'"
SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:949011,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
diff --git a/rules/REQUEST-949-BLOCKING-EVALUATION.conf.orig b/rules/REQUEST-949-BLOCKING-EVALUATION.conf.orig
new file mode 100644
index 0000000..5f370a1
--- /dev/null
+++ b/rules/REQUEST-949-BLOCKING-EVALUATION.conf.orig
@@ -0,0 +1,132 @@
+# ------------------------------------------------------------------------
+# OWASP ModSecurity Core Rule Set ver.3.3.0
+# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.
+#
+# The OWASP ModSecurity Core Rule Set is distributed under
+# Apache Software License (ASL) version 2
+# Please see the enclosed LICENSE file for full details.
+# ------------------------------------------------------------------------
+
+#
+# -= Paranoia Level 0 (empty) =- (apply unconditionally)
+#
+
+# Summing up the anomaly score.
+
+# NOTE: tx.anomaly_score should not be set initially, but masking would lead to difficult bugs.
+# So we add to it.
+SecRule TX:PARANOIA_LEVEL "@ge 1" \
+ "id:949060,\
+ phase:2,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=+%{tx.anomaly_score_pl1}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 2" \
+ "id:949061,\
+ phase:2,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=+%{tx.anomaly_score_pl2}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 3" \
+ "id:949062,\
+ phase:2,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=+%{tx.anomaly_score_pl3}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 4" \
+ "id:949063,\
+ phase:2,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.anomaly_score=+%{tx.anomaly_score_pl4}'"
+
+
+SecMarker "BEGIN-REQUEST-BLOCKING-EVAL"
+
+# These rules use the anomaly score settings specified in the 10 config file.
+# You should also set the desired disruptive action (deny, redirect, etc...).
+#
+# -=[ IP Reputation Checks ]=-
+#
+# Block based on variable IP.REPUT_BLOCK_FLAG and TX.DO_REPUT_BLOCK
+#
+SecRule IP:REPUT_BLOCK_FLAG "@eq 1" \
+ "id:949100,\
+ phase:2,\
+ deny,\
+ log,\
+ msg:'Request Denied by IP Reputation Enforcement',\
+ logdata:'Previous Block Reason: %{ip.reput_block_reason}',\
+ tag:'application-multi',\
+ tag:'language-multi',\
+ tag:'platform-multi',\
+ tag:'attack-reputation-ip',\
+ ver:'OWASP_CRS/3.3.0',\
+ severity:'CRITICAL',\
+ chain"
+ SecRule TX:DO_REPUT_BLOCK "@eq 1" \
+ "setvar:'tx.inbound_anomaly_score=%{tx.anomaly_score}'"
+
+#
+# -=[ Anomaly Mode: Overall Transaction Anomaly Score ]=-
+#
+SecRule TX:ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" \
+ "id:949110,\
+ phase:2,\
+ deny,\
+ t:none,\
+ log,\
+ msg:'Inbound Anomaly Score Exceeded (Total Score: %{TX.ANOMALY_SCORE})',\
+ tag:'application-multi',\
+ tag:'language-multi',\
+ tag:'platform-multi',\
+ tag:'attack-generic',\
+ ver:'OWASP_CRS/3.3.0',\
+ severity:'CRITICAL',\
+ setvar:'tx.inbound_anomaly_score=%{tx.anomaly_score}'"
+
+
+
+SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:949011,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
+SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:949012,phase:2,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
+#
+# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher)
+#
+
+
+
+SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:949013,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
+SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:949014,phase:2,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
+#
+# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher)
+#
+
+
+
+SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:949015,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
+SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:949016,phase:2,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
+#
+# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher)
+#
+
+
+
+SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:949017,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
+SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:949018,phase:2,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION"
+#
+# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher)
+#
+
+
+
+#
+# -= Paranoia Levels Finished =-
+#
+SecMarker "END-REQUEST-949-BLOCKING-EVALUATION"
diff --git a/rules/RESPONSE-950-DATA-LEAKAGES.conf b/rules/RESPONSE-950-DATA-LEAKAGES.conf
index c34607e..a192359 100644
--- a/rules/RESPONSE-950-DATA-LEAKAGES.conf
+++ b/rules/RESPONSE-950-DATA-LEAKAGES.conf
@@ -95,7 +95,7 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:950014,phase:4,pass,nolog,skipAf
#
SecRule RESPONSE_STATUS "@rx ^5\d{2}$" \
"id:950100,\
- phase:4,\
+ phase:3,\
block,\
capture,\
t:none,\
diff --git a/rules/RESPONSE-959-BLOCKING-EVALUATION.conf b/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
index 8f8114c..26b525c 100644
--- a/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
+++ b/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
@@ -21,7 +21,67 @@
# -= Paranoia Level 0 (empty) =- (apply unconditionally)
#
-# Summing up the anomaly score.
+
+# Skipping early blocking
+
+SecRule TX:BLOCKING_EARLY "!@eq 1" \
+ "id:959050,\
+ phase:3,\
+ pass,\
+ t:none,\
+ nolog,\
+ skipAfter:BLOCKING_EARLY_ANOMALY_SCORING"
+
+SecRule TX:BLOCKING_EARLY "!@eq 1" \
+ "id:959051,\
+ phase:4,\
+ pass,\
+ t:none,\
+ nolog,\
+ skipAfter:BLOCKING_EARLY_ANOMALY_SCORING"
+
+# Summing up the anomaly score for early blocking
+
+SecRule TX:PARANOIA_LEVEL "@ge 1" \
+ "id:959052,\
+ phase:3,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.outbound_anomaly_score=+%{tx.anomaly_score_pl1}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 2" \
+ "id:959053,\
+ phase:3,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.outbound_anomaly_score=+%{tx.anomaly_score_pl2}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 3" \
+ "id:959054,\
+ phase:3,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.outbound_anomaly_score=+%{tx.anomaly_score_pl3}'"
+
+SecRule TX:PARANOIA_LEVEL "@ge 4" \
+ "id:959055,\
+ phase:3,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.outbound_anomaly_score=+%{tx.anomaly_score_pl4}'"
+
+SecAction "id:959059,\
+ phase:4,\
+ pass,\
+ t:none,\
+ nolog,\
+ setvar:'tx.outbound_anomaly_score=0'"
+
+SecMarker BLOCKING_EARLY_ANOMALY_SCORING
# NOTE: tx.anomaly_score should not be set initially, but masking would lead to difficult bugs.
# So we add to it.
@@ -75,6 +135,21 @@ SecRule TX:OUTBOUND_ANOMALY_SCORE "@ge %{tx.outbound_anomaly_score_threshold}" \
ver:'OWASP_CRS/3.3.0',\
setvar:'tx.anomaly_score=+%{tx.outbound_anomaly_score}'"
+SecRule TX:BLOCKING_EARLY "@eq 1" \
+ "id:959101,\
+ phase:3,\
+ deny,\
+ t:none,\
+ msg:'Outbound Anomaly Score Exceeded in phase 3 (Total Score: %{TX.OUTBOUND_ANOMALY_SCORE})',\
+ tag:'application-multi',\
+ tag:'language-multi',\
+ tag:'platform-multi',\
+ tag:'attack-generic',\
+ ver:'OWASP_CRS/3.3.0',\
+ severity:'CRITICAL',\
+ chain"
+ SecRule TX:OUTBOUND_ANOMALY_SCORE "@ge %{tx.outbound_anomaly_score_threshold}" \
+ "setvar:'tx.anomaly_score=%{tx.outbound_anomaly_score}'"
SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:959011,phase:3,pass,nolog,skipAfter:END-RESPONSE-959-BLOCKING-EVALUATION"

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,21 @@
Summary: ModSecurity Rules
Name: mod_security_crs
Version: 3.3.0
Release: 3%{?dist}
Release: 4%{?dist}
License: ASL 2.0
URL: https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project
Source: https://github.com/coreruleset/coreruleset/archive/refs/tags/v%{version}.tar.gz
BuildArch: noarch
Requires: mod_security >= 2.8.0
Obsoletes: mod_security_crs-extras < 3.0.0
Patch0: mod_security_crs-early-blocking.patch
%description
This package provides the base rules for mod_security.
%prep
%setup -q -n coreruleset-%{version}
%patch0 -p1 -b.early_blocking
%build
@ -44,6 +46,10 @@ done
%{_datarootdir}/mod_modsecurity_crs
%changelog
* Thu Aug 04 2022 Tomas Korbar <tkorbar@redhat.com> - 3.3.0-4
- Backport early blocking feature
- Resolves: rhbz#2115313
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 3.3.0-3
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688