From acd9d1354ee8e4ccb562d278bd04d3115e493cfc Mon Sep 17 00:00:00 2001 From: Seth Malaki Date: Thu, 7 Dec 2023 16:32:02 +0000 Subject: [PATCH] update CoreRuleset payload for dikastes' new WAF engine (#2991) - move and reorganise coreruleset delivery - now embedded, no need to rely on go:generate - reorganise how we do the customisations, put all our custom CRS behaviour in its own tigera.conf file - replace generated files with embedded - update files-to-skip - dikastes now provides a basedir option for enhanced security - bump coreruleset from v3.3.5 -> v4.0.0-rc2 --- git-hooks/files-to-skip | 1 - .../applicationlayer_controller.go | 18 +- .../applicationlayer/applicationlayer.go | 18 +- .../coreruleset}/crs-setup.conf | 731 +++--- .../coreruleset}/modsecdefault.conf | 100 +- ...00-EXCLUSION-RULES-BEFORE-CRS.conf.example | 50 +- .../rules}/REQUEST-901-INITIALIZATION.conf | 259 +- .../rules}/REQUEST-905-COMMON-EXCEPTIONS.conf | 10 +- .../REQUEST-911-METHOD-ENFORCEMENT.conf | 32 +- .../rules/REQUEST-913-SCANNER-DETECTION.conf | 86 + .../REQUEST-920-PROTOCOL-ENFORCEMENT.conf | 683 +++-- .../rules}/REQUEST-921-PROTOCOL-ATTACK.conf | 237 +- .../rules}/REQUEST-922-MULTIPART-ATTACK.conf | 18 +- .../REQUEST-930-APPLICATION-ATTACK-LFI.conf | 203 ++ .../REQUEST-931-APPLICATION-ATTACK-RFI.conf | 189 ++ .../REQUEST-932-APPLICATION-ATTACK-RCE.conf | 1824 ++++++++++++++ .../REQUEST-933-APPLICATION-ATTACK-PHP.conf | 240 +- ...EQUEST-934-APPLICATION-ATTACK-GENERIC.conf | 388 +++ .../REQUEST-941-APPLICATION-ATTACK-XSS.conf | 502 ++-- .../REQUEST-942-APPLICATION-ATTACK-SQLI.conf | 1975 +++++++++++++++ ...3-APPLICATION-ATTACK-SESSION-FIXATION.conf | 51 +- .../REQUEST-944-APPLICATION-ATTACK-JAVA.conf | 246 +- .../REQUEST-949-BLOCKING-EVALUATION.conf | 223 ++ .../rules}/RESPONSE-950-DATA-LEAKAGES.conf | 66 +- .../rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf | 404 +++ .../RESPONSE-952-DATA-LEAKAGES-JAVA.conf | 42 +- .../RESPONSE-953-DATA-LEAKAGES-PHP.conf | 92 +- .../RESPONSE-954-DATA-LEAKAGES-IIS.conf | 64 +- .../rules/RESPONSE-955-WEB-SHELLS.conf | 548 ++++ .../RESPONSE-959-BLOCKING-EVALUATION.conf | 233 ++ .../rules/RESPONSE-980-CORRELATION.conf | 136 + ...999-EXCLUSION-RULES-AFTER-CRS.conf.example | 2 +- .../embed/coreruleset/rules/iis-errors.data | 59 + .../coreruleset/rules}/java-classes.data | 21 + .../rules}/java-code-leakages.data | 0 .../coreruleset/rules}/java-errors.data | 0 .../embed/coreruleset/rules/lfi-os-files.data | 720 ++++++ .../rules/php-config-directives.data | 571 +++++ .../coreruleset/rules/php-errors-pl2.data | 6 + .../embed/coreruleset/rules/php-errors.data | 2146 ++++++++++++++++ .../rules/php-function-names-933150.data | 245 ++ .../rules/php-function-names-933151.data | 2201 +++++++++++++++++ .../coreruleset/rules/php-variables.data | 30 + .../coreruleset/rules/restricted-files.data | 267 ++ .../coreruleset/rules/restricted-upload.data | 174 ++ .../rules/scanners-user-agents.data | 112 + .../embed/coreruleset/rules/sql-errors.data | 172 ++ .../embed/coreruleset/rules/ssrf.data | 177 ++ .../embed/coreruleset/rules/unix-shell.data | 665 +++++ .../coreruleset/rules/web-shells-php.data | 161 ++ .../rules/windows-powershell-commands.data | 425 ++++ .../embed/coreruleset/tigera.conf | 21 + .../coreruleset}/unicode.mapping | 0 pkg/render/applicationlayer/embed/embed.go | 61 + .../applicationlayer/embed/embed_test.go | 53 + pkg/render/applicationlayer/gen.go | 54 - ...QUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf | 423 ---- ...ST-903.9002-WORDPRESS-EXCLUSION-RULES.conf | 760 ------ ...ST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf | 416 ---- ...EST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf | 273 -- ...QUEST-903.9005-CPANEL-EXCLUSION-RULES.conf | 64 - ...UEST-903.9006-XENFORO-EXCLUSION-RULES.conf | 587 ----- .../REQUEST-910-IP-REPUTATION.conf | 323 --- .../REQUEST-912-DOS-PROTECTION.conf | 324 --- .../REQUEST-913-SCANNER-DETECTION.conf | 199 -- .../REQUEST-930-APPLICATION-ATTACK-LFI.conf | 156 -- .../REQUEST-931-APPLICATION-ATTACK-RFI.conf | 153 -- .../REQUEST-932-APPLICATION-ATTACK-RCE.conf | 730 ------ ...REQUEST-934-APPLICATION-ATTACK-NODEJS.conf | 96 - .../REQUEST-942-APPLICATION-ATTACK-SQLI.conf | 1596 ------------ .../REQUEST-949-BLOCKING-EVALUATION.conf | 133 - .../RESPONSE-951-DATA-LEAKAGES-SQL.conf | 476 ---- .../RESPONSE-959-BLOCKING-EVALUATION.conf | 116 - .../RESPONSE-980-CORRELATION.conf | 170 -- .../crawlers-user-agents.data | 41 - .../modsec-core-ruleset/iis-errors.data | 13 - .../modsec-core-ruleset/lfi-os-files.data | 1115 --------- .../php-config-directives.data | 276 --- .../modsec-core-ruleset/php-errors.data | 219 -- .../php-function-names-933150.data | 44 - .../php-function-names-933151.data | 1264 ---------- .../modsec-core-ruleset/php-variables.data | 19 - .../modsec-core-ruleset/restricted-files.data | 145 -- .../restricted-upload.data | 23 - .../modsec-core-ruleset/scanners-headers.data | 8 - .../modsec-core-ruleset/scanners-urls.data | 17 - .../scanners-user-agents.data | 217 -- .../scripting-user-agents.data | 28 - .../modsec-core-ruleset/sql-errors.data | 80 - .../modsec-core-ruleset/unix-shell.data | 115 - .../windows-powershell-commands.data | 253 -- .../applicationlayer/modsecurityrules.go | 62 - 92 files changed, 16470 insertions(+), 12476 deletions(-) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset}/crs-setup.conf (57%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset}/modsecdefault.conf (72%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example (79%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-901-INITIALIZATION.conf (63%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-905-COMMON-EXCEPTIONS.conf (88%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-911-METHOD-ENFORCEMENT.conf (65%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-913-SCANNER-DETECTION.conf rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-920-PROTOCOL-ENFORCEMENT.conf (68%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-921-PROTOCOL-ATTACK.conf (63%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-922-MULTIPART-ATTACK.conf (68%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-933-APPLICATION-ATTACK-PHP.conf (72%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-941-APPLICATION-ATTACK-XSS.conf (52%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf (71%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/REQUEST-944-APPLICATION-ATTACK-JAVA.conf (60%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/RESPONSE-950-DATA-LEAKAGES.conf (67%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/RESPONSE-952-DATA-LEAKAGES-JAVA.conf (69%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/RESPONSE-953-DATA-LEAKAGES-PHP.conf (59%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/RESPONSE-954-DATA-LEAKAGES-IIS.conf (60%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-955-WEB-SHELLS.conf create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-959-BLOCKING-EVALUATION.conf create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-980-CORRELATION.conf rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example (98%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/iis-errors.data rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/java-classes.data (51%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/java-code-leakages.data (100%) rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset/rules}/java-errors.data (100%) create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/lfi-os-files.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/php-config-directives.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/php-errors-pl2.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/php-errors.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/php-function-names-933150.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/php-function-names-933151.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/php-variables.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/restricted-files.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/restricted-upload.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/scanners-user-agents.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/sql-errors.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/ssrf.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/unix-shell.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/web-shells-php.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/rules/windows-powershell-commands.data create mode 100644 pkg/render/applicationlayer/embed/coreruleset/tigera.conf rename pkg/render/applicationlayer/{modsec-core-ruleset => embed/coreruleset}/unicode.mapping (100%) create mode 100644 pkg/render/applicationlayer/embed/embed.go create mode 100644 pkg/render/applicationlayer/embed/embed_test.go delete mode 100644 pkg/render/applicationlayer/gen.go delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-910-IP-REPUTATION.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-912-DOS-PROTECTION.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-913-SCANNER-DETECTION.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-930-APPLICATION-ATTACK-LFI.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-931-APPLICATION-ATTACK-RFI.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-932-APPLICATION-ATTACK-RCE.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-942-APPLICATION-ATTACK-SQLI.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-949-BLOCKING-EVALUATION.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-951-DATA-LEAKAGES-SQL.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-959-BLOCKING-EVALUATION.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-980-CORRELATION.conf delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/crawlers-user-agents.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/iis-errors.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/lfi-os-files.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/php-config-directives.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/php-errors.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/php-function-names-933150.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/php-function-names-933151.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/php-variables.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/restricted-files.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/restricted-upload.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/scanners-headers.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/scanners-urls.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/scanners-user-agents.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/scripting-user-agents.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/sql-errors.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/unix-shell.data delete mode 100644 pkg/render/applicationlayer/modsec-core-ruleset/windows-powershell-commands.data delete mode 100644 pkg/render/applicationlayer/modsecurityrules.go diff --git a/git-hooks/files-to-skip b/git-hooks/files-to-skip index 08e15d6deb..bc95e50a7b 100644 --- a/git-hooks/files-to-skip +++ b/git-hooks/files-to-skip @@ -1,4 +1,3 @@ api/v1/zz_generated.deepcopy.go api/v1beta1/zz_generated.deepcopy.go pkg/apis/crd.projectcalico.org/v1/zz_generated.deepcopy.go -pkg/render/applicationlayer/modsecurityrules.go diff --git a/pkg/controller/applicationlayer/applicationlayer_controller.go b/pkg/controller/applicationlayer/applicationlayer_controller.go index 6ea74a5326..ee773d3aaf 100644 --- a/pkg/controller/applicationlayer/applicationlayer_controller.go +++ b/pkg/controller/applicationlayer/applicationlayer_controller.go @@ -16,7 +16,6 @@ package applicationlayer import ( "context" - "encoding/base64" "errors" "fmt" @@ -29,6 +28,7 @@ import ( "github.com/tigera/operator/pkg/controller/utils/imageset" "github.com/tigera/operator/pkg/render" "github.com/tigera/operator/pkg/render/applicationlayer" + "github.com/tigera/operator/pkg/render/applicationlayer/embed" rmeta "github.com/tigera/operator/pkg/render/common/meta" corev1 "k8s.io/api/core/v1" @@ -419,23 +419,19 @@ func (r *ReconcileApplicationLayer) getModSecurityRuleSet(ctx context.Context) ( } func getDefaultCoreRuleset(ctx context.Context) (*corev1.ConfigMap, error) { + data, err := embed.AsMap() + if err != nil { + return nil, err + } + ruleset := &corev1.ConfigMap{ TypeMeta: metav1.TypeMeta{Kind: "ConfigMap", APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ Name: applicationlayer.ModSecurityRulesetConfigMapName, Namespace: common.OperatorNamespace(), }, - Data: make(map[string]string), + Data: data, } - - for filename, dataBase64 := range applicationlayer.ModsecurityCoreRuleSet { - if data, err := base64.StdEncoding.DecodeString(dataBase64); err == nil { - ruleset.Data[filename] = string(data) - } else { - return nil, err - } - } - return ruleset, nil } diff --git a/pkg/render/applicationlayer/applicationlayer.go b/pkg/render/applicationlayer/applicationlayer.go index 90ab36a9b0..b0cc1f7030 100644 --- a/pkg/render/applicationlayer/applicationlayer.go +++ b/pkg/render/applicationlayer/applicationlayer.go @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:generate go run gen.go - package applicationlayer import ( @@ -59,9 +57,11 @@ const ( DikastesSyncVolumeName = "dikastes-sync" DikastesContainerName = "dikastes" ModSecurityRulesetVolumeName = "modsecurity-ruleset" + ModSecurityRulesetVolumePath = "/etc/modsecurity-ruleset" ModSecurityRulesetConfigMapName = "modsecurity-ruleset" ModSecurityRulesetHashAnnotation = "hash.operator.tigera.io/modsecurity-ruleset" CalicoLogsVolumeName = "var-log-calico" + CalicologsVolumePath = "/var/log/calico" ) func ApplicationLayer( @@ -295,17 +295,25 @@ func (c *component) containers() []corev1.Container { } if c.config.WAFEnabled { - commandArgs = append(commandArgs, "--rules", "/etc/modsecurity-ruleset") + commandArgs = append( + commandArgs, + "--waf-enabled", + "--waf-ruleset-base-dir", ModSecurityRulesetVolumePath, + "--waf-directive", "Include modsecdefault.conf", + "--waf-directive", "Include crs-setup.conf", + "--waf-directive", "Include tigera.conf", + "--waf-directive", "Include rules/*.conf", + ) volMounts = append( volMounts, []corev1.VolumeMount{ { Name: CalicoLogsVolumeName, - MountPath: "/var/log/calico", + MountPath: CalicologsVolumePath, }, { Name: ModSecurityRulesetVolumeName, - MountPath: "/etc/modsecurity-ruleset", + MountPath: ModSecurityRulesetVolumePath, ReadOnly: true, }, }..., diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/crs-setup.conf b/pkg/render/applicationlayer/embed/coreruleset/crs-setup.conf similarity index 57% rename from pkg/render/applicationlayer/modsec-core-ruleset/crs-setup.conf rename to pkg/render/applicationlayer/embed/coreruleset/crs-setup.conf index 360d629668..23807a3ccd 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/crs-setup.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/crs-setup.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -19,8 +19,8 @@ # # See also: # https://coreruleset.org/ -# https://github.com/SpiderLabs/owasp-modsecurity-crs -# https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project +# https://github.com/coreruleset/coreruleset +# https://owasp.org/www-project-modsecurity-core-rule-set/ # @@ -175,12 +175,12 @@ SecDefaultAction "phase:2,log,auditlog,pass" # Uncomment this rule to change the default: # #SecAction \ -# "id:900000,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.paranoia_level=1" +# "id:900000,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.blocking_paranoia_level=1" # It is possible to execute rules from a higher paranoia level but not include @@ -189,24 +189,24 @@ SecDefaultAction "phase:2,log,auditlog,pass" # the new rules would lead to false positives that raise your score above the # threshold. # This optional feature is enabled by uncommenting the following rule and -# setting the tx.executing_paranoia_level. -# Technically, rules up to the level defined in tx.executing_paranoia_level -# will be executed, but only the rules up to tx.paranoia_level affect the +# setting the tx.detection_paranoia_level. +# Technically, rules up to the level defined in tx.detection_paranoia_level +# will be executed, but only the rules up to tx.blocking_paranoia_level affect the # anomaly scores. -# By default, tx.executing_paranoia_level is set to tx.paranoia_level. -# tx.executing_paranoia_level must not be lower than tx.paranoia_level. +# By default, tx.detection_paranoia_level is set to tx.blocking_paranoia_level. +# tx.detection_paranoia_level must not be lower than tx.blocking_paranoia_level. # -# Please notice that setting tx.executing_paranoia_level to a higher paranoia +# Please notice that setting tx.detection_paranoia_level to a higher paranoia # level results in a performance impact that is equally high as setting -# tx.paranoia_level to said level. +# tx.blocking_paranoia_level to said level. # #SecAction \ -# "id:900001,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.executing_paranoia_level=1" +# "id:900001,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.detection_paranoia_level=1" # @@ -225,16 +225,16 @@ SecDefaultAction "phase:2,log,auditlog,pass" # Uncomment this rule to change the default: # #SecAction \ -# "id:900010,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.enforce_bodyproc_urlencoded=1" +# "id:900010,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.enforce_bodyproc_urlencoded=1" # -# -- [[ 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. @@ -258,19 +258,19 @@ SecDefaultAction "phase:2,log,auditlog,pass" # that all configuration variables are set before the CRS rules are processed.) # #SecAction \ -# "id:900100,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.critical_anomaly_score=5,\ -# setvar:tx.error_anomaly_score=4,\ -# setvar:tx.warning_anomaly_score=3,\ -# setvar:tx.notice_anomaly_score=2" +# "id:900100,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.critical_anomaly_score=5,\ +# setvar:tx.error_anomaly_score=4,\ +# setvar:tx.warning_anomaly_score=3,\ +# setvar:tx.notice_anomaly_score=2" # -# -- [[ 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. @@ -309,58 +309,122 @@ SecDefaultAction "phase:2,log,auditlog,pass" # # Uncomment this rule to change the defaults: # -SecAction \ -"id:900110,\ - phase:1,\ - nolog,\ - pass,\ - t:none,\ - setvar:tx.inbound_anomaly_score_threshold=100,\ - setvar:tx.outbound_anomaly_score_threshold=100" - -# -# -- [[ Application Specific Rule Exclusions ]] ---------------------------------------- -# -# Some well-known applications may undertake actions that appear to be -# malicious. This includes actions such as allowing HTML or Javascript within -# parameters. In such cases the CRS aims to prevent false positives by allowing -# administrators to enable prebuilt, application specific exclusions on an -# application by application basis. -# These application specific exclusions are distinct from the rules that would -# be placed in the REQUEST-900-EXCLUSION-RULES-BEFORE-CRS configuration file as -# they are prebuilt for specific applications. The 'REQUEST-900' file is -# designed for users to add their own custom exclusions. Note, using these -# application specific exclusions may loosen restrictions of the CRS, -# especially if used with an application they weren't designed for. As a result -# they should be applied with care. -# To use this functionality you must specify a supported application. To do so -# uncomment rule 900130. In addition to uncommenting the rule you will need to -# specify which application(s) you'd like to enable exclusions for. Only a -# (very) limited set of applications are currently supported, please use the -# filenames prefixed with 'REQUEST-903' to guide you in your selection. -# Such filenames use the following convention: -# REQUEST-903.9XXX-{APPNAME}-EXCLUSIONS-RULES.conf -# -# It is recommended if you run multiple web applications on your site to limit -# the effects of the exclusion to only the path where the excluded webapp -# resides using a rule similar to the following example: -# SecRule REQUEST_URI "@beginsWith /wordpress/" setvar:tx.crs_exclusions_wordpress=1 - -# -# Modify and uncomment this rule to select which application: +#SecAction \ +# "id:900110,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.inbound_anomaly_score_threshold=5,\ +# setvar:tx.outbound_anomaly_score_threshold=4" + + +# +# -- [[ Application Specific Rule Exclusions ]] -------------------------------- +# +# CRS 3.x contained exclusion packages to tweak the CRS for use with common +# web applications, lowering the number of false positives. +# +# In CRS 4, these are no longer part of the CRS itself, but they are available +# as "CRS plugins". Some plugins improve support for web applications, and others +# may bring new functionality. Plugins are not installed by default, but can be +# downloaded from the plugin registry: +# https://github.com/coreruleset/plugin-registry +# +# For detailed information about using and installing plugins, please see: +# https://coreruleset.org/docs/concepts/plugins/ + + +# +# -- [[ Anomaly Score Reporting Level ]] --------------------------------------- +# +# When a request is blocked due to the anomaly score meeting or exceeding the +# anomaly threshold then the blocking rule will also report the anomaly score. +# This applies to the separate inbound and outbound anomaly scores. +# +# In phase 5, there are additional rules that can perform additional reporting +# of anomaly scores with a verbosity that depends on the reporting level defined +# below. +# +# By setting the reporting level you control whether you want additional +# reporting beyond the blocking rule or not and, if yes, which requests should +# be covered. The higher the reporting level, the more verbose the reporting is. +# +# There are 6 reporting levels: +# +# 0 - Reporting disabled +# 1 - Reporting for requests with a blocking anomaly score >= a threshold +# 2 - Reporting for requests with a detection anomaly score >= a threshold +# 3 - Reporting for requests with a blocking anomaly score greater than 0 +# 4 - Reporting for requests with a detection anomaly score greater than 0 +# 5 - Reporting for all requests +# +# Note: Reporting levels 1 and 2 make it possible to differentiate between +# requests that are blocked and requests that are *not* blocked but would have +# been blocked if the blocking PL was equal to detection PL. This may be useful +# for certain FP tuning methodologies, for example moving to a higher PL. +# +# A value of 5 can be useful on platforms where you are interested in logging +# non-scoring requests, yet it is not possible to report this information in +# the request/access log. This applies to Nginx, for example. +# +#SecAction \ +# "id:900115,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.reporting_level=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.early_blocking to 1 in order +# to enable early blocking. The variable tx.early_blocking is set to 0 by +# default. Early blocking is thus disabled by default. +# +# Please note that early blocking 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 early blocking again at some point in the future, then new alerts +# from phase 2 might pop up. #SecAction \ -# "id:900130,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.crs_exclusions_cpanel=1,\ -# setvar:tx.crs_exclusions_drupal=1,\ -# setvar:tx.crs_exclusions_dokuwiki=1,\ -# setvar:tx.crs_exclusions_nextcloud=1,\ -# setvar:tx.crs_exclusions_wordpress=1,\ -# setvar:tx.crs_exclusions_xenforo=1" +# "id:900120,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.early_blocking=1" + + +# +# -- [[ Initialize Default Collections ]] ----------------------------------- +# +# CRS provides a centralized option to initialize and populate collections +# meant to be used by plugins (E.g.DoS protection plugin). +# By default, Global and IP collections (see rule 901320), +# being not used by core rules, are not initialized. +# +# Uncomment this rule to change the default: +# +#SecAction \ +# "id:900130,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.enable_default_collections=1" + # # -- [[ HTTP Policy Settings ]] ------------------------------------------------ @@ -371,7 +435,6 @@ SecAction \ # # These variables are used in the following rule files: # - REQUEST-911-METHOD-ENFORCEMENT.conf -# - REQUEST-912-DOS-PROTECTION.conf # - REQUEST-920-PROTOCOL-ENFORCEMENT.conf # HTTP methods that a client is allowed to use. @@ -381,12 +444,12 @@ SecAction \ # MERGE MKACTIVITY MKCOL MOVE PROPFIND PROPPATCH PUT UNLOCK # Uncomment this rule to change the default. #SecAction \ -# "id:900200,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'" +# "id:900200,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'" # Content-Types that a client is allowed to send in a request. # Default: |application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| @@ -407,105 +470,141 @@ SecAction \ # # To prevent blocking request with not allowed content-type by default, you can create an exclusion # rule that removes rule 920420. For example: -# SecRule REQUEST_HEADERS:Content-Type "@rx ^text/plain" \ -# "id:1234,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# ctl:ruleRemoveById=920420,\ -# chain" -# SecRule REQUEST_URI "@rx ^/foo/bar" "t:none" +#SecRule REQUEST_HEADERS:Content-Type "@rx ^text/plain" \ +# "id:1234,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# ctl:ruleRemoveById=920420,\ +# chain" +# SecRule REQUEST_URI "@rx ^/foo/bar" \ +# "t:none" # # Uncomment this rule to change the default. # -SecAction \ -"id:900220,\ - phase:1,\ - nolog,\ - pass,\ - t:none,\ - setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json| |application/grpc| |application/grpc+proto| |application/grpc+json| |application/octet-stream|'" +#SecAction \ +# "id:900220,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json|'" # Allowed HTTP versions. -# Default: HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 -# Example for legacy clients: HTTP/0.9 HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 +# Default: HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0 +# Example for legacy clients: HTTP/0.9 HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0 # Note that some web server versions use 'HTTP/2', some 'HTTP/2.0', so # we include both version strings by default. # Uncomment this rule to change the default. #SecAction \ -# "id:900230,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0'" +# "id:900230,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0'" # Forbidden file extensions. # Guards against unintended exposure of development/configuration files. -# Default: .asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/ +# Default: .asa/ .asax/ .ascx/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/ # Example: .bak/ .config/ .conf/ .db/ .ini/ .log/ .old/ .pass/ .pdb/ .rdb/ .sql/ +# Note that .axd was removed due to false positives (see PR 1925). +# +# To additionally guard against configuration/install archive files from being +# accidentally exposed, common archive file extensions can be added to the +# restricted extensions list. An example list of common archive file extensions +# is presented below: +# .7z/ .br/ .bz/ .bz2/ .cab/ .cpio/ .gz/ .img/ .iso/ .jar/ .rar/ .tar/ .tbz2/ .tgz/ .txz/ .xz/ .zip/ .zst/ +# (Source: https://en.wikipedia.org/wiki/List_of_archive_formats) +# # Uncomment this rule to change the default. #SecAction \ -# "id:900240,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'" - -# Forbidden request headers. -# Header names should be lowercase, enclosed by /slashes/ as delimiters. -# Default: /accept-charset/ /content-encoding/ /proxy/ /lock-token/ /content-range/ /if/ -# -# Note: Accept-Charset is a deprecated header that should not be used by clients and -# ignored by servers. It can be used for a response WAF bypass, by asking for a charset -# that the WAF cannot decode. -# Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset -# -# Note: Content-Encoding is used to list any encodings that have been applied to the -# original payload. It is only used for compression, which isn't supported by CRS by -# default since it blocks newlines and null bytes inside the request body. Most -# compression algorithms require at least null bytes per RFC. Blocking it shouldn't -# break anything and increases security since ModSecurity is incapable of properly -# scanning compressed request bodies. -# -# Note: Blocking Proxy header prevents 'httpoxy' vulnerability: https://httpoxy.org +# "id:900240,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'" + +# Restricted request headers. +# The HTTP request headers that CRS restricts are split into two categories: +# basic (always forbidden) and extended (may be forbidden). All header names +# should be lowercase and enclosed by /slashes/ as delimiters. +# +# [ Basic ] +# Includes deprecated headers and headers with known security risks. Always +# forbidden. +# Default: /content-encoding/ /proxy/ /lock-token/ /content-range/ /if/ /x-http-method-override/ /x-http-method/ /x-method-override/ +# +# /content-encoding/ +# Used to list any encodings that have been applied to the original payload. +# Only used for compression, which isn't supported by CRS by default since CRS +# blocks newlines and null bytes inside the request body. Most compression +# algorithms require at least null bytes per RFC. Blocking Content-Encoding +# shouldn't break anything and increases security since WAF engines, including +# ModSecurity, are typically incapable of properly scanning compressed request +# bodies. +# +# /proxy/ +# Blocking this prevents the 'httpoxy' vulnerability: https://httpoxy.org +# +# /lock-token/ +# +# /content-range/ +# +# /if/ +# +# /x-http-method-override/ +# /x-http-method/ +# /x-method-override/ +# Blocking these headers prevents method override attacks, as described here: +# https://www.sidechannel.blog/en/http-method-override-what-it-is-and-how-a-pentester-can-use-it # # Uncomment this rule to change the default. #SecAction \ -# "id:900250,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:'tx.restricted_headers=/accept-charset/ /content-encoding/ /proxy/ /lock-token/ /content-range/ /if/'" - -# File extensions considered static files. -# Extensions include the dot, lowercase, enclosed by /slashes/ as delimiters. -# Used in DoS protection rule. See section "Anti-Automation / DoS Protection". -# Default: /.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/ +# "id:900250,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:'tx.restricted_headers_basic=/content-encoding/ /proxy/ /lock-token/ /content-range/ /if/ /x-http-method-override/ /x-http-method/ /x-method-override/'" +# +# [ Extended ] +# Includes deprecated headers that are still in use (so false positives are +# possible) and headers with possible security risks. Forbidden at a higher +# paranoia level. +# Default: /accept-charset/ +# +# /accept-charset/ +# Deprecated header that should not be used by clients and should be ignored +# by servers. Can be used for a response WAF bypass by asking for a charset +# that the WAF cannot decode. Considered to be a good indicator of suspicious +# behavior but produces too many false positives to be forbidden by default. +# References: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset +# https://github.com/coreruleset/coreruleset/issues/3140 +# # Uncomment this rule to change the default. #SecAction \ -# "id:900260,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:'tx.static_extensions=/.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/'" +# "id:900255,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:'tx.restricted_headers_extended=/accept-charset/'" # Content-Types charsets that a client is allowed to send in a request. -# Default: utf-8|iso-8859-1|iso-8859-15|windows-1252 +# The content-types are enclosed by |pipes| as delimiters to guarantee exact matches. +# Default: |utf-8| |iso-8859-1| |iso-8859-15| |windows-1252| # Uncomment this rule to change the default. -# Use "|" to separate multiple charsets like in the rule defining -# tx.allowed_request_content_type. #SecAction \ -# "id:900280,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:'tx.allowed_request_content_type_charset=utf-8|iso-8859-1|iso-8859-15|windows-1252'" +# "id:900280,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:'tx.allowed_request_content_type_charset=|utf-8| |iso-8859-1| |iso-8859-15| |windows-1252|'" # # -- [[ HTTP Argument/Upload Limits ]] ----------------------------------------- @@ -522,72 +621,72 @@ SecAction \ # Example: 255 # Uncomment this rule to set a limit. #SecAction \ -# "id:900300,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.max_num_args=255" +# "id:900300,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.max_num_args=255" # Block request if the length of any argument name is too high # Default: unlimited # Example: 100 # Uncomment this rule to set a limit. #SecAction \ -# "id:900310,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.arg_name_length=100" +# "id:900310,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.arg_name_length=100" # Block request if the length of any argument value is too high # Default: unlimited # Example: 400 # Uncomment this rule to set a limit. #SecAction \ -# "id:900320,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.arg_length=400" +# "id:900320,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.arg_length=400" # Block request if the total length of all combined arguments is too high # Default: unlimited # Example: 64000 # Uncomment this rule to set a limit. #SecAction \ -# "id:900330,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.total_arg_length=64000" +# "id:900330,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.total_arg_length=64000" # Block request if the file size of any individual uploaded file is too high # Default: unlimited # Example: 1048576 # Uncomment this rule to set a limit. #SecAction \ -# "id:900340,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.max_file_size=1048576" +# "id:900340,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.max_file_size=1048576" # Block request if the total size of all combined uploaded files is too high # Default: unlimited # Example: 1048576 # Uncomment this rule to set a limit. #SecAction \ -# "id:900350,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.combined_file_sizes=1048576" +# "id:900350,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.combined_file_sizes=1048576" # @@ -612,7 +711,7 @@ SecAction \ # following directive somewhere after the inclusion of the CRS # (E.g., RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf). # -# SecRuleUpdateActionById 901150 "nolog" +#SecRuleUpdateActionById 901450 "nolog" # # ATTENTION: If this TX.sampling_percentage is below 100, then some of the # requests will bypass the Core Rules completely and you lose the ability to @@ -620,148 +719,14 @@ SecAction \ # # Uncomment this rule to enable this feature: # -#SecAction "id:900400,\ -# phase:1,\ -# pass,\ -# nolog,\ -# setvar:tx.sampling_percentage=100" - - -# -# -- [[ Project Honey Pot HTTP Blacklist ]] ------------------------------------ -# -# Optionally, you can check the client IP address against the Project Honey Pot -# HTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a -# free API key. Set it here with SecHttpBlKey. -# -# Project Honeypot returns multiple different malicious IP types. -# You may specify which you want to block by enabling or disabling them below. -# -# Ref: https://www.projecthoneypot.org/httpbl.php -# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey -# -# Uncomment these rules to use this feature: -# -#SecHttpBlKey XXXXXXXXXXXXXXXXX -#SecAction "id:900500,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.block_search_ip=1,\ -# setvar:tx.block_suspicious_ip=1,\ -# setvar:tx.block_harvester_ip=1,\ -# setvar:tx.block_spammer_ip=1" - - -# -# -- [[ GeoIP Database ]] ------------------------------------------------------ -# -# There are some rulesets that inspect geolocation data of the client IP address -# (geoLookup). The CRS uses geoLookup to implement optional country blocking. -# -# To use geolocation, we make use of the MaxMind GeoIP database. -# This database is not included with the CRS and must be downloaded. -# -# There are two formats for the GeoIP database. ModSecurity v2 uses GeoLite (.dat files), -# and ModSecurity v3 uses GeoLite2 (.mmdb files). -# -# If you use ModSecurity 3, MaxMind provides a binary for updating GeoLite2 files, -# see https://github.com/maxmind/geoipupdate. -# -# Download the package for your OS, and read https://dev.maxmind.com/geoip/geoipupdate/ -# for configuration options. -# -# Warning: GeoLite (not GeoLite2) databases are considered legacy, and not being updated anymore. -# See https://support.maxmind.com/geolite-legacy-discontinuation-notice/ for more info. -# -# Therefore, if you use ModSecurity v2, you need to regenerate updated .dat files -# from CSV files first. -# -# You can achieve this using https://github.com/sherpya/geolite2legacy -# Pick the zip files from maxmind site: -# https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country-CSV.zip -# -# Follow the guidelines for installing the tool and run: -# ./geolite2legacy.py -i GeoLite2-Country-CSV.zip \ -# -f geoname2fips.csv -o /usr/share/GeoliteCountry.dat -# -# Update the database regularly, see Step 3 of the configuration link above. -# -# By default, when you execute `sudo geoipupdate` on Linux, files from the free database -# will be downloaded to `/usr/share/GeoIP` (both v1 and v2). -# -# Then choose from: -# - `GeoLite2-Country.mmdb` (if you are using ModSecurity v3) -# - `GeoLiteCountry.dat` (if you are using ModSecurity v2) -# -# Ref: http://blog.spiderlabs.com/2010/10/detecting-malice-with-modsecurity-geolocation-data.html -# Ref: http://blog.spiderlabs.com/2010/11/detecting-malice-with-modsecurity-ip-forensics.html -# -# Uncomment only one of the next rules here to use this feature. -# Choose the one depending on the ModSecurity version you are using, and change the path accordingly: -# -# For ModSecurity v3: -#SecGeoLookupDB /usr/share/GeoIP/GeoLite2-Country.mmdb -# For ModSecurity v2 (points to the converted one): -#SecGeoLookupDB /usr/share/GeoIP/GeoLiteCountry.dat - -# -# -=[ Block Countries ]=- -# -# Rules in the IP Reputation file can check the client against a list of high -# risk country codes. These countries have to be defined in the variable -# tx.high_risk_country_codes via their ISO 3166 two-letter country code: -# https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements -# -# If you are sure that you are not getting any legitimate requests from a given -# country, then you can disable all access from that country via this variable. -# The rule performing the test has the rule id 910100. -# -# This rule requires SecGeoLookupDB to be enabled and the GeoIP database to be -# downloaded (see the section "GeoIP Database" above.) -# -# By default, the list is empty. A list used by some sites was the following: -# setvar:'tx.high_risk_country_codes=UA ID YU LT EG RO BG TR RU PK MY CN'" -# -# Uncomment this rule to use this feature: -# #SecAction \ -# "id:900600,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:'tx.high_risk_country_codes='" +# "id:900400,\ +# phase:1,\ +# pass,\ +# nolog,\ +# setvar:tx.sampling_percentage=100" -# -# -- [[ Anti-Automation / DoS Protection ]] ------------------------------------ -# -# Optional DoS protection against clients making requests too quickly. -# -# When a client is making more than 100 requests (excluding static files) within -# 60 seconds, this is considered a 'burst'. After two bursts, the client is -# blocked for 600 seconds. -# -# Requests to static files are not counted towards DoS; they are listed in the -# 'tx.static_extensions' setting, which you can change in this file (see -# section "HTTP Policy Settings"). -# -# For a detailed description, see rule file REQUEST-912-DOS-PROTECTION.conf. -# -# Uncomment this rule to use this feature: -# -#SecAction \ -# "id:900700,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:'tx.dos_burst_time_slice=60',\ -# setvar:'tx.dos_counter_threshold=100',\ -# setvar:'tx.dos_block_timeout=600'" - # # -- [[ Check UTF-8 encoding ]] ------------------------------------------------ @@ -773,62 +738,12 @@ SecAction \ # Uncomment this rule to use this feature: # #SecAction \ -# "id:900950,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.crs_validate_utf8_encoding=1" - - -# -# -- [[ Blocking Based on IP Reputation ]] ------------------------------------ -# -# Blocking based on reputation is permanent in the CRS. Unlike other rules, -# which look at the individual request, the blocking of IPs is based on -# a persistent record in the IP collection, which remains active for a -# certain amount of time. -# -# There are two ways an individual client can become flagged for blocking: -# - External information (RBL, GeoIP, etc.) -# - Internal information (Core Rules) -# -# The record in the IP collection carries a flag, which tags requests from -# individual clients with a flag named IP.reput_block_flag. -# But the flag alone is not enough to have a client blocked. There is also -# a global switch named tx.do_reput_block. This is off by default. If you set -# it to 1 (=On), requests from clients with the IP.reput_block_flag will -# be blocked for a certain duration. -# -# Variables -# ip.reput_block_flag Blocking flag for the IP collection record -# ip.reput_block_reason Reason (= rule message) that caused to blocking flag -# tx.do_reput_block Switch deciding if we really block based on flag -# tx.reput_block_duration Setting to define the duration of a block -# -# It may be important to know, that all the other core rules are skipped for -# requests, when it is clear that they carry the blocking flag in question. -# -# Uncomment this rule to use this feature: -# -#SecAction \ -# "id:900960,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.do_reput_block=1" -# -# Uncomment this rule to change the blocking time: -# Default: 300 (5 minutes) -# -#SecAction \ -# "id:900970,\ -# phase:1,\ -# nolog,\ -# pass,\ -# t:none,\ -# setvar:tx.reput_block_duration=300" +# "id:900950,\ +# phase:1,\ +# pass,\ +# t:none,\ +# nolog,\ +# setvar:tx.crs_validate_utf8_encoding=1" # @@ -838,11 +753,11 @@ SecAction \ # to a lower setting which is appropriate to most sites. # This increases performance by cleaning out stale collection (block) entries. # -# This value should be greater than or equal to: -# tx.reput_block_duration (see section "Blocking Based on IP Reputation") and -# tx.dos_block_timeout (see section "Anti-Automation / DoS Protection"). +# This value should be greater than or equal to any block durations or timeouts +# set by plugins that make use of ModSecurity's persistent collections (e.g. the +# DoS protection and IP reputation plugins). # -# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecCollectionTimeout +# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecCollectionTimeout # Please keep this directive uncommented. # Default: 600 (10 minutes) @@ -866,4 +781,4 @@ SecAction \ pass,\ t:none,\ nolog,\ - setvar:tx.crs_setup_version=335" + setvar:tx.crs_setup_version=400" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/modsecdefault.conf b/pkg/render/applicationlayer/embed/coreruleset/modsecdefault.conf similarity index 72% rename from pkg/render/applicationlayer/modsec-core-ruleset/modsecdefault.conf rename to pkg/render/applicationlayer/embed/coreruleset/modsecdefault.conf index 395d82cedc..3b9d8a7416 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/modsecdefault.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/modsecdefault.conf @@ -1,6 +1,6 @@ # -- Rule engine initialization ---------------------------------------------- -# Enable ModSecurity, attaching it to every transaction. Use detection +# Enable Coraza, attaching it to every transaction. Use detection # only to start with, because that minimises the chances of post-installation # disruption. # @@ -9,13 +9,12 @@ SecRuleEngine DetectionOnly # -- Request body handling --------------------------------------------------- -# Allow ModSecurity to access request bodies. If you don't, ModSecurity +# Allow Coraza to access request bodies. If you don't, Coraza # won't be able to see any POST parameters, which opens a large security # hole for attackers to exploit. # SecRequestBodyAccess On - # Enable XML request body parser. # Initiate XML Processor in case of xml content-type # @@ -43,30 +42,18 @@ SecRule REQUEST_HEADERS:Content-Type "^application/json" \ # low as practical. # SecRequestBodyLimit 13107200 + +SecRequestBodyInMemoryLimit 131072 + SecRequestBodyNoFilesLimit 131072 # What to do if the request body size is above our configured limit. # Keep in mind that this setting will automatically be set to ProcessPartial # when SecRuleEngine is set to DetectionOnly mode in order to minimize -# disruptions when initially deploying ModSecurity. +# disruptions when initially deploying Coraza. # SecRequestBodyLimitAction Reject -# Maximum parsing depth allowed for JSON objects. You want to keep this -# value as low as practical. -# -SecRequestBodyJsonDepthLimit 512 - -# Maximum number of args allowed per request. You want to keep this -# value as low as practical. The value should match that in rule 200007. -SecArgumentsLimit 1000 - -# If SecArgumentsLimit has been set, you probably want to reject any -# request body that has only been partly parsed. The value used in this -# rule should match what was used with SecArgumentsLimit -SecRule &ARGS "@ge 1000" \ -"id:'200007', phase:2,t:none,log,deny,status:400,msg:'Failed to fully parse request body due to large argument count',severity:2" - # Verify that we've correctly processed the request body. # As a rule of thumb, when failing to process a request body # you should reject the request (when deployed in blocking mode) @@ -98,7 +85,7 @@ FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'" # Did we see anything that might be a boundary? # -# Here is a short description about the ModSecurity Multipart parser: the +# Here is a short description about the Coraza Multipart parser: the # parser returns with value 0, if all "boundary-like" line matches with # the boundary string which given in MIME header. In any other cases it returns # with different value, eg. 1 or 2. @@ -125,7 +112,7 @@ FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'" # # You can choose, which one is what you need. The example below contains the # 'strict' mode, which means if there are any lines with start of "--", then -# ModSecurity blocked the content. But the next, commented example contains +# Coraza blocked the content. But the next, commented example contains # the 'permissive' mode, then you check only if the necessary lines exists in # correct order. Whit this, you can enable to upload PEM files (eg "----BEGIN.."), # or other text files, which contains eg. HTTP headers. @@ -143,25 +130,18 @@ FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'" SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \ "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'" - -# PCRE Tuning -# We want to avoid a potential RegEx DoS condition -# -SecPcreMatchLimit 1000 -SecPcreMatchLimitRecursion 1000 - # Some internal errors will set flags in TX and we will need to look for these. # All of these are prefixed with "MSC_". The following flags currently exist: # -# MSC_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded. +# COR_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded. # -SecRule TX:/^MSC_/ "!@streq 0" \ - "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'" +SecRule TX:/^COR_/ "!@streq 0" \ + "id:'200005',phase:2,t:none,deny,msg:'Coraza internal error flagged: %{MATCHED_VAR_NAME}'" # -- Response body handling -------------------------------------------------- -# Allow ModSecurity to access response bodies. +# Allow Coraza to access response bodies. # You should have this directive enabled in order to identify errors # and data leakage issues. # @@ -188,15 +168,7 @@ SecResponseBodyLimitAction ProcessPartial # -- Filesystem configuration ------------------------------------------------ -# The location where ModSecurity stores temporary files (for example, when -# it needs to handle a file upload that is larger than the configured limit). -# -# This default setting is chosen due to all systems have /tmp available however, -# this is less than ideal. It is recommended that you specify a location that's private. -# -SecTmpDir /tmp/ - -# The location where ModSecurity will keep its persistent data. This default setting +# The location where Coraza will keep its persistent data. This default setting # is chosen due to all systems have /tmp available however, it # too should be updated to a place that other users can't access. # @@ -205,11 +177,11 @@ SecDataDir /tmp/ # -- File uploads handling configuration ------------------------------------- -# The location where ModSecurity stores intercepted uploaded files. This -# location must be private to ModSecurity. You don't want other users on +# The location where Coraza stores intercepted uploaded files. This +# location must be private to Coraza. You don't want other users on # the server to access the files, do you? # -#SecUploadDir /opt/modsecurity/var/upload/ +#SecUploadDir /opt/coraza/var/upload/ # By default, only keep the files that were determined to be unusual # in some way (by an external inspection script). For this to work you @@ -219,17 +191,24 @@ SecDataDir /tmp/ # Uploaded files are by default created with permissions that do not allow # any other user to access them. You may need to relax that if you want to -# interface ModSecurity to an external program (e.g., an anti-virus). +# interface Coraza to an external program (e.g., an anti-virus). # #SecUploadFileMode 0600 # -- Debug log configuration ------------------------------------------------- -# The default debug log configuration is to duplicate the error, warning -# and notice messages from the error log. -# -#SecDebugLog /opt/modsecurity/var/log/debug.log +# Default debug log path +# Debug levels: +# 0: No logging (least verbose) +# 1: Error +# 2: Warn +# 3: Info +# 4-8: Debug +# 9: Trace (most verbose) +# Most logging has not been implemented because it will be replaced with +# advanced rule profiling options +#SecDebugLog /opt/coraza/var/log/debug.log #SecDebugLogLevel 3 @@ -240,19 +219,15 @@ SecDataDir /tmp/ # level response status codes). # SecAuditEngine RelevantOnly -SecAuditLogRelevantStatus "^(?:5|4(?!04))" +SecAuditLogRelevantStatus "^(?:(5|4)(0|1)[0-9])$" # Log everything we know about a transaction. SecAuditLogParts ABIJDEFHZ # Use a single file for logging. This is much easier to look at, but -# assumes that you will use the audit log only ocassionally. +# assumes that you will use the audit log only occasionally. # SecAuditLogType Serial -SecAuditLog /var/log/modsec_audit.log - -# Specify the path for concurrent audit logging. -#SecAuditLogStorageDir /opt/modsecurity/var/audit/ # -- Miscellaneous ----------------------------------------------------------- @@ -268,18 +243,3 @@ SecArgumentSeparator & # evasion attacks (against the rules that examine named cookies). # SecCookieFormat 0 - -# Specify your Unicode Code Point. -# This mapping is used by the t:urlDecodeUni transformation function -# to properly map encoded data to your language. Properly setting -# these directives helps to reduce false positives and negatives. -# -SecUnicodeMapFile unicode.mapping 20127 - -# Improve the quality of ModSecurity by sharing information about your -# current ModSecurity version and dependencies versions. -# The following information will be shared: ModSecurity version, -# Web Server version, APR version, PCRE version, Lua version, Libxml2 -# version, Anonymous unique id for host. -SecStatusEngine On - diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example similarity index 79% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example index ad857bfb0e..e856911a5b 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -82,9 +82,9 @@ # This ruleset allows you to control how ModSecurity will handle traffic # originating from Authorized Vulnerability Scanning (AVS) sources. See # related blog post - -# http://blog.spiderlabs.com/2010/12/advanced-topic-of-the-week-handling-authorized-scanning-traffic.html +# https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/updated-advanced-topic-of-the-week-handling-authorized-scanning-traffic/ # -# White-list ASV network block (no blocking or logging of AVS traffic) Update +# Allow List ASV network block (no blocking or logging of AVS traffic) Update # IP network block as appropriate for your AVS traffic # # ModSec Rule Exclusion: Disable Rule Engine for known ASV IP @@ -130,7 +130,7 @@ # Example Exclusion Rule: Removing a specific ARGS parameter from inspection # for all CRS rules # -# This rule illustrates that we can use tagging very effectively to whitelist a +# This rule illustrates that we can use tagging very effectively to allow list a # common false positive across an entire ModSecurity instance. This can be done # because every rule in OWASP_CRS is tagged with OWASP_CRS. This will NOT # affect custom rules. @@ -150,6 +150,10 @@ # This rule illustrates that we can remove a rule range via a ctl action. # This uses the fact, that rules are grouped by topic in rule files covering # a certain id range. +# IMPORTANT: ModSecurity v3, aka libModSecurity, does not currently support the +# use of rule ranges in a ruleRemoveById ctl action (this feature has been +# planned for v3.1). Consider using ruleRemoveByTag as a workaround, if +# appropriate. # # ModSecurity Rule Exclusion: Disable all SQLi and XSS rules # SecRule REQUEST_FILENAME "@beginsWith /admin" \ @@ -160,7 +164,37 @@ # ctl:ruleRemoveById=941000-942999" # # -# The application specific rule exclusion files -# REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf -# REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf -# bring additional examples which can be useful then tuning a service. +# The application-specific rule exclusion plugins +# (see: https://github.com/coreruleset/plugin-registry) +# provide additional examples which can be useful then tuning a service. + + +# +# Example Rule: Allow monitoring tools and scripts +# +# Uncomment this rule to allow all requests from trusted IPs and User-Agent. +# This can be useful for monitoring tools like Monit, Nagios, or other agents. +# For example, if you're using AWS Load Balancer, you may need to trust all +# requests from "10.0.0.0/8" subnet that come with the user-agent +# "ELB-HealthChecker/2.0". By doing this, all requests that match these +# conditions will not be matched against the following rules: +# +# - id: 911100 (allowed methods) +# - id: 913100 (scan detection) +# - id: 920280 (missing/empty host header) +# - id: 920350 (IP address in host header) +# - tag: attack-disclosure (all RESPONSE-*-DATA-LEAKAGES rules) +# +# SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8" \ +# "id:1005,\ +# phase:1,\ +# pass,\ +# nolog,\ +# chain" +# SecRule REQUEST_METHOD "@pm GET HEAD" "chain" +# SecRule REQUEST_HEADERS:User-Agent "@pm ELB-HealthChecker" \ +# "ctl:ruleRemoveById=911100,\ +# ctl:ruleRemoveById=913100,\ +# ctl:ruleRemoveById=920280,\ +# ctl:ruleRemoveById=920350,\ +# ctl:ruleRemoveByTag=attack-disclosure" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-901-INITIALIZATION.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-901-INITIALIZATION.conf similarity index 63% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-901-INITIALIZATION.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-901-INITIALIZATION.conf index 27fd54ad1f..498ad885f1 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-901-INITIALIZATION.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-901-INITIALIZATION.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -12,7 +12,7 @@ # This file REQUEST-901-INITIALIZATION.conf initializes the Core Rules # and performs preparatory actions. It also fixes errors and omissions # of variable definitions in the file crs-setup.conf. -# The setup.conf can and should be edited by the user, this file +# The crs-setup.conf can and should be edited by the user, this file # is part of the CRS installation and should not be altered. # @@ -24,9 +24,9 @@ # # - Producer: ModSecurity for Apache/2.9.1 (http://www.modsecurity.org/); OWASP_CRS/3.1.0. # -# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecComponentSignature +# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#seccomponentsignature # -SecComponentSignature "OWASP_CRS/3.3.5" +SecComponentSignature "OWASP_CRS/4.0.0-rc2" # # -=[ Default setup values ]=- @@ -59,7 +59,7 @@ SecRule &TX:crs_setup_version "@eq 0" \ log,\ auditlog,\ msg:'ModSecurity Core Rule Set is deployed without configuration! Please copy the crs-setup.conf.example template to crs-setup.conf, and include the crs-setup.conf file in your webserver configuration before including the CRS rules. See the INSTALL file in the CRS directory for detailed instructions',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL'" @@ -67,62 +67,80 @@ SecRule &TX:crs_setup_version "@eq 0" \ # -=[ Default setup values ]=- # # Some constructs or individual rules will fail if certain parameters -# are not set in the setup.conf file. The following rules will catch +# are not set in the crs-setup.conf file. The following rules will catch # these cases and assign sane default values. # -# Default Inbound Anomaly Threshold Level (rule 900110 in setup.conf) +# Default Inbound Anomaly Threshold Level (rule 900110 in crs-setup.conf) SecRule &TX:inbound_anomaly_score_threshold "@eq 0" \ "id:901100,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.inbound_anomaly_score_threshold=5'" -# Default Outbound Anomaly Threshold Level (rule 900110 in setup.conf) +# Default Outbound Anomaly Threshold Level (rule 900110 in crs-setup.conf) SecRule &TX:outbound_anomaly_score_threshold "@eq 0" \ "id:901110,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.outbound_anomaly_score_threshold=4'" -# Default Paranoia Level (rule 900000 in setup.conf) -SecRule &TX:paranoia_level "@eq 0" \ +# Default Reporting Level (rule 900115 in crs-setup.conf) +SecRule &TX:reporting_level "@eq 0" \ + "id:901111,\ + phase:1,\ + pass,\ + nolog,\ + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.reporting_level=4'" + +# Default Early Blocking (rule 900120 in crs-setup.conf) +SecRule &TX:early_blocking "@eq 0" \ + "id:901115,\ + phase:1,\ + pass,\ + nolog,\ + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.early_blocking=0'" + +# Default Blocking Paranoia Level (rule 900000 in crs-setup.conf) +SecRule &TX:blocking_paranoia_level "@eq 0" \ "id:901120,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.paranoia_level=1'" + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.blocking_paranoia_level=1'" -# Default Executing Paranoia Level (rule 900000 in setup.conf) -SecRule &TX:executing_paranoia_level "@eq 0" \ +# Default Detection Paranoia Level (rule 900001 in crs-setup.conf) +SecRule &TX:detection_paranoia_level "@eq 0" \ "id:901125,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.executing_paranoia_level=%{TX.PARANOIA_LEVEL}'" + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.detection_paranoia_level=%{TX.blocking_paranoia_level}'" -# Default Sampling Percentage (rule 900400 in setup.conf) +# Default Sampling Percentage (rule 900400 in crs-setup.conf) SecRule &TX:sampling_percentage "@eq 0" \ "id:901130,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.sampling_percentage=100'" -# Default Anomaly Scores (rule 900100 in setup.conf) +# Default Anomaly Scores (rule 900100 in crs-setup.conf) SecRule &TX:critical_anomaly_score "@eq 0" \ "id:901140,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.critical_anomaly_score=5'" SecRule &TX:error_anomaly_score "@eq 0" \ @@ -130,7 +148,7 @@ SecRule &TX:error_anomaly_score "@eq 0" \ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.error_anomaly_score=4'" SecRule &TX:warning_anomaly_score "@eq 0" \ @@ -138,7 +156,7 @@ SecRule &TX:warning_anomaly_score "@eq 0" \ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.warning_anomaly_score=3'" SecRule &TX:notice_anomaly_score "@eq 0" \ @@ -146,117 +164,90 @@ SecRule &TX:notice_anomaly_score "@eq 0" \ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.notice_anomaly_score=2'" -# Default do_reput_block -SecRule &TX:do_reput_block "@eq 0" \ - "id:901150,\ - phase:1,\ - pass,\ - nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.do_reput_block=0'" - -# Default block duration -SecRule &TX:reput_block_duration "@eq 0" \ - "id:901152,\ - phase:1,\ - pass,\ - nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.reput_block_duration=300'" - -# Default HTTP policy: allowed_methods (rule 900200) +# Default HTTP policy: allowed_methods (rule 900200 in crs-setup.conf) SecRule &TX:allowed_methods "@eq 0" \ "id:901160,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'" -# Default HTTP policy: allowed_request_content_type (rule 900220) +# Default HTTP policy: allowed_request_content_type (rule 900220 in crs-setup.conf) SecRule &TX:allowed_request_content_type "@eq 0" \ "id:901162,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json|'" -# Default HTTP policy: allowed_request_content_type_charset (rule 900270) +# Default HTTP policy: allowed_request_content_type_charset (rule 900280 in crs-setup.conf) SecRule &TX:allowed_request_content_type_charset "@eq 0" \ "id:901168,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.allowed_request_content_type_charset=utf-8|iso-8859-1|iso-8859-15|windows-1252'" + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.allowed_request_content_type_charset=|utf-8| |iso-8859-1| |iso-8859-15| |windows-1252|'" -# Default HTTP policy: allowed_http_versions (rule 900230) +# Default HTTP policy: allowed_http_versions (rule 900230 in crs-setup.conf) SecRule &TX:allowed_http_versions "@eq 0" \ "id:901163,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0'" + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0'" -# Default HTTP policy: restricted_extensions (rule 900240) +# Default HTTP policy: restricted_extensions (rule 900240 in crs-setup.conf) SecRule &TX:restricted_extensions "@eq 0" \ "id:901164,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'" + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'" -# Default HTTP policy: restricted_headers (rule 900250) -SecRule &TX:restricted_headers "@eq 0" \ +# Default HTTP policy: restricted_headers_basic (rule 900250 in crs-setup.conf) +SecRule &TX:restricted_headers_basic "@eq 0" \ "id:901165,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.restricted_headers=/accept-charset/ /content-encoding/ /proxy/ /lock-token/ /content-range/ /if/'" + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.restricted_headers_basic=/content-encoding/ /proxy/ /lock-token/ /content-range/ /if/ /x-http-method-override/ /x-http-method/ /x-method-override/'" -# Default HTTP policy: static_extensions (rule 900260) -SecRule &TX:static_extensions "@eq 0" \ - "id:901166,\ +# Default HTTP policy: restricted_headers_extended (rule 900255 in crs-setup.conf) +SecRule &TX:restricted_headers_extended "@eq 0" \ + "id:901171,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.static_extensions=/.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/'" + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.restricted_headers_extended=/accept-charset/'" -# Default enforcing of body processor URLENCODED +# Default enforcing of body processor URLENCODED (rule 900010 in crs-setup.conf) SecRule &TX:enforce_bodyproc_urlencoded "@eq 0" \ "id:901167,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.enforce_bodyproc_urlencoded=0'" -# Default check for UTF8 encoding validation +# Default check for UTF8 encoding validation (rule 900950 in crs-setup.conf) SecRule &TX:crs_validate_utf8_encoding "@eq 0" \ "id:901169,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'tx.crs_validate_utf8_encoding=0'" -# Default monitor_anomaly_score value -SecRule &TX:monitor_anomaly_score "@eq 0" \ - "id:901170,\ - phase:1,\ - pass,\ - nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.monitor_anomaly_score=0'" - # # -=[ Initialize internal variables ]=- # @@ -264,7 +255,6 @@ SecRule &TX:monitor_anomaly_score "@eq 0" \ # Initialize anomaly scoring variables. # All _score variables start at 0, and are incremented by the various rules # upon detection of a possible attack. -# sql_error_match is used for shortcutting rules for performance reasons. SecAction \ "id:901200,\ @@ -272,12 +262,13 @@ SecAction \ pass,\ t:none,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.anomaly_score=0',\ - setvar:'tx.anomaly_score_pl1=0',\ - setvar:'tx.anomaly_score_pl2=0',\ - setvar:'tx.anomaly_score_pl3=0',\ - setvar:'tx.anomaly_score_pl4=0',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + setvar:'tx.blocking_inbound_anomaly_score=0',\ + setvar:'tx.detection_inbound_anomaly_score=0',\ + setvar:'tx.inbound_anomaly_score_pl1=0',\ + setvar:'tx.inbound_anomaly_score_pl2=0',\ + setvar:'tx.inbound_anomaly_score_pl3=0',\ + setvar:'tx.inbound_anomaly_score_pl4=0',\ setvar:'tx.sql_injection_score=0',\ setvar:'tx.xss_score=0',\ setvar:'tx.rfi_score=0',\ @@ -286,42 +277,35 @@ SecAction \ setvar:'tx.php_injection_score=0',\ setvar:'tx.http_violation_score=0',\ setvar:'tx.session_fixation_score=0',\ - setvar:'tx.inbound_anomaly_score=0',\ - setvar:'tx.outbound_anomaly_score=0',\ + setvar:'tx.blocking_outbound_anomaly_score=0',\ + setvar:'tx.detection_outbound_anomaly_score=0',\ setvar:'tx.outbound_anomaly_score_pl1=0',\ setvar:'tx.outbound_anomaly_score_pl2=0',\ setvar:'tx.outbound_anomaly_score_pl3=0',\ setvar:'tx.outbound_anomaly_score_pl4=0',\ - setvar:'tx.sql_error_match=0'" + setvar:'tx.anomaly_score=0'" # # -=[ Initialize collections ]=- # # Create both Global and IP collections for rules to use. -# There are some CRS rules that assume that these two collections -# have already been initiated. -# - -SecRule REQUEST_HEADERS:User-Agent "@rx ^.*$" \ - "id:901318,\ - phase:1,\ - pass,\ - t:none,t:sha1,t:hexEncode,\ - nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'tx.ua_hash=%{MATCHED_VAR}'" +# Some plugins assume that these two collections have already +# been initialized. +# IP collection is initialized with the IP address concatened with the hashed user agent. -SecAction \ - "id:901321,\ +# Disable collection initialization by default (see rule 900130 in crs-setup.conf) +SecRule TX:ENABLE_DEFAULT_COLLECTIONS "@eq 1" \ + "id:901320,\ phase:1,\ pass,\ - t:none,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ - initcol:global=global,\ - initcol:ip=%{remote_addr}_%{tx.ua_hash},\ - setvar:'tx.real_ip=%{remote_addr}'" + ver:'OWASP_CRS/4.0.0-rc2',\ + chain" + SecRule REQUEST_HEADERS:User-Agent "@rx ^.*$" \ + "t:none,t:sha1,t:hexEncode,\ + initcol:global=global,\ + initcol:ip=%{remote_addr}_%{MATCHED_VAR}" # # -=[ Initialize Correct Body Processing ]=- @@ -338,7 +322,7 @@ SecRule REQBODY_PROCESSOR "!@rx (?:URLENCODED|MULTIPART|XML|JSON)" \ noauditlog,\ msg:'Enabling body inspection',\ ctl:forceRequestBodyVariable=On,\ - ver:'OWASP_CRS/3.3.5'" + ver:'OWASP_CRS/4.0.0-rc2'" # Force body processor URLENCODED SecRule TX:enforce_bodyproc_urlencoded "@eq 1" \ @@ -349,7 +333,7 @@ SecRule TX:enforce_bodyproc_urlencoded "@eq 1" \ nolog,\ noauditlog,\ msg:'Enabling forced body inspection for ASCII content',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ chain" SecRule REQBODY_PROCESSOR "!@rx (?:URLENCODED|MULTIPART|XML|JSON)" \ "ctl:requestBodyProcessor=URLENCODED" @@ -377,57 +361,30 @@ SecRule TX:enforce_bodyproc_urlencoded "@eq 1" \ # # We take the entropy contained in the UNIQUE_ID. We hash that variable and # take the first integer numbers out of it. Theoretically, it is possible -# there are no integers in a sha1 hash. We make sure we get two -# integer numbers by taking the last two digits from the DURATION counter -# (in microseconds). -# Finally, leading zeros are removed from the two-digit random number. -# +# but highly improbable that there are no integers in a hexEncoded sha1 hash. +# In the very rare event that two integers are not matched (due to only being +# a-f in all, or all but one positions) 901450 will not be triggered. +# Leading zeros are not removed from the two-digit random number, and are +# handled gracefullly by 901450 SecRule TX:sampling_percentage "@eq 100" \ "id:901400,\ phase:1,\ pass,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ skipAfter:END-SAMPLING" -SecRule UNIQUE_ID "@rx ^." \ +SecRule UNIQUE_ID "@rx ^[a-f]*([0-9])[a-f]*([0-9])" \ "id:901410,\ phase:1,\ pass,\ - t:sha1,t:hexEncode,\ - nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'TX.sampling_rnd100=%{MATCHED_VAR}'" - -SecRule DURATION "@rx (..)$" \ - "id:901420,\ - phase:1,\ - pass,\ - capture,\ - nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'TX.sampling_rnd100=%{TX.sampling_rnd100}%{TX.1}'" - -SecRule TX:sampling_rnd100 "@rx ^[a-f]*([0-9])[a-f]*([0-9])" \ - "id:901430,\ - phase:1,\ - pass,\ capture,\ + t:sha1,t:hexEncode,\ nolog,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'TX.sampling_rnd100=%{TX.1}%{TX.2}'" -SecRule TX:sampling_rnd100 "@rx ^0([0-9])" \ - "id:901440,\ - phase:1,\ - pass,\ - capture,\ - nolog,\ - ver:'OWASP_CRS/3.3.5',\ - setvar:'TX.sampling_rnd100=%{TX.1}'" - - # # Sampling decision # @@ -448,8 +405,8 @@ SecRule TX:sampling_rnd100 "!@lt %{tx.sampling_percentage}" \ log,\ noauditlog,\ msg:'Sampling: Disable the rule engine based on sampling_percentage %{TX.sampling_percentage} and random number %{TX.sampling_rnd100}',\ - ctl:ruleEngine=Off,\ - ver:'OWASP_CRS/3.3.5'" + ctl:ruleRemoveByTag=OWASP_CRS,\ + ver:'OWASP_CRS/4.0.0-rc2'" SecMarker "END-SAMPLING" @@ -458,13 +415,13 @@ SecMarker "END-SAMPLING" # Configuration Plausibility Checks # -# Make sure executing paranoia level is not lower than paranoia level -SecRule TX:executing_paranoia_level "@lt %{tx.paranoia_level}" \ +# Make sure detection paranoia level is not lower than paranoia level +SecRule TX:detection_paranoia_level "@lt %{tx.blocking_paranoia_level}" \ "id:901500,\ phase:1,\ deny,\ status:500,\ t:none,\ log,\ - msg:'Executing paranoia level configured is lower than the paranoia level itself. This is illegal. Blocking request. Aborting',\ - ver:'OWASP_CRS/3.3.5'" + msg:'Detection paranoia level configured is lower than the paranoia level itself. This is illegal. Blocking request. Aborting',\ + ver:'OWASP_CRS/4.0.0-rc2'" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-905-COMMON-EXCEPTIONS.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-905-COMMON-EXCEPTIONS.conf similarity index 88% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-905-COMMON-EXCEPTIONS.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-905-COMMON-EXCEPTIONS.conf index 191f2ea3a6..5af67b03f9 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-905-COMMON-EXCEPTIONS.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-905-COMMON-EXCEPTIONS.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -24,11 +24,11 @@ SecRule REQUEST_LINE "@streq GET /" \ tag:'language-multi',\ tag:'platform-apache',\ tag:'attack-generic',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ chain" SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ "t:none,\ - ctl:ruleEngine=Off,\ + ctl:ruleRemoveByTag=OWASP_CRS,\ ctl:auditEngine=Off" # @@ -44,12 +44,12 @@ SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ tag:'language-multi',\ tag:'platform-apache',\ tag:'attack-generic',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ chain" SecRule REQUEST_HEADERS:User-Agent "@endsWith (internal dummy connection)" \ "t:none,\ chain" SecRule REQUEST_LINE "@rx ^(?:GET /|OPTIONS \*) HTTP/[12]\.[01]$" \ "t:none,\ - ctl:ruleEngine=Off,\ + ctl:ruleRemoveByTag=OWASP_CRS,\ ctl:auditEngine=Off" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-911-METHOD-ENFORCEMENT.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-911-METHOD-ENFORCEMENT.conf similarity index 65% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-911-METHOD-ENFORCEMENT.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-911-METHOD-ENFORCEMENT.conf index 840fe2be5b..2831bc0fc9 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-911-METHOD-ENFORCEMENT.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-911-METHOD-ENFORCEMENT.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -14,10 +14,10 @@ -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:911011,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:911012,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:911011,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:911012,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # @@ -27,7 +27,7 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:911012,phase:2,pass,nolog,skipAf # SecRule REQUEST_METHOD "!@within %{tx.allowed_methods}" \ "id:911100,\ - phase:2,\ + phase:1,\ block,\ msg:'Method is not allowed by policy',\ logdata:'%{MATCHED_VAR}',\ @@ -39,33 +39,33 @@ SecRule REQUEST_METHOD "!@within %{tx.allowed_methods}" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/274',\ tag:'PCI/12.1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:911013,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:911014,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:911013,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:911014,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:911015,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:911016,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:911015,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:911016,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:911017,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:911018,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:911017,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:911018,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # diff --git a/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-913-SCANNER-DETECTION.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-913-SCANNER-DETECTION.conf new file mode 100644 index 0000000000..519634ab1c --- /dev/null +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-913-SCANNER-DETECTION.conf @@ -0,0 +1,86 @@ +# ------------------------------------------------------------------------ +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2023 Core Rule Set project. 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) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:913011,phase:1,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:913012,phase:2,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# +# -=[ Security Scanner Checks ]=- +# +# This rule inspects the default User-Agent and Header values sent by +# various commercial and open source scanners, mostly +# security / vulnerability scanners. +# +# It is based on a curated list of known malicious scanners in widespread use. +# This list is maintained in scanners-user-agents.data. +# +# With CRSv4, the project has given up on keeping track of different categories +# of scanners and scripting agents, mostly because it's very hard to draw +# a line between benign, mostly benign and malicious. And because dedicated +# attackers will change the user agent anyways. + +SecRule REQUEST_HEADERS:User-Agent "@pmFromFile scanners-user-agents.data" \ + "id:913100,\ + phase:1,\ + block,\ + capture,\ + t:none,\ + msg:'Found User-Agent associated with security scanner',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-reputation-scanner',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/224/541/310',\ + tag:'PCI/6.5.10',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:913013,phase:1,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:913014,phase:2,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:913015,phase:1,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:913016,phase:2,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:913017,phase:1,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:913018,phase:2,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-913-SCANNER-DETECTION" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-920-PROTOCOL-ENFORCEMENT.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf similarity index 68% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-920-PROTOCOL-ENFORCEMENT.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf index 7f3138797e..eca84d0d4a 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-920-PROTOCOL-ENFORCEMENT.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -14,7 +14,7 @@ # # The purpose of this rules file is to enforce HTTP RFC requirements that state how # the client is supposed to interact with the server. -# https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html +# https://www.rfc-editor.org/rfc/rfc9110.html @@ -23,10 +23,10 @@ # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:920011,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:920012,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:920011,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:920012,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # @@ -37,17 +37,22 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:920012,phase:2,pass,nolog,skipAf # Uses rule negation against the regex for positive security. The regex specifies the proper # construction of URI request lines such as: # -# "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]] +# "http" "://" authority path-abempty [ "?" query ] # # It also outlines proper construction for CONNECT, OPTIONS and GET requests. # +# Regular expression generated from regex-assembly/920100.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 920100 +# # -=[ References ]=- -# https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.2.1 +# https://www.rfc-editor.org/rfc/rfc9110.html#section-4.2.1 # http://capec.mitre.org/data/definitions/272.html # -SecRule REQUEST_LINE "!@rx ^(?i:(?:[a-z]{3,10}\s+(?:\w{3,7}?://[\w\-\./]*(?::\d+)?)?/[^?#]*(?:\?[^#\s]*)?(?:#[\S]*)?|connect (?:\d{1,3}\.){3}\d{1,3}\.?(?::\d+)?|options \*)\s+[\w\./]+|get /[^?#]*(?:\?[^#\s]*)?(?:#[\S]*)?)$" \ +SecRule REQUEST_LINE "!@rx (?i)^(?:get /[^#\?]*(?:\?[^\s\v#]*)?(?:#[^\s\v]*)?|(?:connect (?:(?:[0-9]{1,3}\.){3}[0-9]{1,3}\.?(?::[0-9]+)?|[\--9A-Z_a-z]+:[0-9]+)|options \*|[a-z]{3,10}[\s\v]+(?:[0-9A-Z_a-z]{3,7}?://[\--9A-Z_a-z]*(?::[0-9]+)?)?/[^#\?]*(?:\?[^\s\v#]*)?(?:#[^\s\v]*)?)[\s\v]+[\.-9A-Z_a-z]+)$" \ "id:920100,\ - phase:2,\ + phase:1,\ block,\ t:none,\ msg:'Invalid HTTP Request Line',\ @@ -59,9 +64,9 @@ SecRule REQUEST_LINE "!@rx ^(?i:(?:[a-z]{3,10}\s+(?:\w{3,7}?://[\w\-\./]*(?::\d+ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'WARNING',\ - setvar:'tx.anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" # @@ -76,27 +81,31 @@ SecRule REQUEST_LINE "!@rx ^(?i:(?:[a-z]{3,10}\s+(?:\w{3,7}?://[\w\-\./]*(?::\d+ # # -=[ Rule Logic ]=- # These rules check for the existence of the ' " ; = meta-characters in -# either the file or file name variables. -# HTML entities may lead to false positives, why they are allowed on PL1. -# Negative look behind assertions allow frequently used entities &_; +# either the "name" (FILES) and "filename" (FILES_NAMES) variables. +# HTML entities may lead to false positives, which is why +# frequently used ones, such as "ä", are allowed at PL1. # # -=[ Targets, characters and html entities ]=- # -# 920120: PL1 : FILES_NAMES, FILES -# ['\";=] but allowed: -# &[aAoOuUyY]uml); &[aAeEiIoOuU]circ; &[eEiIoOuUyY]acute; -# &[aAeEiIoOuU]grave; &[cC]cedil; &[aAnNoO]tilde; & ' +# 920120 + 920122: PL1 : FILES_NAMES, FILES +# Disallow ['\";=], except for frequently used HTML entities (see 920120.data). # # 920121: PL2 : FILES_NAMES, FILES -# ['\";=] : ' " ; = meta-characters -# -# Not supported by re2 (?@-]+)*$" \ +# - application/soap+xml; charset=utf-8; action="urn:localhost-hwh#getQuestions" +# - application/*+json + +SecRule REQUEST_HEADERS:Content-Type "!@rx ^[\w/.+*-]+(?:\s?;\s?(?:action|boundary|charset|component|start(?:-info)?|type|version)\s?=\s?['\"\w.()+,/:=?<>@#*-]+)*$" \ "id:920470,\ phase:1,\ block,\ @@ -928,16 +957,16 @@ SecRule REQUEST_HEADERS:Content-Type "!@rx ^[\w/.+-]+(?:\s?;\s?(?:action|boundar tag:'OWASP_CRS',\ tag:'capec/1000/255/153',\ tag:'PCI/12.1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # In case Content-Type header can be parsed, check the mime-type against # the policy defined in the 'allowed_request_content_type' variable. # To change your policy, edit crs-setup.conf and activate rule 900220. SecRule REQUEST_HEADERS:Content-Type "@rx ^[^;\s]+" \ "id:920420,\ - phase:2,\ + phase:1,\ block,\ capture,\ t:none,\ @@ -951,13 +980,13 @@ SecRule REQUEST_HEADERS:Content-Type "@rx ^[^;\s]+" \ tag:'OWASP_CRS',\ tag:'capec/1000/255/153',\ tag:'PCI/12.1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.content_type=|%{tx.0}|',\ chain" SecRule TX:content_type "!@within %{tx.allowed_request_content_type}" \ "t:lowercase,\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -968,7 +997,7 @@ SecRule REQUEST_HEADERS:Content-Type "@rx charset\s*=\s*[\"']?([^;\"'\s]+)" \ phase:1,\ block,\ capture,\ - t:none,t:lowercase,\ + t:none,\ msg:'Request content type charset is not allowed by policy',\ logdata:'%{MATCHED_VAR}',\ tag:'application-multi',\ @@ -979,13 +1008,14 @@ SecRule REQUEST_HEADERS:Content-Type "@rx charset\s*=\s*[\"']?([^;\"'\s]+)" \ tag:'OWASP_CRS',\ tag:'capec/1000/255/153',\ tag:'PCI/12.1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ + setvar:'tx.content_type_charset=|%{tx.1}|',\ chain" - SecRule TX:1 "!@rx ^%{tx.allowed_request_content_type_charset}$" \ - "t:none,\ + SecRule TX:content_type_charset "!@within %{tx.allowed_request_content_type_charset}" \ + "t:lowercase,\ ctl:forceRequestBodyVariable=On,\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Restrict charset parameter inside content type header to occur max once. @@ -1005,9 +1035,9 @@ SecRule REQUEST_HEADERS:Content-Type "@rx charset.*?charset" \ tag:'OWASP_CRS',\ tag:'capec/1000/255/153',\ tag:'PCI/12.1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Restrict protocol versions. @@ -1027,16 +1057,16 @@ SecRule REQUEST_PROTOCOL "!@within %{tx.allowed_http_versions}" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'PCI/6.5.10',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Restrict file extension # SecRule REQUEST_BASENAME "@rx \.([^.]+)$" \ "id:920440,\ - phase:2,\ + phase:1,\ block,\ capture,\ t:none,\ @@ -1050,13 +1080,13 @@ SecRule REQUEST_BASENAME "@rx \.([^.]+)$" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'PCI/6.5.10',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.extension=.%{tx.1}/',\ chain" SecRule TX:EXTENSION "@within %{tx.restricted_extensions}" \ "t:none,t:urlDecodeUni,t:lowercase,\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Backup or "working" file extension @@ -1064,7 +1094,7 @@ SecRule REQUEST_BASENAME "@rx \.([^.]+)$" \ # SecRule REQUEST_FILENAME "@rx \.[^.~]+~(?:/.*|)$" \ "id:920500,\ - phase:2,\ + phase:1,\ block,\ t:none,t:urlDecodeUni,\ msg:'Attempt to access a backup or working file',\ @@ -1077,38 +1107,47 @@ SecRule REQUEST_FILENAME "@rx \.[^.~]+~(?:/.*|)$" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'PCI/6.5.10',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Restricted HTTP headers # # -=[ Rule Logic ]=- -# The use of certain headers is restricted. They are listed in the variable -# TX.restricted_headers. -# -# The headers are transformed into lowercase before the match. In order to -# make sure that only complete header names are matching, the names in -# TX.restricted_headers are wrapped in slashes. This guarantees that the -# header Range (-> /range/) is not matching the restricted header -# /content-range/ for example. +# The use of certain headers is restricted. They are listed in two variables: +# - TX.restricted_headers_basic: Known security risks, always forbidden (rule +# 920450) +# - TX.restricted_headers_extended: Possible false positives, possible security +# risks, may be forbidden (rule 920451) +# +# The headers are transformed into lowercase before the match. In order to make +# sure that only complete header names match, the names in the +# TX.restricted_headers_* variables are wrapped in slashes. This guarantees that +# the Range header (which becomes /range/) will not match the restricted +# /content-range/ header, for example. # # This is a chained rule, where the first rule fills a set of variables of the -# form TX.header_name_. The second rule is then executed for all -# variables of the form TX.header_name_. +# form TX.header_name__. The second rule is then executed +# for all variables of the form TX.header_name__. # # As a consequence of the construction of the rule, the alert message and the # alert data will not display the original header name Content-Range, but # /content-range/ instead. # +# This rule has a stricter sibling, 920451, which matches against the variable +# TX.restricted_headers_extended. It handles deprecated headers that are still +# in use (so false positives are possible, hence unsuitable for blocking in a +# default paranoia level 1 installation) and headers with possible security +# risks. # # -=[ References ]=- # https://access.redhat.com/security/vulnerabilities/httpoxy (Header Proxy) +# https://www.sidechannel.blog/en/http-method-override-what-it-is-and-how-a-pentester-can-use-it # SecRule REQUEST_HEADERS_NAMES "@rx ^.*$" \ "id:920450,\ - phase:2,\ + phase:1,\ block,\ capture,\ t:none,t:lowercase,\ @@ -1122,12 +1161,41 @@ SecRule REQUEST_HEADERS_NAMES "@rx ^.*$" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'PCI/12.1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.header_name_%{tx.0}=/%{tx.0}/',\ + setvar:'tx.header_name_920450_%{tx.0}=/%{tx.0}/',\ chain" - SecRule TX:/^header_name_/ "@within %{tx.restricted_headers}" \ - "setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + SecRule TX:/^header_name_920450_/ "@within %{tx.restricted_headers_basic}" \ + "setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Rule against CVE-2022-21907 +# This rule blocks Accept-Encoding headers longer than 50 characters. +# The length of 50 is a heuristic based on the length of values from +# the RFC (https://datatracker.ietf.org/doc/rfc9110/) +# and the respective values assigned by IANA +# (https://www.iana.org/assignments/http-parameters/http-parameters.xml#content-coding). +# +# This rule has a stricter sibling: 920521 +# +SecRule REQUEST_HEADERS:Accept-Encoding "@gt 50" \ + "id:920520,\ + phase:1,\ + block,\ + t:none,t:lowercase,t:length,\ + msg:'Accept-Encoding header exceeded sensible length',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/255/153',\ + tag:'PCI/12.1',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Restrict response charsets that we allow. @@ -1139,12 +1207,12 @@ SecRule REQUEST_HEADERS_NAMES "@rx ^.*$" \ # Some servers rely on the request Accept header to determine what charset to respond with. # This rule restricts these to familiar charsets. # -# Regular expression generated from util/regexp-assemble/data/920600.data. +# Regular expression generated from regex-assembly/920600.ra. # To update the regular expression run the following shell script -# (consult util/regexp-assemble/README.md for details): -# util/regexp-assemble/regexp-assemble.py update 920600 +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 920600 # -SecRule REQUEST_HEADERS:Accept "!@rx ^(?:(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+)\/(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+))(?:\s*+;\s*+(?:(?:charset\s*+=\s*+(?:\"?(?:iso-8859-15?|windows-1252|utf-8)\b\"?))|(?:(?:c(?:h(?:a(?:r(?:s(?:e[^t\"(),\/:;<=>?![\x5c\]{}]|[^e\"(),/:;<=>?![\x5c\]{}])|[^s\"(),/:;<=>?![\x5c\]{}])|[^r\"(),/:;<=>?![\x5c\]{}])|[^a\"(),/:;<=>?![\x5c\]{}])|[^h\"(),/:;<=>?![\x5c\]{}])|[^c\"(),/:;<=>?![\x5c\]{}])[^\"(),/:;<=>?![\x5c\]{}]*(?:)\s*+=\s*+[^(),/:;<=>?![\x5c\]{}]+)|;?))*(?:\s*+,\s*+(?:(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+)\/(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+))(?:\s*+;\s*+(?:(?:charset\s*+=\s*+(?:\"?(?:iso-8859-15?|windows-1252|utf-8)\b\"?))|(?:(?:c(?:h(?:a(?:r(?:s(?:e[^t\"(),\/:;<=>?![\x5c\]{}]|[^e\"(),/:;<=>?![\x5c\]{}])|[^s\"(),/:;<=>?![\x5c\]{}])|[^r\"(),/:;<=>?![\x5c\]{}])|[^a\"(),/:;<=>?![\x5c\]{}])|[^h\"(),/:;<=>?![\x5c\]{}])|[^c\"(),/:;<=>?![\x5c\]{}])[^\"(),/:;<=>?![\x5c\]{}]*(?:)\s*+=\s*+[^(),/:;<=>?![\x5c\]{}]+)|;?))*)*$" \ +SecRule REQUEST_HEADERS:Accept "!@rx ^(?:(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)/(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\v]*;[\s\v]*(?:charset[\s\v]*=[\s\v]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\v -\"\(-\),/:-\?\[-\]c\{\}]|c(?:[^!-\"\(-\),/:-\?\[-\]h\{\}]|h(?:[^!-\"\(-\),/:-\?\[-\]a\{\}]|a(?:[^!-\"\(-\),/:-\?\[-\]r\{\}]|r(?:[^!-\"\(-\),/:-\?\[-\]s\{\}]|s(?:[^!-\"\(-\),/:-\?\[-\]e\{\}]|e[^!-\"\(-\),/:-\?\[-\]t\{\}]))))))[^!-\"\(-\),/:-\?\[-\]\{\}]*[\s\v]*=[\s\v]*[^!\(-\),/:-\?\[-\]\{\}]+);?)*(?:[\s\v]*,[\s\v]*(?:(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)/(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\v]*;[\s\v]*(?:charset[\s\v]*=[\s\v]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\v -\"\(-\),/:-\?\[-\]c\{\}]|c(?:[^!-\"\(-\),/:-\?\[-\]h\{\}]|h(?:[^!-\"\(-\),/:-\?\[-\]a\{\}]|a(?:[^!-\"\(-\),/:-\?\[-\]r\{\}]|r(?:[^!-\"\(-\),/:-\?\[-\]s\{\}]|s(?:[^!-\"\(-\),/:-\?\[-\]e\{\}]|e[^!-\"\(-\),/:-\?\[-\]t\{\}]))))))[^!-\"\(-\),/:-\?\[-\]\{\}]*[\s\v]*=[\s\v]*[^!\(-\),/:-\?\[-\]\{\}]+);?)*)*$" \ "id:920600,\ phase:1,\ block,\ @@ -1157,9 +1225,56 @@ SecRule REQUEST_HEADERS:Accept "!@rx ^(?:(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+)\/(?: tag:'attack-protocol',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Unicode character bypass check for non JSON requests +# See reported bypass in issue: +# https://github.com/coreruleset/coreruleset/issues/2512 +# +SecRule REQBODY_PROCESSOR "!@streq JSON" \ + "id:920540,\ + phase:2,\ + block,\ + t:none,\ + msg:'Possible Unicode character bypass detected',\ + logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/255/153/267/72',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + chain" + SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@rx (?i)\x5cu[0-9a-f]{4}" \ + "setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Disallow any raw URL fragments. The '#' character should be omitted or URL-encoded. +# CRS rules generally do not check REQUEST_URI_RAW, but some servers accept the fragment as part of the URL path/query. +# This creates false negative evasions. +# +SecRule REQUEST_URI_RAW "@contains #" \ + "id:920610,\ + phase:1,\ + block,\ + t:none,\ + msg:'Raw (unencoded) fragment in request URI',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # The following rule (920620) checks for the presence of 2 or more request Content-Type headers. @@ -1189,14 +1304,15 @@ SecRule &REQUEST_HEADERS:Content-Type "@gt 1" \ tag:'attack-protocol',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:920013,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:920014,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:920013,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:920014,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # # @@ -1221,7 +1337,7 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:920014,phase:2,pass,nolog,skipAf SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){6}" \ "id:920200,\ - phase:2,\ + phase:1,\ block,\ t:none,\ msg:'Range: Too many fields (6 or more)',\ @@ -1233,11 +1349,11 @@ SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'WARNING',\ chain" SecRule REQUEST_BASENAME "!@endsWith .pdf" \ - "setvar:'tx.anomaly_score_pl2=+%{tx.warning_anomaly_score}'" + "setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'" # # This is a sibling of rule 920200 @@ -1245,7 +1361,7 @@ SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d SecRule REQUEST_BASENAME "@endsWith .pdf" \ "id:920201,\ - phase:2,\ + phase:1,\ block,\ t:none,\ msg:'Range: Too many fields for pdf request (63 or more)',\ @@ -1257,11 +1373,11 @@ SecRule REQUEST_BASENAME "@endsWith .pdf" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'WARNING',\ chain" SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){63}" \ - "setvar:'tx.anomaly_score_pl2=+%{tx.warning_anomaly_score}'" + "setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'" SecRule ARGS "@rx %[0-9a-fA-F]{2}" \ @@ -1278,46 +1394,11 @@ SecRule ARGS "@rx %[0-9a-fA-F]{2}" \ tag:'OWASP_CRS',\ tag:'capec/1000/255/153/267/120',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'WARNING',\ - setvar:'tx.anomaly_score_pl2=+%{tx.warning_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'" -# -# Missing Accept Header -# -# -=[ Rule Logic ]=- -# This rule generates a notice if the Accept header is missing. -# -# Notice: The rule tries to avoid known false positives by ignoring -# OPTIONS requests coming from known offending User-Agents via two -# chained rules. -# As ModSecurity only reports the match of the last matching rule, -# the alert is misleading. -# -SecRule &REQUEST_HEADERS:Accept "@eq 0" \ - "id:920300,\ - phase:2,\ - pass,\ - t:none,\ - msg:'Request Missing an Accept Header',\ - tag:'application-multi',\ - tag:'language-multi',\ - tag:'platform-multi',\ - tag:'attack-protocol',\ - tag:'OWASP_CRS',\ - tag:'capec/1000/210/272',\ - tag:'PCI/6.5.10',\ - tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ - severity:'NOTICE',\ - chain" - SecRule REQUEST_METHOD "!@rx ^OPTIONS$" \ - "chain" - SecRule REQUEST_HEADERS:User-Agent "!@pm AppleWebKit Android" \ - "t:none,\ - setvar:'tx.anomaly_score_pl2=+%{tx.notice_anomaly_score}'" - # # PL2: This is a stricter sibling of 920270. # @@ -1335,9 +1416,9 @@ SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@validateByteRange 9,10,13, tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" @@ -1350,7 +1431,7 @@ SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@validateByteRange 9,10,13, SecRule &REQUEST_HEADERS:User-Agent "@eq 0" \ "id:920320,\ - phase:2,\ + phase:1,\ pass,\ t:none,\ msg:'Missing User Agent Header',\ @@ -1362,9 +1443,9 @@ SecRule &REQUEST_HEADERS:User-Agent "@eq 0" \ tag:'capec/1000/210/272',\ tag:'PCI/6.5.10',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'NOTICE',\ - setvar:'tx.anomaly_score_pl2=+%{tx.notice_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.notice_anomaly_score}'" # @@ -1384,9 +1465,9 @@ SecRule FILES_NAMES|FILES "@rx ['\";=]" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # @@ -1398,7 +1479,7 @@ SecRule FILES_NAMES|FILES "@rx ['\";=]" \ SecRule REQUEST_HEADERS:Content-Length "!@rx ^0$" \ "id:920341,\ - phase:2,\ + phase:1,\ block,\ t:none,\ msg:'Request Containing Content Requires Content-Type header',\ @@ -1409,18 +1490,45 @@ SecRule REQUEST_HEADERS:Content-Length "!@rx ^0$" \ tag:'paranoia-level/2',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" SecRule &REQUEST_HEADERS:Content-Type "@eq 0" \ "t:none,\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# +# PL2: This is a stricter sibling of 920450. +# +SecRule REQUEST_HEADERS_NAMES "@rx ^.*$" \ + "id:920451,\ + phase:1,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'HTTP header is restricted by policy (%{MATCHED_VAR})',\ + logdata:'Restricted header detected: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/210/272',\ + tag:'PCI/12.1',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.header_name_920451_%{tx.0}=/%{tx.0}/',\ + chain" + SecRule TX:/^header_name_920451_/ "@within %{tx.restricted_headers_extended}" \ + "setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:920015,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:920016,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:920015,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:920016,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # # @@ -1443,9 +1551,48 @@ SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteR tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/3',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# +# Missing Accept Header +# +# This rule has been moved to PL3 +# +# -=[ Rule Logic ]=- +# This rule generates a notice if the Accept header is missing. +# RFC 7231 does not enforce the use of the Accept header. +# It is just typical browser behavior to send and it can indicate a malicious client. +# +# Notice: The rule tries to avoid known false positives by ignoring +# OPTIONS requests, CONNECT requests, and requests coming from known +# offending User-Agents via two chained rules. +# As ModSecurity only reports the match of the last matching rule, +# the alert is misleading. +# +SecRule &REQUEST_HEADERS:Accept "@eq 0" \ + "id:920300,\ + phase:1,\ + pass,\ + t:none,\ + msg:'Request Missing an Accept Header',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/210/272',\ + tag:'PCI/6.5.10',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'NOTICE',\ + chain" + SecRule REQUEST_METHOD "!@rx ^(?:OPTIONS|CONNECT)$" \ + "chain" + SecRule REQUEST_HEADERS:User-Agent "!@pm AppleWebKit Android" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.notice_anomaly_score}'" # @@ -1456,7 +1603,7 @@ SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteR # Note that this only works in combination with a User-Agent prefix. # # This rule is based on a blog post by Soroush Dalili at -# https://soroush.secproject.com/blog/2019/05/x-up-devcap-post-charset-header-in-aspnet-to-bypass-wafs-again/ +# https://soroush.me/blog/2019/05/x-up-devcap-post-charset-header-in-aspnet-to-bypass-wafs-again/ # SecRule &REQUEST_HEADERS:x-up-devcap-post-charset "@ge 1" \ "id:920490,\ @@ -1471,19 +1618,19 @@ SecRule &REQUEST_HEADERS:x-up-devcap-post-charset "@ge 1" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/3',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" SecRule REQUEST_HEADERS:User-Agent "@rx ^(?i)up" \ "t:none,\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # -# Cache-Control Request Header whitelist +# Cache-Control Request Header allow list # # -=[ Rule Logic ]=- -# This rule aims to strictly whitelist the Cache-Control request header +# This rule aims to strictly allow list the Cache-Control request header # values and to blocks all violations. This should be useful to intercept # "bad bot" and tools that impersonate a real browser but with wrong request # header setup. @@ -1520,21 +1667,49 @@ SecRule &REQUEST_HEADERS:Cache-Control "@gt 0" \ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ - tag:'header-whitelist',\ + tag:'header-allowlist',\ tag:'paranoia-level/3',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" - SecRule REQUEST_HEADERS:Cache-Control "!@rx ^(?:(?:max-age=[0-9]+|min-fresh=[0-9]+|no-cache|no-store|no-transform|only-if-cached|max-stale(?:=[0-9]+)?)(\s*\,\s*|$)){1,7}$" \ - "setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + SecRule REQUEST_HEADERS:Cache-Control "!@rx ^(?:(?:max-age=[0-9]+|min-fresh=[0-9]+|no-cache|no-store|no-transform|only-if-cached|max-stale(?:=[0-9]+)?)(?:\s*\,\s*|$)){1,7}$" \ + "setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" +# +# This rule checks for valid Accept-Encoding headers +# +# This rule has a less strict sibling: 920520 +# +# Regular expression generated from regex-assembly/920521.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 920521 +# +SecRule REQUEST_HEADERS:Accept-Encoding "!@rx br|compress|deflate|(?:pack200-)?gzip|identity|\*|^$|aes128gcm|exi|zstd|x-(?:compress|gzip)" \ + "id:920521,\ + phase:1,\ + block,\ + t:none,t:lowercase,\ + msg:'Illegal Accept-Encoding header',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/255/153',\ + tag:'PCI/12.1',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:920017,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:920018,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:920017,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:920018,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # # @@ -1543,7 +1718,7 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:920018,phase:2,pass,nolog,skipAf SecRule REQUEST_BASENAME "@endsWith .pdf" \ "id:920202,\ - phase:2,\ + phase:1,\ block,\ t:none,\ msg:'Range: Too many fields for pdf request (6 or more)',\ @@ -1555,11 +1730,11 @@ SecRule REQUEST_BASENAME "@endsWith .pdf" \ tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/4',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'WARNING',\ chain" SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){6}" \ - "setvar:'tx.anomaly_score_pl4=+%{tx.warning_anomaly_score}'" + "setvar:'tx.inbound_anomaly_score_pl4=+%{tx.warning_anomaly_score}'" # @@ -1582,16 +1757,16 @@ SecRule ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteRange 38,44-46,48-58,61,65-90 tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/4',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # # This is a stricter sibling of 920270. # -SecRule REQUEST_HEADERS|!REQUEST_HEADERS:User-Agent|!REQUEST_HEADERS:Referer|!REQUEST_HEADERS:Cookie|!REQUEST_HEADERS:Sec-Fetch-User "@validateByteRange 32,34,38,42-59,61,65-90,95,97-122" \ +SecRule REQUEST_HEADERS|!REQUEST_HEADERS:User-Agent|!REQUEST_HEADERS:Referer|!REQUEST_HEADERS:Cookie|!REQUEST_HEADERS:Sec-Fetch-User|!REQUEST_HEADERS:Sec-CH-UA|!REQUEST_HEADERS:Sec-CH-UA-Mobile "@validateByteRange 32,34,38,42-59,61,65-90,95,97-122" \ "id:920274,\ - phase:2,\ + phase:1,\ block,\ t:none,t:urlDecodeUni,\ msg:'Invalid character in request headers (outside of very strict set)',\ @@ -1603,19 +1778,21 @@ SecRule REQUEST_HEADERS|!REQUEST_HEADERS:User-Agent|!REQUEST_HEADERS:Referer|!RE tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/4',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # # This is a stricter sibling of 920270. -# The 'Sec-Fetch-User' header may contain the '?' (63) character. -# Therefore we exclude this header from rule 920274 which forbids '?'. -# https://www.w3.org/TR/fetch-metadata/#http-headerdef-sec-fetch-user +# The headers of this rule are Structured Header booleans, for which only `?0`, +# and `?1` are inconspicuous. +# Structured Header boolean: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-header-structure-19#section-3.3.6 +# Sec-Fetch-User: https://www.w3.org/TR/fetch-metadata/#http-headerdef-sec-fetch-user +# Sec-CH-UA-Mobile: https://wicg.github.io/ua-client-hints/#sec-ch-ua-mobile # -SecRule REQUEST_HEADERS:Sec-Fetch-User "@validateByteRange 32,34,38,42-59,61,63,65-90,95,97-122" \ +SecRule REQUEST_HEADERS:Sec-Fetch-User|REQUEST_HEADERS:Sec-CH-UA-Mobile "!@rx ^(?:\?[01])?$" \ "id:920275,\ - phase:2,\ + phase:1,\ block,\ t:none,t:urlDecodeUni,\ msg:'Invalid character in request headers (outside of very strict set)',\ @@ -1627,9 +1804,9 @@ SecRule REQUEST_HEADERS:Sec-Fetch-User "@validateByteRange 32,34,38,42-59,61,63, tag:'OWASP_CRS',\ tag:'capec/1000/210/272',\ tag:'paranoia-level/4',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # -=[ Abnormal Character Escapes ]=- # @@ -1656,13 +1833,12 @@ SecRule REQUEST_HEADERS:Sec-Fetch-User "@validateByteRange 32,34,38,42-59,61,63, # This rule is also triggered by the following exploit(s): # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # -SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@rx (?:^|[^\\\\])\\\\[cdeghijklmpqwxyz123456789]" \ +SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@rx (?:^|[^\x5c])\x5c[cdeghijklmpqwxyz123456789]" \ "id:920460,\ phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,\ - log,\ + t:none,t:htmlEntityDecode,t:lowercase,\ msg:'Abnormal character escapes in request',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -1672,11 +1848,10 @@ SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@rx (?:^|[^\\\\])\\\\[cdegh tag:'paranoia-level/4',\ tag:'OWASP_CRS',\ tag:'capec/1000/153/267',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-921-PROTOCOL-ATTACK.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-921-PROTOCOL-ATTACK.conf similarity index 63% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-921-PROTOCOL-ATTACK.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-921-PROTOCOL-ATTACK.conf index fe5d4f68aa..17dd113b6a 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-921-PROTOCOL-ATTACK.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-921-PROTOCOL-ATTACK.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -14,10 +14,10 @@ -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:921011,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:921012,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:921011,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:921012,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # @@ -31,12 +31,12 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:921012,phase:2,pass,nolog,skipAf # [ References ] # http://projects.webappsec.org/HTTP-Request-Smuggling # -SecRule ARGS_NAMES|ARGS|REQUEST_BODY|XML:/* "@rx (?:get|post|head|options|connect|put|delete|trace|track|patch|propfind|propatch|mkcol|copy|move|lock|unlock)\s+(?:\/|\w)[^\s]*(?:\s+http\/\d|[\r\n])" \ +SecRule ARGS_NAMES|ARGS|REQUEST_BODY|XML:/* "@rx (?:get|post|head|options|connect|put|delete|trace|track|patch|propfind|propatch|mkcol|copy|move|lock|unlock)\s+[^\s]+\s+http/\d" \ "id:921110,\ phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,\ + t:none,t:htmlEntityDecode,t:lowercase,\ msg:'HTTP Request Smuggling Attack',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -46,18 +46,17 @@ SecRule ARGS_NAMES|ARGS|REQUEST_BODY|XML:/* "@rx (?:get|post|head|options|connec tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/33',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ HTTP Response Splitting ]=- # # [ Rule Logic ] # These rules look for Carriage Return (CR) %0d and Linefeed (LF) %0a characters. -# These characters may cause problems if the data is returned in a respones header and +# These characters may cause problems if the data is returned in a response header and # may be interpreted by an intermediary proxy server and treated as two separate # responses. # @@ -69,7 +68,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:lowercase,\ + t:none,t:lowercase,\ msg:'HTTP Response Splitting Attack',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -79,11 +78,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/34',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:\bhttp/\d|<(?:html|meta)\b)" \ @@ -91,7 +89,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,\ + t:none,t:htmlEntityDecode,t:lowercase,\ msg:'HTTP Response Splitting Attack',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -101,11 +99,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/34',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ HTTP Header Injection ]=- @@ -123,7 +120,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # SecRule REQUEST_HEADERS_NAMES|REQUEST_HEADERS "@rx [\n\r]" \ "id:921140,\ - phase:2,\ + phase:1,\ block,\ capture,\ t:none,t:htmlEntityDecode,\ @@ -136,11 +133,10 @@ SecRule REQUEST_HEADERS_NAMES|REQUEST_HEADERS "@rx [\n\r]" \ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/273',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # Detect newlines in argument names. @@ -155,7 +151,7 @@ SecRule ARGS_NAMES "@rx [\n\r]" \ phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:htmlEntityDecode,\ + t:none,t:htmlEntityDecode,\ msg:'HTTP Header Injection Attack via payload (CR/LF detected)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -165,11 +161,10 @@ SecRule ARGS_NAMES "@rx [\n\r]" \ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/33',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule ARGS_GET_NAMES|ARGS_GET "@rx [\n\r]+(?:\s|location|refresh|(?:set-)?cookie|(?:x-)?(?:forwarded-(?:for|host|server)|host|via|remote-ip|remote-addr|originating-IP))\s*:" \ @@ -177,7 +172,7 @@ SecRule ARGS_GET_NAMES|ARGS_GET "@rx [\n\r]+(?:\s|location|refresh|(?:set-)?cook phase:1,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,\ + t:none,t:htmlEntityDecode,t:lowercase,\ msg:'HTTP Header Injection Attack via payload (CR/LF and header-name detected)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -187,17 +182,17 @@ SecRule ARGS_GET_NAMES|ARGS_GET "@rx [\n\r]+(?:\s|location|refresh|(?:set-)?cook tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/33',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # -=[ HTTP Splitting ]=- # # This rule detect \n or \r in the REQUEST FILENAME -# Reference: https://www.owasp.org/index.php/Testing_for_HTTP_Splitting/Smuggling_(OTG-INPVAL-016) +# Reference: https://wiki.owasp.org/index.php/Testing_for_HTTP_Splitting/Smuggling_(OTG-INPVAL-016) +# Reference: https://owasp.org/www-project-web-security-testing-guide/assets/archive/OWASP_Testing_Guide_v4.pdf # SecRule REQUEST_FILENAME "@rx [\n\r]" \ "id:921190,\ @@ -213,11 +208,10 @@ SecRule REQUEST_FILENAME "@rx [\n\r]" \ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/34',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -230,7 +224,7 @@ SecRule REQUEST_FILENAME "@rx [\n\r]" \ # # [ References ] # * https://www.blackhat.com/presentations/bh-europe-08/Alonso-Parada/Whitepaper/bh-eu-08-alonso-parada-WP.pdf -# * https://blog.ripstech.com/2017/joomla-takeover-in-20-seconds-with-ldap-injection-cve-2017-14596/ +# * https://www.sonarsource.com/blog/joomla-takeover-in-20-seconds-with-ldap-injection-cve-2017-14596/ # * https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/276#issue-126581660 SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ^[^:\(\)\&\|\!\<\>\~]*\)\s*(?:\((?:[^,\(\)\=\&\|\!\<\>\~]+[><~]?=|\s*[&!|]\s*(?:\)|\()?\s*)|\)\s*\(\s*[\&\|\!]\s*|[&!|]\s*\([^\(\)\=\&\|\!\<\>\~]+[><~]?=[^:\(\)\&\|\!\<\>\~]*)" \ @@ -244,12 +238,12 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'application-multi',\ tag:'language-ldap',\ tag:'platform-multi',\ + tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/248/136',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ Body Processor Bypass ]=- @@ -259,12 +253,12 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # This rule intends to detect content types in the Content-Type header outside of the actual content type declaration. # This prevents bypasses targeting the Modsecurity recommended rules controlling which body processor is used. # -# Regular expression generated from util/regexp-assemble/data/921421.data. +# Regular expression generated from regex-assembly/921421.ra. # To update the regular expression run the following shell script -# (consult util/regexp-assemble/README.md for details): -# util/regexp-assemble/regexp-assemble.py update 921421 +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 921421 # -SecRule REQUEST_HEADERS:Content-Type "@rx ^[^;\s,]+[;\s,].*?(?:(?:application(?:\/soap\+|\/)|text\/)xml|application\/(?:.+[+])?json)" \ +SecRule REQUEST_HEADERS:Content-Type "@rx ^[^\s\v,;]+[\s\v,;].*?(?:application/(?:.+\+)?json|(?:application/(?:soap\+)?|text/)xml)" \ "id:921421,\ phase:1,\ block,\ @@ -280,15 +274,41 @@ SecRule REQUEST_HEADERS:Content-Type "@rx ^[^;\s,]+[;\s,].*?(?:(?:application(?: tag:'OWASP_CRS',\ tag:'capec/1000/255/153',\ tag:'PCI/12.1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:921013,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:921014,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# Rule against CVE-2021-40438: +# A crafted request uri-path can cause mod_proxy to forward the request to an origin server choosen by the remote user. +# This issue affects Apache HTTP Server 2.4.48 and earlier. +# GET /?unix:AAAAAAAAAAAAA|http://coreruleset.org/ +# +SecRule REQUEST_URI "@rx unix:[^|]*\|" \ + "id:921240,\ + phase:1,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'mod_proxy attack attempt detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-apache',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/210/272/220/33',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:921013,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:921014,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # @@ -300,7 +320,7 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:921014,phase:2,pass,nolog,skipAf # SecRule ARGS_GET "@rx [\n\r]" \ "id:921151,\ - phase:2,\ + phase:1,\ block,\ capture,\ t:none,t:urlDecodeUni,t:htmlEntityDecode,\ @@ -313,11 +333,10 @@ SecRule ARGS_GET "@rx [\n\r]" \ tag:'paranoia-level/2',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220/33',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # # -=[ Body Processor Bypass ]=- @@ -329,12 +348,12 @@ SecRule ARGS_GET "@rx [\n\r]" \ # [ References ] # * See rule 921422 # -# Regular expression generated from util/regexp-assemble/data/921422.data. +# Regular expression generated from regex-assembly/921422.ra. # To update the regular expression run the following shell script -# (consult util/regexp-assemble/README.md for details): -# util/regexp-assemble/regexp-assemble.py update 921422 +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 921422 # -SecRule REQUEST_HEADERS:Content-Type "@rx ^[^;\s,]+[;\s,].*?\b(?:(audio|image|video|csv|css|vnd|pdf|plain|json|soap|xml|x-www-form-urlencoded|form-data|related|x-amf|octet|stream|csp|report)|(text|multipart|application)|(\/|\+))\b" \ +SecRule REQUEST_HEADERS:Content-Type "@rx ^[^\s\v,;]+[\s\v,;].*?\b(?:((?:tex|multipar)t|application)|((?:audi|vide)o|image|cs[sv]|(?:vn|relate)d|p(?:df|lain)|json|(?:soa|cs)p|x(?:ml|-www-form-urlencoded)|form-data|x-amf|(?:octe|repor)t|stream)|([\+/]))\b" \ "id:921422,\ phase:1,\ block,\ @@ -350,15 +369,15 @@ SecRule REQUEST_HEADERS:Content-Type "@rx ^[^;\s,]+[;\s,].*?\b(?:(audio|image|vi tag:'OWASP_CRS',\ tag:'capec/1000/255/153',\ tag:'PCI/12.1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:921015,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:921016,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:921015,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:921016,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # # @@ -386,9 +405,9 @@ SecRule &REQUEST_HEADERS:Range "@gt 0" \ tag:'paranoia-level/3',\ tag:'OWASP_CRS',\ tag:'capec/1000/210/272/220',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # -=[ HTTP Parameter Pollution ]=- @@ -420,7 +439,7 @@ SecRule ARGS_NAMES "@rx ." \ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/137/15/460',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ setvar:'TX.paramcounter_%{MATCHED_VAR_NAME}=+1'" SecRule TX:/paramcounter_.*/ "@gt 1" \ @@ -436,21 +455,103 @@ SecRule TX:/paramcounter_.*/ "@gt 1" \ tag:'OWASP_CRS',\ tag:'capec/1000/152/137/15/460',\ tag:'paranoia-level/3',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" SecRule MATCHED_VARS_NAMES "@rx TX:paramcounter_(.*)" \ "capture,\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# -=[ HTTP Parameter Pollution ]=- +# +# [ Rule Logic ] +# Parameter pollution rule 921180 PL3 can by bypassed when a weak backend parameter +# parser is ignoring additional characters in a parameter array name after the +# closing of the array. +# Rule 921210 PL3 prevents this by disallowing arbitrary strings after an array has +# been closed or inbetween the square brackets in multidimensional arrays. +# Please note that rule 921120 allows for 2-dimensional, but not for higher dimensional +# arrays. If these are flagged as attacks, a rule exclusion will have to be +# deployed; ideally for the parameter(s) in question. +# +# [ References ] +# Private bug bounty in Spring 2022, findings Z05OZUCH. +# +# [ Payloads ] +# * foo[1]a=bar&foo[1]b= - parameter parsers often cut after the closing of +# the array. 921180 PL3 takes the full name, though. +# This impediance mismatch allows for bypasses. +# * foo[1]x[1]=bar&foo[1]x[2]= - extension of 1; this has the advantage that +# the parameter name does end with "]" just like a valid array notation. +# +SecRule ARGS_NAMES "@rx (][^\]]+$|][^\]]+\[)" \ + "id:921210,\ + phase:2,\ + pass,\ + log,\ + msg:'HTTP Parameter Pollution after detecting bogus char after parameter array',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/137/15/460',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:921017,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:921018,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:921017,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:921018,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + +# -=[ HTTP Parameter Pollution ]=- # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# [ Rule Logic ] +# Parameter pollution rule 921180 PL3 and 921210 PL3 can by bypassed if a +# weak backend parameter parser ignores parameter array alltogether at +# cuts parameter names at the first occurrence of the "[" character. +# The rule 921220 PL4 prevents this by disallowing parameter array names. +# +# If an application needs parameter array names, then this rule should be +# disabled, ideally by issueing a rule exclusion for the parameter names +# that need it. +# +# [ References ] +# Private bug bounty in Spring 2022, finding 5UXE4RK0. # +# [ Payloads ] +# * foo[1]=bar&foo[2]= +# * foo=bar&foo[1]= +# * foo[1]=bar&foo[1]acb]= - this is an edge case that 921210 PL3 is not +# able to catch since the parameter name ends with "]". +# +SecRule ARGS_NAMES "@rx \[" \ + "id:921220,\ + phase:2,\ + pass,\ + log,\ + msg:'HTTP Parameter Pollution possible via array notation',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/137/15/460',\ + tag:'paranoia-level/4',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-922-MULTIPART-ATTACK.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-922-MULTIPART-ATTACK.conf similarity index 68% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-922-MULTIPART-ATTACK.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-922-MULTIPART-ATTACK.conf index 13847061de..3450045364 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-922-MULTIPART-ATTACK.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-922-MULTIPART-ATTACK.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -38,17 +38,17 @@ SecRule &MULTIPART_PART_HEADERS:_charset_ "!@eq 0" \ tag:'OWASP_CRS',\ tag:'capec/1000/255/153',\ tag:'paranoia-level/1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" SecRule ARGS:_charset_ "!@within |%{tx.allowed_request_content_type_charset}|" \ "t:lowercase,\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # Only allow specific charsets same as Rule 920600 # Note: this is in phase:2 because these are headers that come in the body -SecRule MULTIPART_PART_HEADERS "@rx ^content-type\s*+:\s*+(.*)$" \ +SecRule MULTIPART_PART_HEADERS "@rx ^content-type\s*:\s*(.*)$" \ "id:922110,\ phase:2,\ block,\ @@ -63,12 +63,12 @@ SecRule MULTIPART_PART_HEADERS "@rx ^content-type\s*+:\s*+(.*)$" \ tag:'OWASP_CRS',\ tag:'capec/272/220',\ tag:'paranoia-level/1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" - SecRule TX:1 "!@rx ^(?:(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+)\/(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+))(?:\s*+;\s*+(?:(?:charset\s*+=\s*+(?:\"?(?:iso-8859-15?|windows-1252|utf-8)\b\"?))|(?:(?:c(?:h(?:a(?:r(?:s(?:e[^t\"(),\/:;<=>?![\x5c\]{}]|[^e\"(),/:;<=>?![\x5c\]{}])|[^s\"(),/:;<=>?![\x5c\]{}])|[^r\"(),/:;<=>?![\x5c\]{}])|[^a\"(),/:;<=>?![\x5c\]{}])|[^h\"(),/:;<=>?![\x5c\]{}])|[^c\"(),/:;<=>?![\x5c\]{}])[^\"(),/:;<=>?![\x5c\]{}]*(?:)\s*+=\s*+[^(),/:;<=>?![\x5c\]{}]+)|;?))*(?:\s*+,\s*+(?:(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+)\/(?:\*|[^\"(),\/:;<=>?![\x5c\]{}]+))(?:\s*+;\s*+(?:(?:charset\s*+=\s*+(?:\"?(?:iso-8859-15?|windows-1252|utf-8)\b\"?))|(?:(?:c(?:h(?:a(?:r(?:s(?:e[^t\"(),\/:;<=>?![\x5c\]{}]|[^e\"(),/:;<=>?![\x5c\]{}])|[^s\"(),/:;<=>?![\x5c\]{}])|[^r\"(),/:;<=>?![\x5c\]{}])|[^a\"(),/:;<=>?![\x5c\]{}])|[^h\"(),/:;<=>?![\x5c\]{}])|[^c\"(),/:;<=>?![\x5c\]{}])[^\"(),/:;<=>?![\x5c\]{}]*(?:)\s*+=\s*+[^(),/:;<=>?![\x5c\]{}]+)|;?))*)*$" \ + SecRule TX:1 "!@rx ^(?:(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)/(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\v]*;[\s\v]*(?:charset[\s\v]*=[\s\v]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\v -\"\(-\),/:-\?\[-\]c\{\}]|c(?:[^!-\"\(-\),/:-\?\[-\]h\{\}]|h(?:[^!-\"\(-\),/:-\?\[-\]a\{\}]|a(?:[^!-\"\(-\),/:-\?\[-\]r\{\}]|r(?:[^!-\"\(-\),/:-\?\[-\]s\{\}]|s(?:[^!-\"\(-\),/:-\?\[-\]e\{\}]|e[^!-\"\(-\),/:-\?\[-\]t\{\}]))))))[^!-\"\(-\),/:-\?\[-\]\{\}]*[\s\v]*=[\s\v]*[^!\(-\),/:-\?\[-\]\{\}]+);?)*(?:[\s\v]*,[\s\v]*(?:(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)/(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\v]*;[\s\v]*(?:charset[\s\v]*=[\s\v]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\v -\"\(-\),/:-\?\[-\]c\{\}]|c(?:[^!-\"\(-\),/:-\?\[-\]h\{\}]|h(?:[^!-\"\(-\),/:-\?\[-\]a\{\}]|a(?:[^!-\"\(-\),/:-\?\[-\]r\{\}]|r(?:[^!-\"\(-\),/:-\?\[-\]s\{\}]|s(?:[^!-\"\(-\),/:-\?\[-\]e\{\}]|e[^!-\"\(-\),/:-\?\[-\]t\{\}]))))))[^!-\"\(-\),/:-\?\[-\]\{\}]*[\s\v]*=[\s\v]*[^!\(-\),/:-\?\[-\]\{\}]+);?)*)*$" \ "t:lowercase,\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # Content-Transfer-Encoding was deprecated by rfc7578 in 2015 and should not be used (see: https://www.rfc-editor.org/rfc/rfc7578#section-4.7) # Note: this is in phase:2 because these are headers that come in the body @@ -87,6 +87,6 @@ SecRule MULTIPART_PART_HEADERS "@rx content-transfer-encoding:(.*)" \ tag:'OWASP_CRS',\ tag:'capec/272/220',\ tag:'paranoia-level/1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" diff --git a/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf new file mode 100644 index 0000000000..097e7f54d3 --- /dev/null +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf @@ -0,0 +1,203 @@ +# ------------------------------------------------------------------------ +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2023 Core Rule Set project. 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) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:930011,phase:1,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:930012,phase:2,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# +# -=[ Directory Traversal Attacks ]=- +# +# Ref: https://github.com/wireghoul/dotdotpwn +# +# [ Encoded /../ Payloads ] +# +# Regular expression generated from regex-assembly/930100.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 930100 +# +SecRule REQUEST_URI_RAW|ARGS|REQUEST_HEADERS|!REQUEST_HEADERS:Referer|FILES|XML:/* "@rx (?i)(?:[/\x5c]|%(?:2(?:f|5(?:2f|5c|c(?:1%259c|0%25af))|%46)|5c|c(?:0%(?:[2aq]f|5c|9v)|1%(?:[19p]c|8s|af))|(?:bg%q|(?:e|f(?:8%8)?0%8)0%80%a)f|u(?:221[5-6]|EFC8|F025|002f)|%3(?:2(?:%(?:%6|4)6|F)|5%%63)|1u)|0x(?:2f|5c))(?:\.(?:%0[0-1]|\?)?|\?\.?|%(?:2(?:(?:5(?:2|c0%25a))?e|%45)|c0(?:\.|%[25-6ae-f]e)|u(?:(?:ff0|002)e|2024)|%32(?:%(?:%6|4)5|E)|(?:e|f(?:(?:8|c%80)%8)?0%8)0%80%ae)|0x2e){2,3}(?:[/\x5c]|%(?:2(?:f|5(?:2f|5c|c(?:1%259c|0%25af))|%46)|5c|c(?:0%(?:[2aq]f|5c|9v)|1%(?:[19p]c|8s|af))|(?:bg%q|(?:e|f(?:8%8)?0%8)0%80%a)f|u(?:221[5-6]|EFC8|F025|002f)|%3(?:2(?:%(?:%6|4)6|F)|5%%63)|1u)|0x(?:2f|5c))" \ + "id:930100,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Path Traversal Attack (/../) or (/.../)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-lfi',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/255/153/126',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}'" + +# +# [ Decoded /../ or /..;/ Payloads ] +# +# To prevent '..' from triggering, the regexp is split into two parts: +# - ../ +# - /.. +# OR +# - .../ +# - /... +# +# Semicolon added to prevent path traversal via reverse proxy mapping '/..;/' (Tomcat) +# +SecRule REQUEST_URI|ARGS|REQUEST_HEADERS|!REQUEST_HEADERS:Referer|FILES|XML:/* "@rx (?:(?:^|[\x5c/;])\.{2,3}[\x5c/;]|[\x5c/;]\.{2,3}(?:[\x5c/;]|$))" \ + "id:930110,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,t:cmdLine,\ + msg:'Path Traversal Attack (/../) or (/.../)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-lfi',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/255/153/126',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + multiMatch,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}'" + +# +# -=[ OS File Access ]=- +# +# We check for OS file access with the help of a local file with OS files data. +# +# Ref: https://github.com/lightos/Panoptic/blob/master/cases.xml +# +# If you wonder where support for Google OAuth2 has gone, see: +# https://github.com/coreruleset/google-oauth2-plugin +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile lfi-os-files.data" \ + "id:930120,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,\ + msg:'OS File Access Attempt',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-lfi',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/255/153/126',\ + tag:'PCI/6.5.4',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# -=[ Restricted File Access ]=- +# +# Detects attempts to retrieve application source code, metadata, +# credentials and version control history possibly reachable in a web root. +# +SecRule REQUEST_FILENAME "@pmFromFile restricted-files.data" \ + "id:930130,\ + phase:1,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,\ + msg:'Restricted File Access Attempt',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-lfi',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/255/153/126',\ + tag:'PCI/6.5.4',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:930013,phase:1,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:930014,phase:2,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + +# +# -=[ OS File Access ]=- +# +# This is a stricter sibling of rule 930120. +# This stricter sibling checks for OS file data in request headers referer and user-agent. +# We check for OS file access with the help of a local file with OS files data. +# +# Ref: https://github.com/lightos/Panoptic/blob/master/cases.xml +# +SecRule REQUEST_HEADERS:Referer|REQUEST_HEADERS:User-Agent "@pmFromFile lfi-os-files.data" \ + "id:930121,\ + phase:1,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,\ + msg:'OS File Access Attempt in REQUEST_HEADERS',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-lfi',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/255/153/126',\ + tag:'PCI/6.5.4',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:930015,phase:1,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:930016,phase:2,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:930017,phase:1,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:930018,phase:2,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-930-APPLICATION-ATTACK-LFI" diff --git a/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf new file mode 100644 index 0000000000..80d77d2299 --- /dev/null +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf @@ -0,0 +1,189 @@ +# ------------------------------------------------------------------------ +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2023 Core Rule Set project. 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. +# ------------------------------------------------------------------------ +# +# RFI Attacks +# + +# +# -= Paranoia Level 0 (empty) =- (apply unconditionally) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:931011,phase:1,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:931012,phase:2,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# -=[ Rule Logic ]=- +# These rules look for common types of Remote File Inclusion (RFI) attack methods. +# - URL Contains an IP Address +# - The PHP "include()" Function +# - RFI Data Ends with Question Mark(s) (?) +# - RFI Host Doesn't Match Local Host +# +# -=[ References ]=- +# http://projects.webappsec.org/Remote-File-Inclusion +# http://tacticalwebappsec.blogspot.com/2009/06/generic-remote-file-inclusion-attack.html +# +SecRule ARGS "@rx ^(?i:file|ftps?|https?)://(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})" \ + "id:931100,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Possible Remote File Inclusion (RFI) Attack: URL Parameter using IP Address',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rfi',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/175/253',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +SecRule QUERY_STRING|REQUEST_BODY "@rx (?i)(?:\binclude\s*\([^)]*|mosConfig_absolute_path|_CONF\[path\]|_SERVER\[DOCUMENT_ROOT\]|GALLERY_BASEDIR|path\[docroot\]|appserv_root|config\[root_dir\])=(?:file|ftps?|https?)://" \ + "id:931110,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Possible Remote File Inclusion (RFI) Attack: Common RFI Vulnerable Parameter Name used w/URL Payload',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rfi',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/175/253',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +SecRule ARGS "@rx ^(?i:file|ftps?|https?).*?\?+$" \ + "id:931120,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Possible Remote File Inclusion (RFI) Attack: URL Payload Used w/Trailing Question Mark Character (?)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rfi',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/175/253',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:931013,phase:1,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:931014,phase:2,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + +# url:file:// can be used by Java applications using +# org.apache.commons.io.IOUtils to access internal files, so this has been added +# +# This rule has one (stricter) sibling: 931131. +# That rule applies the same regular expression to the request filename in phase 1. +# +# Regular expression generated from regex-assembly/931130.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 931130 +# +SecRule ARGS "@rx (?i)(?:(?:url|jar):)?(?:a(?:cap|f[ps]|ttachment)|b(?:eshare|itcoin|lob)|c(?:a(?:llto|p)|id|vs|ompress.(?:zlib|bzip2))|d(?:a(?:v|ta)|ict|n(?:s|tp))|e(?:d2k|xpect)|f(?:(?:ee)?d|i(?:le|nger|sh)|tps?)|g(?:it|o(?:pher)?|lob)|h(?:323|ttps?)|i(?:ax|cap|(?:ma|p)ps?|rc[6s]?)|ja(?:bbe)?r|l(?:dap[is]?|ocal_file)|m(?:a(?:ilto|ven)|ms|umble)|n(?:e(?:tdoc|ws)|fs|ntps?)|ogg|p(?:aparazzi|h(?:ar|p)|op(?:2|3s?)|r(?:es|oxy)|syc)|r(?:mi|sync|tm(?:f?p)?|ar)|s(?:3|ftp|ips?|m(?:[bs]|tps?)|n(?:ews|mp)|sh(?:2(?:.(?:s(?:hell|(?:ft|c)p)|exec|tunnel))?)?|vn(?:\+ssh)?)|t(?:e(?:amspeak|lnet)|ftp|urns?)|u(?:dp|nreal|t2004)|v(?:entrilo|iew-source|nc)|w(?:ebcal|ss?)|x(?:mpp|ri)|zip)://(?:[^@]+@)?([^/]*)" \ + "id:931130,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Possible Remote File Inclusion (RFI) Attack: Off-Domain Reference/Link',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rfi',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/175/253',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rfi_parameter_%{MATCHED_VAR_NAME}=.%{tx.1}',\ + chain" + SecRule TX:/rfi_parameter_.*/ "!@endsWith .%{request_headers.host}" \ + "setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This is a (stricter) sibling of 931130. +# +# Regular expression generated from regex-assembly/931131.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 931131 +# +SecRule REQUEST_FILENAME "@rx (?i)(?:(?:url|jar):)?(?:a(?:cap|f[ps]|ttachment)|b(?:eshare|itcoin|lob)|c(?:a(?:llto|p)|id|vs|ompress.(?:zlib|bzip2))|d(?:a(?:v|ta)|ict|n(?:s|tp))|e(?:d2k|xpect)|f(?:(?:ee)?d|i(?:le|nger|sh)|tps?)|g(?:it|o(?:pher)?|lob)|h(?:323|ttps?)|i(?:ax|cap|(?:ma|p)ps?|rc[6s]?)|ja(?:bbe)?r|l(?:dap[is]?|ocal_file)|m(?:a(?:ilto|ven)|ms|umble)|n(?:e(?:tdoc|ws)|fs|ntps?)|ogg|p(?:aparazzi|h(?:ar|p)|op(?:2|3s?)|r(?:es|oxy)|syc)|r(?:mi|sync|tm(?:f?p)?|ar)|s(?:3|ftp|ips?|m(?:[bs]|tps?)|n(?:ews|mp)|sh(?:2(?:.(?:s(?:hell|(?:ft|c)p)|exec|tunnel))?)?|vn(?:\+ssh)?)|t(?:e(?:amspeak|lnet)|ftp|urns?)|u(?:dp|nreal|t2004)|v(?:entrilo|iew-source|nc)|w(?:ebcal|ss?)|x(?:mpp|ri)|zip)://(?:[^@]+@)?([^/]*)" \ + "id:931131,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Possible Remote File Inclusion (RFI) Attack: Off-Domain Reference/Link',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rfi',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/175/253',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rfi_parameter_%{MATCHED_VAR_NAME}=.%{tx.1}',\ + chain" + SecRule TX:/rfi_parameter_.*/ "!@endsWith .%{request_headers.host}" \ + "setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:931015,phase:1,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:931016,phase:2,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:931017,phase:1,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:931018,phase:2,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-931-APPLICATION-ATTACK-RFI" diff --git a/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf new file mode 100644 index 0000000000..6dabf3e34b --- /dev/null +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf @@ -0,0 +1,1824 @@ +# ------------------------------------------------------------------------ +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2023 Core Rule Set project. 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) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:932011,phase:1,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:932012,phase:2,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + + +# [ Unix command injection ] +# +# This rule detects Unix command injections. +# A command injection takes a form such as: +# +# foo.jpg;uname -a +# foo.jpg||uname -a +# +# The vulnerability exists when an application executes a shell command +# without proper input escaping/validation. +# +# This rule is also triggered by an Oracle WebLogic Remote Command Execution exploit: +# [ Oracle WebLogic vulnerability CVE-2017-10271 - Exploit tested: https://www.exploit-db.com/exploits/43458 ] +# +# To prevent false positives, we look for a 'starting sequence' that +# precedes a command in shell syntax, such as: ; | & $( ` <( >( +# Anatomy of the regexp with examples of patterns caught: +# +# 1. Starting tokens +# +# ; ;ifconfig +# \{ {ifconfig} +# \| |ifconfig +# \|\| ||ifconfig +# & &ifconfig +# && &&ifconfig +# \n ;\nifconfig +# \r ;\rifconfig +# \$\( $(ifconfig) +# \$\(\( $((ifconfig)) +# ` `ifconfig` +# \${ ${ifconfig} +# <\( <( ifconfig ) +# >\( >( ifconfig ) +# \(\s*\) a() ( ifconfig; ); a +# +# 2. Command prefixes +# +# { { ifconfig } +# \s*\(\s* ( ifconfig ) +# \w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+ VARNAME=xyz ifconfig +# !\s* ! ifconfig +# \$ $ifconfig +# +# 3. Quoting +# +# ' 'ifconfig' +# \" "ifconfig" +# +# 4. Paths +# +# [\?\*\[\]\(\)\-\|+\w'\"\./\x5c]+/ /sbin/ifconfig, /s?in/./ifconfig, /s[a-b]in/ifconfig etc. +# +# An effort was made to combat evasions by shell quoting (e.g. 'ls', +# 'l'"s", \l\s are all valid). ModSecurity has a t:cmdLine +# transformation built-in to deal with this, but unfortunately, it +# replaces ';' characters and lowercases the payload, which is less +# useful for this case. However, emulating the transformation makes +# the regexp more complex. +# +# This is the base Rule to prevent Unix Command Injection +# for prefix + two and three characters. +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932230.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932230 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\n\r;`\{]|\|\|?|&&?|\$(?:\(\(?|\{)|[<>]\(|\([\s\v]*\))[\s\v]*(?:[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:7[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[arx])?|(?:(?:b[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z|x)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z|h[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[\s\v&\),<>\|].*|[ckz][\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h|d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?f|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:n[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?v|s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h)|f[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[dg]|g[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[&,<>\|]|(?:[\--\.0-9A-Z_a-z][\"'\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\*\-0-9\?-@_a-\{]*)?\x5c?)+[\s\v&,<>\|]).*|p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?g)|i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?r[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?b|l[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:s|z[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:4|[\s\v&\),<>\|].*))|p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:h[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[\s\v&\),<>\|].*|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|x[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z)|r[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?c(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[\s\v&\),<>\|].*)?|s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|(?:e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|(?:s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?)?h)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[\s\v&\),<>\|].*|v[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n)|u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?3[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m)\b" \ + "id:932230,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix Command Injection (2-3 chars)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# [ Unix command injection ] +# +# This is the base Rule to prevent Unix Command Injection +# for prefix + more than 4 characters. +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932235.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932235 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\n\r;`\{]|\|\|?|&&?|\$(?:\(\(?|\{)|[<>]\(|\([\s\v]*\))[\s\v]*(?:[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:HEAD|POST|y(?:arn|elp))[\s\v&\)<>\|]|a(?:dd(?:group|user)|getty|l(?:ias|pine)[\s\v&\)<>\|]|nsible-playbook|pt(?:-get|itude[\s\v&\)<>\|])|r(?:ch[\s\v&\)<>\|]|ia2c)|s(?:cii(?:-xfr|85)|pell)|tobm|xel)|b(?:a(?:s(?:e(?:32|64|n(?:ame[\s\v&\)<>\|]|c))|h[\s\v&\)<>\|])|tch[\s\v&\)<>\|])|lkid|pftrace|r(?:eaksw|idge[\s\v&\)<>\|])|sd(?:cat|iff|tar)|u(?:iltin|n(?:dler[\s\v&\)<>\|]|zip2)|s(?:ctl|ybox))|y(?:ebug|obu)|z(?:c(?:at|mp)|diff|e(?:grep|xe)|f?grep|ip2(?:recover)?|less|more))|c(?:a(?:ncel|psh)[\s\v&\)<>\|]|ertbot|h(?:attr|(?:dir|root)[\s\v&\)<>\|]|eck_(?:by_ssh|cups|log|memory|raid|s(?:sl_cert|tatusfile))|(?:flag|pas)s|g(?:passwd|rp)|mod|o(?:om|wn)|sh)|lang(?:[\s\v&\)<>\|]|\+\+)|o(?:(?:b|pro)c|lumn[\s\v&\)<>\|]|m(?:m(?:and[\s\v&\)<>\|])?|p(?:oser|ress)[\s\v&\)<>\|])|w(?:say|think))|p(?:an|io|ulimit)|r(?:ash[\s\v&\)<>\|]|on(?:tab)?)|s(?:plit|vtool)|u(?:psfilter|rl[\s\v&\)<>\|]))|d(?:(?:a(?:sh|te)|i(?:alog|ff))[\s\v&\)<>\|]|hclient|m(?:esg|idecode|setup)|o(?:as|(?:cker|ne)[\s\v&\)<>\|]|sbox)|pkg|vips)|e(?:2fsck|(?:asy_instal|va)l|cho[\s\v&\)<>\|]|fax|grep|macs|n(?:d(?:if|sw)|v-update)|sac|x(?:ec[\s\v&\)<>\|]|iftool|p(?:(?:and|(?:ec|or)t)[\s\v&\)<>\|]|r)))|f(?:acter|(?:etch|lock|unction)[\s\v&\)<>\|]|grep|i(?:le(?:[\s\v&\)<>\|]|test)|(?:n(?:d|ger)|sh)[\s\v&\)<>\|])|o(?:ld[\s\v&\)<>\|]|reach)|ping|tp(?:stats|who))|g(?:awk[\s\v&\)<>\|]|core|e(?:ni(?:e[\s\v&\)<>\|]|soimage)|tfacl[\s\v&\)<>\|])|hci|i(?:mp[\s\v&\)<>\|]|nsh)|r(?:ep[\s\v&\)<>\|]|oup(?:[\s\v&\)<>\|]|mod))|tester|unzip|z(?:cat|exe|ip))|h(?:(?:ash|i(?:ghlight|story))[\s\v&\)<>\|]|e(?:ad[\s\v&\)<>\|]|xdump)|ost(?:id|name)|ping3|t(?:digest|op|passwd))|i(?:conv|f(?:config|top)|nstall[\s\v&\)<>\|]|onice|p(?:6?tables|config)|spell)|j(?:ava[\s\v&\)<>\|]|exec|o(?:(?:bs|in)[\s\v&\)<>\|]|urnalctl)|runscript)|k(?:ill(?:[\s\v&\)<>\|]|all)|nife[\s\v&\)<>\|]|sshell)|l(?:a(?:st(?:[\s\v&\)<>\|]|comm|log(?:in)?)|tex[\s\v&\)<>\|])|dconfig|ess(?:[\s\v&\)<>\|]|echo|(?:fil|pip)e)|ftp(?:get)?|(?:inks|ynx)[\s\v&\)<>\|]|o(?:(?:ca(?:l|te)|ok)[\s\v&\)<>\|]|g(?:inctl|(?:nam|sav)e)|setup)|s(?:-F|b_release|cpu|hw|mod|of|pci|usb)|trace|ua(?:la)?tex|wp-(?:d(?:ownload|ump)|mirror|request)|z(?:4c(?:at)?|c(?:at|mp)|diff|[e-f]?grep|less|m(?:a(?:dec|info)?|ore)))|m(?:a(?:il(?:[\s\v&\)<>q\|]|x[\s\v&\)<>\|])|ke[\s\v&\)<>\|]|ster\.passwd|wk)|k(?:dir[\s\v&\)<>\|]|fifo|nod|temp)|locate|o(?:(?:re|unt)[\s\v&\)<>\|]|squitto)|sg(?:attrib|c(?:at|onv)|filter|merge|uniq)|utt[\s\v&\)<>\|]|ysql(?:admin|dump(?:slow)?|hotcopy|show)?)|n(?:a(?:no[\s\v&\)<>\|]|sm|wk)|c(?:\.(?:openbsd|traditional)|at)|e(?:ofetch|t(?:(?:c|st)at|kit-ftp|plan))|(?:ice|ull)[\s\v&\)<>\|]|map|o(?:de[\s\v&\)<>\|]|hup)|ping|roff|s(?:enter|lookup|tat))|o(?:ctave[\s\v&\)<>\|]|nintr|p(?:en(?:ssl|v(?:pn|t))|kg))|p(?:a(?:(?:cman|rted|tch)[\s\v&\)<>\|]|s(?:swd|te[\s\v&\)<>\|]))|d(?:f(?:la)?tex|ksh)|er(?:f|l(?:5|sh)?|ms[\s\v&\)<>\|])|(?:ft|gre)p|hp(?:-cgi|[57])|i(?:(?:co|ng)[\s\v&\)<>\|]|dstat|gz)|k(?:exec|g_?info|ill)|opd|rint(?:env|f[\s\v&\)<>\|])|s(?:ed|ftp|ql)|tar(?:diff|grep)?|u(?:ppet[\s\v&\)<>\|]|shd)|wd\.db|ython[^\s\v])|r(?:ak(?:e[\s\v&\)<>\|]|u)|bash|e(?:a(?:delf|lpath)|(?:dcarpet|name|p(?:eat|lace))[\s\v&\)<>\|]|stic)|l(?:ogin|wrap)|m(?:dir[\s\v&\)<>\|]|user)|nano|oute[\s\v&\)<>\|]|pm(?:db|(?:quer|verif)y)|sync|u(?:by[^\s\v]|n-(?:mailcap|parts))|vi(?:ew|m))|s(?:(?:ash|nap)[\s\v&\)<>\|]|c(?:hed|r(?:een|ipt)[\s\v&\)<>\|])|diff|e(?:(?:lf|rvice)[\s\v&\)<>\|]|ndmail|t(?:arch|env|facl[\s\v&\)<>\|]|sid))|ftp|h(?:\.distrib|(?:adow|ells)[\s\v&\)<>\|]|u(?:f|tdown[\s\v&\)<>\|]))|l(?:eep[\s\v&\)<>\|]|sh)|mbclient|o(?:cat|elim|(?:rt|urce)[\s\v&\)<>\|])|p(?:lit[\s\v&\)<>\|]|wd\.db)|qlite3|sh(?:-key(?:ge|sca)n|pass)|t(?:art-stop-daemon|d(?:buf|err|in|out)|r(?:ace|ings[\s\v&\)<>\|]))|udo|ys(?:ctl|tem(?:ctl|d-resolve)))|t(?:a(?:il[\s\v&\)<>f\|]|sk(?:[\s\v&\)<>\|]|set))|c(?:l?sh|p(?:dump|ing|traceroute))|elnet|ftp|ime(?:(?:out)?[\s\v&\)<>\|]|datectl)|mux|ouch[\s\v&\)<>\|]|r(?:aceroute6?|off)|shark)|u(?:limit[\s\v&\)<>\|]|n(?:ame|(?:compress|s(?:et|hare))[\s\v&\)<>\|]|expand|iq|l(?:ink[\s\v&\)<>\|]|z(?:4|ma))|(?:pig|x)z|rar|z(?:ip[\s\v&\)<>\|]|std))|p(?:2date[\s\v&\)<>\|]|date-alternatives)|ser(?:(?:ad|mo)d|del)|u(?:de|en)code)|v(?:algrind|i(?:ew[\s\v&\)<>\|]|gr|mdiff|pw|rsh)|olatility[\s\v&\)<>\|])|w(?:a(?:ll|tch)[\s\v&\)<>\|]|get|h(?:iptail[\s\v&\)<>\|]|o(?:ami|is))|i(?:reshark|sh[\s\v&\)<>\|]))|x(?:args|e(?:la)?tex|mo(?:dmap|re)|pad|term|z(?:c(?:at|mp)|d(?:ec|iff)|[e-f]?grep|less|more))|z(?:athura|c(?:at|mp)|diff|e(?:grep|ro[\s\v&\)<>\|])|f?grep|ip(?:c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|less|more|run|s(?:oelim|td(?:(?:ca|m)t|grep|less)?)|ypper))" \ + "id:932235,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix Command Injection (command without evasion)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Windows PowerShell, cmdlets and options ] +# +# Detect some common PowerShell commands, cmdlets and options. +# These commands should be relatively uncommon in normal text, but +# potentially useful for code injection. +# +# If you are not running Windows, it is safe to disable this rule. +# +# https://learn.microsoft.com/en-us/previous-versions/technet-magazine/ff714569(v=msdn.10) +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile windows-powershell-commands.data" \ + "id:932120,\ + phase:2,\ + block,\ + capture,\ + t:none,t:cmdLine,\ + msg:'Remote Command Execution: Windows PowerShell Command Found',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'language-powershell',\ + tag:'platform-windows',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Windows Powershell cmdlet aliases ] +# +# Attempts to detect aliases of the common PowerShell cmdlets in windows-powershell-commands.data +# If you are not running Windows, it is safe to disable this rule. +# +# There are other aliases which are similar to Unix, but they are properly handled by rule 932105 +# +# Regular expression generated from regex-assembly/932125.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932125 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:[\n\r;`\{]|\|\|?|&&?)[\s\v]*[\s\v\"'-\(,@]*(?:[\"'\.-9A-Z_a-z]+/|(?:[\"'\x5c\^]*[0-9A-Z_a-z][\"'\x5c\^]*:.*|[ \"'\.-9A-Z\x5c\^-_a-z]*)\x5c)?[\"\^]*(?:(?:a[\"\^]*(?:c|s[\"\^]*n[\"\^]*p)|e[\"\^]*(?:b[\"\^]*p|p[\"\^]*(?:a[\"\^]*l|c[\"\^]*s[\"\^]*v|s[\"\^]*n)|[tx][\"\^]*s[\"\^]*n)|f[\"\^]*(?:[cltw]|o[\"\^]*r[\"\^]*e[\"\^]*a[\"\^]*c[\"\^]*h)|i[\"\^]*(?:[cr][\"\^]*m|e[\"\^]*x|h[\"\^]*y|i|p[\"\^]*(?:a[\"\^]*l|c[\"\^]*s[\"\^]*v|m[\"\^]*o|s[\"\^]*n)|s[\"\^]*e|w[\"\^]*(?:m[\"\^]*i|r))|m[\"\^]*(?:a[\"\^]*n|[dipv]|o[\"\^]*u[\"\^]*n[\"\^]*t)|o[\"\^]*g[\"\^]*v|p[\"\^]*(?:o[\"\^]*p|u[\"\^]*s[\"\^]*h)[\"\^]*d|t[\"\^]*r[\"\^]*c[\"\^]*m|w[\"\^]*j[\"\^]*b)[\"\^]*[\s\v,\.-/;-<>].*|c[\"\^]*(?:(?:(?:d|h[\"\^]*d[\"\^]*i[\"\^]*r|v[\"\^]*p[\"\^]*a)[\"\^]*|p[\"\^]*(?:[ip][\"\^]*)?)[\s\v,\.-/;-<>].*|l[\"\^]*(?:(?:[cipv]|h[\"\^]*y)[\"\^]*[\s\v,\.-/;-<>].*|s)|n[\"\^]*s[\"\^]*n)|d[\"\^]*(?:(?:b[\"\^]*p|e[\"\^]*l|i[\"\^]*(?:f[\"\^]*f|r))[\"\^]*[\s\v,\.-/;-<>].*|n[\"\^]*s[\"\^]*n)|g[\"\^]*(?:(?:(?:(?:a[\"\^]*)?l|b[\"\^]*p|d[\"\^]*r|h[\"\^]*y|(?:w[\"\^]*m[\"\^]*)?i|j[\"\^]*b|[u-v])[\"\^]*|c[\"\^]*(?:[ims][\"\^]*)?|m[\"\^]*(?:o[\"\^]*)?|s[\"\^]*(?:n[\"\^]*(?:p[\"\^]*)?|v[\"\^]*))[\s\v,\.-/;-<>].*|e[\"\^]*r[\"\^]*r|p[\"\^]*(?:(?:s[\"\^]*)?[\s\v,\.-/;-<>].*|v))|l[\"\^]*s|n[\"\^]*(?:(?:a[\"\^]*l|d[\"\^]*r|[iv]|m[\"\^]*o|s[\"\^]*n)[\"\^]*[\s\v,\.-/;-<>].*|p[\"\^]*s[\"\^]*s[\"\^]*c)|r[\"\^]*(?:(?:(?:(?:b[\"\^]*)?p|e[\"\^]*n|(?:w[\"\^]*m[\"\^]*)?i|j[\"\^]*b|n[\"\^]*[ip])[\"\^]*|d[\"\^]*(?:r[\"\^]*)?|m[\"\^]*(?:(?:d[\"\^]*i[\"\^]*r|o)[\"\^]*)?|s[\"\^]*n[\"\^]*(?:p[\"\^]*)?|v[\"\^]*(?:p[\"\^]*a[\"\^]*)?)[\s\v,\.-/;-<>].*|c[\"\^]*(?:j[\"\^]*b[\"\^]*[\s\v,\.-/;-<>].*|s[\"\^]*n)|u[\"\^]*j[\"\^]*b)|s[\"\^]*(?:(?:(?:a[\"\^]*(?:j[\"\^]*b|l|p[\"\^]*s|s[\"\^]*v)|b[\"\^]*p|[civ]|w[\"\^]*m[\"\^]*i)[\"\^]*|l[\"\^]*(?:s[\"\^]*)?|p[\"\^]*(?:(?:j[\"\^]*b|p[\"\^]*s|s[\"\^]*v)[\"\^]*)?)[\s\v,\.-/;-<>].*|h[\"\^]*c[\"\^]*m|u[\"\^]*j[\"\^]*b))(?:\.[\"\^]*[0-9A-Z_a-z]+)?\b" \ + "id:932125,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Windows Powershell Alias Command Injection',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-windows',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Unix shell expressions ] +# +# Detects the following patterns which are common in Unix shell scripts +# and one-liners: +# +# $(foo) Command substitution +# ${foo} Parameter expansion +# <(foo) Process substitution +# >(foo) Process substitution +# $((foo)) Arithmetic expansion +# /e[t]c Shell glob expression to bypass wordlists +# +# Regular expression generated from regex-assembly/932130.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932130 +# +# This rule has a stricter sibling: 932131 (PL2) that applies the same regex to User-Agent and Referer +# +# This rule is essential to defend against the Log4J / Log4Shell attacks (see also rule 944150) +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \$(?:\((?:.*|\(.*\))\)|\{.*\})|[<>]\(.*\)|/[0-9A-Z_a-z]*\[!?.+\]" \ + "id:932130,\ + phase:2,\ + block,\ + capture,\ + t:none,t:cmdLine,\ + msg:'Remote Command Execution: Unix Shell Expression Found',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Windows FOR, IF commands ] +# +# This rule detects Windows command shell FOR and IF commands. +# If you are not running Windows, it is safe to disable this rule. +# +# Examples: +# +# FOR %a IN (set) DO +# FOR /D %a IN (dirs) DO +# FOR /F "options" %a IN (text|"text") DO +# FOR /L %a IN (start,step,end) DO +# FOR /R C:\dir %A IN (set) DO +# +# IF [/I] [NOT] EXIST filename | DEFINED define | ERRORLEVEL n | CMDEXTVERSION n +# IF [/I] [NOT] item1 [==|EQU|NEQ|LSS|LEQ|GTR|GEQ] item2 +# IF [/I] [NOT] (item1) [==|EQU|NEQ|LSS|LEQ|GTR|GEQ] (item2) +# +# http://ss64.com/nt/if.html +# http://ss64.com/nt/for.html +# +# Regular expression generated from regex-assembly/932140.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932140 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \b(?:for(?:/[dflr].*)? %+[^ ]+ in\(.*\)[\s\v]?do|if(?:/i)?(?: not)?(?: (?:e(?:xist|rrorlevel)|defined|cmdextversion)\b|[ \(].*(?:\b(?:g(?:eq|tr)|equ|neq|l(?:eq|ss))\b|==)))" \ + "id:932140,\ + phase:2,\ + block,\ + capture,\ + t:none,t:cmdLine,\ + msg:'Remote Command Execution: Windows FOR/IF Command Found',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-windows',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Unix direct remote command execution ] +# +# Detects Unix commands at the start of a parameter (direct RCE). +# Example: foo=wget%20www.example.com +# +# In this rule we use a different check from command injection (rule 932230), where a +# command string is appended (injected) to a regular parameter, and then +# passed to a shell unescaped. +# +# Additionaly, we require a trailing space (denoting command parameters) or command +# separator character after the command. +# +# This rule is also triggered by an Oracle WebLogic Remote Command Execution exploit: +# [ Oracle WebLogic vulnerability CVE-2017-10271 - Exploit tested: https://www.exploit-db.com/exploits/43458 ] +# +# An effort was made to combat evasions by shell quoting (e.g. 'ls', +# 'l'"s", \l\s are all valid). ModSecurity has a t:cmdLine +# transformation built-in to deal with this, but unfortunately, it +# replaces ';' characters and lowercases the payload, which is less +# useful for this case. However, emulating the transformation makes +# the regexp more complex. +# +# This is the base Rule to prevent Direct Unix Command Injection +# without prefix match. +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932250.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932250 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:^|=)[\s\v]*(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:7[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[arx])?|(?:b[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z|x)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z|[ckz][\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h|d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?f|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:n[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?v|s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h)|f[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[dg]|g[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?c|p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?g)|(?:h[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?u|u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?r[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?b|l[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:s|z(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?4)?)|p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:h[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|x[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z)|r[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?c(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p)?|s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|(?:s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?)?h|v[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n)|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?3[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m)[\s\v&\)<>\|]" \ + "id:932250,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Direct Unix Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# [ Unix command injection ] +# +# This rule complements rule 932250 for commands of 4 characters and up. +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932260.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932260 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:^|=)[\s\v]*(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:a(?:ddgroup|xel)|b(?:ase(?:32|64|nc)|lkid|sd(?:cat|iff|tar)|u(?:iltin|nzip2|sybox)|yobu|z(?:c(?:at|mp)|diff|e(?:grep|xe)|f?grep|ip2(?:recover)?|less|more))|c(?:h(?:g(?:passwd|rp)|pass|sh)|lang\+\+|oproc|ron)|d(?:iff[\s\v&\)<>\|]|mesg|oas)|e(?:2fsck|grep)|f(?:grep|iletest|tp(?:stats|who))|g(?:r(?:ep[\s\v&\)<>\|]|oupmod)|unzip|z(?:cat|exe|ip))|htop|l(?:ast(?:comm|log(?:in)?)|ess(?:echo|(?:fil|pip)e)|ftp(?:get)?|osetup|s(?:-F|b_release|cpu|mod|of|pci|usb)|wp-download|z(?:4c(?:at)?|c(?:at|mp)|diff|[e-f]?grep|less|m(?:a(?:dec|info)?|ore)))|m(?:a(?:ilq|ster\.passwd)|k(?:fifo|nod|temp)|locate|ysql(?:admin|dump(?:slow)?|hotcopy|show))|n(?:c(?:\.(?:openbsd|traditional)|at)|et(?:(?:c|st)at|kit-ftp|plan)|ohup|ping|stat)|onintr|p(?:dksh|erl5?|(?:ft|gre)p|hp(?:-cgi|[57])|igz|k(?:exec|ill)|(?:op|se)d|rint(?:env|f[\s\v&\)<>\|])|tar(?:diff|grep)?|wd\.db|ython[2-3])|r(?:(?:bas|ealpat)h|m(?:dir[\s\v&\)<>\|]|user)|nano|sync)|s(?:diff|e(?:ndmail|t(?:env|sid))|ftp|(?:h\.distri|pwd\.d)b|ocat|td(?:err|in|out)|udo|ysctl)|t(?:ailf|c(?:p(?:ing|traceroute)|sh)|elnet|imeout[\s\v&\)<>\|]|raceroute6?)|u(?:n(?:ame|lz(?:4|ma)|(?:pig|x)z|rar|zstd)|ser(?:(?:ad|mo)d|del))|vi(?:gr|pw)|w(?:get|hoami)|x(?:args|z(?:c(?:at|mp)|d(?:ec|iff)|[e-f]?grep|less|more))|z(?:c(?:at|mp)|diff|[e-f]?grep|ip(?:c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|less|more|run|std(?:(?:ca|m)t|grep|less)?))" \ + "id:932260,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Direct Unix Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + chain" + SecRule MATCHED_VAR "!@rx [0-9]\s*\'\s*[0-9]" \ + "t:none,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# [ Unix shell history invocation ] +# +# Detects Unix shell history invocations in any context. +# +# Example: +# GET /?rce=example.com +# GET /?rce=curl%20 +# GET /?rce=!-1!-2 +# +# Will execute `curl example.com`. We should be able to detect the '!-' sequence with a very low risk of false-positives since the sequence is very specific +# and does not allow for whitespaces in between. +# +# This rule has stricter siblings: +# * 932331 (PL3) +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx !-\d" \ + "id:932330,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix shell history invocation',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Unix shell snippets ] +# +# Detect some common sequences found in shell commands and scripts. +# +# Some commands which were restricted in earlier rules due to FP, +# have been added here with their full path, in order to catch some +# cases where the full path is sent. +# +# Rule relations: +# +# .932160 (base rule, PL1, unix shell commands with full path) +# ..932161 (stricter sibling, PL2, unix shell commands with full path in User-Agent and Referer request headers) +# +# This rule is also triggered by an Apache Struts Remote Code Execution exploit: +# [ Apache Struts vulnerability CVE-2017-9805 - Exploit tested: https://www.exploit-db.com/exploits/42627 ] +# +# This rule is also triggered by an Oracle WebLogic Remote Command Execution exploit: +# [ Oracle WebLogic vulnerability CVE-2017-10271 - Exploit tested: https://www.exploit-db.com/exploits/43458 ] + +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile unix-shell.data" \ + "id:932160,\ + phase:2,\ + block,\ + capture,\ + t:none,t:cmdLine,t:normalizePath,\ + msg:'Remote Command Execution: Unix Shell Code Found',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Shellshock vulnerability (CVE-2014-6271 and CVE-2014-7169) ] +# +# Detect exploitation of "Shellshock" GNU Bash RCE vulnerability. +# +# Based on ModSecurity rules created by Red Hat. +# Permission for use was granted by Martin Prpic +# +# https://access.redhat.com/articles/1212303 +# +SecRule REQUEST_HEADERS|REQUEST_LINE "@rx ^\(\s*\)\s+{" \ + "id:932170,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecode,\ + msg:'Remote Command Execution: Shellshock (CVE-2014-6271)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +SecRule ARGS_NAMES|ARGS|FILES_NAMES "@rx ^\(\s*\)\s+{" \ + "id:932171,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecode,t:urlDecodeUni,\ + msg:'Remote Command Execution: Shellshock (CVE-2014-6271)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Unix shell alias detection ] +# +# Detects Unix shell alias invocations in any context. +# +# Example: +# GET /?rce=alias%20a=b +# +# Shell aliasing can be performed to substitute anything in commands, escaping +# +# References: https://pubs.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap03.html#tag_03_10 : +# "In the shell command language, a word consisting solely of underscores, digits, and alphabetics +# from the portable character set and any of the following characters: '!', '%', ',', '@'." +# +# Implementations may allow other characters within alias names as an extension. +# +# Regular expression generated from regex-assembly/932175.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932175 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \ba[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?l[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?s\b[\s\v]+[!-\"%',0-9@-Z_a-z]+=[^\s\v]" \ + "id:932175,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix shell alias invocation',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# -=[ Restricted File Upload ]=- +# +# Detects attempts to upload a file with a forbidden filename. +# +# Many application contain Unrestricted File Upload vulnerabilities. +# https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload +# +# These might be abused to upload configuration files or other files +# that affect the behavior of the web server, possibly causing remote +# code execution. +# +SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X-File-Name \ + "@pmFromFile restricted-upload.data" \ + "id:932180,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Restricted File Upload Attempt',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Windows command injection ] +# +# This rule detects Windows shell command injections. +# If you are not running Windows, it is safe to disable this rule. +# +# New in CRSv4: The rules 932110 and 932115 were reorganized and renumbered to 932370 and 932380. +# The new rules target specific Windows binaries to simplify future updates of the command list. +# +# A command injection takes a form such as: +# +# foo.jpg&ver /r +# foo.jpg|ver /r +# +# The vulnerability exists when an application executes a shell command +# without proper input escaping/validation. +# +# To prevent false positives, we look for a 'starting sequence' that +# precedes a command in CMD syntax, such as: ; | & ` +# +# Anatomy of the regexp: +# +# 1. Starting tokens +# +# ; ;cmd +# \{ {cmd +# \| |cmd +# \|\| ||cmd +# & &cmd +# && &&cmd +# \n \ncmd +# \r \rcmd +# ` `cmd +# +# 2. Command prefixes +# +# ( (cmd) +# , ,cmd +# @ @cmd +# ' 'cmd' +# " "cmd" +# \s spacing+cmd +# +# 3. Paths +# +# [\w'\"\./]+/ /path/cmd +# [\x5c'\"\^]*\w[\x5c'\"\^]*:.*\x5c C:\Program Files\cmd +# [\^\.\w '\"/\x5c]*\x5c)?[\"\^]* \\net\share\dir\cmd +# +# 4. Quoting +# +# \" "cmd" +# \^ ^cmd +# +# 5. Extension/switches +# +# \.[\"\^]*\w+ cmd.com, cmd.exe, etc. +# /b cmd/h +# +# An effort is made to combat evasions by CMD syntax; for example, +# the following strings are valid: c^md, @cmd, "c"md. ModSecurity +# has a t:cmdLine transformation built-in to deal with some of these, +# but unfortunately, that transformation replaces ';' characters (so +# we cannot match on the start of a command) and '\' characters (so we +# have trouble matching paths). This makes the regexp more complex. +# +# This rule is case-insensitive. +# +# Regular expression generated from regex-assembly/932370.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932370 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:t[\"\^]*i[\"\^]*m[\"\^]*e|[\n\r;`\{]|\|\|?|&&?)[\s\v]*[\s\v\"'-\(,@]*(?:[\"'\.-9A-Z_a-z]+/|(?:[\"'\x5c\^]*[0-9A-Z_a-z][\"'\x5c\^]*:.*|[ \"'\.-9A-Z\x5c\^-_a-z]*)\x5c)?[\"\^]*(?:a[\"\^]*(?:c[\"\^]*c[\"\^]*c[\"\^]*h[\"\^]*e[\"\^]*c[\"\^]*k[\"\^]*c[\"\^]*o[\"\^]*n[\"\^]*s[\"\^]*o[\"\^]*l[\"\^]*e|d[\"\^]*(?:p[\"\^]*l[\"\^]*u[\"\^]*s|v[\"\^]*p[\"\^]*a[\"\^]*c[\"\^]*k)|(?:g[\"\^]*e[\"\^]*n[\"\^]*t[\"\^]*e[\"\^]*x[\"\^]*e[\"\^]*c[\"\^]*u[\"\^]*t[\"\^]*o|s[\"\^]*p[\"\^]*n[\"\^]*e[\"\^]*t[\"\^]*_[\"\^]*c[\"\^]*o[\"\^]*m[\"\^]*p[\"\^]*i[\"\^]*l[\"\^]*e)[\"\^]*r|p[\"\^]*p[\"\^]*(?:i[\"\^]*n[\"\^]*s[\"\^]*t[\"\^]*a[\"\^]*l[\"\^]*l[\"\^]*e[\"\^]*r|v[\"\^]*l[\"\^]*p)|t[\"\^]*(?:[\s\v,\.-/;-<>].*|b[\"\^]*r[\"\^]*o[\"\^]*k[\"\^]*e[\"\^]*r))|b[\"\^]*(?:a[\"\^]*s[\"\^]*h|g[\"\^]*i[\"\^]*n[\"\^]*f[\"\^]*o|i[\"\^]*t[\"\^]*s[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*i[\"\^]*n)|c[\"\^]*(?:d[\"\^]*b|e[\"\^]*r[\"\^]*t[\"\^]*(?:o[\"\^]*c|r[\"\^]*e[\"\^]*q|u[\"\^]*t[\"\^]*i[\"\^]*l)|l[\"\^]*_[\"\^]*(?:i[\"\^]*n[\"\^]*v[\"\^]*o[\"\^]*c[\"\^]*a[\"\^]*t[\"\^]*i[\"\^]*o[\"\^]*n|l[\"\^]*o[\"\^]*a[\"\^]*d[\"\^]*a[\"\^]*s[\"\^]*s[\"\^]*e[\"\^]*m[\"\^]*b[\"\^]*l[\"\^]*y|m[\"\^]*u[\"\^]*t[\"\^]*e[\"\^]*x[\"\^]*v[\"\^]*e[\"\^]*r[\"\^]*i[\"\^]*f[\"\^]*i[\"\^]*e[\"\^]*r[\"\^]*s)|m[\"\^]*(?:d(?:[\"\^]*(?:k[\"\^]*e[\"\^]*y|l[\"\^]*3[\"\^]*2))?|s[\"\^]*t[\"\^]*p)|o[\"\^]*(?:m[\"\^]*s[\"\^]*v[\"\^]*c[\"\^]*s|n[\"\^]*(?:f[\"\^]*i[\"\^]*g[\"\^]*s[\"\^]*e[\"\^]*c[\"\^]*u[\"\^]*r[\"\^]*i[\"\^]*t[\"\^]*y[\"\^]*p[\"\^]*o[\"\^]*l[\"\^]*i[\"\^]*c[\"\^]*y|h[\"\^]*o[\"\^]*s[\"\^]*t|t[\"\^]*r[\"\^]*o[\"\^]*l)|r[\"\^]*e[\"\^]*g[\"\^]*e[\"\^]*n)|r[\"\^]*e[\"\^]*a[\"\^]*t[\"\^]*e[\"\^]*d[\"\^]*u[\"\^]*m[\"\^]*p|s[\"\^]*(?:c(?:[\"\^]*r[\"\^]*i[\"\^]*p[\"\^]*t)?|i)|u[\"\^]*s[\"\^]*t[\"\^]*o[\"\^]*m[\"\^]*s[\"\^]*h[\"\^]*e[\"\^]*l[\"\^]*l[\"\^]*h[\"\^]*o[\"\^]*s[\"\^]*t)|d[\"\^]*(?:a[\"\^]*t[\"\^]*a[\"\^]*s[\"\^]*v[\"\^]*c[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l|e[\"\^]*(?:f[\"\^]*a[\"\^]*u[\"\^]*l[\"\^]*t[\"\^]*p[\"\^]*a[\"\^]*c[\"\^]*k|s[\"\^]*k(?:[\"\^]*t[\"\^]*o[\"\^]*p[\"\^]*i[\"\^]*m[\"\^]*g[\"\^]*d[\"\^]*o[\"\^]*w[\"\^]*n[\"\^]*l[\"\^]*d[\"\^]*r)?|v[\"\^]*(?:i[\"\^]*c[\"\^]*e[\"\^]*c[\"\^]*r[\"\^]*e[\"\^]*d[\"\^]*e[\"\^]*n[\"\^]*t[\"\^]*i[\"\^]*a[\"\^]*l[\"\^]*d[\"\^]*e[\"\^]*p[\"\^]*l[\"\^]*o[\"\^]*y[\"\^]*m[\"\^]*e[\"\^]*n[\"\^]*t|t[\"\^]*o[\"\^]*o[\"\^]*l[\"\^]*s[\"\^]*l[\"\^]*a[\"\^]*u[\"\^]*n[\"\^]*c[\"\^]*h[\"\^]*e[\"\^]*r))|f[\"\^]*s[\"\^]*(?:h[\"\^]*i[\"\^]*m|v[\"\^]*c)|i[\"\^]*(?:a[\"\^]*n[\"\^]*t[\"\^]*z|s[\"\^]*k[\"\^]*s[\"\^]*h[\"\^]*a[\"\^]*d[\"\^]*o[\"\^]*w)|n[\"\^]*(?:s[\"\^]*c[\"\^]*m[\"\^]*d|x)|o[\"\^]*t[\"\^]*n[\"\^]*e[\"\^]*t|u[\"\^]*m[\"\^]*p[\"\^]*6[\"\^]*4|x[\"\^]*c[\"\^]*a[\"\^]*p)|e[\"\^]*(?:s[\"\^]*e[\"\^]*n[\"\^]*t[\"\^]*u[\"\^]*t[\"\^]*l|v[\"\^]*e[\"\^]*n[\"\^]*t[\"\^]*v[\"\^]*w[\"\^]*r|x[\"\^]*(?:c[\"\^]*e[\"\^]*l|p[\"\^]*(?:a[\"\^]*n[\"\^]*d|l[\"\^]*o[\"\^]*r[\"\^]*e[\"\^]*r)|t[\"\^]*(?:e[\"\^]*x[\"\^]*p[\"\^]*o[\"\^]*r[\"\^]*t|r[\"\^]*a[\"\^]*c[\"\^]*3[\"\^]*2)))|f[\"\^]*(?:i[\"\^]*n[\"\^]*(?:d[\"\^]*s[\"\^]*t|g[\"\^]*e)[\"\^]*r|l[\"\^]*t[\"\^]*m[\"\^]*c|o[\"\^]*r[\"\^]*f[\"\^]*i[\"\^]*l[\"\^]*e[\"\^]*s|s[\"\^]*(?:i(?:[\"\^]*a[\"\^]*n[\"\^]*y[\"\^]*c[\"\^]*p[\"\^]*u)?|u[\"\^]*t[\"\^]*i[\"\^]*l)|t[\"\^]*p)|g[\"\^]*(?:f[\"\^]*x[\"\^]*d[\"\^]*o[\"\^]*w[\"\^]*n[\"\^]*l[\"\^]*o[\"\^]*a[\"\^]*d[\"\^]*w[\"\^]*r[\"\^]*a[\"\^]*p[\"\^]*p[\"\^]*e[\"\^]*r|p[\"\^]*s[\"\^]*c[\"\^]*r[\"\^]*i[\"\^]*p[\"\^]*t)|h[\"\^]*h|i[\"\^]*(?:e[\"\^]*(?:4[\"\^]*u[\"\^]*i[\"\^]*n[\"\^]*i[\"\^]*t|a[\"\^]*d[\"\^]*v[\"\^]*p[\"\^]*a[\"\^]*c[\"\^]*k|e[\"\^]*x[\"\^]*e[\"\^]*c|f[\"\^]*r[\"\^]*a[\"\^]*m[\"\^]*e)|l[\"\^]*a[\"\^]*s[\"\^]*m|m[\"\^]*e[\"\^]*w[\"\^]*d[\"\^]*b[\"\^]*l[\"\^]*d|n[\"\^]*(?:f[\"\^]*d[\"\^]*e[\"\^]*f[\"\^]*a[\"\^]*u[\"\^]*l[\"\^]*t[\"\^]*i[\"\^]*n[\"\^]*s[\"\^]*t[\"\^]*a[\"\^]*l|s[\"\^]*t[\"\^]*a[\"\^]*l[\"\^]*l[\"\^]*u[\"\^]*t[\"\^]*i)[\"\^]*l)|j[\"\^]*s[\"\^]*c|l[\"\^]*(?:a[\"\^]*u[\"\^]*n[\"\^]*c[\"\^]*h[\"\^]*-[\"\^]*v[\"\^]*s[\"\^]*d[\"\^]*e[\"\^]*v[\"\^]*s[\"\^]*h[\"\^]*e[\"\^]*l[\"\^]*l|d[\"\^]*i[\"\^]*f[\"\^]*d[\"\^]*e)|m[\"\^]*(?:a[\"\^]*(?:k[\"\^]*e[\"\^]*c[\"\^]*a[\"\^]*b|n[\"\^]*a[\"\^]*g[\"\^]*e[\"\^]*-[\"\^]*b[\"\^]*d[\"\^]*e|v[\"\^]*i[\"\^]*n[\"\^]*j[\"\^]*e[\"\^]*c[\"\^]*t)|f[\"\^]*t[\"\^]*r[\"\^]*a[\"\^]*c[\"\^]*e|i[\"\^]*c[\"\^]*r[\"\^]*o[\"\^]*s[\"\^]*o[\"\^]*f[\"\^]*t|m[\"\^]*c|p[\"\^]*c[\"\^]*m[\"\^]*d[\"\^]*r[\"\^]*u[\"\^]*n|s[\"\^]*(?:(?:b[\"\^]*u[\"\^]*i[\"\^]*l|o[\"\^]*h[\"\^]*t[\"\^]*m[\"\^]*e)[\"\^]*d|c[\"\^]*o[\"\^]*n[\"\^]*f[\"\^]*i[\"\^]*g|d[\"\^]*(?:e[\"\^]*p[\"\^]*l[\"\^]*o[\"\^]*y|t)|h[\"\^]*t[\"\^]*(?:a|m[\"\^]*l)|i[\"\^]*e[\"\^]*x[\"\^]*e[\"\^]*c|p[\"\^]*u[\"\^]*b|x[\"\^]*s[\"\^]*l))|n[\"\^]*(?:e[\"\^]*t[\"\^]*s[\"\^]*h|t[\"\^]*d[\"\^]*s[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l)|o[\"\^]*(?:d[\"\^]*b[\"\^]*c[\"\^]*c[\"\^]*o[\"\^]*n[\"\^]*f|f[\"\^]*f[\"\^]*l[\"\^]*i[\"\^]*n[\"\^]*e[\"\^]*s[\"\^]*c[\"\^]*a[\"\^]*n[\"\^]*n[\"\^]*e[\"\^]*r[\"\^]*s[\"\^]*h[\"\^]*e[\"\^]*l[\"\^]*l|n[\"\^]*e[\"\^]*d[\"\^]*r[\"\^]*i[\"\^]*v[\"\^]*e[\"\^]*s[\"\^]*t[\"\^]*a[\"\^]*n[\"\^]*d[\"\^]*a[\"\^]*l[\"\^]*o[\"\^]*n[\"\^]*e[\"\^]*u[\"\^]*p[\"\^]*d[\"\^]*a[\"\^]*t[\"\^]*e[\"\^]*r|p[\"\^]*e[\"\^]*n[\"\^]*c[\"\^]*o[\"\^]*n[\"\^]*s[\"\^]*o[\"\^]*l[\"\^]*e)|p[\"\^]*(?:c[\"\^]*(?:a[\"\^]*l[\"\^]*u[\"\^]*a|w[\"\^]*(?:r[\"\^]*u[\"\^]*n|u[\"\^]*t[\"\^]*l))|(?:e[\"\^]*s[\"\^]*t[\"\^]*e|s)[\"\^]*r|(?:k[\"\^]*t[\"\^]*m[\"\^]*o|u[\"\^]*b[\"\^]*p[\"\^]*r)[\"\^]*n|n[\"\^]*p[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l|o[\"\^]*w[\"\^]*e[\"\^]*r[\"\^]*p[\"\^]*n[\"\^]*t|r[\"\^]*(?:e[\"\^]*s[\"\^]*e[\"\^]*n[\"\^]*t[\"\^]*a[\"\^]*t[\"\^]*i[\"\^]*o[\"\^]*n[\"\^]*h[\"\^]*o[\"\^]*s[\"\^]*t|i[\"\^]*n[\"\^]*t(?:[\"\^]*b[\"\^]*r[\"\^]*m)?|o[\"\^]*(?:c[\"\^]*d[\"\^]*u[\"\^]*m[\"\^]*p|t[\"\^]*o[\"\^]*c[\"\^]*o[\"\^]*l[\"\^]*h[\"\^]*a[\"\^]*n[\"\^]*d[\"\^]*l[\"\^]*e[\"\^]*r)))|r[\"\^]*(?:a[\"\^]*s[\"\^]*a[\"\^]*u[\"\^]*t[\"\^]*o[\"\^]*u|c[\"\^]*s[\"\^]*i|(?:d[\"\^]*r[\"\^]*l[\"\^]*e[\"\^]*a[\"\^]*k[\"\^]*d[\"\^]*i[\"\^]*a|p[\"\^]*c[\"\^]*p[\"\^]*i[\"\^]*n)[\"\^]*g|e[\"\^]*(?:g(?:[\"\^]*(?:a[\"\^]*s[\"\^]*m|e[\"\^]*d[\"\^]*i[\"\^]*t|i[\"\^]*(?:n[\"\^]*i|s[\"\^]*t[\"\^]*e[\"\^]*r[\"\^]*-[\"\^]*c[\"\^]*i[\"\^]*m[\"\^]*p[\"\^]*r[\"\^]*o[\"\^]*v[\"\^]*i[\"\^]*d[\"\^]*e[\"\^]*r)|s[\"\^]*v[\"\^]*(?:c[\"\^]*s|r[\"\^]*3[\"\^]*2)))?|(?:m[\"\^]*o[\"\^]*t|p[\"\^]*l[\"\^]*a[\"\^]*c)[\"\^]*e)|u[\"\^]*n[\"\^]*(?:d[\"\^]*l[\"\^]*l[\"\^]*3[\"\^]*2|(?:e[\"\^]*x[\"\^]*e|s[\"\^]*c[\"\^]*r[\"\^]*i[\"\^]*p[\"\^]*t)[\"\^]*h[\"\^]*e[\"\^]*l[\"\^]*p[\"\^]*e[\"\^]*r|o[\"\^]*n[\"\^]*c[\"\^]*e))|s[\"\^]*(?:c[\"\^]*(?:[\s\v,\.-/;-<>].*|h[\"\^]*t[\"\^]*a[\"\^]*s[\"\^]*k[\"\^]*s|r[\"\^]*i[\"\^]*p[\"\^]*t[\"\^]*r[\"\^]*u[\"\^]*n[\"\^]*n[\"\^]*e[\"\^]*r)|e[\"\^]*t[\"\^]*(?:r[\"\^]*e[\"\^]*s|t[\"\^]*i[\"\^]*n[\"\^]*g[\"\^]*s[\"\^]*y[\"\^]*n[\"\^]*c[\"\^]*h[\"\^]*o[\"\^]*s[\"\^]*t|u[\"\^]*p[\"\^]*a[\"\^]*p[\"\^]*i)|h[\"\^]*(?:d[\"\^]*o[\"\^]*c[\"\^]*v[\"\^]*w|e[\"\^]*l[\"\^]*l[\"\^]*3[\"\^]*2)|q[\"\^]*(?:l[\"\^]*(?:d[\"\^]*u[\"\^]*m[\"\^]*p[\"\^]*e[\"\^]*r|(?:t[\"\^]*o[\"\^]*o[\"\^]*l[\"\^]*s[\"\^]*)?p[\"\^]*s)|u[\"\^]*i[\"\^]*r[\"\^]*r[\"\^]*e[\"\^]*l)|s[\"\^]*h|t[\"\^]*o[\"\^]*r[\"\^]*d[\"\^]*i[\"\^]*a[\"\^]*g|y[\"\^]*(?:n[\"\^]*c[\"\^]*a[\"\^]*p[\"\^]*p[\"\^]*v[\"\^]*p[\"\^]*u[\"\^]*b[\"\^]*l[\"\^]*i[\"\^]*s[\"\^]*h[\"\^]*i[\"\^]*n[\"\^]*g[\"\^]*s[\"\^]*e[\"\^]*r[\"\^]*v[\"\^]*e[\"\^]*r|s[\"\^]*s[\"\^]*e[\"\^]*t[\"\^]*u[\"\^]*p))|t[\"\^]*(?:e[\"\^]*[\s\v,\.-/;-<>].*|r[\"\^]*a[\"\^]*c[\"\^]*k[\"\^]*e[\"\^]*r|t[\"\^]*(?:d[\"\^]*i[\"\^]*n[\"\^]*j[\"\^]*e[\"\^]*c[\"\^]*t|t[\"\^]*r[\"\^]*a[\"\^]*c[\"\^]*e[\"\^]*r))|u[\"\^]*(?:n[\"\^]*r[\"\^]*e[\"\^]*g[\"\^]*m[\"\^]*p[\"\^]*2|p[\"\^]*d[\"\^]*a[\"\^]*t[\"\^]*e|r[\"\^]*l|t[\"\^]*i[\"\^]*l[\"\^]*i[\"\^]*t[\"\^]*y[\"\^]*f[\"\^]*u[\"\^]*n[\"\^]*c[\"\^]*t[\"\^]*i[\"\^]*o[\"\^]*n[\"\^]*s)|v[\"\^]*(?:b[\"\^]*c|e[\"\^]*r[\"\^]*c[\"\^]*l[\"\^]*s[\"\^]*i[\"\^]*d|i[\"\^]*s[\"\^]*u[\"\^]*a[\"\^]*l[\"\^]*u[\"\^]*i[\"\^]*a[\"\^]*v[\"\^]*e[\"\^]*r[\"\^]*i[\"\^]*f[\"\^]*y[\"\^]*n[\"\^]*a[\"\^]*t[\"\^]*i[\"\^]*v[\"\^]*e|s[\"\^]*(?:i[\"\^]*i[\"\^]*s[\"\^]*e[\"\^]*x[\"\^]*e[\"\^]*l[\"\^]*a[\"\^]*u[\"\^]*n[\"\^]*c[\"\^]*h|j[\"\^]*i[\"\^]*t[\"\^]*d[\"\^]*e[\"\^]*b[\"\^]*u[\"\^]*g[\"\^]*g)[\"\^]*e[\"\^]*r)|w[\"\^]*(?:a[\"\^]*b|(?:f|m[\"\^]*i)[\"\^]*c|i[\"\^]*n[\"\^]*(?:g[\"\^]*e[\"\^]*t|r[\"\^]*m|w[\"\^]*o[\"\^]*r[\"\^]*d)|l[\"\^]*r[\"\^]*m[\"\^]*d[\"\^]*r|o[\"\^]*r[\"\^]*k[\"\^]*f[\"\^]*o[\"\^]*l[\"\^]*d[\"\^]*e[\"\^]*r[\"\^]*s|s[\"\^]*(?:(?:c[\"\^]*r[\"\^]*i[\"\^]*p|r[\"\^]*e[\"\^]*s[\"\^]*e)[\"\^]*t|l)|t[\"\^]*[\s\v,\.-/;-<>].*|u[\"\^]*a[\"\^]*u[\"\^]*c[\"\^]*l[\"\^]*t)|x[\"\^]*w[\"\^]*i[\"\^]*z[\"\^]*a[\"\^]*r[\"\^]*d|z[\"\^]*i[\"\^]*p[\"\^]*f[\"\^]*l[\"\^]*d[\"\^]*r)(?:\.[\"\^]*[0-9A-Z_a-z]+)?\b" \ + "id:932370,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Windows Command Injection',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-windows',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# This rule detects Windows shell command injections. +# If you are not running Windows, it is safe to disable this rule. +# +# New in CRSv4: The rules 932110 and 932115 were reorganized and renumbered to 932370 and 932380. +# The new rules target specific Windows binaries to simplify future updates of the command list. +# +# See rule 932370 above for further explanation. +# +# This rule is case-insensitive. +# +# Regular expression generated from regex-assembly/932380.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932380 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:t[\"\^]*i[\"\^]*m[\"\^]*e|[\n\r;`\{]|\|\|?|&&?)[\s\v]*[\s\v\"'-\(,@]*(?:[\"'\.-9A-Z_a-z]+/|(?:[\"'\x5c\^]*[0-9A-Z_a-z][\"'\x5c\^]*:.*|[ \"'\.-9A-Z\x5c\^-_a-z]*)\x5c)?[\"\^]*(?:a[\"\^]*(?:s[\"\^]*s[\"\^]*o[\"\^]*c|t[\"\^]*(?:m[\"\^]*a[\"\^]*d[\"\^]*m|t[\"\^]*r[\"\^]*i[\"\^]*b)|u[\"\^]*(?:d[\"\^]*i[\"\^]*t[\"\^]*p[\"\^]*o[\"\^]*l|t[\"\^]*o[\"\^]*(?:c[\"\^]*(?:h[\"\^]*k|o[\"\^]*n[\"\^]*v)|(?:f[\"\^]*m|m[\"\^]*o[\"\^]*u[\"\^]*n)[\"\^]*t)))|b[\"\^]*(?:c[\"\^]*d[\"\^]*(?:b[\"\^]*o[\"\^]*o|e[\"\^]*d[\"\^]*i)[\"\^]*t|(?:d[\"\^]*e[\"\^]*h[\"\^]*d|o[\"\^]*o[\"\^]*t)[\"\^]*c[\"\^]*f[\"\^]*g|i[\"\^]*t[\"\^]*s[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*i[\"\^]*n)|c[\"\^]*(?:a[\"\^]*c[\"\^]*l[\"\^]*s|e[\"\^]*r[\"\^]*t[\"\^]*(?:r[\"\^]*e[\"\^]*q|u[\"\^]*t[\"\^]*i[\"\^]*l)|h[\"\^]*(?:c[\"\^]*p|d[\"\^]*i[\"\^]*r|g[\"\^]*(?:l[\"\^]*o[\"\^]*g[\"\^]*o[\"\^]*n|p[\"\^]*o[\"\^]*r[\"\^]*t|u[\"\^]*s[\"\^]*r)|k[\"\^]*(?:d[\"\^]*s[\"\^]*k|n[\"\^]*t[\"\^]*f[\"\^]*s))|l[\"\^]*e[\"\^]*a[\"\^]*n[\"\^]*m[\"\^]*g[\"\^]*r|m[\"\^]*(?:d(?:[\"\^]*k[\"\^]*e[\"\^]*y)?|s[\"\^]*t[\"\^]*p)|s[\"\^]*c[\"\^]*r[\"\^]*i[\"\^]*p[\"\^]*t)|d[\"\^]*(?:c[\"\^]*(?:d[\"\^]*i[\"\^]*a[\"\^]*g|g[\"\^]*p[\"\^]*o[\"\^]*f[\"\^]*i[\"\^]*x)|e[\"\^]*(?:f[\"\^]*r[\"\^]*a[\"\^]*g|l)|f[\"\^]*s[\"\^]*(?:d[\"\^]*i[\"\^]*a|r[\"\^]*m[\"\^]*i)[\"\^]*g|i[\"\^]*(?:a[\"\^]*n[\"\^]*t[\"\^]*z|r|s[\"\^]*(?:k[\"\^]*(?:c[\"\^]*o[\"\^]*(?:m[\"\^]*p|p[\"\^]*y)|p[\"\^]*(?:a[\"\^]*r[\"\^]*t|e[\"\^]*r[\"\^]*f)|r[\"\^]*a[\"\^]*i[\"\^]*d|s[\"\^]*h[\"\^]*a[\"\^]*d[\"\^]*o[\"\^]*w)|p[\"\^]*d[\"\^]*i[\"\^]*a[\"\^]*g))|n[\"\^]*s[\"\^]*c[\"\^]*m[\"\^]*d|(?:o[\"\^]*s[\"\^]*k[\"\^]*e|r[\"\^]*i[\"\^]*v[\"\^]*e[\"\^]*r[\"\^]*q[\"\^]*u[\"\^]*e[\"\^]*r)[\"\^]*y)|e[\"\^]*(?:n[\"\^]*d[\"\^]*l[\"\^]*o[\"\^]*c[\"\^]*a[\"\^]*l|v[\"\^]*e[\"\^]*n[\"\^]*t[\"\^]*c[\"\^]*r[\"\^]*e[\"\^]*a[\"\^]*t[\"\^]*e)|E[\"\^]*v[\"\^]*n[\"\^]*t[\"\^]*c[\"\^]*m[\"\^]*d|f[\"\^]*(?:c|i[\"\^]*(?:l[\"\^]*e[\"\^]*s[\"\^]*y[\"\^]*s[\"\^]*t[\"\^]*e[\"\^]*m[\"\^]*s|n[\"\^]*d[\"\^]*s[\"\^]*t[\"\^]*r)|l[\"\^]*a[\"\^]*t[\"\^]*t[\"\^]*e[\"\^]*m[\"\^]*p|o[\"\^]*r(?:[\"\^]*f[\"\^]*i[\"\^]*l[\"\^]*e[\"\^]*s)?|r[\"\^]*e[\"\^]*e[\"\^]*d[\"\^]*i[\"\^]*s[\"\^]*k|s[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l|(?:t[\"\^]*y[\"\^]*p|v[\"\^]*e[\"\^]*u[\"\^]*p[\"\^]*d[\"\^]*a[\"\^]*t)[\"\^]*e)|g[\"\^]*(?:e[\"\^]*t[\"\^]*(?:m[\"\^]*a[\"\^]*c|t[\"\^]*y[\"\^]*p[\"\^]*e)|o[\"\^]*t[\"\^]*o|p[\"\^]*(?:f[\"\^]*i[\"\^]*x[\"\^]*u[\"\^]*p|(?:r[\"\^]*e[\"\^]*s[\"\^]*u[\"\^]*l[\"\^]*)?t|u[\"\^]*p[\"\^]*d[\"\^]*a[\"\^]*t[\"\^]*e)|r[\"\^]*a[\"\^]*f[\"\^]*t[\"\^]*a[\"\^]*b[\"\^]*l)|h[\"\^]*(?:e[\"\^]*l[\"\^]*p[\"\^]*c[\"\^]*t[\"\^]*r|o[\"\^]*s[\"\^]*t[\"\^]*n[\"\^]*a[\"\^]*m[\"\^]*e)|i[\"\^]*(?:c[\"\^]*a[\"\^]*c[\"\^]*l[\"\^]*s|f|p[\"\^]*(?:c[\"\^]*o[\"\^]*n[\"\^]*f[\"\^]*i[\"\^]*g|x[\"\^]*r[\"\^]*o[\"\^]*u[\"\^]*t[\"\^]*e)|r[\"\^]*f[\"\^]*t[\"\^]*p)|j[\"\^]*e[\"\^]*t[\"\^]*p[\"\^]*a[\"\^]*c[\"\^]*k|k[\"\^]*(?:l[\"\^]*i[\"\^]*s[\"\^]*t|s[\"\^]*e[\"\^]*t[\"\^]*u[\"\^]*p|t[\"\^]*(?:m[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l|p[\"\^]*a[\"\^]*s[\"\^]*s))|l[\"\^]*(?:o[\"\^]*(?:d[\"\^]*c[\"\^]*t[\"\^]*r|g[\"\^]*(?:m[\"\^]*a[\"\^]*n|o[\"\^]*f[\"\^]*f))|p[\"\^]*[q-r])|m[\"\^]*(?:a[\"\^]*(?:c[\"\^]*f[\"\^]*i[\"\^]*l[\"\^]*e|k[\"\^]*e[\"\^]*c[\"\^]*a[\"\^]*b|p[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*i[\"\^]*n)|k[\"\^]*(?:d[\"\^]*i[\"\^]*r|l[\"\^]*i[\"\^]*n[\"\^]*k)|m[\"\^]*c|o[\"\^]*u[\"\^]*n[\"\^]*t[\"\^]*v[\"\^]*o[\"\^]*l|q[\"\^]*(?:b[\"\^]*k[\"\^]*u[\"\^]*p|(?:t[\"\^]*g[\"\^]*)?s[\"\^]*v[\"\^]*c)|s[\"\^]*(?:d[\"\^]*t|i[\"\^]*(?:e[\"\^]*x[\"\^]*e[\"\^]*c|n[\"\^]*f[\"\^]*o[\"\^]*3[\"\^]*2)|t[\"\^]*s[\"\^]*c))|n[\"\^]*(?:b[\"\^]*t[\"\^]*s[\"\^]*t[\"\^]*a[\"\^]*t|e[\"\^]*t[\"\^]*(?:c[\"\^]*f[\"\^]*g|d[\"\^]*o[\"\^]*m|s[\"\^]*(?:h|t[\"\^]*a[\"\^]*t))|f[\"\^]*s[\"\^]*(?:a[\"\^]*d[\"\^]*m[\"\^]*i[\"\^]*n|s[\"\^]*(?:h[\"\^]*a[\"\^]*r[\"\^]*e|t[\"\^]*a[\"\^]*t))|l[\"\^]*(?:b[\"\^]*m[\"\^]*g[\"\^]*r|t[\"\^]*e[\"\^]*s[\"\^]*t)|s[\"\^]*l[\"\^]*o[\"\^]*o[\"\^]*k[\"\^]*u[\"\^]*p|t[\"\^]*(?:b[\"\^]*a[\"\^]*c[\"\^]*k[\"\^]*u[\"\^]*p|c[\"\^]*m[\"\^]*d[\"\^]*p[\"\^]*r[\"\^]*o[\"\^]*m[\"\^]*p[\"\^]*t|f[\"\^]*r[\"\^]*s[\"\^]*u[\"\^]*t[\"\^]*l))|o[\"\^]*(?:f[\"\^]*f[\"\^]*l[\"\^]*i[\"\^]*n[\"\^]*e|p[\"\^]*e[\"\^]*n[\"\^]*f[\"\^]*i[\"\^]*l[\"\^]*e[\"\^]*s)|p[\"\^]*(?:a[\"\^]*(?:g[\"\^]*e[\"\^]*f[\"\^]*i[\"\^]*l[\"\^]*e[\"\^]*c[\"\^]*o[\"\^]*n[\"\^]*f[\"\^]*i|t[\"\^]*h[\"\^]*p[\"\^]*i[\"\^]*n)[\"\^]*g|(?:b[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*i|k[\"\^]*t[\"\^]*m[\"\^]*o)[\"\^]*n|e[\"\^]*(?:n[\"\^]*t[\"\^]*n[\"\^]*t|r[\"\^]*f[\"\^]*m[\"\^]*o[\"\^]*n)|n[\"\^]*p[\"\^]*u[\"\^]*(?:n[\"\^]*a[\"\^]*t[\"\^]*t[\"\^]*e[\"\^]*n[\"\^]*d|t[\"\^]*i[\"\^]*l)|o[\"\^]*(?:p[\"\^]*d|w[\"\^]*e[\"\^]*r[\"\^]*s[\"\^]*h[\"\^]*e[\"\^]*l[\"\^]*l)|r[\"\^]*n[\"\^]*(?:c[\"\^]*n[\"\^]*f[\"\^]*g|(?:d[\"\^]*r[\"\^]*v|m[\"\^]*n[\"\^]*g)[\"\^]*r|j[\"\^]*o[\"\^]*b[\"\^]*s|p[\"\^]*o[\"\^]*r[\"\^]*t|q[\"\^]*c[\"\^]*t[\"\^]*l)|u[\"\^]*(?:b[\"\^]*p[\"\^]*r[\"\^]*n|s[\"\^]*h[\"\^]*(?:d|p[\"\^]*r[\"\^]*i[\"\^]*n[\"\^]*t[\"\^]*e[\"\^]*r[\"\^]*c[\"\^]*o[\"\^]*n[\"\^]*n[\"\^]*e[\"\^]*c[\"\^]*t[\"\^]*i[\"\^]*o[\"\^]*n[\"\^]*s))|w[\"\^]*(?:l[\"\^]*a[\"\^]*u[\"\^]*n[\"\^]*c[\"\^]*h[\"\^]*e[\"\^]*r|s[\"\^]*h))|q[\"\^]*(?:a[\"\^]*p[\"\^]*p[\"\^]*s[\"\^]*r[\"\^]*v|p[\"\^]*r[\"\^]*o[\"\^]*c[\"\^]*e[\"\^]*s[\"\^]*s|u[\"\^]*s[\"\^]*e[\"\^]*r|w[\"\^]*i[\"\^]*n[\"\^]*s[\"\^]*t[\"\^]*a)|r[\"\^]*(?:d(?:[\"\^]*p[\"\^]*s[\"\^]*i[\"\^]*g[\"\^]*n)?|e[\"\^]*(?:f[\"\^]*s[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l|g(?:[\"\^]*(?:i[\"\^]*n[\"\^]*i|s[\"\^]*v[\"\^]*r[\"\^]*3[\"\^]*2))?|l[\"\^]*o[\"\^]*g|(?:(?:p[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*i|s[\"\^]*c[\"\^]*a)[\"\^]*)?n|x[\"\^]*e[\"\^]*c)|i[\"\^]*s[\"\^]*e[\"\^]*t[\"\^]*u[\"\^]*p|m[\"\^]*d[\"\^]*i[\"\^]*r|o[\"\^]*b[\"\^]*o[\"\^]*c[\"\^]*o[\"\^]*p[\"\^]*y|p[\"\^]*c[\"\^]*(?:i[\"\^]*n[\"\^]*f[\"\^]*o|p[\"\^]*i[\"\^]*n[\"\^]*g)|s[\"\^]*h|u[\"\^]*n[\"\^]*d[\"\^]*l[\"\^]*l[\"\^]*3[\"\^]*2|w[\"\^]*i[\"\^]*n[\"\^]*s[\"\^]*t[\"\^]*a)|s[\"\^]*(?:a[\"\^]*n|c[\"\^]*(?:h[\"\^]*t[\"\^]*a[\"\^]*s[\"\^]*k[\"\^]*s|w[\"\^]*c[\"\^]*m[\"\^]*d)|e[\"\^]*(?:c[\"\^]*e[\"\^]*d[\"\^]*i[\"\^]*t|r[\"\^]*v[\"\^]*e[\"\^]*r[\"\^]*(?:(?:c[\"\^]*e[\"\^]*i[\"\^]*p|w[\"\^]*e[\"\^]*r)[\"\^]*o[\"\^]*p[\"\^]*t[\"\^]*i[\"\^]*n|m[\"\^]*a[\"\^]*n[\"\^]*a[\"\^]*g[\"\^]*e[\"\^]*r[\"\^]*c[\"\^]*m[\"\^]*d)|t[\"\^]*x)|f[\"\^]*c|(?:h[\"\^]*o[\"\^]*w[\"\^]*m[\"\^]*o[\"\^]*u[\"\^]*n|u[\"\^]*b[\"\^]*s)[\"\^]*t|x[\"\^]*s[\"\^]*t[\"\^]*r[\"\^]*a[\"\^]*c[\"\^]*e|y[\"\^]*s[\"\^]*(?:o[\"\^]*c[\"\^]*m[\"\^]*g[\"\^]*r|t[\"\^]*e[\"\^]*m[\"\^]*i[\"\^]*n[\"\^]*f[\"\^]*o))|t[\"\^]*(?:a[\"\^]*(?:k[\"\^]*e[\"\^]*o[\"\^]*w[\"\^]*n|p[\"\^]*i[\"\^]*c[\"\^]*f[\"\^]*g|s[\"\^]*k[\"\^]*(?:k[\"\^]*i[\"\^]*l[\"\^]*l|l[\"\^]*i[\"\^]*s[\"\^]*t))|(?:c[\"\^]*m[\"\^]*s[\"\^]*e[\"\^]*t[\"\^]*u|f[\"\^]*t)[\"\^]*p|(?:(?:e[\"\^]*l[\"\^]*n[\"\^]*e|i[\"\^]*m[\"\^]*e[\"\^]*o[\"\^]*u)[\"\^]*|r[\"\^]*a[\"\^]*c[\"\^]*e[\"\^]*r[\"\^]*(?:p[\"\^]*)?)t|l[\"\^]*n[\"\^]*t[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*n|p[\"\^]*m[\"\^]*(?:t[\"\^]*o[\"\^]*o[\"\^]*l|v[\"\^]*s[\"\^]*c[\"\^]*m[\"\^]*g[\"\^]*r)|s[\"\^]*(?:(?:d[\"\^]*i[\"\^]*s[\"\^]*)?c[\"\^]*o[\"\^]*n|e[\"\^]*c[\"\^]*i[\"\^]*m[\"\^]*p|k[\"\^]*i[\"\^]*l[\"\^]*l|p[\"\^]*r[\"\^]*o[\"\^]*f)|y[\"\^]*p[\"\^]*e[\"\^]*p[\"\^]*e[\"\^]*r[\"\^]*f|z[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l)|u[\"\^]*n[\"\^]*(?:e[\"\^]*x[\"\^]*p[\"\^]*o[\"\^]*s[\"\^]*e|i[\"\^]*q[\"\^]*u[\"\^]*e[\"\^]*i[\"\^]*d|l[\"\^]*o[\"\^]*d[\"\^]*c[\"\^]*t[\"\^]*r)|v[\"\^]*(?:o[\"\^]*l|s[\"\^]*s[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*i[\"\^]*n)|w[\"\^]*(?:a[\"\^]*i[\"\^]*t[\"\^]*f[\"\^]*o[\"\^]*r|b[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*i[\"\^]*n|(?:d[\"\^]*s|e[\"\^]*(?:c|v[\"\^]*t))[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l|h[\"\^]*(?:e[\"\^]*r[\"\^]*e|o[\"\^]*a[\"\^]*m[\"\^]*i)|i[\"\^]*n[\"\^]*(?:n[\"\^]*t(?:[\"\^]*3[\"\^]*2)?|r[\"\^]*s)|m[\"\^]*i[\"\^]*c|s[\"\^]*c[\"\^]*r[\"\^]*i[\"\^]*p[\"\^]*t)|x[\"\^]*c[\"\^]*o[\"\^]*p[\"\^]*y)(?:\.[\"\^]*[0-9A-Z_a-z]+)?\b" \ + "id:932380,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Windows Command Injection',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-windows',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:932013,phase:1,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:932014,phase:2,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + +# [ Unix command injection ] +# +# This rule targets pefix + the source command (dot character) at PL2. +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932231.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932231 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\n\r;`\{]|\|\|?|&&?|\$(?:\(\(?|\{)|[<>]\(|\([\s\v]*\))[\s\v]*(?:[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*\.[\s\v].*\b" \ + "id:932231,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix Command Injection',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This is a stricter sibling of rule 932130. +# +# It applies the same regular expression to the +# User-Agent and Referer HTTP headers. +# +# Unlike the sibling rule, this rule runs in phase 1. +# +SecRule REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer "@rx (?:\$(?:\((?:\(.*\)|.*)\)|\{.*})|[<>]\(.*\)|\[!?.+\])" \ + "id:932131,\ + phase:1,\ + block,\ + capture,\ + t:none,t:cmdLine,\ + msg:'Remote Command Execution: Unix Shell Expression Found',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ Rule 932200 ]=- +# +# Block RCE Bypass using different techniques: +# - uninitialized variables (https://www.secjuice.com/web-application-firewall-waf-evasion/) +# - string concatenations (https://medium.com/secjuice/web-application-firewall-waf-evasion-techniques-2-125995f3e7b0) +# - globbing patterns (https://medium.com/secjuice/waf-evasion-techniques-718026d693d8) +# +# Examples: +# - foo;cat$u+/etc$u/passwd +# - bar;cd+/etc;/bin$u/ca*+passwd +# - foo;ca\t+/et\c/pa\s\swd +# - foo;c'at'+/etc/pa's'swd +# - foo;c$@at+/et$@c/pas$@swd +# - foo;c$!at+/et$!c/pas$!swd +# - foo;c$*at+/et$*c/pas$*swd +# - foo;c$?at+/et$?c/pas$?swd +# - foo;c$-at+/et$-c/pas$-swd +# - foo;c$_at+/et$_c/pas$_swd +# - foo;c$$at+/et$$c/pas$$swd +# +# Regex notes: https://regex101.com/r/V6wrCO/1 +# +# Regular expression generated from regex-assembly/932200.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932200 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@rx ['\*\?\x5c`][^\n/]+/|/[^/]+?['\*\?\x5c`]|\$[!#-\$\(\*\-0-9\?-\[_a-\{]" \ + "id:932200,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,t:urlDecodeUni,\ + msg:'RCE Bypass Technique',\ + logdata:'Matched Data: %{TX.0} found within %{TX.932200_MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.932200_matched_var_name=%{matched_var_name}',\ + chain" + SecRule MATCHED_VAR "@rx /" \ + "t:none,t:urlDecodeUni,\ + chain" + SecRule MATCHED_VAR "@rx \s" \ + "t:none,t:urlDecodeUni,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ Rule 932205 ]=- +# +# Sibling of 932200 targeting the Referer header. URLs cause false positives in rule 932200 +# and must be handled with additional checks. +# +# Regular expression generated from regex-assembly/932205.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932205 +# +SecRule REQUEST_HEADERS:Referer "@rx ^[^\.]+\.[^;\?]+[;\?](.*(['\*\?\x5c`][^\n/]+/|/[^/]+?['\*\?\x5c`]|\$[!#-\$\(\*\-0-9\?-\[_a-\{]))" \ + "id:932205,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,t:urlDecodeUni,\ + msg:'RCE Bypass Technique',\ + logdata:'Matched Data: %{TX.2} found within %{TX.932205_MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.932205_matched_var_name=%{matched_var_name}',\ + chain" + SecRule TX:1 "@rx /" \ + "t:none,t:urlDecodeUni,\ + chain" + SecRule TX:1 "@rx \s" \ + "t:none,t:urlDecodeUni,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ Rule 932206 ]=- +# +# Sibling of 932200 targeting the Referer header. URLs cause false positives in rule 932200 +# and must be handled with additional checks. +# +# Regular expression generated from regex-assembly/932206.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932206 +# +SecRule REQUEST_HEADERS:Referer "@rx ^[^\.]*?(?:['\*\?\x5c`][^\n/]+/|/[^/]+?['\*\?\x5c`]|\$[!#-\$\(\*\-0-9\?-\[_a-\{])" \ + "id:932206,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,t:urlDecodeUni,\ + msg:'RCE Bypass Technique',\ + logdata:'Matched Data: %{TX.0} found within %{TX.932206_MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.932206_matched_var_name=%{matched_var_name}',\ + chain" + SecRule MATCHED_VAR "@rx /" \ + "t:none,t:urlDecodeUni,\ + chain" + SecRule MATCHED_VAR "@rx \s" \ + "t:none,t:urlDecodeUni,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/932220.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932220 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i).\|(?:[\s\v]*|t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\n\r;`\{]|\|\|?|&&?|\$(?:\(\(?|\{)|[<>]\(|\([\s\v]*\))[\s\v]*(?:[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:7[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[arx])?|G[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?E[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?T|a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:b|(?:p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?)?t|r(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[jp])?|s(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h)?|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[ks])|b[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z|c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[8-9][\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?9|[au][\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t|c|(?:m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?)?p|s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h)|d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[dfu]|i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[gr])|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[bdx]|n[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?v|q[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n|s(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h)?)|f[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[c-dgi]|m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t|t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p)|g[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[chr][\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?c|d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?b|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m|i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t|o|p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?g)|h[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:d|u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p)|i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[dp]|r[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?b)|j[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:j[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?s|q)|k[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h|l[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:d(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d)?|[nps]|u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?a|z(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?4)?)|m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n|t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?r|v)|n[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[cl]|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t|(?:p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?)?m)|o[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:[at][\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?x|d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?b|f|(?:k[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?)?g|h[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[cp]|r(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?y)?|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|x[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?z)|r[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?r|c(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p)?|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[dv]|(?:p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?)?m)|s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[dt]|[g-hu]|s(?:[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h)?|v[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n)|t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[cr]|b[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?l|[co][\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[ex]|i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?c)|u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|l)|v[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:3[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m|c)|x[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:x[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|z)|y[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:e[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?s|u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m)|z[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p|s[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?h))" \ + "id:932220,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix Command Injection with pipe',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# -=[ Rule 932240 ]=- +# +# Generic RCE Bypass blocking using different techniques: see https://github.com/coreruleset/coreruleset/issues/2632 +# +# This rule complements rule 932230 with generic evasion detection. +# Anything that uses a well-known evasion technique should be blocked at this level. +# The chained rule will exclude false positives due to german thousands separators (e.g., 10'000). +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932240.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932240 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS|XML:/* "@rx (?i)[\-0-9_a-z]+(?:[\"'\[-\]]+|\$+[!#\*\-0-9\?-@\x5c_a-\{]+|``|[\$<>]\(\))[\s\v]*[\-0-9_a-z]+" \ + "id:932240,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix Command Injection evasion attempt detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + chain" + SecRule MATCHED_VAR "!@rx [0-9]\s*\'\s*[0-9]" \ + "t:none,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + + + +# [ Sqlite System Command Execution ] +# +# This rule prevents execution of SQLite CLI commands like .system and .shell +# +# You can find a vulnerable script and a sample payload here: +# https://github.com/qxxxb/ctf/tree/master/2021/zer0pts_ctf/baby_sqli +# +# List of sqlite3 CLI commands: +# https://sqlite.org/cli.html +# +# Regular expression generated from regex-assembly/932210.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932210 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ;[\s\v]*\.[\s\v]*[\"']?(?:a(?:rchive|uth)|b(?:a(?:ckup|il)|inary)|c(?:d|h(?:anges|eck)|lone|onnection)|d(?:atabases|b(?:config|info)|ump)|e(?:cho|qp|x(?:cel|it|p(?:ert|lain)))|f(?:ilectrl|ullschema)|he(?:aders|lp)|i(?:mpo(?:rt|ster)|ndexes|otrace)|l(?:i(?:mi|n)t|o(?:ad|g))|(?:mod|n(?:onc|ullvalu)|unmodul)e|o(?:nce|pen|utput)|p(?:arameter|r(?:int|o(?:gress|mpt)))|quit|re(?:ad|cover|store)|s(?:ave|c(?:anstats|hema)|e(?:lftest|parator|ssion)|h(?:a3sum|ell|ow)?|tats|ystem)|t(?:ables|estc(?:ase|trl)|ime(?:out|r)|race)|vfs(?:info|list|name)|width)" \ + "id:932210,\ + phase:2,\ + block,\ + t:none,t:escapeSeqDecode,t:compressWhitespace,\ + msg:'Remote Command Execution: SQLite System Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# -=[ SMTP/IMAP/POP3 Command Execution ]=- +# +# Rationale +# ========= +# +# The rules for email command execution are based on the RFCs for each protocol. +# Some of the commands have optional and/or additional parameters, so we tried to be +# precise to avoid as many FP in PL2 rules. +# For those commands that resemble common English words, and may pose a higher risk of false positives, +# they have been split off to a sibling rule in PL3. + +# =[ SMTP Command Execution ]= +# +# This rule prevents execution of SMTP related system commands. +# +# List of SMTP commands: from rfc 5321 (https://www.rfc-editor.org/rfc/rfc5321) +# +# Regular expression generated from regex-assembly/932300.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932300 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \r\n(?s:.)*?\b(?:(?i:E)(?:HLO [\--\.A-Za-z\x17f\x212a]{1,255}|XPN .{1,64})|HELO [\--\.A-Za-z\x17f\x212a]{1,255}|MAIL FROM:<.{1,64}(?i:@).{1,255}(?i:>)|(?i:R)(?:CPT TO:(?:(?i:<).{1,64}(?i:@).{1,255}(?i:>)|(?i: ))?(?i:<).{1,64}(?i:>)|SET\b)|VRFY .{1,64}(?: <.{1,64}(?i:@).{1,255}(?i:>)|(?i:@).{1,255})|AUTH [\-0-9A-Z_a-z\x17f\x212a]{1,20}(?i: )(?:(?:[\+/-9A-Z_a-z\x17f\x212a]{4})*(?:[\+/-9A-Z_a-z\x17f\x212a]{2}(?i:=)|[\+/-9A-Z_a-z\x17f\x212a]{3}))?(?i:=)|STARTTLS\b|NOOP\b(?:(?i: ).{1,255})?)" \ + "id:932300,\ + phase:2,\ + block,\ + t:none,t:escapeSeqDecode,\ + msg:'Remote Command Execution: SMTP Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/137/134',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# =[ IMAP Command Execution ]= +# +# This rule prevents execution of IMAP4 related system commands. +# +# List of IMAP4 commands: from rfc 3501 (https://datatracker.ietf.org/doc/html/rfc3501#section-9) +# +# Note: Mailbox International Naming Convention uses UTF-7, so it was left out explicitly. +# +# Regular expression generated from regex-assembly/932310.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932310 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?is)\r\n[0-9A-Z_a-z]{1,50}\b (?:A(?:PPEND (?:[\"-#%-&\*\--9A-Z\x5c_a-z]+)?(?: \([ \x5ca-z]+\))?(?: \"?[0-9]{1,2}-[0-9A-Z_a-z]{3}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} [\+\-][0-9]{4}\"?)? \{[0-9]{1,20}\+?\}|UTHENTICATE [\-0-9_a-z]{1,20}\r\n)|L(?:SUB (?:[\"-#\*\.-9A-Z_a-z~]+)? (?:[\"%-&\*\.-9A-Z\x5c_a-z]+)?|ISTRIGHTS (?:[\"%-&\*\--9A-Z\x5c_a-z]+)?)|S(?:TATUS (?:[\"%-&\*\--9A-Z\x5c_a-z]+)? \((?:U(?:NSEEN|IDNEXT)|MESSAGES|UIDVALIDITY|RECENT| )+\)|ETACL (?:[\"%-&\*\--9A-Z\x5c_a-z]+)? [\+\-][ac-eik-lpr-tw-x]+?)|UID (?:COPY|FETCH|STORE) (?:[\*,0-:]+)?|(?:(?:DELETE|GET)ACL|MYRIGHTS) (?:[\"%-&\*\--9A-Z\x5c_a-z]+)?)" \ + "id:932310,\ + phase:2,\ + block,\ + t:none,t:escapeSeqDecode,\ + msg:'Remote Command Execution: IMAP Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/137/134',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# =[ POP3 Command Execution ]= +# +# This rule prevents execution of POP3 related system commands. +# +# List of POP3 commands: +# - from rfc 1939 (https://www.rfc-editor.org/rfc/rfc1939#appendix-B) +# - extensions from rfc 2449 (https://www.rfc-editor.org/rfc/rfc2449) +# +# These commands all have some kind of parameter that makes them a good PL2 target. +# +# Regular expression generated from regex-assembly/932320.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932320 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?is)\r\n.*?\b(?:(?:LIST|TOP [0-9]+)(?: [0-9]+)?|U(?:SER .+?|IDL(?: [0-9]+)?)|PASS .+?|(?:RETR|DELE) [0-9]+?|A(?:POP [0-9A-Z_a-z]+ [0-9a-f]{32}|UTH [\-0-9A-Z_]{1,20} (?:(?:[\+/-9A-Z_a-z]{4})*(?:[\+/-9A-Z_a-z]{2}=|[\+/-9A-Z_a-z]{3}))?=))" \ + "id:932320,\ + phase:2,\ + block,\ + t:none,t:escapeSeqDecode,\ + msg:'Remote Command Execution: POP3 Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/137/134',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# [ Unix command injection ] +# +# This is a stricter sibling of rules 932230, 932235, 932250, 932260. +# This stricter sibling detects Unix RCE with and without prefix and words of any length. +# It uses the same regex. +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932236.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932236 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:(?:^|=)[\s\v]*(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*|(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\n\r;`\{]|\|\|?|&&?|\$(?:\(\(?|\{)|[<>]\(|\([\s\v]*\))[\s\v]*(?:[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*)[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:7z[arx]?|(?:(?:GE|POS)T|HEAD)[\s\v&\)<>\|]|a(?:(?:b|w[ks]|l(?:ias|pine))[\s\v&\)<>\|]|pt(?:[\s\v&\)<>\|]|-get)|r(?:[\s\v&\)<>j\|]|(?:p|ch)[\s\v&\)<>\|]|ia2c)|s(?:h?[\s\v&\)<>\|]|cii(?:-xfr|85)|pell)|t(?:[\s\v&\)<>\|]|obm)|dd(?:group|user)|getty|nsible-playbook|xel)|b(?:z(?:z[\s\v&\)<>\|]|c(?:at|mp)|diff|e(?:grep|xe)|f?grep|ip2(?:recover)?|less|more)|a(?:s(?:e(?:32|64|n(?:ame[\s\v&\)<>\|]|c))|h[\s\v&\)<>\|])|tch[\s\v&\)<>\|])|lkid|pftrace|r(?:eaksw|idge[\s\v&\)<>\|])|sd(?:cat|iff|tar)|u(?:iltin|n(?:dler[\s\v&\)<>\|]|zip2)|s(?:ctl|ybox))|y(?:ebug|obu))|c(?:[8-9]9|(?:a(?:t|ncel|psh)|c)[\s\v&\)<>\|]|mp|p(?:[\s\v&\)<>\|]|an|io|ulimit)|s(?:h|plit|vtool)|u(?:(?:t|rl)[\s\v&\)<>\|]|psfilter)|ertbot|h(?:attr|(?:dir|root)[\s\v&\)<>\|]|eck_(?:by_ssh|cups|log|memory|raid|s(?:sl_cert|tatusfile))|(?:flag|pas)s|g(?:passwd|rp)|mod|o(?:om|wn)|sh)|lang(?:[\s\v&\)<>\|]|\+\+)|o(?:(?:b|pro)c|lumn[\s\v&\)<>\|]|m(?:m(?:and[\s\v&\)<>\|])?|p(?:oser|ress)[\s\v&\)<>\|])|w(?:say|think))|r(?:ash[\s\v&\)<>\|]|on(?:tab)?))|d(?:(?:[du]|i(?:(?:alo)?g|r|ff)|a(?:sh|te))[\s\v&\)<>\|]|f|hclient|m(?:esg|idecode|setup)|o(?:as|(?:cker|ne)[\s\v&\)<>\|]|sbox)|pkg|vips)|e(?:(?:[bd]|cho)[\s\v&\)<>\|]|n(?:v(?:-update)?|d(?:if|sw))|qn|s(?:[\s\v&\)<>h\|]|ac)|x(?:(?:ec)?[\s\v&\)<>\|]|iftool|p(?:(?:and|(?:ec|or)t)[\s\v&\)<>\|]|r))|2fsck|(?:asy_instal|va)l|fax|grep|macs)|f(?:(?:c|etch|lock|unction)[\s\v&\)<>\|]|d|g(?:rep)?|i(?:(?:n(?:d|ger)|sh)?[\s\v&\)<>\|]|le(?:[\s\v&\)<>\|]|test))|mt|tp(?:[\s\v&\)<>\|]|stats|who)|acter|o(?:ld[\s\v&\)<>\|]|reach)|ping)|g(?:c(?:c[^\s\v]|ore)|db|e(?:(?:m|tfacl)[\s\v&\)<>\|]|ni(?:e[\s\v&\)<>\|]|soimage))|hci?|i(?:(?:t|mp)[\s\v&\)<>\|]|nsh)|(?:o|awk)[\s\v&\)<>\|]|pg|r(?:c|ep[\s\v&\)<>\|]|oup(?:[\s\v&\)<>\|]|mod))|tester|unzip|z(?:cat|exe|ip))|h(?:(?:d|up|ash|i(?:ghlight|story))[\s\v&\)<>\|]|e(?:ad[\s\v&\)<>\|]|xdump)|ost(?:id|name)|ping3|t(?:digest|op|passwd))|i(?:d|p(?:6?tables|config)?|rb|conv|f(?:config|top)|nstall[\s\v&\)<>\|]|onice|spell)|j(?:js|q|ava[\s\v&\)<>\|]|exec|o(?:(?:bs|in)[\s\v&\)<>\|]|urnalctl)|runscript)|k(?:s(?:h|shell)|ill(?:[\s\v&\)<>\|]|all)|nife[\s\v&\)<>\|])|l(?:d(?:d?[\s\v&\)<>\|]|config)|(?:[np]|inks|ynx)[\s\v&\)<>\|]|s(?:-F|b_release|cpu|hw|mod|of|pci|usb)?|ua(?:[\s\v&\)<>\|]|(?:la)?tex)|z(?:[\s\v&\)4<>\|]|4c(?:at)?|c(?:at|mp)|diff|[e-f]?grep|less|m(?:a(?:dec|info)?|ore))|a(?:st(?:[\s\v&\)<>\|]|comm|log(?:in)?)|tex[\s\v&\)<>\|])|ess(?:[\s\v&\)<>\|]|echo|(?:fil|pip)e)|ftp(?:get)?|o(?:(?:ca(?:l|te)|ok)[\s\v&\)<>\|]|g(?:inctl|(?:nam|sav)e)|setup)|trace|wp-(?:d(?:ownload|ump)|mirror|request))|m(?:a(?:(?:n|ke)[\s\v&\)<>\|]|il(?:[\s\v&\)<>q\|]|x[\s\v&\)<>\|])|ster\.passwd|wk)|tr|(?:v|utt)[\s\v&\)<>\|]|k(?:dir[\s\v&\)<>\|]|fifo|nod|temp)|locate|o(?:(?:re|unt)[\s\v&\)<>\|]|squitto)|sg(?:attrib|c(?:at|onv)|filter|merge|uniq)|ysql(?:admin|dump(?:slow)?|hotcopy|show)?)|n(?:c(?:[\s\v&\)<>\|]|\.(?:openbsd|traditional)|at)|e(?:t(?:[\s\v&\)<>\|]|(?:c|st)at|kit-ftp|plan)|ofetch)|(?:(?:ul)?l|ice)[\s\v&\)<>\|]|m(?:[\s\v&\)<>\|]|ap)|p(?:m[\s\v&\)<>\|]|ing)|a(?:no[\s\v&\)<>\|]|sm|wk)|o(?:de[\s\v&\)<>\|]|hup)|roff|s(?:enter|lookup|tat))|o(?:(?:d|ctave)[\s\v&\)<>\|]|nintr|p(?:en(?:ssl|v(?:pn|t))|kg))|p(?:a(?:(?:x|rted|tch)[\s\v&\)<>\|]|s(?:swd|te[\s\v&\)<>\|]))|d(?:b|f(?:la)?tex|ksh)|f(?:[\s\v&\)<>\|]|tp)|g(?:rep)?|hp(?:[\s\v&\)57<>\|]|-cgi)|i(?:(?:co?|ng)[\s\v&\)<>\|]|p[^\s\v]|dstat|gz)|k(?:g(?:_?info)?|exec|ill)|r(?:y?[\s\v&\)<>\|]|int(?:env|f[\s\v&\)<>\|]))|t(?:x|ar(?:diff|grep)?)|wd(?:\.db)?|xz|er(?:f|l(?:5|sh)?|ms[\s\v&\)<>\|])|opd|s(?:ed|ftp|ql)|u(?:ppet[\s\v&\)<>\|]|shd)|ython[^\s\v])|r(?:a(?:r[\s\v&\)<>\|]|k(?:e[\s\v&\)<>\|]|u))|c(?:p[\s\v&\)<>\|])?|e(?:(?:d(?:carpet)?|v|name|p(?:eat|lace))[\s\v&\)<>\|]|a(?:delf|lpath)|stic)|m(?:(?:dir)?[\s\v&\)<>\|]|user)|pm(?:[\s\v&\)<>\|]|db|(?:quer|verif)y)|bash|l(?:ogin|wrap)|nano|oute[\s\v&\)<>\|]|sync|u(?:by[^\s\v]|n-(?:mailcap|parts))|vi(?:ew|m))|s(?:c(?:p|hed|r(?:een|ipt)[\s\v&\)<>\|])|e(?:(?:d|lf|rvice)[\s\v&\)<>\|]|t(?:arch|env|facl[\s\v&\)<>\|]|sid)?|ndmail)|(?:g|ash|nap)[\s\v&\)<>\|]|h(?:(?:adow|ells)?[\s\v&\)<>\|]|\.distrib|u(?:f|tdown[\s\v&\)<>\|]))|s(?:[\s\v&\)<>\|]|h(?:[\s\v&\)<>\|]|-key(?:ge|sca)n|pass))|u(?:[\s\v&\)<>\|]|do)|vn|diff|ftp|l(?:eep[\s\v&\)<>\|]|sh)|mbclient|o(?:cat|elim|(?:rt|urce)[\s\v&\)<>\|])|p(?:lit[\s\v&\)<>\|]|wd\.db)|qlite3|t(?:art-stop-daemon|d(?:buf|err|in|out)|r(?:ace|ings[\s\v&\)<>\|]))|ys(?:ctl|tem(?:ctl|d-resolve)))|t(?:a(?:c|r[\s\v&\)<>\|]|il[\s\v&\)<>f\|]|sk(?:[\s\v&\)<>\|]|set))|bl|c(?:p(?:[\s\v&\)<>\|]|dump|ing|traceroute)|l?sh)|e(?:[ex][\s\v&\)<>\|]|lnet)|i(?:c[\s\v&\)<>\|]|me(?:(?:out)?[\s\v&\)<>\|]|datectl))|o(?:p|uch[\s\v&\)<>\|])|ftp|mux|r(?:aceroute6?|off)|shark)|u(?:dp|l(?:imit)?[\s\v&\)<>\|]|n(?:ame|(?:compress|s(?:et|hare))[\s\v&\)<>\|]|expand|iq|l(?:ink[\s\v&\)<>\|]|z(?:4|ma))|(?:pig|x)z|rar|z(?:ip[\s\v&\)<>\|]|std))|pdate-alternatives|ser(?:(?:ad|mo)d|del)|u(?:de|en)code)|v(?:i(?:m(?:[\s\v&\)<>\|]|diff)|ew[\s\v&\)<>\|]|gr|pw|rsh)|algrind|olatility[\s\v&\)<>\|])|w(?:3m|c|a(?:ll|tch)[\s\v&\)<>\|]|get|h(?:iptail[\s\v&\)<>\|]|o(?:ami|is))|i(?:reshark|sh[\s\v&\)<>\|]))|x(?:(?:x|pa)d|z(?:[\s\v&\)<>\|]|c(?:at|mp)|d(?:ec|iff)|[e-f]?grep|less|more)|args|e(?:la)?tex|mo(?:dmap|re)|term)|y(?:(?:e(?:s|lp)|arn)[\s\v&\)<>\|]|um)|z(?:ip(?:[\s\v&\)<>\|]|c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|s(?:h|oelim|td(?:(?:ca|m)t|grep|less)?)|athura|c(?:at|mp)|diff|e(?:grep|ro[\s\v&\)<>\|])|f?grep|less|more|run|ypper))" \ + "id:932236,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix Command Injection (command without evasion)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# [ Unix command injection ] +# +# This is a sibling of rule 932236. +# This sibling detects Unix RCE in request headers Referer and User-Agent. +# It uses the same regex but excludes known user-agents to avoid false positives. +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# +# Regular expression generated from regex-assembly/932239.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932239 +# +SecRule REQUEST_HEADERS:Referer|REQUEST_HEADERS:User-Agent "@rx (?i)(?:(?:^|=)[\s\v]*(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*|(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\n\r;`\{]|\|\|?|&&?|\$(?:\(\(?|\{)|[<>]\(|\([\s\v]*\))[\s\v]*(?:[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*)[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:7z[arx]?|(?:(?:GE|POS)T|HEAD)[\s\v&\)<>\|]|a(?:(?:b|w[ks]|l(?:ias|pine))[\s\v&\)<>\|]|pt(?:[\s\v&\)<>\|]|-get)|r(?:[\s\v&\)<>j\|]|(?:p|ch)[\s\v&\)<>\|]|ia2c)|s(?:h?[\s\v&\)<>\|]|cii(?:-xfr|85)|pell)|t(?:[\s\v&\)<>\|]|obm)|dd(?:group|user)|getty|nsible-playbook|xel)|b(?:z(?:z[\s\v&\)<>\|]|c(?:at|mp)|diff|e(?:grep|xe)|f?grep|ip2(?:recover)?|less|more)|a(?:s(?:e(?:32|64|n(?:ame[\s\v&\)<>\|]|c))|h[\s\v&\)<>\|])|tch[\s\v&\)<>\|])|lkid|pftrace|r(?:eaksw|idge[\s\v&\)<>\|])|sd(?:cat|iff|tar)|u(?:iltin|n(?:dler[\s\v&\)<>\|]|zip2)|s(?:ctl|ybox))|y(?:ebug|obu))|c(?:[8-9]9|(?:a(?:t|ncel|psh)|c)[\s\v&\)<>\|]|mp|p(?:[\s\v&\)<>\|]|io|ulimit)|s(?:h|plit|vtool)|u(?:t[\s\v&\)<>\|]|psfilter)|ertbot|h(?:attr|(?:dir|root)[\s\v&\)<>\|]|eck_(?:by_ssh|cups|log|memory|raid|s(?:sl_cert|tatusfile))|(?:flag|pas)s|g(?:passwd|rp)|mod|o(?:om|wn)|sh)|lang(?:[\s\v&\)<>\|]|\+\+)|o(?:(?:b|pro)c|lumn[\s\v&\)<>\|]|m(?:m(?:and[\s\v&\)<>\|])?|p(?:oser|ress)[\s\v&\)<>\|])|w(?:say|think))|r(?:ash[\s\v&\)<>\|]|on(?:tab)?))|d(?:(?:[du]|i(?:(?:alo)?g|r|ff)|a(?:sh|te))[\s\v&\)<>\|]|f|hclient|m(?:esg|idecode|setup)|o(?:as|(?:cker|ne)[\s\v&\)<>\|]|sbox)|pkg|vips)|e(?:(?:[bd]|cho)[\s\v&\)<>\|]|n(?:v(?:-update)?|d(?:if|sw))|qn|s(?:[\s\v&\)<>h\|]|ac)|x(?:(?:ec)?[\s\v&\)<>\|]|iftool|p(?:(?:and|(?:ec|or)t)[\s\v&\)<>\|]|r))|2fsck|(?:asy_instal|va)l|fax|grep|macs)|f(?:(?:c|etch|lock|unction)[\s\v&\)<>\|]|d|g(?:rep)?|i(?:(?:n(?:d|ger)|sh)?[\s\v&\)<>\|]|le(?:[\s\v&\)<>\|]|test))|mt|tp(?:[\s\v&\)<>\|]|stats|who)|acter|o(?:ld[\s\v&\)<>\|]|reach)|ping)|g(?:c(?:c[^\s\v]|ore)|db|e(?:(?:m|tfacl)[\s\v&\)<>\|]|ni(?:e[\s\v&\)<>\|]|soimage))|hci?|i(?:(?:t|mp)[\s\v&\)<>\|]|nsh)|(?:o|awk)[\s\v&\)<>\|]|pg|r(?:c|ep[\s\v&\)<>\|]|oup(?:[\s\v&\)<>\|]|mod))|tester|unzip|z(?:cat|exe|ip))|h(?:(?:d|up|ash|i(?:ghlight|story))[\s\v&\)<>\|]|e(?:ad[\s\v&\)<>\|]|xdump)|ost(?:id|name)|ping3|t(?:digest|op|passwd))|i(?:d|p(?:6?tables|config)?|rb|conv|f(?:config|top)|nstall[\s\v&\)<>\|]|onice|spell)|j(?:js|q|ava[\s\v&\)<>\|]|exec|o(?:(?:bs|in)[\s\v&\)<>\|]|urnalctl)|runscript)|k(?:s(?:h|shell)|ill(?:[\s\v&\)<>\|]|all)|nife[\s\v&\)<>\|])|l(?:d(?:d?[\s\v&\)<>\|]|config)|(?:[np]|ynx)[\s\v&\)<>\|]|s(?:-F|b_release|cpu|hw|mod|of|pci|usb)?|ua(?:[\s\v&\)<>\|]|(?:la)?tex)|z(?:[\s\v&\)4<>\|]|4c(?:at)?|c(?:at|mp)|diff|[e-f]?grep|less|m(?:a(?:dec|info)?|ore))|a(?:st(?:[\s\v&\)<>\|]|comm|log(?:in)?)|tex[\s\v&\)<>\|])|ess(?:[\s\v&\)<>\|]|echo|(?:fil|pip)e)|ftp(?:get)?|o(?:(?:ca(?:l|te)|ok)[\s\v&\)<>\|]|g(?:inctl|(?:nam|sav)e)|setup)|trace|wp-(?:d(?:ownload|ump)|mirror|request))|m(?:a(?:(?:n|ke)[\s\v&\)<>\|]|il(?:[\s\v&\)<>q\|]|x[\s\v&\)<>\|])|ster\.passwd|wk)|tr|(?:v|utt)[\s\v&\)<>\|]|k(?:dir[\s\v&\)<>\|]|fifo|nod|temp)|locate|o(?:(?:re|unt)[\s\v&\)<>\|]|squitto)|sg(?:attrib|c(?:at|onv)|filter|merge|uniq)|ysql(?:admin|dump(?:slow)?|hotcopy|show)?)|n(?:c(?:[\s\v&\)<>\|]|\.(?:openbsd|traditional)|at)|e(?:t(?:[\s\v&\)<>\|]|(?:c|st)at|kit-ftp|plan)|ofetch)|(?:(?:ul)?l|ice)[\s\v&\)<>\|]|m(?:[\s\v&\)<>\|]|ap)|p(?:m[\s\v&\)<>\|]|ing)|a(?:no[\s\v&\)<>\|]|sm|wk)|o(?:de[\s\v&\)<>\|]|hup)|roff|s(?:enter|lookup|tat))|o(?:(?:d|ctave)[\s\v&\)<>\|]|nintr|p(?:en(?:ssl|v(?:pn|t))|kg))|p(?:a(?:(?:x|rted|tch)[\s\v&\)<>\|]|s(?:swd|te[\s\v&\)<>\|]))|d(?:b|f(?:la)?tex|ksh)|f(?:[\s\v&\)<>\|]|tp)|g(?:rep)?|hp(?:[\s\v&\)57<>\|]|-cgi)|i(?:(?:co?|ng)[\s\v&\)<>\|]|p[^\s\v]|dstat|gz)|k(?:g(?:_?info)?|exec|ill)|r(?:y?[\s\v&\)<>\|]|int(?:env|f[\s\v&\)<>\|]))|t(?:x|ar(?:diff|grep)?)|wd(?:\.db)?|xz|er(?:f|l(?:5|sh)?|ms[\s\v&\)<>\|])|opd|s(?:ed|ftp|ql)|u(?:ppet[\s\v&\)<>\|]|shd)|ython[2-3])|r(?:a(?:r[\s\v&\)<>\|]|k(?:e[\s\v&\)<>\|]|u))|c(?:p[\s\v&\)<>\|])?|e(?:(?:d(?:carpet)?|v|name|p(?:eat|lace))[\s\v&\)<>\|]|a(?:delf|lpath)|stic)|m(?:(?:dir)?[\s\v&\)<>\|]|user)|pm(?:[\s\v&\)<>\|]|db|(?:quer|verif)y)|bash|l(?:ogin|wrap)|nano|oute[\s\v&\)<>\|]|sync|u(?:by[^\s\v]|n-(?:mailcap|parts))|vi(?:ew|m))|s(?:c(?:p|hed|r(?:een|ipt)[\s\v&\)<>\|])|e(?:(?:d|lf|rvice)[\s\v&\)<>\|]|t(?:arch|env|facl[\s\v&\)<>\|]|sid)?|ndmail)|(?:g|ash)[\s\v&\)<>\|]|h(?:(?:adow|ells)?[\s\v&\)<>\|]|\.distrib|u(?:f|tdown[\s\v&\)<>\|]))|s(?:[\s\v&\)<>\|]|h(?:[\s\v&\)<>\|]|-key(?:ge|sca)n|pass))|u(?:[\s\v&\)<>\|]|do)|vn|diff|ftp|l(?:eep[\s\v&\)<>\|]|sh)|mbclient|o(?:cat|elim|(?:rt|urce)[\s\v&\)<>\|])|p(?:lit[\s\v&\)<>\|]|wd\.db)|qlite3|t(?:art-stop-daemon|d(?:buf|err|in|out)|r(?:ace|ings[\s\v&\)<>\|]))|ys(?:ctl|tem(?:ctl|d-resolve)))|t(?:a(?:c|r[\s\v&\)<>\|]|il[\s\v&\)<>f\|]|sk(?:[\s\v&\)<>\|]|set))|bl|c(?:p(?:[\s\v&\)<>\|]|dump|ing|traceroute)|l?sh)|e(?:[ex][\s\v&\)<>\|]|lnet)|i(?:c[\s\v&\)<>\|]|me(?:(?:out)?[\s\v&\)<>\|]|datectl))|o(?:p|uch[\s\v&\)<>\|])|ftp|mux|r(?:aceroute6?|off)|shark)|u(?:dp|l(?:imit)?[\s\v&\)<>\|]|n(?:ame|(?:compress|s(?:et|hare))[\s\v&\)<>\|]|expand|iq|l(?:ink[\s\v&\)<>\|]|z(?:4|ma))|(?:pig|x)z|rar|z(?:ip[\s\v&\)<>\|]|std))|pdate-alternatives|ser(?:(?:ad|mo)d|del)|u(?:de|en)code)|v(?:i(?:m(?:[\s\v&\)<>\|]|diff)|ew[\s\v&\)<>\|]|gr|pw|rsh)|algrind|olatility[\s\v&\)<>\|])|w(?:c|a(?:ll|tch)[\s\v&\)<>\|]|h(?:iptail[\s\v&\)<>\|]|o(?:ami|is))|i(?:reshark|sh[\s\v&\)<>\|]))|x(?:(?:x|pa)d|z(?:[\s\v&\)<>\|]|c(?:at|mp)|d(?:ec|iff)|[e-f]?grep|less|more)|args|e(?:la)?tex|mo(?:dmap|re)|term)|y(?:(?:e(?:s|lp)|arn)[\s\v&\)<>\|]|um)|z(?:ip(?:[\s\v&\)<>\|]|c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|s(?:h|oelim|td(?:(?:ca|m)t|grep|less)?)|athura|c(?:at|mp)|diff|e(?:grep|ro[\s\v&\)<>\|])|f?grep|less|more|run|ypper))" \ + "id:932239,\ + phase:1,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix Command Injection found in user-agent or referer header',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# [ Unix shell snippets ] +# +# Detect some common sequences found in shell commands and scripts. +# +# Some commands which were restricted in earlier rules due to FP, +# have been added here with their full path, in order to catch some +# cases where the full path is sent. +# +# Rule relations: +# +# .932160 (base rule, PL1, unix shell commands with full path) +# ..932161 (stricter sibling, PL2, unix shell commands with full path in User-Agent and Referer request headers) +# +SecRule REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer "@pmFromFile unix-shell.data" \ + "id:932161,\ + phase:2,\ + block,\ + capture,\ + t:none,t:cmdLine,t:normalizePath,\ + msg:'Remote Command Execution: Unix Shell Code Found in REQUEST_HEADERS',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:932015,phase:1,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:932016,phase:2,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + +# [ Unix command injection ] +# +# This rule targets pefix + commans that are prone to false positive detection at PL3. +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932232.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932232 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\n\r;`\{]|\|\|?|&&?|\$(?:\(\(?|\{)|[<>]\(|\([\s\v]*\))[\s\v]*(?:[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:(?:a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?2[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|v[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[\s\v&\),<>\|].*|d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?f|p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[\s\v&\),<>\|].*|s)|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:h[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?o|[\s\v&\),<>\|].*))\b" \ + "id:932232,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Unix Command Injection',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# [ Unix command injection ] +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932237.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932237 +# +SecRule REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer "@rx (?i)\b(?:7z[arx]?|(?:(?:GE|POS)T|HEAD)[\s\v&\)<>\|]|a(?:(?:b|w[ks]|l(?:ias|pine))[\s\v&\)<>\|]|pt(?:(?:itude)?[\s\v&\)<>\|]|-get)|r(?:[\s\v&\)<>j\|]|(?:p|ch)[\s\v&\)<>\|]|ia2c)|s(?:h?[\s\v&\)<>\|]|cii(?:-xfr|85)|pell)|t(?:[\s\v&\)<>\|]|obm)|dd(?:group|user)|getty|nsible-playbook|xel)|b(?:z(?:z[\s\v&\)<>\|]|c(?:at|mp)|diff|e(?:grep|xe)|f?grep|ip2(?:recover)?|less|more)|a(?:s(?:e(?:32|64|n(?:ame[\s\v&\)<>\|]|c))|h[\s\v&\)<>\|])|tch[\s\v&\)<>\|])|lkid|pftrace|r(?:eaksw|idge[\s\v&\)<>\|])|sd(?:cat|iff|tar)|u(?:iltin|n(?:dler[\s\v&\)<>\|]|zip2)|s(?:ctl|ybox))|y(?:ebug|obu))|c(?:[8-9]9|(?:a(?:t|ncel|psh)|c)[\s\v&\)<>\|]|mp|p(?:[\s\v&\)<>\|]|io|ulimit)|s(?:h|plit|vtool)|u(?:t[\s\v&\)<>\|]|psfilter)|ertbot|h(?:attr|(?:dir|root)[\s\v&\)<>\|]|eck_(?:by_ssh|cups|log|memory|raid|s(?:sl_cert|tatusfile))|(?:flag|pas)s|g(?:passwd|rp)|mod|o(?:om|wn)|sh)|lang(?:[\s\v&\)<>\|]|\+\+)|o(?:(?:b|pro)c|lumn[\s\v&\)<>\|]|m(?:m(?:and[\s\v&\)<>\|])?|p(?:oser|ress)[\s\v&\)<>\|])|w(?:say|think))|r(?:ash[\s\v&\)<>\|]|on(?:tab)?))|d(?:(?:[du]|i(?:(?:alo)?g|r|ff)|a(?:sh|te))[\s\v&\)<>\|]|n?f|hclient|m(?:esg|idecode|setup)|o(?:as|(?:cker|ne)[\s\v&\)<>\|]|sbox)|pkg|vips)|e(?:(?:[bd]|cho)[\s\v&\)<>\|]|n(?:v(?:-update)?|d(?:if|sw))|qn|s(?:[\s\v&\)<>h\|]|ac)|x(?:(?:ec)?[\s\v&\)<>\|]|iftool|p(?:(?:and|(?:ec|or)t)[\s\v&\)<>\|]|r))|2fsck|(?:asy_instal|va)l|fax|grep|macs)|f(?:(?:c|etch|lock|unction)[\s\v&\)<>\|]|d|g(?:rep)?|i(?:(?:n(?:d|ger)|sh)?[\s\v&\)<>\|]|le(?:[\s\v&\)<>\|]|test))|mt|tp(?:[\s\v&\)<>\|]|stats|who)|acter|o(?:ld[\s\v&\)<>\|]|reach)|ping)|g(?:c(?:c[^\s\v]|ore)|db|e(?:(?:m|tfacl)[\s\v&\)<>\|]|ni(?:e[\s\v&\)<>\|]|soimage))|hci?|i(?:(?:t|mp)[\s\v&\)<>\|]|nsh)|(?:o|awk)[\s\v&\)<>\|]|pg|r(?:c|ep[\s\v&\)<>\|]|oup(?:[\s\v&\)<>\|]|mod))|tester|unzip|z(?:cat|exe|ip))|h(?:(?:d|up|ash|i(?:ghlight|story))[\s\v&\)<>\|]|e(?:ad[\s\v&\)<>\|]|xdump)|ost(?:id|name)|ping3|t(?:digest|op|passwd))|i(?:d|p(?:6?tables|config)?|rb|conv|f(?:config|top)|nstall[\s\v&\)<>\|]|onice|spell)|j(?:js|q|ava[\s\v&\)<>\|]|exec|o(?:(?:bs|in)[\s\v&\)<>\|]|urnalctl)|runscript)|k(?:s(?:h|shell)|ill(?:[\s\v&\)<>\|]|all)|nife[\s\v&\)<>\|])|l(?:d(?:d?[\s\v&\)<>\|]|config)|(?:[np]|ynx)[\s\v&\)<>\|]|s(?:-F|b_release|cpu|hw|mod|of|pci|usb)?|ua(?:[\s\v&\)<>\|]|(?:la)?tex)|z(?:[\s\v&\)4<>\|]|4c(?:at)?|c(?:at|mp)|diff|[e-f]?grep|less|m(?:a(?:dec|info)?|ore))|a(?:st(?:[\s\v&\)<>\|]|comm|log(?:in)?)|tex[\s\v&\)<>\|])|ess(?:[\s\v&\)<>\|]|echo|(?:fil|pip)e)|ftp(?:get)?|o(?:(?:ca(?:l|te)|ok)[\s\v&\)<>\|]|g(?:inctl|(?:nam|sav)e)|setup)|trace|wp-(?:d(?:ownload|ump)|mirror|request))|m(?:a(?:(?:n|ke)[\s\v&\)<>\|]|il(?:[\s\v&\)<>q\|]|x[\s\v&\)<>\|])|ster\.passwd|wk)|tr|(?:v|utt)[\s\v&\)<>\|]|k(?:dir[\s\v&\)<>\|]|fifo|nod|temp)|locate|o(?:(?:re|unt)[\s\v&\)<>\|]|squitto)|sg(?:attrib|c(?:at|onv)|filter|merge|uniq)|ysql(?:admin|dump(?:slow)?|hotcopy|show)?)|n(?:c(?:[\s\v&\)<>\|]|\.(?:openbsd|traditional)|at)|e(?:t(?:[\s\v&\)<>\|]|(?:c|st)at|kit-ftp|plan)|ofetch)|(?:(?:ul)?l|ice)[\s\v&\)<>\|]|m(?:[\s\v&\)<>\|]|ap)|p(?:m[\s\v&\)<>\|]|ing)|a(?:no[\s\v&\)<>\|]|sm|wk)|o(?:de[\s\v&\)<>\|]|hup)|roff|s(?:enter|lookup|tat))|o(?:(?:d|ctave)[\s\v&\)<>\|]|nintr|p(?:en(?:ssl|v(?:pn|t))|kg))|p(?:a(?:(?:x|cman|rted|tch)[\s\v&\)<>\|]|s(?:swd|te[\s\v&\)<>\|]))|d(?:b|f(?:la)?tex|ksh)|f(?:[\s\v&\)<>\|]|tp)|g(?:rep)?|hp(?:[\s\v&\)57<>\|]|-cgi)|i(?:(?:co?|ng)[\s\v&\)<>\|]|p[^\s\v]|dstat|gz)|k(?:g(?:_?info)?|exec|ill)|r(?:y?[\s\v&\)<>\|]|int(?:env|f[\s\v&\)<>\|]))|s(?:[\s\v&\)<>\|]|ed|ftp|ql)?|t(?:x|ar(?:diff|grep)?)|wd(?:\.db)?|xz|er(?:f|l(?:5|sh)?|ms[\s\v&\)<>\|])|opd|u(?:ppet[\s\v&\)<>\|]|shd)|ython[2-3])|r(?:a(?:r[\s\v&\)<>\|]|k(?:e[\s\v&\)<>\|]|u))|c(?:p[\s\v&\)<>\|])?|e(?:(?:d(?:carpet)?|v|name|p(?:eat|lace))[\s\v&\)<>\|]|a(?:delf|lpath)|stic)|m(?:(?:dir)?[\s\v&\)<>\|]|user)|pm(?:[\s\v&\)<>\|]|db|(?:quer|verif)y)|bash|l(?:ogin|wrap)|nano|oute[\s\v&\)<>\|]|sync|u(?:by[^\s\v]|n-(?:mailcap|parts))|vi(?:ew|m))|s(?:c(?:p|hed|r(?:een|ipt)[\s\v&\)<>\|])|e(?:(?:d|lf|rvice)[\s\v&\)<>\|]|t(?:arch|env|facl[\s\v&\)<>\|]|sid)?|ndmail)|(?:g|ash)[\s\v&\)<>\|]|h(?:(?:adow|ells)?[\s\v&\)<>\|]|\.distrib|u(?:f|tdown[\s\v&\)<>\|]))|s(?:[\s\v&\)<>\|]|h(?:[\s\v&\)<>\|]|-key(?:ge|sca)n|pass))|u(?:[\s\v&\)<>\|]|do)|vn|diff|ftp|l(?:eep[\s\v&\)<>\|]|sh)|mbclient|o(?:cat|elim|(?:rt|urce)[\s\v&\)<>\|])|p(?:lit[\s\v&\)<>\|]|wd\.db)|qlite3|t(?:art-stop-daemon|d(?:buf|err|in|out)|r(?:ace|ings[\s\v&\)<>\|]))|ys(?:ctl|tem(?:ctl|d-resolve)))|t(?:a(?:c|r[\s\v&\)<>\|]|il[\s\v&\)<>f\|]|sk(?:[\s\v&\)<>\|]|set))|bl|c(?:p(?:[\s\v&\)<>\|]|dump|ing|traceroute)|l?sh)|e(?:[ex][\s\v&\)<>\|]|lnet)|i(?:c[\s\v&\)<>\|]|me(?:(?:out)?[\s\v&\)<>\|]|datectl))|o(?:p|uch[\s\v&\)<>\|])|ftp|mux|r(?:aceroute6?|off)|shark)|u(?:dp|l(?:imit)?[\s\v&\)<>\|]|n(?:ame|(?:compress|s(?:et|hare))[\s\v&\)<>\|]|expand|iq|l(?:ink[\s\v&\)<>\|]|z(?:4|ma))|(?:pig|x)z|rar|z(?:ip[\s\v&\)<>\|]|std))|p(?:2date[\s\v&\)<>\|]|date-alternatives)|ser(?:(?:ad|mo)d|del)|u(?:de|en)code)|v(?:i(?:(?:ew)?[\s\v&\)<>\|]|m(?:[\s\v&\)<>\|]|diff)|gr|pw|rsh)|algrind|olatility[\s\v&\)<>\|])|w(?:[\s\v&\)<>c\|]|h(?:o(?:[\s\v&\)<>\|]|ami|is)?|iptail[\s\v&\)<>\|])|a(?:ll|tch)[\s\v&\)<>\|]|i(?:reshark|sh[\s\v&\)<>\|]))|x(?:(?:x|pa)d|z(?:[\s\v&\)<>\|]|c(?:at|mp)|d(?:ec|iff)|[e-f]?grep|less|more)|args|e(?:la)?tex|mo(?:dmap|re)|term)|y(?:(?:e(?:s|lp)|arn)[\s\v&\)<>\|]|um)|z(?:ip(?:[\s\v&\)<>\|]|c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|s(?:h|oelim|td(?:(?:ca|m)t|grep|less)?)|athura|c(?:at|mp)|diff|e(?:grep|ro[\s\v&\)<>\|])|f?grep|less|more|run|ypper))\b" \ + "id:932237,\ + phase:2,\ + block,\ + capture,\ + t:none,t:cmdLine,t:normalizePath,\ + msg:'Remote Command Execution: Unix Shell Code Found in REQUEST_HEADERS',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# [ Unix command injection ] +# +# Rule relations: +# +# .932230 (base rule, PL1, targets prefix + two and three character commands) +# ..932231 (stricter sibling, PL2, targets prefix + the source shortcut command) +# ..932232 (stricter sibling, PL3, targets prefix + additional command words) +# .932235 (base rule, PL1, targets prefix + known command word of length > 3 without evasion) +# +# .932250 (base rule, PL1, targets two and three character commands) +# .932260 (base rule, PL1, targets known command word of length > 3 without evasion) +# +# .932240 (generic detection, PL2, targets generic evasion attempts) +# .932236 (stricter sibling of 932230, 932235, 932250, 932260, PL2, +# - with and without prefix +# - words of any length) +# ..932239 (sibling of 932236, PL2, +# - with and without prefix +# - words of any length +# - targets request headers user-agent and referer only +# - excluded words: known user-agents) +# ..932238 (stricter sibling of 932236, PL3, +# - no excluded words) +# .932237 (stricter sibling of 932230, 932235, 932250, 932260, PL3, +# - targets request headers user-agent and referer only +# - without prefix +# - with word boundaries +# - words of any length +# - excluded words: known user-agents) +# +# +# Regular expression generated from regex-assembly/932238.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932238 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/*|REQUEST_HEADERS:Referer|REQUEST_HEADERS:User-Agent "@rx (?i)(?:(?:^|=)[\s\v]*(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*|(?:t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|[\n\r;`\{]|\|\|?|&&?|\$(?:\(\(?|\{)|[<>]\(|\([\s\v]*\))[\s\v]*(?:[\$\{]|(?:[\s\v]*\(|!)[\s\v]*|[0-9A-Z_a-z]+=(?:[^\s\v]*|\$(?:.*|.*)|[<>].*|'.*'|\".*\")[\s\v]+)*)[\s\v]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:(?:a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d|u[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?2[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?t)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?e|v[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?i)[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[\s\v&\),<>\|].*|d[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?f|p[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?c[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?m[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?a[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?n[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?[\s\v&\),<>\|].*|s)|w[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?(?:h[\"'\)\[-\x5c]*(?:(?:(?:\|\||&&)[\s\v]*)?\$[!#\(\*\-0-9\?-@_a-\{]*)?\x5c?o|[\s\v&\),<>\|].*))" \ + "id:932238,\ + phase:2,\ + block,\ + capture,\ + t:none,t:cmdLine,t:normalizePath,\ + msg:'Remote Command Execution: Unix Shell Code Found in REQUEST_HEADERS',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# +# -=[ Bypass Rule 930120 (wildcard) ]=- +# +# When Paranoia Level is set to 1 and 2, a Remote Command Execution +# could be exploited bypassing rule 930120 (OS File Access Attempt) +# by using wildcard characters. +# +# In some other cases, it could be bypassed even if the Paranoia Level is set to 3. +# Please, keep in mind that this rule could lead to many false positives. +# +# The following two blog posts explain the evasions this rule is designed to detect: +# - https://medium.com/secjuice/waf-evasion-techniques-718026d693d8 +# - https://medium.com/secjuice/web-application-firewall-waf-evasion-techniques-2-125995f3e7b0 + +SecRule ARGS "@rx /(?:[?*]+[a-z/]+|[a-z/]+[?*]+)" \ + "id:932190,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecode,t:urlDecodeUni,t:normalizePath,t:cmdLine,\ + msg:'Remote Command Execution: Wildcard bypass technique attempt',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# -=[ SMTP commands ]=- +# +# This rule prevents execution of SMTP related system commands. +# +# These commands may have a higher risk of false positives. +# For explanation of this rule, see above rule 932300. +# +# Rule 932301 is a stricter sibling of rule 932300. +# +# Regular expression generated from regex-assembly/932301.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932301 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \r\n(?s:.)*?\b(?:DATA|QUIT|HELP(?: .{1,255})?)" \ + "id:932301,\ + phase:2,\ + block,\ + t:none,t:escapeSeqDecode,\ + msg:'Remote Command Execution: SMTP Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'capec/137/134',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# =[ IMAP4 Command Execution ]= +# +# This rule prevents execution of IMAP4 related system commands. +# +# These commands may have a higher risk of false positives. +# For explanation of this rule, see above rule 932310. +# +# Rule 932311 is a stricter sibling of rule 932310. +# +# Regular expression generated from regex-assembly/932311.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932311 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?is)\r\n[0-9A-Z_a-z]{1,50}\b (?:C(?:(?:REATE|OPY [\*,0-:]+) [\"-#%-&\*\--9A-Z\x5c_a-z]+|APABILITY|HECK|LOSE)|DELETE [\"-#%-&\*\--\.0-9A-Z\x5c_a-z]+|EX(?:AMINE [\"-#%-&\*\--\.0-9A-Z\x5c_a-z]+|PUNGE)|FETCH [\*,0-:]+|L(?:IST [\"-#\*\--9A-Z\x5c_a-z~]+? [\"-#%-&\*\--9A-Z\x5c_a-z]+|OG(?:IN [\--\.0-9@_a-z]{1,40} .*?|OUT))|RENAME [\"-#%-&\*\--9A-Z\x5c_a-z]+? [\"-#%-&\*\--9A-Z\x5c_a-z]+|S(?:E(?:LECT [\"-#%-&\*\--9A-Z\x5c_a-z]+|ARCH(?: CHARSET [\--\.0-9A-Z_a-z]{1,40})? (?:(KEYWORD \x5c)?(?:A(?:LL|NSWERED)|BCC|D(?:ELETED|RAFT)|(?:FLAGGE|OL)D|RECENT|SEEN|UN(?:(?:ANSWER|FLAGG)ED|D(?:ELETED|RAFT)|SEEN)|NEW)|(?:BODY|CC|FROM|HEADER .{1,100}|NOT|OR .{1,255}|T(?:EXT|O)) .{1,255}|LARGER [0-9]{1,20}|[\*,0-:]+|(?:BEFORE|ON|S(?:ENT(?:(?:BEFOR|SINC)E|ON)|INCE)) \"?[0-9]{1,2}-[0-9A-Z_a-z]{3}-[0-9]{4}\"?|S(?:MALLER [0-9]{1,20}|UBJECT .{1,255})|U(?:ID [\*,0-:]+?|NKEYWORD \x5c(Seen|(?:Answer|Flagg)ed|D(?:eleted|raft)|Recent))))|T(?:ORE [\*,0-:]+? [\+\-]?FLAGS(?:\.SILENT)? (?:\(\x5c[a-z]{1,20}\))?|ARTTLS)|UBSCRIBE [\"-#%-&\*\--9A-Z\x5c_a-z]+)|UN(?:SUBSCRIBE [\"-#%-&\*\--9A-Z\x5c_a-z]+|AUTHENTICATE)|NOOP)" \ + "id:932311,\ + phase:2,\ + block,\ + t:none,t:escapeSeqDecode,\ + msg:'Remote Command Execution: IMAP Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'capec/137/134',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# =[ POP3 Command Execution ]= +# +# This rule prevents execution of POP3 related system commands. +# +# These commands may have a higher risk of false positives. +# For explanation of this rule, see above rule 932320. +# +# Rule 932321 is a stricter sibling of rule 932320. +# +# Regular expression generated from regex-assembly/932321.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 932321 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \r\n(?s:.)*?\b(?:(?:QUI|STA|RSE)(?i:T)|NOOP|CAPA)" \ + "id:932321,\ + phase:2,\ + block,\ + t:none,t:escapeSeqDecode,\ + msg:'Remote Command Execution: POP3 Command Execution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'capec/137/134',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# =[ Unix shell history invocation ]= +# +# This rule is a stricter sibling of 932330. +# Shell history can also be invoked by providing an absolute position: '!1' or by repeating the last command '!!'. +# The latter might seem harmless as you would expect that it already requires a successful exploitation, but it is a threat in disguise. +# +# Imagine the following requests: +# GET /?rce=c +# GET /?rce=!!!! +# The last request will invoke /usr/bin/cc, which is otherwise blocked by 932150. +# +# Neither !1 nor !! is necessarily valid speech, but blocking either of them is much more likely to cause false-positives than 932330. +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx !(?:\d|!)" \ + "id:932331,\ + phase:2,\ + block,\ + t:none,\ + msg:'Remote Command Execution: Unix shell history invocation',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-shell',\ + tag:'platform-unix',\ + tag:'attack-rce',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/88',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:932017,phase:1,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:932018,phase:2,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-932-APPLICATION-ATTACK-RCE" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-933-APPLICATION-ATTACK-PHP.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf similarity index 72% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-933-APPLICATION-ATTACK-PHP.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf index 58be88f2f7..4a8e149710 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-933-APPLICATION-ATTACK-PHP.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -14,18 +14,18 @@ -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:933011,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:933012,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:933011,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:933012,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # # -=[ PHP Injection Attacks ]=- # # [ References ] -# http://rips-scanner.sourceforge.net/ -# https://www.owasp.org/index.php/PHP_Top_5#P1:_Remote_Code_Executionh +# https://rips-scanner.sourceforge.net/ +# https://wiki.owasp.org/index.php/PHP_Top_5#P1:_Remote_Code_Executionh # # @@ -44,12 +44,12 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:933012,phase:2,pass,nolog,skipAf # Therefore, that pattern is now checked by rule 933190 in paranoia levels # 3 or higher. # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:<\?(?:[^x]|x[^m]|xm[^l]|xml[^\s]|xml$|$)|<\?php|\[(?:\/|\\\\)?php\])" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:<\?(?:[^x]|x[^m]|xm[^l]|xml[^\s]|xml$|$)|<\?php|\[(?:/|\x5c)?php\])" \ "id:933100,\ phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:lowercase,\ + t:none,t:lowercase,\ msg:'PHP Injection Attack: PHP Open Tag Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -59,11 +59,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Script Uploads ] @@ -72,7 +71,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # (.php, .phps, .phtml, .php5 etc). # # Many application contain Unrestricted File Upload vulnerabilities. -# https://www.owasp.org/index.php/Unrestricted_File_Upload +# https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload # # Attackers may use such a vulnerability to achieve remote code execution # by uploading a .php file. If the upload storage location is predictable @@ -80,13 +79,13 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # .php file and have the code within it executed on the server. # # Also block files with just dot (.) characters after the extension: -# https://community.rapid7.com/community/metasploit/blog/2013/08/15/time-to-patch-joomla +# https://www.rapid7.com/blog/post/2013/08/15/time-to-patch-joomla/ # # Some AJAX uploaders use the nonstandard request headers X-Filename, # X_Filename, or X-File-Name to transmit the file name to the server; # scan these request headers as well as multipart/form-data file names. # -SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X.Filename|REQUEST_HEADERS:X-File-Name "@rx .*\.(?:php\d*|phtml)\.*$" \ +SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X.Filename|REQUEST_HEADERS:X-File-Name "@rx .*\.ph(?:p\d*|tml|ar|ps|t|pt)\.*$" \ "id:933110,\ phase:2,\ block,\ @@ -101,11 +100,10 @@ SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEAD tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -116,9 +114,9 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:normalisePath,t:lowercase,\ + t:none,t:normalisePath,\ msg:'PHP Injection Attack: Configuration Directive Found',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.933120_TX_0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ @@ -126,14 +124,14 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ + setvar:'tx.933120_tx_0=%{tx.0}',\ chain" SecRule MATCHED_VARS "@pm =" \ "capture,\ - ctl:auditLogParts=+E,\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -144,7 +142,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME phase:2,\ block,\ capture,\ - t:none,t:normalisePath,t:urlDecodeUni,t:lowercase,\ + t:none,t:normalisePath,t:urlDecodeUni,\ msg:'PHP Injection Attack: Variables Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -154,11 +152,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -191,11 +188,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -206,7 +202,15 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # could lead to RCE as describled by Sam Thomas at BlackHat USA 2018 (https://bit.ly/2yaKV5X), even # wrappers like zlib://, glob://, rar://, zip://, etc... could lead to LFI and expect:// to RCE. # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:zlib|glob|phar|ssh2|rar|ogg|expect|zip)://" \ +# Valid PHP wrappers can be found in the PHP documentation here: +# https://www.php.net/manual/en/wrappers.php +# +# Regular expression generated from regex-assembly/933200.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 933200 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:bzip2|expect|glob|ogg|(?:ph|r)ar|ssh2(?:.(?:s(?:hell|(?:ft|c)p)|exec|tunnel))?|z(?:ip|lib))://" \ "id:933200,\ phase:2,\ block,\ @@ -220,11 +224,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -247,7 +250,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # false positives in natural language or other contexts. # Examples: 'chr', 'eval'. # To mitigate false positives, a regexp looks for PHP function syntax, e.g. 'eval()'. -# Regexp is generated from function names in util/regexp-assemble/regexp-933160.data +# Regexp is generated from function names in util/regexp-assemble/data/933160.data # # - Rule 933151: ~1300 words of lesser importance. This includes most PHP functions and keywords. # Examples: 'addslashes', 'array_diff'. @@ -261,7 +264,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # Examples: 'abs', 'cos'. # To mitigate false positives, a regexp matches on function syntax, e.g. 'abs()'. # This rule only runs in paranoia level 3 or higher. -# Regexp is generated from function names in util/regexp-assemble/regexp-933161.data +# Regexp is generated from function names in util/regexp-assemble/data/933161.data # @@ -278,7 +281,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F phase:2,\ block,\ capture,\ - t:none,t:lowercase,\ + t:none,\ msg:'PHP Injection Attack: High-Risk PHP Function Name Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -288,11 +291,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -321,13 +323,12 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F # [ Apache Struts vulnerability CVE-2018-11776 - Exploit tested: https://www.exploit-db.com/exploits/45260 ] # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # -# Regexp generated from util/regexp-assemble/regexp-933160.data using Regexp::Assemble. -# See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage. +# Regular expression generated from regex-assembly/933160.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 933160 # -# Note that after assemble, PHP function syntax pre/postfix is added to the Regexp::Assemble -# output. Example: "@rx (?i)\bASSEMBLE_OUTPUT_HERE(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" -# -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:s(?:e(?:t(?:_(?:e(?:xception|rror)_handler|magic_quotes_runtime|include_path)|defaultstub)|ssion_s(?:et_save_handler|tart))|qlite_(?:(?:(?:unbuffered|single|array)_)?query|create_(?:aggregate|function)|p?open|exec)|tr(?:eam_(?:context_create|socket_client)|ipc?slashes|rev)|implexml_load_(?:string|file)|ocket_c(?:onnect|reate)|h(?:ow_sourc|a1_fil)e|pl_autoload_register|ystem)|p(?:r(?:eg_(?:replace(?:_callback(?:_array)?)?|match(?:_all)?|split)|oc_(?:(?:terminat|clos|nic)e|get_status|open)|int_r)|o(?:six_(?:get(?:(?:e[gu]|g)id|login|pwnam)|mk(?:fifo|nod)|ttyname|kill)|pen)|hp(?:_(?:strip_whitespac|unam)e|version|info)|g_(?:(?:execut|prepar)e|connect|query)|a(?:rse_(?:ini_file|str)|ssthru)|utenv)|r(?:unkit_(?:function_(?:re(?:defin|nam)e|copy|add)|method_(?:re(?:defin|nam)e|copy|add)|constant_(?:redefine|add))|e(?:(?:gister_(?:shutdown|tick)|name)_function|ad(?:(?:gz)?file|_exif_data|dir))|awurl(?:de|en)code)|i(?:mage(?:createfrom(?:(?:jpe|pn)g|x[bp]m|wbmp|gif)|(?:jpe|pn)g|g(?:d2?|if)|2?wbmp|xbm)|s_(?:(?:(?:execut|write?|read)ab|fi)le|dir)|ni_(?:get(?:_all)?|set)|terator_apply|ptcembed)|g(?:et(?:_(?:c(?:urrent_use|fg_va)r|meta_tags)|my(?:[gpu]id|inode)|(?:lastmo|cw)d|imagesize|env)|z(?:(?:(?:defla|wri)t|encod|fil)e|compress|open|read)|lob)|a(?:rray_(?:u(?:intersect(?:_u?assoc)?|diff(?:_u?assoc)?)|intersect_u(?:assoc|key)|diff_u(?:assoc|key)|filter|reduce|map)|ssert(?:_options)?)|h(?:tml(?:specialchars(?:_decode)?|_entity_decode|entities)|(?:ash(?:_(?:update|hmac))?|ighlight)_file|e(?:ader_register_callback|x2bin))|f(?:i(?:le(?:(?:[acm]tim|inod)e|(?:_exist|perm)s|group)?|nfo_open)|tp_(?:nb_(?:ge|pu)|connec|ge|pu)t|(?:unction_exis|pu)ts|write|open)|o(?:b_(?:get_(?:c(?:ontents|lean)|flush)|end_(?:clean|flush)|clean|flush|start)|dbc_(?:result(?:_all)?|exec(?:ute)?|connect)|pendir)|m(?:b_(?:ereg(?:_(?:replace(?:_callback)?|match)|i(?:_replace)?)?|parse_str)|(?:ove_uploaded|d5)_file|ethod_exists|ysql_query|kdir)|e(?:x(?:if_(?:t(?:humbnail|agname)|imagetype|read_data)|ec)|scapeshell(?:arg|cmd)|rror_reporting|val)|c(?:url_(?:file_create|exec|init)|onvert_uuencode|reate_function|hr)|u(?:n(?:serialize|pack)|rl(?:de|en)code|[ak]?sort)|(?:json_(?:de|en)cod|debug_backtrac|tmpfil)e|b(?:(?:son_(?:de|en)|ase64_en)code|zopen)|var_dump)(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b\(?[\"']*(?:assert(?:_options)?|c(?:hr|reate_function)|e(?:val|x(?:ec|p))|file(?:group)?|glob|i(?:mage(?:gif|(?:jpe|pn)g|wbmp|xbm)|s_a)|md5|o(?:pendir|rd)|p(?:assthru|open|rev)|(?:read|tmp)file|un(?:pac|lin)k|s(?:tat|ubstr|ystem))(?:/(?:\*.*\*/|/.*)|#.*[\s\v]|\")*[\"']*\)?[\s\v]*\(.*\)" \ "id:933160,\ phase:2,\ block,\ @@ -342,11 +343,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -363,7 +363,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F # unserialize() call, resulting in an arbitrary PHP object(s) injection into the # application scope. # -# https://www.owasp.org/index.php/PHP_Object_Injection +# https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection # # In serialized form, PHP objects have the following format: # @@ -371,7 +371,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F # O:3:"Foo":0:{} # # Also detected are PHP objects with a custom unserializer: -# http://www.phpinternalsbook.com/classes_objects/serialization.html +# https://www.phpinternalsbook.com/php5/classes_objects/serialization.html # These have the following format: # # C:11:"ArrayObject":37:{x:i:0;a:1:{s:1:"a";s:1:"b";};m:a:0:{}} @@ -398,11 +398,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_H tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" @@ -454,24 +453,24 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ PHP Functions: Variable Function Prevent Bypass ] # # Referring to https://www.secjuice.com/php-rce-bypass-filters-sanitization-waf/ +# Regex test on https://regex101.com/r/x1tfXG/1 # the rule 933180 could be bypassed by using the following payloads: # -# - (system)('uname') -# - (sy.(st).em)('uname') -# - (string)"system"('uname') -# - define('x', 'sys' . 'tem');(x)/* comment */('uname') -# - $y = 'sys'.'tem';($y)('uname') +# - (system)('uname'); +# - (sy.(st).em)('uname'); +# - (string)"system"('uname'); +# - define('x', 'sys' . 'tem');(x)/* comment */('uname'); +# - $y = 'sys'.'tem';($y)('uname'); # - define('z', [['sys' .'tem']]);(z)[0][0]('uname'); -# - (system)(ls) +# - (system)(ls); # - (/**/system)(ls/**/); # - (['system'])[0]('uname'); # - (++[++system++][++0++])++{/*dsasd*/0}++(++ls++); @@ -481,12 +480,17 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F # - [ACME] this is a test (just a test) # - Test (with two) rounded (brackets) # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:(?:\(|\[)[a-zA-Z0-9_.$\"'\[\](){}/*\s]+(?:\)|\])[0-9_.$\"'\[\](){}/*\s]*\([a-zA-Z0-9_.$\"'\[\](){}/*\s].*\)|\([\s]*string[\s]*\)[\s]*(?:\"|'))" \ +# Regular expression generated from regex-assembly/933210.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 933210 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:\((?:.+\)(?:[\"'][\-0-9A-Z_a-z]+[\"'])?\(.+|[^\)]*string[^\)]*\)[\s\v\"'\--\.0-9A-\[\]_a-\{\}]+\([^\)]*)|(?:\[[0-9]+\]|\{[0-9]+\}|\$[^\(-\),\.-/;\x5c]+|[\"'][\-0-9A-Z\x5c_a-z]+[\"'])\(.+)\);" \ "id:933210,\ phase:2,\ block,\ capture,\ - t:none,t:urlDecode,t:replaceComments,t:compressWhitespace,\ + t:none,t:urlDecode,t:replaceComments,t:removeWhitespace,\ msg:'PHP Injection Attack: Variable Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -496,16 +500,15 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:933013,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:933014,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:933013,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:933014,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # # @@ -530,9 +533,9 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F phase:2,\ block,\ capture,\ - t:none,t:lowercase,\ + t:none,\ msg:'PHP Injection Attack: Medium-Risk PHP Function Name Found',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.933151_TX_0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ @@ -540,22 +543,22 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ + setvar:'tx.933151_tx_0=%{tx.0}',\ chain" SecRule MATCHED_VARS "@pm (" \ "capture,\ - ctl:auditLogParts=+E,\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:933015,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:933016,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:933015,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:933016,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # # @@ -574,12 +577,13 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:933016,phase:2,pass,nolog,skipAf # regex in this case to look for these values whereas in its sibling rule we use # @pmFromFile for flexibility and performance. # -# To rebuild the regexp: -# cd util/regexp-assemble -# ./regexp-assemble.pl < regexp-933131.data +# Regular expression generated from regex-assembly/933131.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 933131 # # This rule is a stricter sibling of rule 933130. -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:HTTP_(?:ACCEPT(?:_(?:ENCODING|LANGUAGE|CHARSET))?|(?:X_FORWARDED_FO|REFERE)R|(?:USER_AGEN|HOS)T|CONNECTION|KEEP_ALIVE)|PATH_(?:TRANSLATED|INFO)|ORIG_PATH_INFO|QUERY_STRING|REQUEST_URI|AUTH_TYPE)" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx AUTH_TYPE|HTTP_(?:ACCEPT(?:_(?:CHARSET|ENCODING|LANGUAGE))?|CONNECTION|(?:HOS|USER_AGEN)T|KEEP_ALIVE|(?:REFERE|X_FORWARDED_FO)R)|ORIG_PATH_INFO|PATH_(?:INFO|TRANSLATED)|QUERY_STRING|REQUEST_URI" \ "id:933131,\ phase:2,\ block,\ @@ -594,11 +598,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/3',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # @@ -619,13 +622,12 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # [ Apache Struts vulnerability CVE-2018-11776 - Exploit tested: https://www.exploit-db.com/exploits/45262 ] # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # -# Regexp generated from util/regexp-assemble/regexp-933161.data using Regexp::Assemble. -# See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage. -# -# Note that after assemble, PHP function syntax pre/postfix is added to the Regexp::Assemble -# output. Example: "@rx (?i)\bASSEMBLE_OUTPUT_HERE(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" +# Regular expression generated from regex-assembly/933161.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 933161 # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:i(?:s(?:_(?:in(?:t(?:eger)?|finite)|n(?:u(?:meric|ll)|an)|(?:calla|dou)ble|s(?:calar|tring)|f(?:inite|loat)|re(?:source|al)|l(?:ink|ong)|a(?:rray)?|object|bool)|set)|n(?:(?:clud|vok)e|t(?:div|val))|(?:mplod|dat)e|conv)|s(?:t(?:r(?:(?:le|sp)n|coll)|at)|(?:e(?:rializ|ttyp)|huffl)e|i(?:milar_text|zeof|nh?)|p(?:liti?|rintf)|(?:candi|ubst)r|y(?:mlink|slog)|o(?:undex|rt)|leep|rand|qrt)|f(?:ile(?:(?:siz|typ)e|owner|pro)|l(?:o(?:atval|ck|or)|ush)|(?:rea|mo)d|t(?:ell|ok)|unction|close|gets|stat|eof)|c(?:h(?:o(?:wn|p)|eckdate|root|dir|mod)|o(?:(?:(?:nsta|u)n|mpac)t|sh?|py)|lose(?:dir|log)|(?:urren|ryp)t|eil)|e(?:x(?:(?:trac|i)t|p(?:lode)?)|a(?:ster_da(?:te|ys)|ch)|r(?:ror_log|egi?)|mpty|cho|nd)|l(?:o(?:g(?:1[0p])?|caltime)|i(?:nk(?:info)?|st)|(?:cfirs|sta)t|evenshtein|trim)|d(?:i(?:(?:skfreespac)?e|r(?:name)?)|e(?:fined?|coct)|(?:oubleva)?l|ate)|r(?:e(?:(?:quir|cod|nam)e|adlin[ek]|wind|set)|an(?:ge|d)|ound|sort|trim)|m(?:b(?:split|ereg)|i(?:crotime|n)|a(?:i[ln]|x)|etaphone|y?sql|hash)|u(?:n(?:(?:tain|se)t|iqid|link)|s(?:leep|ort)|cfirst|mask)|a(?:s(?:(?:se|o)rt|inh?)|r(?:sort|ray)|tan[2h]?|cosh?|bs)|t(?:e(?:xtdomain|mpnam)|a(?:int|nh?)|ouch|ime|rim)|h(?:e(?:ader(?:s_(?:lis|sen)t)?|brev)|ypot|ash)|p(?:a(?:thinfo|ck)|r(?:intf?|ev)|close|o[sw]|i)|g(?:et(?:t(?:ext|ype)|date)|mdate)|o(?:penlog|ctdec|rd)|b(?:asename|indec)|n(?:atsor|ex)t|k(?:sort|ey)|quotemeta|wordwrap|virtual|join)(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:a(?:bs|s(?:in|sert(?:_options)?))|basename|c(?:h(?:eckdate|r(?:oot)?)|o(?:(?:mpac|(?:nsta|u)n)t|py|sh?)|r(?:eate_function|ypt)|urrent)|d(?:ate|e(?:coct|fined?)|ir)|e(?:nd|val|x(?:ec|p(?:lode)?|tract))|f(?:ile(?:(?:[acm]tim|inod|siz|typ)e|group|owner|perms)?|l(?:o(?:ck|or)|ush))|glob|h(?:ash|eader)|i(?:date|m(?:age(?:gif|(?:jpe|pn)g|wbmp|xbm)|plode)|s_a)|key|l(?:ink|og)|m(?:a(?:il|x)|d5|in)|n(?:ame|ext)|o(?:pendir|rd)|p(?:a(?:ck|ss(?:thru)?)|i|o(?:pen|w)|rev)|r(?:an(?:d|ge)|e(?:(?:adfil|nam)e|set)|ound)|s(?:(?:erializ|huffl)e|in|leep|(?:or|ta)t|ubstr|y(?:mlink|s(?:log|tem)))|t(?:an|(?:im|mpfil)e|ouch|rim)|u(?:cfirst|n(?:lin|pac)k)|virtual)(?:[\s\v]|/\*.*\*/|(?:#|//).*)*\(.*\)" \ "id:933161,\ phase:2,\ block,\ @@ -640,11 +642,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/3',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # @@ -683,11 +684,10 @@ SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEAD tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/3',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # [ PHP Closing Tag Found ] @@ -713,17 +713,51 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/3',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# [ PHP Functions: Variable Function Prevent Bypass ] +# +# This rule is a stricter sibling of 933210. +# Unlike 933210, this rule will also match "this is a 'dog' (not a cat)", because the semi-colon at the end of the string is optional. +# This is useful for PHP evals where the semi-colon is already hardcoded: +# +# +# Any potential function calls not at the end of a string will require a semi-colon to form valid PHP, which is automatically covered by 933210. +# +# Regular expression generated from regex-assembly/933211.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 933211 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:\((?:.+\)(?:[\"'][\-0-9A-Z_a-z]+[\"'])?\(.+|[^\)]*string[^\)]*\)[\s\v\"'\--\.0-9A-\[\]_a-\{\}]+\([^\)]*)|(?:\[[0-9]+\]|\{[0-9]+\}|\$[^\(-\),\.-/;\x5c]+|[\"'][\-0-9A-Z\x5c_a-z]+[\"'])\(.+)\)(?:;|$)?" \ + "id:933211,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecode,t:replaceComments,t:removeWhitespace,\ + msg:'PHP Injection Attack: Variable Function Call Found',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-injection-php',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:933017,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:933018,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:933017,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:933018,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # diff --git a/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf new file mode 100644 index 0000000000..f191ed6dd4 --- /dev/null +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf @@ -0,0 +1,388 @@ +# ------------------------------------------------------------------------ +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2023 Core Rule Set project. 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) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:934011,phase:1,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:934012,phase:2,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + + +# [ NodeJS Insecure unserialization / generic RCE signatures ] +# +# Libraries performing insecure unserialization: +# - node-serialize: _$$ND_FUNC$$_ (CVE-2017-5941) +# - funcster: __js_function +# +# See: +# https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/ +# https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/ +# +# Some generic snippets used: +# - function() { +# - new Function( +# - eval( +# - String.fromCharCode( +# +# Last two are used by nodejsshell.py, +# https://github.com/ajinabraham/Node.Js-Security-Course/blob/master/nodejsshell.py +# +# As base64 is sometimes (but not always) used to encode serialized values, +# use multiMatch and t:base64decode. +# +# Regular expression generated from regex-assembly/934100.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 934100 +# +# Stricter sibling: 934101 +SecRule REQUEST_FILENAME|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx _(?:\$\$ND_FUNC\$\$_|_js_function)|(?:\beval|new[\s\v]+Function[\s\v]*)\(|String\.fromCharCode|function\(\)\{|this\.constructor|module\.exports=|\([\s\v]*[^0-9A-Z_a-z]child_process[^0-9A-Z_a-z][\s\v]*\)|process(?:\.(?:(?:a(?:ccess|ppendfile|rgv|vailability)|c(?:aveats|h(?:mod|own)|(?:los|opyfil)e|p|reate(?:read|write)stream)|ex(?:ec(?:file)?|ists)|f(?:ch(?:mod|own)|data(?:sync)?|s(?:tat|ync)|utimes)|inodes|l(?:chmod|ink|stat|utimes)|mkd(?:ir|temp)|open(?:dir)?|r(?:e(?:ad(?:dir|file|link|v)?|name)|m)|s(?:pawn(?:file)?|tat|ymlink)|truncate|u(?:n(?:link|watchfile)|times)|w(?:atchfile|rite(?:file|v)?))(?:sync)?(?:\.call)?\(|binding|constructor|env|global|main(?:Module)?|process|require)|\[[\"'`](?:(?:a(?:ccess|ppendfile|rgv|vailability)|c(?:aveats|h(?:mod|own)|(?:los|opyfil)e|p|reate(?:read|write)stream)|ex(?:ec(?:file)?|ists)|f(?:ch(?:mod|own)|data(?:sync)?|s(?:tat|ync)|utimes)|inodes|l(?:chmod|ink|stat|utimes)|mkd(?:ir|temp)|open(?:dir)?|r(?:e(?:ad(?:dir|file|link|v)?|name)|m)|s(?:pawn(?:file)?|tat|ymlink)|truncate|u(?:n(?:link|watchfile)|times)|w(?:atchfile|rite(?:file|v)?))(?:sync)?|binding|constructor|env|global|main(?:Module)?|process|require)[\"'`]\])|(?:binding|constructor|env|global|main(?:Module)?|process|require)\[|console(?:\.(?:debug|error|info|trace|warn)(?:\.call)?\(|\[[\"'`](?:debug|error|info|trace|warn)[\"'`]\])|require(?:\.(?:resolve(?:\.call)?\(|main|extensions|cache)|\[[\"'`](?:(?:resolv|cach)e|main|extensions)[\"'`]\])" \ + "id:934100,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:jsDecode,t:removeWhitespace,t:base64Decode,t:urlDecodeUni,t:jsDecode,t:removeWhitespace,\ + msg:'Node.js Injection Attack 1/2',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-javascript',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + multiMatch,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +SecRule REQUEST_FILENAME|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:close|exists|fork|(?:ope|spaw)n|re(?:ad|quire)|w(?:atch|rite))[\s\v]*\(" \ + "id:934101,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:jsDecode,t:base64Decode,t:urlDecodeUni,t:jsDecode,\ + msg:'Node.js Injection Attack 2/2',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-javascript',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + multiMatch,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# -=[ SSRF Attacks ]=- +# +# We provide only partial protection to SSRF. DNS Rebinding attacks needs +# to be handled at application level, and even those might be difficult to catch. +# +# PL1 rules are based on common attacks on cloud providers, based on well-known URLs. +# +# -=[ References ]=- +# https://highon.coffee/blog/ssrf-cheat-sheet/ +# https://cwe.mitre.org/data/definitions/918.html +# https://capec.mitre.org/data/definitions/664.html) +# +# Preventing: https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@pmFromFile ssrf.data" \ + "id:934110,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Possible Server Side Request Forgery (SSRF) Attack: Cloud provider metadata URL in Parameter',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-ssrf',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/664',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# JavaScript prototype pollution injection attempts +# +# Example from https://hackerone.com/reports/869574 critical +# vulnerability in the TypeORM library: +# {"text":"a","title":{"__proto__":{"where":{"name":"sqlinjection","where":null}}}} +# +# Test cases are based on this list of payloads: +# https://github.com/BlackFan/client-side-prototype-pollution/blob/master/README.md +# +# See also: https://cwe.mitre.org/data/definitions/1321.html +# +# Note: only server-based (not DOM-based) attacks are covered here. +# Stricter sibling: 934131 + +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:__proto__|constructor\s*(?:\.|\[)\s*prototype)" \ + "id:934130,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:jsDecode,t:base64Decode,t:urlDecodeUni,t:jsDecode,\ + msg:'JavaScript Prototype Pollution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-javascript',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1/180/77',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + multiMatch,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# [ Ruby generic RCE signatures ] +# +# Detects Ruby-based injection attacks. +# Example: Process.spawn("id") +# +# Regular expression generated from regex-assembly/934150.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 934150 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx Process[\s\v]*\.[\s\v]*spawn[\s\v]*\(" \ + "id:934150,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Ruby Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-ruby',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# [ NodeJS DoS signatures ] +# +# NodeJS runs in a single thread, so any evaluated payloads that block execution can cause an easy DoS. +# This rule attempts to block e.g. while(true). +# +# Regular expression generated from regex-assembly/934160.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 934160 +# +SecRule REQUEST_FILENAME|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx while[\s\v]*\([\s\v\(]*(?:!+(?:false|null|undefined|NaN|[\+\-]?0|\"{2}|'{2}|`{2})|(?:!!)*(?:(?:t(?:rue|his)|[\+\-]?(?:Infinity|[1-9][0-9]*)|new [A-Za-z][0-9A-Z_a-z]*|window|String|(?:Boolea|Functio)n|Object|Array)\b|\{.*\}|\[.*\]|\"[^\"]+\"|'[^']+'|`[^`]+`)).*\)" \ + "id:934160,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:jsDecode,t:base64Decode,t:urlDecodeUni,t:jsDecode,t:replaceComments,\ + msg:'Node.js DoS attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-javascript',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + multiMatch,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# [ PHP data: scheme ] +# +# PHP supports the `data:` scheme without using `//` before the content-type. +# +# Regular expression generated from regex-assembly/934170.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 934170 +# +SecRule REQUEST_FILENAME|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ^data:(?:(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)/(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\v]*;[\s\v]*(?:charset[\s\v]*=[\s\v]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\v -\"\(-\),/:-\?\[-\]c\{\}]|c(?:[^!-\"\(-\),/:-\?\[-\]h\{\}]|h(?:[^!-\"\(-\),/:-\?\[-\]a\{\}]|a(?:[^!-\"\(-\),/:-\?\[-\]r\{\}]|r(?:[^!-\"\(-\),/:-\?\[-\]s\{\}]|s(?:[^!-\"\(-\),/:-\?\[-\]e\{\}]|e[^!-\"\(-\),/:-\?\[-\]t\{\}]))))))[^!-\"\(-\),/:-\?\[-\]\{\}]*[\s\v]*=[\s\v]*[^!\(-\),/:-\?\[-\]\{\}]+);?)*(?:[\s\v]*,[\s\v]*(?:(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)/(?:\*|[^!-\"\(-\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\v]*;[\s\v]*(?:charset[\s\v]*=[\s\v]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\v -\"\(-\),/:-\?\[-\]c\{\}]|c(?:[^!-\"\(-\),/:-\?\[-\]h\{\}]|h(?:[^!-\"\(-\),/:-\?\[-\]a\{\}]|a(?:[^!-\"\(-\),/:-\?\[-\]r\{\}]|r(?:[^!-\"\(-\),/:-\?\[-\]s\{\}]|s(?:[^!-\"\(-\),/:-\?\[-\]e\{\}]|e[^!-\"\(-\),/:-\?\[-\]t\{\}]))))))[^!-\"\(-\),/:-\?\[-\]\{\}]*[\s\v]*=[\s\v]*[^!\(-\),/:-\?\[-\]\{\}]+);?)*)*" \ + "id:934170,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'PHP data scheme attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-ssrf',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:934013,phase:1,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:934014,phase:2,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + +# -=[ SSRF Attacks ]=- +# +# PL2 rules adds SSRF capture for common evasion techniques. +# +# We add captures for these evasion techniques: (see source in util/regexp-assemble/data/regexp-934120.data) +# http://425.510.425.510/ Dotted decimal with overflow (already covered by RFI rule 931100) +# http://2852039166/ Dotless decimal - \d{10} +# http://7147006462/ Dotless decimal with overflow - \d{10} +# http://0xA9.0xFE.0xA9.0xFE/ Dotted hexadecimal - (?:0x[a-f0-9]{2}\.){3}0x[a-f0-9]{2} +# http://0xA9FEA9FE/ Dotless hexadecimal - 0x[a-f0-9]{8} +# http://0x41414141A9FEA9FE/ Dotless hexadecimal with overflow - 0x[a-f0-9]{16} +# http://0251.0376.0251.0376/ Dotted octal - Covered by the same below +# http://0251.00376.000251.0000376/ Dotted octal with padding - (?:0{1,4}\d{3}\.){3}0{1,4}\d{3}) +# http://169.254.43518/ - (?:\d{1,3}\.){2}\.\d{5} +# http://169.16689662/ - \d{1,3}\.\d{8} +# http://[::ffff:a9fe:a9fe] IPV6 Compressed - IPv6 regex from https://ihateregex.io/expr/ipv6/, with [0-9] converted to \d and with non-capturing groups (below) +# http://[0:0:0:0:0:ffff:a9fe:a9fe] IPV6 Expanded - (?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}\d){0,1}\d)\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}\d){0,1}\d)|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(2[0-4]|1{0,1}\d){0,1}\d)\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}\d){0,1}\d)) +# http://[0:0:0:0:0:ffff:169.254.169.254] IPV6/IPV4 - ((?:[0-9a-fA-F]{1,4}:){6}(?:(25[0-5]|(?:2[0-4]|1{0,1}\d){0,1}\d)\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}\d){0,1}\d)) +# http://[::] +# http://127.88.23.245:22/+&@google.com:80#+@google.com:80/ (already covered by RFI rule 931100) +# http://127.88.23.245:22/?@google.com:80/ (already covered by RFI rule 931100) +# http://127.88.23.245:22/#@www.google.com:80/ (already covered by RFI rule 931100) +# http://google.com:80\\@127.88.23.245:22/ (already covered by RFI rule 931100) +# http://google.com:80+&@127.88.23.245:22/#+@google.com:80/ +# http://google.com:80+&@google.com:80#+@127.88.23.245:22/ +# +# Regular expression generated from regex-assembly/934120.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 934120 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)((?:a(?:cap|f[ps]|ttachment)|b(?:eshare|itcoin|lob)|c(?:a(?:llto|p)|id|vs|ompress.(?:zlib|bzip2))|d(?:a(?:v|ta)|ict|n(?:s|tp))|e(?:d2k|xpect)|f(?:(?:ee)?d|i(?:le|nger|sh)|tps?)|g(?:it|o(?:pher)?|lob)|h(?:323|ttps?)|i(?:ax|cap|(?:ma|p)ps?|rc[6s]?)|ja(?:bbe)?r|l(?:dap[is]?|ocal_file)|m(?:a(?:ilto|ven)|ms|umble)|n(?:e(?:tdoc|ws)|fs|ntps?)|ogg|p(?:aparazzi|h(?:ar|p)|op(?:2|3s?)|r(?:es|oxy)|syc)|r(?:mi|sync|tm(?:f?p)?|ar)|s(?:3|ftp|ips?|m(?:[bs]|tps?)|n(?:ews|mp)|sh(?:2(?:.(?:s(?:hell|(?:ft|c)p)|exec|tunnel))?)?|vn(?:\+ssh)?)|t(?:e(?:amspeak|lnet)|ftp|urns?)|u(?:dp|nreal|t2004)|v(?:entrilo|iew-source|nc)|w(?:ebcal|ss?)|x(?:mpp|ri)|zip)://(?:[0-9]{10}|(?:0x[0-9a-f]{2}\.){3}0x[0-9a-f]{2}|0x(?:[0-9a-f]{8}|[0-9a-f]{16})|(?:0{1,4}[0-9]{1,3}\.){3}0{1,4}[0-9]{1,3}|[0-9]{1,3}\.(?:[0-9]{1,3}\.[0-9]{5}|[0-9]{8})|(?:\x5c\x5c[\-0-9a-z]\.?_?)+|\[[0-:a-f]+(?:[\.0-9]+|%[0-9A-Z_a-z]+)?\]|[a-z][\--\.0-9A-Z_a-z]{1,255}:[0-9]{1,5}(?:#?[\s\v]*&?@(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3}|[a-z][\--\.0-9A-Z_a-z]{1,255}):[0-9]{1,5}/?)+|[\.0-9]{0,11}(?:\xe2(?:\x91[\xa0-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xa9\xab-\xbf])|\xe3\x80\x82)+))" \ + "id:934120,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Possible Server Side Request Forgery (SSRF) Attack: URL Parameter using IP Address',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-ssrf',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/664',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \[\s*constructor\s*\]" \ + "id:934131,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:jsDecode,t:base64Decode,t:urlDecodeUni,t:jsDecode,\ + msg:'JavaScript Prototype Pollution',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-javascript',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + multiMatch,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# [ Perl generic RCE signatures ] +# +# Detects Perl-based injection attacks. +# Example: @{[system whoami]} +# +# Regular expression generated from regex-assembly/934140.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 934140 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx @\{.*\}" \ + "id:934140,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Perl Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-perl',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:934015,phase:1,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:934016,phase:2,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:934017,phase:1,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:934018,phase:2,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-934-APPLICATION-ATTACK-GENERIC" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-941-APPLICATION-ATTACK-XSS.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf similarity index 52% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-941-APPLICATION-ATTACK-XSS.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf index 3b2376b9ee..4787b4dc92 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-941-APPLICATION-ATTACK-XSS.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -14,13 +14,55 @@ -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:941011,phase:1,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:941012,phase:2,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:941011,phase:1,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:941012,phase:2,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # +# In CRS v4.0, we have added REQUEST_FILENAME to the list of variables to +# be checked for XSS to catch path-based XSS exploits such as: +# /index.php/%3Csvg/onload=alert() +# +# However, the REQUEST_FILENAME is always populated (while ARGS etc. are +# only set on some requests) and we found that always checking the +# REQUEST_FILENAME has a significant performance impact. +# Therefore, we are disabling the REQUEST_FILENAME XSS checks when the +# REQUEST_FILENAME is clearly not containing special characters necessary +# for a successful XSS. +# +# Some bona-fide REQUEST_FILENAMEs will still contain special characters +# and will be checked by the rules, but it will be a much lower amount, +# and that is a trade-off we are willing to make. +# +# So, we check for XSS in REQUEST_FILENAME only if it contains +# other characters than alphanumeric characters, hyphens, underscores etc. +# typically found in filenames and paths: +# +# - ascii 20 (whitespace) +# - ascii 45-47 (- . /) +# - ascii 48-57 (0-9) +# - ascii 65-90 (A-Z) +# - ascii 95 (underscore) +# - ascii 97-122 (a-z) +# +# If just these characters are present, we remove REQUEST_FILENAME from the target +# list of all the 941xxx rules starting 941100. +# +# Please note that it would be preferable to start without REQUEST_FILENAME in the +# target list and to add it on a case to case base, but the rule language does not +# support this feature at runtime. +# +SecRule REQUEST_FILENAME "!@validateByteRange 20, 45-47, 48-57, 65-90, 95, 97-122" \ + "id:941010,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + ctl:ruleRemoveTargetById=941100-941999;REQUEST_FILENAME" + + # # -=[ Libinjection - XSS Detection ]=- # @@ -33,7 +75,7 @@ SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:941012,phase:2,pass,nolog,skipAf # REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent| # ARGS_NAMES|ARGS|XML:/* # -# 941101: PL2 : REQUEST_HEADERS:Referer +# 941101: PL2 : REQUEST_FILENAME|REQUEST_HEADERS:Referer # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@detectXSS" \ "id:941100,\ @@ -49,11 +91,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_H tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -76,48 +117,21 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_F tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ - severity:'CRITICAL',\ - setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" - - -# -# -=[ XSS Filters - Category 2 ]=- -# XSS vectors making use of event handlers like onerror, onload etc, e.g., -# -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s\"'`;\/0-9=\x0B\x09\x0C\x3B\x2C\x28\x3B]on[a-zA-Z]+[\s\x0B\x09\x0C\x3B\x2C\x28\x3B]*?=" \ - "id:941120,\ - phase:2,\ - block,\ - capture,\ - t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ - msg:'XSS Filter - Category 2: Event Handler Vector',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ - tag:'application-multi',\ - tag:'language-multi',\ - tag:'platform-multi',\ - tag:'attack-xss',\ - tag:'paranoia-level/1',\ - tag:'OWASP_CRS',\ - tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ XSS Filters - Category 3 ]=- # -# Regexp generated from util/regexp-assemble/regexp-941130.data using Regexp::Assemble. -# To rebuild the regexp: -# cd util/regexp-assemble -# ./regexp-assemble.pl regexp-941130.data +# Regular expression generated from regex-assembly/941130.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 941130 # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s\S](?:!ENTITY\s+(?:\S+|%\s+\S+)\s+(?:PUBLIC|SYSTEM)|x(?:link:href|html|mlns)|data:text\/html|pattern\b.*?=|formaction|\@import|;base64)\b" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i).(?:\b(?:x(?:link:href|html|mlns)|data:text/html|formaction|pattern\b.*?=)|!ENTITY[\s\v]+(?:%[\s\v]+)?[^\s\v]+[\s\v]+(?:SYSTEM|PUBLIC)|@import|;base64)\b" \ "id:941130,\ phase:2,\ block,\ @@ -132,23 +146,25 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_H tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ XSS Filters - Category 4 ]=- # XSS vectors making use of javascript uri and tags, e.g.,

+# https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#css-expressions-ie7 +# https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#behaviors-for-older-modes-of-ie +# examples: https://regex101.com/r/FFEpsh/1 # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:<(?:(?:apple|objec)t|isindex|embed|style|form|meta)\b[^>]*?>[\s\S]*?|(?:=|U\s*?R\s*?L\s*?\()\s*?[^>]*?\s*?S\s*?C\s*?R\s*?I\s*?P\s*?T\s*?:)" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)[a-z]+=(?:[^:=]+:.+;)*?[^:=]+:url\(javascript" \ "id:941140,\ phase:2,\ block,\ capture,\ - t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,t:removeWhitespace,\ msg:'XSS Filter - Category 4: Javascript URI Vector',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -158,11 +174,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_H tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # @@ -171,14 +186,12 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_H # # [NoScript InjectionChecker] HTML injection # -# Regexp generated from util/regexp-assemble/regexp-941160.data using Regexp::Assemble. -# To rebuild the regexp: -# cd util/regexp-assemble -# ./regexp-assemble.pl regexp-941160.data -# Note that after assemble an ignore case flag (i) is added to the to the Regexp::Assemble output: -# Add ignore case flag between '?' and ':': "(?i:...)" +# Regular expression generated from regex-assembly/941160.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 941160 # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i:(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)(?:on(?:d(?:e(?:vice(?:(?:orienta|mo)tion|proximity|found|light)|livery(?:success|error)|activate)|r(?:ag(?:e(?:n(?:ter|d)|xit)|(?:gestur|leav)e|start|drop|over)|op)|i(?:s(?:c(?:hargingtimechange|onnect(?:ing|ed))|abled)|aling)|ata(?:setc(?:omplete|hanged)|(?:availabl|chang)e|error)|urationchange|ownloading|blclick)|Moz(?:M(?:agnifyGesture(?:Update|Start)?|ouse(?:PixelScroll|Hittest))|S(?:wipeGesture(?:Update|Start|End)?|crolledAreaChanged)|(?:(?:Press)?TapGestur|BeforeResiz)e|EdgeUI(?:C(?:omplet|ancel)|Start)ed|RotateGesture(?:Update|Start)?|A(?:udioAvailable|fterPaint))|c(?:o(?:m(?:p(?:osition(?:update|start|end)|lete)|mand(?:update)?)|n(?:t(?:rolselect|extmenu)|nect(?:ing|ed))|py)|a(?:(?:llschang|ch)ed|nplay(?:through)?|rdstatechange)|h(?:(?:arging(?:time)?ch)?ange|ecking)|(?:fstate|ell)change|u(?:echange|t)|l(?:ick|ose))|s(?:t(?:a(?:t(?:uschanged|echange)|lled|rt)|k(?:sessione|comma)nd|op)|e(?:ek(?:complete|ing|ed)|(?:lec(?:tstar)?)?t|n(?:ding|t))|(?:peech|ound)(?:start|end)|u(?:ccess|spend|bmit)|croll|how)|m(?:o(?:z(?:(?:pointerlock|fullscreen)(?:change|error)|(?:orientation|time)change|network(?:down|up)load)|use(?:(?:lea|mo)ve|o(?:ver|ut)|enter|wheel|down|up)|ve(?:start|end)?)|essage|ark)|a(?:n(?:imation(?:iteration|start|end)|tennastatechange)|fter(?:(?:scriptexecu|upda)te|print)|udio(?:process|start|end)|d(?:apteradded|dtrack)|ctivate|lerting|bort)|b(?:e(?:fore(?:(?:(?:de)?activa|scriptexecu)te|u(?:nload|pdate)|p(?:aste|rint)|c(?:opy|ut)|editfocus)|gin(?:Event)?)|oun(?:dary|ce)|l(?:ocked|ur)|roadcast|usy)|DOM(?:Node(?:Inserted(?:IntoDocument)?|Removed(?:FromDocument)?)|(?:CharacterData|Subtree)Modified|A(?:ttrModified|ctivate)|Focus(?:Out|In)|MouseScroll)|r(?:e(?:s(?:u(?:m(?:ing|e)|lt)|ize|et)|adystatechange|pea(?:tEven)?t|movetrack|trieving|ceived)|ow(?:s(?:inserted|delete)|e(?:nter|xit))|atechange)|p(?:op(?:up(?:hid(?:den|ing)|show(?:ing|n))|state)|a(?:ge(?:hide|show)|(?:st|us)e|int)|ro(?:pertychange|gress)|lay(?:ing)?)|t(?:ouch(?:(?:lea|mo)ve|en(?:ter|d)|cancel|start)|ransition(?:cancel|end|run)|ime(?:update|out)|ext)|u(?:s(?:erproximity|sdreceived)|p(?:gradeneeded|dateready)|n(?:derflow|load))|f(?:o(?:rm(?:change|input)|cus(?:out|in)?)|i(?:lterchange|nish)|ailed)|l(?:o(?:ad(?:e(?:d(?:meta)?data|nd)|start)|secapture)|evelchange|y)|g(?:amepad(?:(?:dis)?connected|button(?:down|up)|axismove)|et)|e(?:n(?:d(?:Event|ed)?|abled|ter)|rror(?:update)?|mptied|xit)|i(?:cc(?:cardlockerror|infochange)|n(?:coming|valid|put))|o(?:(?:(?:ff|n)lin|bsolet)e|verflow(?:changed)?|pen)|SVG(?:(?:Unl|L)oad|Resize|Scroll|Abort|Error|Zoom)|h(?:e(?:adphoneschange|l[dp])|ashchange|olding)|v(?:o(?:lum|ic)e|ersion)change|w(?:a(?:it|rn)ing|heel)|key(?:press|down|up)|(?:AppComman|Loa)d|no(?:update|match)|Request|zoom)|s(?:tyle|rc)|background|formaction|lowsrc|ping)[\s\x08]*?=|<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?(?:(?:a\W*?(?:n\W*?i\W*?m\W*?a\W*?t\W*?e|p\W*?p\W*?l\W*?e\W*?t|u\W*?d\W*?i\W*?o)|b\W*?(?:i\W*?n\W*?d\W*?i\W*?n\W*?g\W*?s|a\W*?s\W*?e|o\W*?d\W*?y)|i?\W*?f\W*?r\W*?a\W*?m\W*?e|o\W*?b\W*?j\W*?e\W*?c\W*?t|i\W*?m\W*?a?\W*?g\W*?e?|e\W*?m\W*?b\W*?e\W*?d|p\W*?a\W*?r\W*?a\W*?m|v\W*?i\W*?d\W*?e\W*?o|l\W*?i\W*?n\W*?k)[^>\w]|s\W*?(?:c\W*?r\W*?i\W*?p\W*?t|t\W*?y\W*?l\W*?e|e\W*?t[^>\w]|v\W*?g)|m\W*?(?:a\W*?r\W*?q\W*?u\W*?e\W*?e|e\W*?t\W*?a[^>\w])|f\W*?o\W*?r\W*?m))" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)<[^0-9<>A-Z_a-z]*(?:[^\s\v\"'<>]*:)?[^0-9<>A-Z_a-z]*[^0-9A-Z_a-z]*?(?:s[^0-9A-Z_a-z]*?(?:c[^0-9A-Z_a-z]*?r[^0-9A-Z_a-z]*?i[^0-9A-Z_a-z]*?p[^0-9A-Z_a-z]*?t|t[^0-9A-Z_a-z]*?y[^0-9A-Z_a-z]*?l[^0-9A-Z_a-z]*?e|v[^0-9A-Z_a-z]*?g|e[^0-9A-Z_a-z]*?t[^0-9>A-Z_a-z])|f[^0-9A-Z_a-z]*?o[^0-9A-Z_a-z]*?r[^0-9A-Z_a-z]*?m|m[^0-9A-Z_a-z]*?(?:a[^0-9A-Z_a-z]*?r[^0-9A-Z_a-z]*?q[^0-9A-Z_a-z]*?u[^0-9A-Z_a-z]*?e[^0-9A-Z_a-z]*?e|e[^0-9A-Z_a-z]*?t[^0-9A-Z_a-z]*?a[^0-9>A-Z_a-z])|(?:l[^0-9A-Z_a-z]*?i[^0-9A-Z_a-z]*?n[^0-9A-Z_a-z]*?k|o[^0-9A-Z_a-z]*?b[^0-9A-Z_a-z]*?j[^0-9A-Z_a-z]*?e[^0-9A-Z_a-z]*?c[^0-9A-Z_a-z]*?t|e[^0-9A-Z_a-z]*?m[^0-9A-Z_a-z]*?b[^0-9A-Z_a-z]*?e[^0-9A-Z_a-z]*?d|a[^0-9A-Z_a-z]*?(?:p[^0-9A-Z_a-z]*?p[^0-9A-Z_a-z]*?l[^0-9A-Z_a-z]*?e[^0-9A-Z_a-z]*?t|u[^0-9A-Z_a-z]*?d[^0-9A-Z_a-z]*?i[^0-9A-Z_a-z]*?o|n[^0-9A-Z_a-z]*?i[^0-9A-Z_a-z]*?m[^0-9A-Z_a-z]*?a[^0-9A-Z_a-z]*?t[^0-9A-Z_a-z]*?e)|p[^0-9A-Z_a-z]*?a[^0-9A-Z_a-z]*?r[^0-9A-Z_a-z]*?a[^0-9A-Z_a-z]*?m|i?[^0-9A-Z_a-z]*?f[^0-9A-Z_a-z]*?r[^0-9A-Z_a-z]*?a[^0-9A-Z_a-z]*?m[^0-9A-Z_a-z]*?e|b[^0-9A-Z_a-z]*?(?:a[^0-9A-Z_a-z]*?s[^0-9A-Z_a-z]*?e|o[^0-9A-Z_a-z]*?d[^0-9A-Z_a-z]*?y|i[^0-9A-Z_a-z]*?n[^0-9A-Z_a-z]*?d[^0-9A-Z_a-z]*?i[^0-9A-Z_a-z]*?n[^0-9A-Z_a-z]*?g[^0-9A-Z_a-z]*?s)|i[^0-9A-Z_a-z]*?m[^0-9A-Z_a-z]*?a?[^0-9A-Z_a-z]*?g[^0-9A-Z_a-z]*?e?|v[^0-9A-Z_a-z]*?i[^0-9A-Z_a-z]*?d[^0-9A-Z_a-z]*?e[^0-9A-Z_a-z]*?o)[^0-9>A-Z_a-z])|(?:<[0-9A-Z_a-z].*[\s\v/]|[\"'](?:.*[\s\v/])?)(?:background|formaction|lowsrc|on(?:a(?:bort|ctivate|d(?:apteradded|dtrack)|fter(?:print|(?:scriptexecu|upda)te)|lerting|n(?:imation(?:cancel|end|iteration|start)|tennastatechange)|ppcommand|u(?:dio(?:end|process|start)|xclick))|b(?:e(?:fore(?:(?:(?:(?:de)?activa|scriptexecu)t|toggl)e|c(?:opy|ut)|editfocus|input|p(?:aste|rint)|u(?:nload|pdate))|gin(?:Event)?)|l(?:ocked|ur)|oun(?:ce|dary)|roadcast|usy)|c(?:a(?:(?:ch|llschang)ed|nplay(?:through)?|rdstatechange)|(?:ell|fstate)change|h(?:a(?:rging(?:time)?cha)?nge|ecking)|l(?:ick|ose)|o(?:m(?:mand(?:update)?|p(?:lete|osition(?:end|start|update)))|n(?:nect(?:ed|ing)|t(?:extmenu|rolselect))|py)|u(?:echange|t))|d(?:ata(?:(?:availabl|chang)e|error|setc(?:hanged|omplete))|blclick|e(?:activate|livery(?:error|success)|vice(?:found|light|(?:mo|orienta)tion|proximity))|i(?:aling|s(?:abled|c(?:hargingtimechange|onnect(?:ed|ing))))|o(?:m(?:a(?:ctivate|ttrmodified)|(?:characterdata|subtree)modified|focus(?:in|out)|mousescroll|node(?:inserted(?:intodocument)?|removed(?:fromdocument)?))|wnloading)|r(?:ag(?:drop|e(?:n(?:d|ter)|xit)|(?:gestur|leav)e|over|start)|op)|urationchange)|e(?:mptied|n(?:abled|d(?:ed|Event)?|ter)|rror(?:update)?|xit)|f(?:ailed|i(?:lterchange|nish)|o(?:cus(?:in|out)?|rm(?:change|input))|ullscreenchange)|g(?:amepad(?:axismove|button(?:down|up)|(?:dis)?connected)|et)|h(?:ashchange|e(?:adphoneschange|l[dp])|olding)|i(?:cc(?:cardlockerror|infochange)|n(?:coming|put|valid))|key(?:down|press|up)|l(?:evelchange|o(?:ad(?:e(?:d(?:meta)?data|nd)|start)?|secapture)|y)|m(?:ark|essage|o(?:use(?:down|enter|(?:lea|mo)ve|o(?:ut|ver)|up|wheel)|ve(?:end|start)?|z(?:a(?:fterpaint|udioavailable)|(?:beforeresiz|orientationchang|t(?:apgestur|imechang))e|(?:edgeui(?:c(?:ancel|omplet)|start)e|network(?:down|up)loa)d|fullscreen(?:change|error)|m(?:agnifygesture(?:start|update)?|ouse(?:hittest|pixelscroll))|p(?:ointerlock(?:change|error)|resstapgesture)|rotategesture(?:start|update)?|s(?:crolledareachanged|wipegesture(?:end|start|update)?))))|no(?:match|update)|o(?:(?:bsolet|(?:ff|n)lin)e|pen|verflow(?:changed)?)|p(?:a(?:ge(?:hide|show)|int|(?:st|us)e)|lay(?:ing)?|o(?:inter(?:down|enter|(?:(?:lea|mo)v|rawupdat)e|o(?:ut|ver)|up)|p(?:state|up(?:hid(?:den|ing)|show(?:ing|n))))|ro(?:gress|pertychange))|r(?:atechange|e(?:adystatechange|ceived|movetrack|peat(?:Event)?|quest|s(?:et|ize|u(?:lt|m(?:e|ing)))|trieving)|ow(?:e(?:nter|xit)|s(?:delete|inserted)))|s(?:croll(?:end)?|e(?:arch|ek(?:complete|ed|ing)|lect(?:ionchange|start)?|n(?:ding|t)|t)|how|(?:ound|peech)(?:end|start)|t(?:a(?:lled|rt|t(?:echange|uschanged))|k(?:comma|sessione)nd|op)|u(?:bmit|ccess|spend)|vg(?:abort|error|(?:un)?load|resize|scroll|zoom))|t(?:ext|ime(?:out|update)|o(?:ggle|uch(?:cancel|en(?:d|ter)|(?:lea|mo)ve|start))|ransition(?:cancel|end|run|start))|u(?:n(?:derflow|handledrejection|load)|p(?:dateready|gradeneeded)|s(?:erproximity|sdreceived))|v(?:ersion|o(?:ic|lum)e)change|w(?:a(?:it|rn)ing|ebkit(?:animation(?:end|iteration|start)|transitionend)|heel)|zoom)|ping|s(?:rc|tyle))[\x08-\n\f-\r ]*?=" \ "id:941160,\ phase:2,\ block,\ @@ -193,17 +206,16 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_H tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [NoScript InjectionChecker] Attributes injection # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:\W|^)(?:javascript:(?:[\s\S]+[=\\\(\[\.<]|[\s\S]*?(?:\bname\b|\\[ux]\d))|data:(?:(?:[a-z]\w+\/\w[\w+-]+\w)?[;,]|[\s\S]*?;[\s\S]*?\b(?:base64|charset=)|[\s\S]*?,[\s\S]*?<[\s\S]*?\w[\s\S]*?>))|@\W*?i\W*?m\W*?p\W*?o\W*?r\W*?t\W*?(?:\/\*[\s\S]*?)?(?:[\"']|\W*?u\W*?r\W*?l[\s\S]*?\()|\W*?-\W*?m\W*?o\W*?z\W*?-\W*?b\W*?i\W*?n\W*?d\W*?i\W*?n\W*?g[\s\S]*?:[\s\S]*?\W*?u\W*?r\W*?l[\s\S]*?\(" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)(?:\W|^)(?:javascript:(?:[\s\S]+[=\x5c\(\[\.<]|[\s\S]*?(?:\bname\b|\x5c[ux]\d))|data:(?:(?:[a-z]\w+/\w[\w+-]+\w)?[;,]|[\s\S]*?;[\s\S]*?\b(?:base64|charset=)|[\s\S]*?,[\s\S]*?<[\s\S]*?\w[\s\S]*?>))|@\W*?i\W*?m\W*?p\W*?o\W*?r\W*?t\W*?(?:/\*[\s\S]*?)?(?:[\"']|\W*?u\W*?r\W*?l[\s\S]*?\()|[^-]*?-\W*?m\W*?o\W*?z\W*?-\W*?b\W*?i\W*?n\W*?d\W*?i\W*?n\W*?g[^:]*?:\W*?u\W*?r\W*?l[\s\S]*?\(" \ "id:941170,\ phase:2,\ block,\ @@ -218,24 +230,24 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_H tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # -# [Blacklist Keywords from Node-Validator] -# https://raw.github.com/chriso/node-validator/master/validator.js +# [Deny List Keywords from Node-Validator] +# https://github.com/validatorjs/validator.js/ +# This rule has a stricter sibling 941181 (PL2) that covers the additional payload "-->" # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pm document.cookie document.write .parentnode .innerhtml window.location -moz-binding .*?(?:@[i\\\\]|(?:[:=]|&#x?0*(?:58|3A|61|3D);?).*?(?:[(\\\\]|&#x?0*(?:40|28|92|5C);?)))" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i:.*?(?:@[i\x5c]|(?:[:=]|&#x?0*(?:58|3A|61|3D);?).*?(?:[(\x5c]|&#x?0*(?:40|28|92|5C);?)))" \ "id:941190,\ phase:2,\ block,\ @@ -271,14 +282,13 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:<.*[:]?vmlframe.*?[\s/+]*?src[\s/+]*=)" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i:<.*[:]?vmlframe.*?[\s/+]*?src[\s/+]*=)" \ "id:941200,\ phase:2,\ block,\ @@ -293,14 +303,13 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:(?:j|&#x?0*(?:74|4A|106|6A);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:a|&#x?0*(?:65|41|97|61);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:v|&#x?0*(?:86|56|118|76);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:a|&#x?0*(?:65|41|97|61);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:s|&#x?0*(?:83|53|115|73);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:c|&#x?0*(?:67|43|99|63);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:r|&#x?0*(?:82|52|114|72);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:i|&#x?0*(?:73|49|105|69);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:p|&#x?0*(?:80|50|112|70);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:t|&#x?0*(?:84|54|116|74);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?::|&(?:#x?0*(?:58|3A);?|colon;)).)" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)(?:j|&#(?:0*(?:74|106)|x0*[46]A);)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:a|&#(?:0*(?:65|97)|x0*[46]1);)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:v|&#(?:0*(?:86|118)|x0*[57]6);)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:a|&#(?:0*(?:65|97)|x0*[46]1);)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:s|&#(?:0*(?:115|83)|x0*[57]3);)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:c|&#(?:x0*[46]3|0*(?:99|67));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:r|&#(?:x0*[57]2|0*(?:114|82));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:i|&#(?:x0*[46]9|0*(?:105|73));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:p|&#(?:x0*[57]0|0*(?:112|80));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:t|&#(?:x0*[57]4|0*(?:116|84));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?::|&(?:#(?:0*58|x0*3A);?|colon;))." \ "id:941210,\ phase:2,\ block,\ @@ -315,14 +324,13 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:(?:v|&#x?0*(?:86|56|118|76);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:b|&#x?0*(?:66|42|98|62);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:s|&#x?0*(?:83|53|115|73);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:c|&#x?0*(?:67|43|99|63);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:r|&#x?0*(?:82|52|114|72);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:i|&#x?0*(?:73|49|105|69);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:p|&#x?0*(?:80|50|112|70);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:t|&#x?0*(?:84|54|116|74);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?::|&(?:#x?0*(?:58|3A);?|colon;)).)" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)(?:v|&#(?:0*8|x0*5)[36];)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:b|&#(?:0*6[26]|x0*(?:98|42));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:s|&#(?:0*(?:115|83)|x0*[57]3);)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:c|&#(?:x0*[46]3|0*(?:99|67));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:r|&#(?:x0*[57]2|0*(?:114|82));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:i|&#(?:x0*[46]9|0*(?:105|73));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:p|&#(?:x0*[57]0|0*(?:112|80));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?:t|&#(?:x0*[57]4|0*(?:116|84));)(?:[\t-\n\r]|&(?:#(?:0*(?:9|1[03])|x0*[AD]);?|(?:tab|newline);))*(?::|&(?:#(?:0*58|x0*3A);?|colon;))." \ "id:941220,\ phase:2,\ block,\ @@ -337,14 +345,13 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)]" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)]" \ "id:941290,\ phase:2,\ block,\ @@ -491,14 +492,13 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)). However, +# the characters where the brackets would be are ISO 8859-1 characters: +# - ¼: 0x00BC +# - ¾: 0x00BE +# - ¢: 0x00A2 +# +# And this is how the sequence looks in in US-ASCII: +# +# +# +# This enables an attacker to craft a string that will be delivered in a form that a browser will execute as script +# while being ignored by input filters. +# +# This rule looks for a start tag sequence that looks like "<...>" (checks for hex and plain to be sure). +# Because the bytes matched occur in many different languages encoded as multibyte characters (e.g. UTF-8) +# (e.g. German umlauts, Russian characters) this isn't very helpful and can cause many false positives. We, therefore, +# use a chained rule to also look for an end tag sequence that looks like "". Only if the chained rule matches will +# the request be blocked. +# +# This is of course still not perfect but should at least make it harder to hide most tags using this technique while +# requiring very specific patterns in a language to match, which should get rid of most false positives. +# These rules would, for example, not guard against an element without an end tag, e.g. "". +# +# US-ASCII on Wikipedia: https://en.wikipedia.org/wiki/ASCII +# ISO 8859-1 on Wikipedia: https://en.wikipedia.org/wiki/ISO/IEC_8859-1 -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \xbc[^\xbe>]*[\xbe>]|<[^\xbe]*\xbe" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx \xbc[^\xbe>]*[\xbe>]|<[^\xbe]*\xbe" \ "id:941310,\ phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:lowercase,t:urlDecode,t:htmlEntityDecode,t:jsDecode,\ + t:none,t:lowercase,t:urlDecode,t:htmlEntityDecode,t:jsDecode,\ msg:'US-ASCII Malformed Encoding XSS Filter - Attack Detected',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -540,11 +572,13 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ - setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + chain" + SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?:\xbc\s*/\s*[^\xbe>]*[\xbe>])|(?:<\s*/\s*[^\xbe]*\xbe)" \ + "t:none,t:lowercase,t:urlDecode,t:htmlEntityDecode,t:jsDecode,\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # https://nedbatchelder.com/blog/200704/xss_with_utf7.html @@ -552,12 +586,12 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # Reported by Vladimir Ivanov # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \+ADw-.*(?:\+AD4-|>)|<.*\+AD4-" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx \+ADw-.*(?:\+AD4-|>)|<.*\+AD4-" \ "id:941350,\ phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:urlDecode,t:htmlEntityDecode,t:jsDecode,\ + t:none,t:urlDecode,t:htmlEntityDecode,t:jsDecode,\ msg:'UTF-7 Encoding IE XSS - Attack Detected',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -567,11 +601,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Defend against JSFuck and Hieroglyphy obfuscation of Javascript code @@ -595,7 +628,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # !+[] # ! [] -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ![!+ ]\[\]" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx ![!+ ]\[\]" \ "id:941360,\ phase:2,\ block,\ @@ -609,11 +642,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242/63',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Prevent 941180 bypass by using JavaScript global variables @@ -623,7 +655,7 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME # - /?search=/?a=";+alert(self["document"]["cookie"]);// # - /?search=/?a=";+document+/*foo*/+.+/*bar*/+cookie;// # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS|XML:/* "@rx (?:self|document|this|top|window)\s*(?:/\*|[\[)]).+?(?:\]|\*/)" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?:self|document|this|top|window)\s*(?:/\*|[\[)]).+?(?:\]|\*/)" \ "id:941370,\ phase:2,\ block,\ @@ -637,25 +669,84 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS|XML: tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/152/242/63',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# JavaScript methods which take code as a string types are considered unsafe. +# Unsafe JS functions like eval(), setInterval(), setTimeout() +# Unsafe JS constructor new Function() +# https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#dangerous-contexts +# https://snyk.io/blog/5-ways-to-prevent-code-injection-in-javascript-and-node-js/ +# +# Regular expression generated from regex-assembly/941390.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 941390 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)\b(?:eval|set(?:timeout|interval)|new[\s\v]+Function|a(?:lert|tob)|btoa)[\s\v]*\(" \ + "id:941390,\ + phase:2,\ + block,\ + capture,\ + t:none,t:htmlEntityDecode,t:jsDecode,\ + msg:'Javascript method detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'attack-xss',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# JavaScript function without parentheses +# Reference: https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses +# +# Example Payloads: +# [].sort.call`${alert}1337` +# [].map.call`${eval}\\u{61}lert\x281337\x29` +# Reflect.apply.call`${navigation.navigate}${navigation}${[name]}` +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx ((?:\[[^\]]*\][^.]*\.)|Reflect[^.]*\.).*(?:map|sort|apply)[^.]*\..*call[^`]*`.*`" \ + "id:941400,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:compressWhitespace,\ + msg:'XSS JavaScript function without parentheses',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'attack-xss',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:941013,phase:1,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:941014,phase:2,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:941013,phase:1,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:941014,phase:2,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # # # This is a stricter sibling of rule 941100. # -SecRule REQUEST_HEADERS:Referer "@detectXSS" \ +SecRule REQUEST_FILENAME|REQUEST_HEADERS:Referer "@detectXSS" \ "id:941101,\ - phase:2,\ + phase:1,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ @@ -668,18 +759,50 @@ SecRule REQUEST_HEADERS:Referer "@detectXSS" \ tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/2',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# +# -=[ XSS Filters - Category 2 ]=- +# XSS vectors making use of event handlers like onerror, onload etc, e.g., +# +# We are not listing all the known event handlers like rule 941160, but we +# limit the alerts to keywords of 3-25 characters after the prefix ("on"). +# +# The shortest known event is "onget". The longest known event is "onmozorientationchange" +# with 23 chars after the prefix. 25 chars adds a little bit of safety. +# +# This rule has been moved to PL2 since it has a tendency to trigger on random input. +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)[\s\"'`;/0-9=\x0B\x09\x0C\x3B\x2C\x28\x3B]on[a-zA-Z]{3,25}[\s\x0B\x09\x0C\x3B\x2C\x28\x3B]*?=[^=]" \ + "id:941120,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ + msg:'XSS Filter - Category 2: Event Handler Vector',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-xss',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # # -=[ XSS Filters - Category 5 ]=- # HTML attributes - src, style and href # -SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:s(?:tyle|rc)|href)\b[\s\S]*?=" \ +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)\b(?:s(?:tyle|rc)|href)\b[\s\S]*?=" \ "id:941150,\ phase:2,\ block,\ @@ -694,13 +817,43 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_H tag:'OWASP_CRS',\ tag:'capec/1000/152/242',\ tag:'paranoia-level/2',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + + +# +# [Deny List Keywords from Node-Validator] +# https://github.com/validatorjs/validator.js/ +# This rule is a stricter sibling of 941180 (PL1) +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@contains -->" \ + "id:941181,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:lowercase,t:removeNulls,\ + msg:'Node-Validator Deny List Keywords',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-xss',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ XSS Filters from IE ]=- + # Detect tags that are the most common direct HTML injection points. # # ~]" \ + "id:942230,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects conditional SQL injection attempts',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942240.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942240 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)alter[\s\v]*?[0-9A-Z_a-z]+.*?char(?:acter)?[\s\v]+set[\s\v]+[0-9A-Z_a-z]+|[\"'`](?:;*?[\s\v]*?waitfor[\s\v]+(?:time|delay)[\s\v]+[\"'`]|;.*?:[\s\v]*?goto)" \ + "id:942240,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects MySQL charset switch and MSSQL DoS attempts',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:merge.*?using\s*?\(|execute\s*?immediate\s*?[\"'`]|match\s*?[\w(),+-]+\s*?against\s*?\()" \ + "id:942250,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects MATCH AGAINST, MERGE and EXECUTE IMMEDIATE injections',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)union.*?select.*?from" \ + "id:942270,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Looking for basic sql injection. Common attack string for mysql, oracle and others',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942280.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942280 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)select[\s\v]*?pg_sleep|waitfor[\s\v]*?delay[\s\v]?[\"'`]+[\s\v]?[0-9]|;[\s\v]*?shutdown[\s\v]*?(?:[#;\{]|/\*|--)" \ + "id:942280,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects Postgres pg_sleep injection, waitfor delay attacks and database shutdown attempts',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942290.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942290 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\[?\$(?:n(?:e|in?|o[rt])|e(?:q|xists|lemMatch)|l(?:te?|ike)|mod|a(?:ll|nd)|(?:s(?:iz|lic)|wher)e|t(?:ype|ext)|x?or|div|between|regex|jsonSchema)\]?" \ + "id:942290,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Finds basic MongoDB SQL injection attempts',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# This rule has a stricter sibling (942321) that checks for MySQL and PostgreSQL procedures / functions in +# request headers referer and user-agent. +# +# Regular expression generated from regex-assembly/942320.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942320 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)create[\s\v]+(?:function|procedure)[\s\v]*?[0-9A-Z_a-z]+[\s\v]*?\([\s\v]*?\)[\s\v]*?-|d(?:eclare[^0-9A-Z_a-z]+[#@][\s\v]*?[0-9A-Z_a-z]+|iv[\s\v]*?\([\+\-]*[\s\v\.0-9]+,[\+\-]*[\s\v\.0-9]+\))|exec[\s\v]*?\([\s\v]*?@|(?:lo_(?:impor|ge)t|procedure[\s\v]+analyse)[\s\v]*?\(|;[\s\v]*?(?:declare|open)[\s\v]+[\-0-9A-Z_a-z]+|::(?:b(?:igint|ool)|double[\s\v]+precision|int(?:eger)?|numeric|oid|real|(?:tex|smallin)t)" \ + "id:942320,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects MySQL and PostgreSQL stored procedure/function injections',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942350.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942350 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)create[\s\v]+function[\s\v].+[\s\v]returns|;[\s\v]*?(?:alter|(?:(?:cre|trunc|upd)at|renam)e|d(?:e(?:lete|sc)|rop)|(?:inser|selec)t|load)\b[\s\v]*?[\(\[]?[0-9A-Z_a-z]{2,}" \ + "id:942350,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects MySQL UDF injection and other data/structure manipulation attempts',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# This rule has two stricter sibling: 942361 and 942362. +# The keywords 'alter' and 'union' led to false positives. +# Therefore they have been moved to PL2 and the keywords have been extended on PL1. +# The original version also had loose word boundaries and context checksum cause further false positives. +# Because fixing those introduced bypass, the original variant was moved to PL2 as 942362. +# +# Sources for SQL ALTER statements: +# MySQL: https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-definition.html +# Oracle/PLSQL: https://docs.oracle.com/search/?q=alter&size=60&category=database +# PostgreQSL: https://www.postgresql.org/search/?u=%2Fdocs&q=alter +# MSSQL: https://learn.microsoft.com/en-us/sql/t-sql/statements/statements?view=sql-server-ver16 +# DB2: https://www.ibm.com/docs/en/search/alter?scope=SSEPGG_9.5.0 +# +# Regular expression generated from regex-assembly/942360.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942360 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:(?:alter|(?:(?:cre|trunc|upd)at|renam)e|de(?:lete|sc)|(?:inser|selec)t|load)[\s\v]+(?:char|group_concat|load_file)\b[\s\v]*\(?|end[\s\v]*?\);)|[\s\v\(]load_file[\s\v]*?\(|[\"'`][\s\v]+regexp[^0-9A-Z_a-z]|[\"'0-9A-Z_-z][\s\v]+as\b[\s\v]*[\"'0-9A-Z_-z]+[\s\v]*\bfrom|^[^A-Z_a-z]+[\s\v]*?(?:(?:(?:(?:cre|trunc)at|renam)e|d(?:e(?:lete|sc)|rop)|(?:inser|selec)t|load)[\s\v]+[0-9A-Z_a-z]+|u(?:pdate[\s\v]+[0-9A-Z_a-z]+|nion[\s\v]*(?:all|(?:sele|distin)ct)\b)|alter[\s\v]*(?:a(?:(?:ggregat|pplication[\s\v]*rol)e|s(?:sembl|ymmetric[\s\v]*ke)y|u(?:dit|thorization)|vailability[\s\v]*group)|b(?:roker[\s\v]*priority|ufferpool)|c(?:ertificate|luster|o(?:l(?:latio|um)|nversio)n|r(?:edential|yptographic[\s\v]*provider))|d(?:atabase|efault|i(?:mension|skgroup)|omain)|e(?:(?:ndpoi|ve)nt|xte(?:nsion|rnal))|f(?:lashback|oreign|u(?:lltext|nction))|hi(?:erarchy|stogram)|group|in(?:dex(?:type)?|memory|stance)|java|l(?:a(?:ngua|r)ge|ibrary|o(?:ckdown|g(?:file[\s\v]*group|in)))|m(?:a(?:s(?:k|ter[\s\v]*key)|terialized)|e(?:ssage[\s\v]*type|thod)|odule)|(?:nicknam|queu)e|o(?:perator|utline)|p(?:a(?:ckage|rtition)|ermission|ro(?:cedur|fil)e)|r(?:e(?:mot|sourc)e|o(?:l(?:e|lback)|ute))|s(?:chema|e(?:arch|curity|rv(?:er|ice)|quence|ssion)|y(?:mmetric[\s\v]*key|nonym)|togroup)|t(?:able(?:space)?|ext|hreshold|r(?:igger|usted)|ype)|us(?:age|er)|view|w(?:ork(?:load)?|rapper)|x(?:ml[\s\v]*schema|srobject))\b)" \ + "id:942360,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects concatenated basic SQL injection and SQLLFI attempts',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# -=[ Detect MySQL in-line comments ]=- +# +# MySQL in-line comments can be used to bypass SQLi detection. +# +# Ref: https://dev.mysql.com/doc/refman/8.0/en/comments.html: +# SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2 WHERE ... +# CREATE TABLE t1(a INT, KEY (a)) /*!50110 KEY_BLOCK_SIZE=1024 */; +# SELECT /*+ BKA(t1) */ FROM ... ; +# +# http://localhost/test.php?id=9999+or+{if+length((/*!5000select+username/*!50000from*/user+where+id=1))>0} +# +# The minimal string that triggers this regexp is: /*!*/ or /*+*/. +# The rule 942500 is related to 942440 which catches both /*! and */ independently. +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:/\*[!+](?:[\w\s=_\-()]+)?\*/)" \ + "id:942500,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'MySQL in-line comment detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# This rule catches an authentication bypass via SQL injection that abuses semi-colons to end the SQL query early. +# Any characters after the semi-colon are ignored by some DBMSes (e.g. SQLite). +# +# An example of this would be: +# email=admin%40juice-sh.op';&password=foo +# +# The server then turns this into: +# SELECT * FROM users WHERE email='admin@juice-sh.op';' AND password='foo' +# +# Regular expression generated from regex-assembly/942540.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942540 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ^(?:[^']*'|[^\"]*\"|[^`]*`)[\s\v]*;" \ + "id:942540,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:replaceComments,\ + msg:'SQL Authentication bypass (split query)',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/1',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# This rule catches on Scientific Notation bypass payloads in MySQL +# Reference: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md#scientific-notation +# +# Regular expression generated from regex-assembly/942560.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942560 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)1\.e[\(-\),]" \ + "id:942560,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,t:replaceComments,\ + msg:'MySQL Scientific Notation payload detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/1',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# This rule tries to match JSON SQL syntax that could be used as a bypass technique. +# Referring to this research: https://claroty.com/team82/research/js-on-security-off-abusing-json-based-sql-to-bypass-waf +# +# Regular expression generated from regex-assembly/942550.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942550 +# +SecRule REQUEST_FILENAME|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx [\"'`][\[\{].*[\]\}][\"'`].*(::.*jsonb?)?.*(?:(?:@|->?)>|<@|\?[&\|]?|#>>?|[<>]|<-)|(?:(?:@|->?)>|<@|\?[&\|]?|#>>?|[<>]|<-)[\"'`][\[\{].*[\]\}][\"'`]|json_extract.*\(.*\)" \ + "id:942550,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,t:lowercase,t:removeWhitespace,\ + msg:'JSON-Based SQL Injection',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/1',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:942013,phase:1,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:942014,phase:2,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + + +# +# -=[ String Termination/Statement Ending Injection Testing ]=- +# +# Identifies common initial SQLi probing requests where attackers insert/append +# quote characters to the existing normal payload to see how the app/db responds. +# +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# +SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:^\s*[\"'`;]+|[\"'`]+\s*$)" \ + "id:942110,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,\ + msg:'SQL Injection Attack: Common Injection Testing Detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'WARNING',\ + setvar:'tx.sql_injection_score=+%{tx.warning_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'" + + +# +# -=[ SQL Operators ]=- +# +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# +# Regular expression generated from regex-assembly/942120.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942120 +# +SecRule ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)!=|&&|\|\||>[=->]|<(?:<|=>?|>(?:[\s\v]+binary)?)|\b(?:(?:xor|r(?:egexp|like)|i(?:snull|like)|notnull)\b|collate(?:[^0-9A-Z_a-z]*?(?:U&)?[\"'`]|[^0-9A-Z_a-z]+(?:(?:binary|nocase|rtrim)\b|[0-9A-Z_a-z]*?_))|(?:likel(?:ihood|y)|unlikely)[\s\v]*\()|r(?:egexp|like)[\s\v]+binary|not[\s\v]+between[\s\v]+(?:0[\s\v]+and|(?:'[^']*'|\"[^\"]*\")[\s\v]+and[\s\v]+(?:'[^']*'|\"[^\"]*\"))|is[\s\v]+null|like[\s\v]+(?:null|[0-9A-Z_a-z]+[\s\v]+escape\b)|(?:^|[^0-9A-Z_a-z])in[\s\v\+]*\([\s\v\"0-9]+[^\(-\)]*\)|[!<->]{1,2}[\s\v]*all\b" \ + "id:942120,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,\ + msg:'SQL Injection Attack: SQL Operator Detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# +# -=[ SQL Tautologies ]=- +# +# Boolean-based SQL injection or tautology attack. Boolean values (True or False) are used to carry out +# this type of SQL injection. The malicious SQL query forces the web application to return a different result de- +# pending on whether the query returns a TRUE or FALSE result. +# +# The original 942130 was split in two rules: +# - 942130 targets tautologies using equalities (e.g. 1 = 1) +# - 942131 targets tautologies using inequalities (e.g. 1 != 2) +# +# We use captures to check for (in)equality in the regexp. So TX.1 will capture the left hand side (LHS) of the inequality, +# and TX.2 will capture the right hand side (RHS) of the logical query. +# +# Regular expression generated from regex-assembly/942130.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942130 +# +SecRule ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s\v\"'-\)`]*?\b([0-9A-Z_a-z]+)\b[\s\v\"'-\)`]*?(?:=|<=>|(?:sounds[\s\v]+)?like|glob|r(?:like|egexp))[\s\v\"'-\)`]*?\b([0-9A-Z_a-z]+)\b" \ + "id:942130,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:replaceComments,\ + msg:'SQL Injection Attack: SQL Boolean-based attack detected',\ + logdata:'Matched Data: %{TX.0} found within %{TX.942130_MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.942130_matched_var_name=%{matched_var_name}',\ + chain" + SecRule TX:1 "@streq %{TX.2}" \ + "t:none,\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Rule Targeting logical inequalities that return TRUE (e.g. 1 != 2) +# +# +# We use captures to check for (in)equality in the regexp. So TX.1 will capture the left hand side (LHS) of the inequality, +# and TX.2 will capture the right hand side (RHS) of the logical query. +# +# Regular expression generated from regex-assembly/942131.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942131 +# +SecRule ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s\v\"'-\)`]*?\b([0-9A-Z_a-z]+)\b[\s\v\"'-\)`]*?(?:![<->]|<[=->]?|>=?|\^|is[\s\v]+not|not[\s\v]+(?:like|r(?:like|egexp)))[\s\v\"'-\)`]*?\b([0-9A-Z_a-z]+)\b" \ + "id:942131,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:replaceComments,\ + msg:'SQL Injection Attack: SQL Boolean-based attack detected',\ + logdata:'Matched Data: %{TX.0} found within %{TX.942131_MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + multiMatch,\ + setvar:'tx.942131_matched_var_name=%{matched_var_name}',\ + chain" + SecRule TX:1 "!@streq %{TX.2}" \ + "t:none,\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ SQL Function Names ]=- +# +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# +# Regular expression generated from regex-assembly/942150.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942150 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:json(?:_[0-9A-Z_a-z]+)?|a(?:bs|(?:cos|sin)h?|tan[2h]?|vg)|c(?:eil(?:ing)?|h(?:a(?:nges|r(?:set)?)|r)|o(?:alesce|sh?|unt)|ast)|d(?:e(?:grees|fault)|a(?:te|y))|exp|f(?:loor(?:avg)?|ormat|ield)|g(?:lob|roup_concat)|h(?:ex|our)|i(?:f(?:null)?|if|n(?:str)?)|l(?:ast(?:_insert_rowid)?|ength|ike(?:l(?:ihood|y))?|n|o(?:ad_extension|g(?:10|2)?|wer(?:pi)?|cal)|trim)|m(?:ax|in(?:ute)?|o(?:d|nth))|n(?:ullif|ow)|p(?:i|ow(?:er)?|rintf|assword)|quote|r(?:a(?:dians|ndom(?:blob)?)|e(?:p(?:lace|eat)|verse)|ound|trim|ight)|s(?:i(?:gn|nh?)|oundex|q(?:lite_(?:compileoption_(?:get|used)|offset|source_id|version)|rt)|u(?:bstr(?:ing)?|m)|econd|leep)|t(?:anh?|otal(?:_changes)?|r(?:im|unc)|ypeof|ime)|u(?:n(?:icode|likely)|(?:pp|s)er)|zeroblob|bin|v(?:alues|ersion)|week|year)[^0-9A-Z_a-z]*\(" \ + "id:942150,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:lowercase,\ + msg:'SQL Injection Attack: SQL function name detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ SQL Authentication Bypasses ]=- +# +# Authentication bypass occurs when the attacker can log in as another user +# without knowing the user's password. The example bypass could look like this: +# +# x' OR 'x +# +# Because of the quantity of different rules they are split into: +# - 942540 PL1 +# - 942180 PL2 +# - 942260 PL2 +# - 942340 PL2 +# - 942520 PL2 +# - 942521 PL2 +# - 942522 PL2 + +# Regular expression generated from regex-assembly/942180.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942180 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:/\*)+[\"'`]+[\s\v]?(?:--|[#\{]|/\*)?|[\"'`](?:[\s\v]*(?:(?:x?or|and|div|like|between)[\s\v\-0-9A-Z_a-z]+[\(-\)\+-\-<->][\s\v]*[\"'0-9`]|[!=\|](?:[\s\v -!\+\-0-9=]+.*?[\"'-\(`].*?|[\s\v -!0-9=]+.*?[0-9]+)$|(?:like|print)[^0-9A-Z_a-z]+[\"'-\(0-9A-Z_-z]|;)|(?:[<>~]+|[\s\v]*[^\s\v0-9A-Z_a-z]?=[\s\v]*|[^0-9A-Z_a-z]*?[\+=]+[^0-9A-Z_a-z]*?)[\"'`])|[0-9][\"'`][\s\v]+[\"'`][\s\v]+[0-9]|^admin[\s\v]*?[\"'`]|[\s\v\"'-\(`][\s\v]*?glob[^0-9A-Z_a-z]+[\"'-\(0-9A-Z_-z]|[\s\v]is[\s\v]*?0[^0-9A-Z_a-z]|where[\s\v][\s\v,-\.0-9A-Z_a-z]+[\s\v]=" \ + "id:942180,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects basic SQL authentication bypass attempts 1/3',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# +# Regular expression generated from regex-assembly/942200.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942200 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i),.*?[\"'\)0-9`-f][\"'`](?:[\"'`].*?[\"'`]|(?:\r?\n)?\z|[^\"'`]+)|[^0-9A-Z_a-z]select.+[^0-9A-Z_a-z]*?from|(?:alter|(?:(?:cre|trunc|upd)at|renam)e|d(?:e(?:lete|sc)|rop)|(?:inser|selec)t|load)[\s\v]*?\([\s\v]*?space[\s\v]*?\(" \ + "id:942200,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects MySQL comment-/space-obfuscated injections and backtick termination',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# +# Regular expression generated from regex-assembly/942210.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942210 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:&&|\|\||and|between|div|like|n(?:and|ot)|(?:xx?)?or)[\s\v\(]+[0-9A-Z_a-z]+[\s\v\)]*?[!\+=]+[\s\v0-9]*?[\"'-\)=`]|[0-9](?:[\s\v]*?(?:and|between|div|like|x?or)[\s\v]*?[0-9]+[\s\v]*?[\+\-]|[\s\v]+group[\s\v]+by.+\()|/[0-9A-Z_a-z]+;?[\s\v]+(?:and|between|div|having|like|x?or|select)[^0-9A-Z_a-z]|(?:[#;]|--)[\s\v]*?(?:alter|drop|(?:insert|update)[\s\v]*?[0-9A-Z_a-z]{2,})|@.+=[\s\v]*?\([\s\v]*?select|[^0-9A-Z_a-z]SET[\s\v]*?@[0-9A-Z_a-z]+" \ + "id:942210,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects chained SQL injection attempts 1/2',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942260.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942260 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\"'`][\s\v]*?(?:(?:and|n(?:and|ot)|(?:xx?)?or|div|like|between|\|\||&&)[\s\v]+[\s\v0-9A-Z_a-z]+=[\s\v]*?[0-9A-Z_a-z]+[\s\v]*?having[\s\v]+|like[^0-9A-Z_a-z]*?[\"'0-9`])|[0-9A-Z_a-z][\s\v]+like[\s\v]+[\"'`]|like[\s\v]*?[\"'`]%|select[\s\v]+?[\s\v\"'-\),-\.0-9A-\[\]_-z]+from[\s\v]+" \ + "id:942260,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects basic SQL authentication bypass attempts 2/3',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942300.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942300 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\)[\s\v]*?when[\s\v]*?[0-9]+[\s\v]*?then|[\"'`][\s\v]*?(?:[#\{]|--)|/\*![\s\v]?[0-9]+|\b(?:(?:binary|cha?r)[\s\v]*?\([\s\v]*?[0-9]|(?:and|n(?:and|ot)|(?:xx?)?or|div|like|between|r(?:egexp|like))[\s\v]+[0-9A-Z_a-z]+\()|(?:\|\||&&)[\s\v]*?[0-9A-Z_a-z]+\(" \ + "id:942300,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects MySQL comments, conditions and ch(a)r injections',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942310.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942310 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:\([\s\v]*?select[\s\v]*?[0-9A-Z_a-z]+|coalesce|order[\s\v]+by[\s\v]+if[0-9A-Z_a-z]*?)[\s\v]*?\(|\*/from|\+[\s\v]*?[0-9]+[\s\v]*?\+[\s\v]*?@|[0-9A-Z_a-z][\"'`][\s\v]*?(?:(?:[\+\-=@\|]+[\s\v]+?)+|[\+\-=@\|]+)[\(0-9]|@@[0-9A-Z_a-z]+[\s\v]*?[^\s\v0-9A-Z_a-z]|[^0-9A-Z_a-z]!+[\"'`][0-9A-Z_a-z]|[\"'`](?:;[\s\v]*?(?:if|while|begin)|[\s\v0-9]+=[\s\v]*?[0-9])|[\s\v\(]+case[0-9]*?[^0-9A-Z_a-z].+[tw]hen[\s\v\(]" \ + "id:942310,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects chained SQL injection attempts 2/2',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ SQL Injection Probings ]=- +# +# This is a group of three similar rules aiming to detect SQL injection probings. +# +# 942330 PL 2 +# 942370 PL 2 +# 942490 PL 3 +# Regular expression generated from regex-assembly/942330.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942330 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\"'`][\s\v]*?\b(?:x?or|div|like|between|and)\b[\s\v]*?[\"'`]?[0-9]|\x5cx(?:2[37]|3d)|^(?:.?[\"'`]$|[\"'\x5c`]*?(?:[\"'0-9`]+|[^\"'`]+[\"'`])[\s\v]*?\b(?:and|n(?:and|ot)|(?:xx?)?or|div|like|between|\|\||&&)\b[\s\v]*?[\"'0-9A-Z_-z][!&\(-\)\+-\.@])|[^\s\v0-9A-Z_a-z][0-9A-Z_a-z]+[\s\v]*?[\-\|][\s\v]*?[\"'`][\s\v]*?[0-9A-Z_a-z]|@(?:[0-9A-Z_a-z]+[\s\v]+(?:and|x?or|div|like|between)\b[\s\v]*?[\"'0-9`]+|[\-0-9A-Z_a-z]+[\s\v](?:and|x?or|div|like|between)\b[\s\v]*?[^\s\v0-9A-Z_a-z])|[^\s\v0-:A-Z_a-z][\s\v]*?[0-9][^0-9A-Z_a-z]+[^\s\v0-9A-Z_a-z][\s\v]*?[\"'`].|[^0-9A-Z_a-z]information_schema|table_name[^0-9A-Z_a-z]" \ + "id:942330,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects classic SQL injection probings 1/3',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942340.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942340 +# +# Note that part of 942340.data is already optimized, to avoid a +# Regexp::Assemble behaviour, where the regex is not optimized very nicely. +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)in[\s\v]*?\(+[\s\v]*?select|(?:(?:(?i:N)?AND|(?i:X)?(?i:X)?OR|DIV|LIKE|BETWEEN|NOT)[\s\v]+|(?:\|\||&&)[\s\v]*)[\s\v\+0-9A-Z_a-z]+(?:regexp[\s\v]*?\(|sounds[\s\v]+like[\s\v]*?[\"'`]|[0-9=]+x)|[\"'`](?:[\s\v]*?(?:[0-9][\s\v]*?(?:--|#)|is[\s\v]*?(?:[0-9].+[\"'`]?[0-9A-Z_a-z]|[\.0-9]+[\s\v]*?[^0-9A-Z_a-z].*?[\"'`]))|[%-&<->\^]+[0-9][\s\v]*?(?:=|x?or|div|like|between|and)|(?:[^0-9A-Z_a-z]+[\+\-0-9A-Z_a-z]+[\s\v]*?=[\s\v]*?[0-9][^0-9A-Z_a-z]+|\|?[\-0-9A-Z_a-z]{3,}[^\s\v,\.0-9A-Z_a-z]+)[\"'`]|[\s\v]*(?:(?:(?i:N)?AND|(?i:X)?(?i:X)?OR|DIV|LIKE|BETWEEN|NOT)[\s\v]+|(?:\|\||&&)[\s\v]*)(?:array[\s\v]*\[|[0-9A-Z_a-z]+(?:[\s\v]*!?~|[\s\v]+(?:not[\s\v]+)?similar[\s\v]+to[\s\v]+)|(?:tru|fals)e\b))|\bexcept[\s\v]+(?:select\b|values[\s\v]*?\()" \ + "id:942340,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects basic SQL authentication bypass attempts 3/3',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This rule is a stricter sibling of 942360. +# The keywords 'alter' and 'union' led to false positives. +# Therefore they have been moved to PL2 and the keywords have been extended on PL1. +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:^[\W\d]+\s*?(?:alter|union)\b)" \ + "id:942361,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects basic SQL injection based on keyword alter or union',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This rule is a stricter sibling of 942360. +# The loose word boundaries and light context led to false positives. +# Because the stricter variant does miss quite a few legitimate payloads, the loose version was moved to PL2. +# +# Regular expression generated from regex-assembly/942362.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942362 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:alter|(?:(?:cre|trunc|upd)at|renam)e|de(?:lete|sc)|(?:inser|selec)t|load)[\s\v]+(?:char|group_concat|load_file)[\s\v]?\(?|end[\s\v]*?\);|[\s\v\(]load_file[\s\v]*?\(|[\"'`][\s\v]+regexp[^0-9A-Z_a-z]|[^A-Z_a-z][\s\v]+as\b[\s\v]*[\"'0-9A-Z_-z]+[\s\v]*\bfrom|^[^A-Z_a-z]+[\s\v]*?(?:create[\s\v]+[0-9A-Z_a-z]+|(?:d(?:e(?:lete|sc)|rop)|(?:inser|selec)t|load|(?:renam|truncat)e|u(?:pdate|nion[\s\v]*(?:all|(?:sele|distin)ct))|alter[\s\v]*(?:a(?:(?:ggregat|pplication[\s\v]*rol)e|s(?:sembl|ymmetric[\s\v]*ke)y|u(?:dit|thorization)|vailability[\s\v]*group)|b(?:roker[\s\v]*priority|ufferpool)|c(?:ertificate|luster|o(?:l(?:latio|um)|nversio)n|r(?:edential|yptographic[\s\v]*provider))|d(?:atabase|efault|i(?:mension|skgroup)|omain)|e(?:(?:ndpoi|ve)nt|xte(?:nsion|rnal))|f(?:lashback|oreign|u(?:lltext|nction))|hi(?:erarchy|stogram)|group|in(?:dex(?:type)?|memory|stance)|java|l(?:a(?:ngua|r)ge|ibrary|o(?:ckdown|g(?:file[\s\v]*group|in)))|m(?:a(?:s(?:k|ter[\s\v]*key)|terialized)|e(?:ssage[\s\v]*type|thod)|odule)|(?:nicknam|queu)e|o(?:perator|utline)|p(?:a(?:ckage|rtition)|ermission|ro(?:cedur|fil)e)|r(?:e(?:mot|sourc)e|o(?:l(?:e|lback)|ute))|s(?:chema|e(?:arch|curity|rv(?:er|ice)|quence|ssion)|y(?:mmetric[\s\v]*key|nonym)|togroup)|t(?:able(?:space)?|ext|hreshold|r(?:igger|usted)|ype)|us(?:age|er)|view|w(?:ork(?:load)?|rapper)|x(?:ml[\s\v]*schema|srobject)))\b)" \ + "id:942362,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects concatenated basic SQL injection and SQLLFI attempts',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# This rule is a sibling of 942330. See that rule for a description and overview. +# +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# +# Regular expression generated from regex-assembly/942370.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942370 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:Referer|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\"'`](?:[\s\v]*?(?:(?:\*.+(?:x?or|div|like|between|(?:an|i)d)[^0-9A-Z_a-z]*?[\"'`]|(?:x?or|div|like|between|and)[\s\v][^0-9]+[\-0-9A-Z_a-z]+.*?)[0-9]|[^\s\v0-9\?A-Z_a-z]+[\s\v]*?[^\s\v0-9A-Z_a-z]+[\s\v]*?[\"'`]|[^\s\v0-9A-Z_a-z]+[\s\v]*?[^A-Z_a-z].*?(?:#|--))|.*?\*[\s\v]*?[0-9])|\^[\"'`]|[%\(-\+\-<>][\-0-9A-Z_a-z]+[^\s\v0-9A-Z_a-z]+[\"'`][^,]" \ + "id:942370,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects classic SQL injection probings 2/3',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942380.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942380 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:having\b(?:[\s\v]+(?:[0-9]{1,10}|'[^=]{1,10}')[\s\v]*?[<->]| ?(?:[0-9]{1,10} ?[<->]+|[\"'][^=]{1,10}[ \"'<-\?\[]+))|ex(?:ecute(?:\(|[\s\v]{1,5}[\$\.0-9A-Z_a-z]{1,5}[\s\v]{0,3})|ists[\s\v]*?\([\s\v]*?select\b)|(?:create[\s\v]+?table.{0,20}?|like[^0-9A-Z_a-z]*?char[^0-9A-Z_a-z]*?)\()|select.*?case|from.*?limit|order[\s\v]by|exists[\s\v](?:[\s\v]select|s(?:elect[^\s\v](?:if(?:null)?[\s\v]\(|top|concat)|ystem[\s\v]\()|\bhaving\b[\s\v]+[0-9]{1,10}|'[^=]{1,10}')" \ + "id:942380,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQL Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942390.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942390 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:or\b(?:[\s\v]?(?:[0-9]{1,10}|[\"'][^=]{1,10}[\"'])[\s\v]?[<->]+|[\s\v]+(?:[0-9]{1,10}|'[^=]{1,10}')(?:[\s\v]*?[<->])?)|xor\b[\s\v]+(?:[0-9]{1,10}|'[^=]{1,10}')(?:[\s\v]*?[<->])?)|'[\s\v]+x?or[\s\v]+.{1,20}[!\+\-<->]" \ + "id:942390,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQL Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/942400.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942400 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\band\b(?:[\s\v]+(?:[0-9]{1,10}[\s\v]*?[<->]|'[^=]{1,10}')| ?(?:[0-9]{1,10}|[\"'][^=]{1,10}[\"']) ?[<->]+)" \ + "id:942400,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQL Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# The former rule id 942410 was split into three new rules: 942410, 942470, 942480 +# +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# +# Regular expression generated from regex-assembly/942410.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942410 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:a(?:(?:b|co)s|dd(?:dat|tim)e|es_(?:de|en)crypt|s(?:in|cii(?:str)?)|tan2?|vg)|b(?:enchmark|i(?:n(?:_to_num)?|t_(?:and|count|length|x?or)))|c(?:ast|h(?:ar(?:(?:acter)?_length|set)?|r)|iel(?:ing)?|o(?:alesce|ercibility|(?:mpres)?s|n(?:cat(?:_ws)?|nection_id|v(?:ert(?:_tz)?)?)|(?:un)?t)|r32|ur(?:(?:dat|tim)e|rent_(?:date|time(?:stamp)?|user)))|d(?:a(?:t(?:abase|e(?:_(?:add|format|sub)|diff)?)|y(?:name|of(?:month|week|year))?)|count|e(?:code|(?:faul|s_(?:de|en)cryp)t|grees)|ump)|e(?:lt|nc(?:ode|rypt)|x(?:p(?:ort_set)?|tract(?:value)?))|f(?:i(?:eld(?:_in_set)?|nd_in_set)|loor|o(?:rmat|und_rows)|rom_(?:base64|days|unixtime))|g(?:et_(?:format|lock)|r(?:eates|oup_conca)t)|h(?:ex(?:toraw)?|our)|i(?:f(?:null)?|n(?:et6?_(?:aton|ntoa)|s(?:ert|tr)|terval)?|s(?:_(?:(?:free|used)_lock|ipv(?:4(?:_(?:compat|mapped))?|6)|n(?:ot(?:_null)?|ull))|null)?)|l(?:ast(?:_(?:day|insert_id))?|case|e(?:(?:as|f)t|ngth)|n|o(?:ad_file|ca(?:l(?:timestamp)?|te)|g(?:10|2)?|wer)|pad|trim)|m(?:a(?:ke(?:date|_set)|ster_pos_wait|x)|d5|i(?:(?:crosecon)?d|n(?:ute)?)|o(?:d|nth(?:name)?))|n(?:ame_const|o(?:t_in|w)|ullif)|o(?:ct(?:et_length)?|(?:ld_passwo)?rd)|p(?:assword|eriod_(?:add|diff)|g_sleep|i|o(?:sition|w(?:er)?)|rocedure_analyse)|qu(?:arter|ote)|r(?:a(?:dians|nd|wto(?:hex|nhex(?:toraw)?))|e(?:lease_lock|p(?:eat|lace)|verse)|ight|o(?:und|w_count)|pad|trim)|s(?:chema|e(?:c(?:ond|_to_time)|ssion_user)|ha[1-2]?|ig?n|leep|oundex|pace|qrt|t(?:d(?:dev(?:_(?:po|sam)p)?)?|r(?:cmp|_to_date))|u(?:b(?:(?:dat|tim)e|str(?:ing(?:_index)?)?)|m)|ys(?:date|tem_user))|t(?:an|ime(?:diff|_(?:format|to_sec)|stamp(?:add|diff)?)?|o_(?:base64|n?char|(?:day|second)s)|r(?:im|uncate))|u(?:case|n(?:compress(?:ed_length)?|hex|ix_timestamp)|p(?:datexml|per)|ser|tc_(?:date|time(?:stamp)?)|uid(?:_short)?)|v(?:a(?:lues|r(?:iance|_(?:po|sam)p))|ersion)|we(?:ek(?:day|ofyear)?|ight_string)|xmltype|year(?:week)?)[^0-9A-Z_a-z]*?\(" \ + "id:942410,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQL Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# The former rule id 942410 was split into three new rules: 942410, 942470, 942480 +# +# Regular expression generated from regex-assembly/942470.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942470 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)autonomous_transaction|(?:current_use|n?varcha|tbcreato)r|db(?:a_users|ms_java)|open(?:owa_util|query|rowset)|s(?:p_(?:(?:addextendedpro|sqlexe)c|execute(?:sql)?|help|is_srvrolemember|makewebtask|oacreate|p(?:assword|repare)|replwritetovarbin)|ql_(?:longvarchar|variant))|utl_(?:file|http)|xp_(?:availablemedia|(?:cmdshel|servicecontro)l|dirtree|e(?:numdsn|xecresultset)|filelist|loginconfig|makecab|ntsec(?:_enumdomains)?|reg(?:addmultistring|delete(?:key|value)|enum(?:key|value)s|re(?:ad|movemultistring)|write)|terminate(?:_process)?)" \ + "id:942470,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQL Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# The former rule id 942410 was split into three new rules: 942410, 942470, 942480 +# +# Regular expression generated from regex-assembly/942480.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942480 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:(?:d(?:bms_[0-9A-Z_a-z]+\.|elete\b[^0-9A-Z_a-z]*?\bfrom)|(?:group\b.*?\bby\b.{1,100}?\bhav|overlay\b[^0-9A-Z_a-z]*?\(.*?\b[^0-9A-Z_a-z]*?plac)ing|in(?:ner\b[^0-9A-Z_a-z]*?\bjoin|sert\b[^0-9A-Z_a-z]*?\binto|to\b[^0-9A-Z_a-z]*?\b(?:dump|out)file)|load\b[^0-9A-Z_a-z]*?\bdata\b.*?\binfile|s(?:elect\b.{1,100}?\b(?:(?:.*?\bdump\b.*|(?:count|length)\b.{1,100}?)\bfrom|(?:data_typ|from\b.{1,100}?\bwher)e|instr|to(?:_(?:cha|numbe)r|p\b.{1,100}?\bfrom))|ys_context)|u(?:nion\b.{1,100}?\bselect|tl_inaddr))\b|print\b[^0-9A-Z_a-z]*?@@)|(?:collation[^0-9A-Z_a-z]*?\(a|@@version|;[^0-9A-Z_a-z]*?\b(?:drop|shutdown))\b|'(?:dbo|msdasql|s(?:a|qloledb))'" \ + "id:942480,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQL Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# +# [ SQL Injection Character Anomaly Usage ] +# +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# +# This rules attempts to gauge when there is an excessive use of +# meta-characters within a single parameter payload. +# +# Expect a lot of false positives with this rule. +# The most likely false positive instances will be free-form text fields. +# This will make it necessary to disable the rule for certain known parameters. +# The following directive is an example to switch off the rule globally for +# the parameter foo. Place this instruction in your configuration after +# the include directive for the Core Rules Set. +# +# SecRuleUpdateTargetById 942430 "!ARGS:foo" +# + +SecRule ARGS_NAMES|ARGS|XML:/* "@rx ((?:[~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>][^~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>]*?){12})" \ + "id:942430,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (12)',\ + logdata:'Matched Data: %{TX.1} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.warning_anomaly_score}'" + + +# +# -=[ Detect SQL Comment Sequences ]=- +# +# Example Payloads Detected: +# ------------------------- +# OR 1# +# DROP sampletable;-- +# admin'-- +# DROP/*comment*/sampletable +# DR/**/OP/*bypass deny listing*/sampletable +# SELECT/*avoid-spaces*/password/**/FROM/**/Members +# SELECT /*!32302 1/0, */ 1 FROM tablename +# ‘ or 1=1# +# ‘ or 1=1-- - +# ‘ or 1=1/* +# ' or 1=1;\x00 +# 1='1' or-- - +# ' /*!50000or*/1='1 +# ' /*!or*/1='1 +# 0/**/union/*!50000select*/table_name`foo`/**/ +# ------------------------- +# +# The chained rule is designed to prevent false positives by specifically +# targeting JWT tokens. Starting with 'ey' targets JWT tokens, where the 'ey' +# prefix corresponds to the beginning of the Base64-encoded header section. +# +# example: +# $ echo '{"' | base64 +# eyIK +# +# Regular expression generated from regex-assembly/942440.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942440 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx /\*!?|\*/|[';]--|--(?:[\s\v]|[^\-]*?-)|[^&\-]#.*?[\s\v]|;?\x00" \ + "id:942440,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQL Comment Sequence Detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + chain" + SecRule MATCHED_VARS "!@rx ^ey[\-0-9A-Z_a-z]+\.ey[\-0-9A-Z_a-z]+\.[\-0-9A-Z_a-z]+$" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + + +# +# -=[ SQL Hex Evasion Methods ]=- +# +# Hex encoding detection: +# (?i:\b0x[a-f\d]{3,}) will match any 3 or more hex bytes after "0x", together forming a hexadecimal payload(e.g 0xf00, 0xf00d and so on) +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:\b0x[a-f\d]{3,})" \ + "id:942450,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQL Hex Encoding Identified',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# +# -=[ Detect SQLi bypass: backticks ]=- +# +# Quotes and backticks can be used to bypass SQLi detection. +# +# Example: +# GET http://localhost/test.php?id=9999%20or+{`if`(2=(select+2+from+wp_users+where+user_login='admin'))} +# +# The minimum text between the ticks or backticks must be 2 (if, for example) and a maximum of 29. +# 29 is a compromise: The lower this number (29), the lower the probability of FP and the higher the probability of false negatives. +# In tests we got a minimum number of FP with {2,29}. +# +# Base64 encoding detection: +# (?:[A-Za-z0-9+/]{4})+ #match any number of 4-letter blocks of the base64 char set +# (?:[A-Za-z0-9+/]{2}== #match 2-letter block of the base64 char set followed by "==", together forming a 4-letter block +# | # or +# [A-Za-z0-9+/]{3}= #match 3-letter block of the base64 char set followed by "=", together forming a 4-letter block +# )? +# +# The minimal string that triggers this regexp is: `if` +# +# The rule 942510 is related to 942110 which catches a single ' or ` +# +# The rule 942511 is similar to this rule, but triggers on normal quotes +# ('if'). That rule runs in paranoia level 3 or higher since it is prone to +# false positives in natural text. +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:`(?:(?:[\w\s=_\-+{}()<@]){2,29}|(?:[A-Za-z0-9+/]{4})+(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)`)" \ + "id:942510,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQLi bypass attempt by ticks or backticks detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# Regular expression generated from regex-assembly/942520.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942520 +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\"'`][\s\v]*?(?:(?:is[\s\v]+not|not[\s\v]+(?:like|glob|(?:betwee|i)n|null|regexp|match)|mod|div|sounds[\s\v]+like)\b|[%-&\*-\+\-/<->\^\|])" \ + "id:942520,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects basic SQL authentication bypass attempts 4.0/4',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# Complementary rule to PL2 942520 that block and/or-based bypasses. +# It blocks data with odd number of quotes and then (and|or). +# +# The rule uses the expression ^b*a*(b*a*b*a*)* to odd number of a's. It's not +# vulnerable to ReDos as it executes linearly many steps compared to input size. +# +# Regular expression generated from regex-assembly/942521.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942521 +# +SecRule REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)^(?:[^']*?(?:'[^']*?'[^']*?)*?'|[^\"]*?(?:\"[^\"]*?\"[^\"]*?)*?\"|[^`]*?(?:`[^`]*?`[^`]*?)*?`)[\s\v]*([0-9A-Z_a-z]+)\b" \ + "id:942521,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects basic SQL authentication bypass attempts 4.1/4',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + chain" + SecRule TX:1 "@rx ^(?:and|or)$" \ + "t:none,\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# Complementary rule to PL2 942521 that block escaped quotes followed by (and|or) +# +SecRule ARGS_NAMES|ARGS|XML:/* "@rx ^.*?\x5c['\"`](?:.*?['\"`])?\s*(?:and|or)\b" \ + "id:942522,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects basic SQL authentication bypass attempts 4.1/4',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# +# This is a sibling of rule 942100 that adds checking of the path. +# +# REQUEST_BASENAME provides the last url segment (slash excluded). +# This segment is the most likely to be used for injections. Stripping out +# the slash permits libinjection to do not consider it as a payload starting +# with not unary arithmetical operators (not a valid SQL command, e.g. +# '/9 union all'). The latter would lead to do not detect malicious payloads. +# +# REQUEST_FILENAME matches SQLi payloads inside (or across) other segments +# of the path. Here, libinjection will detect a true positive only if +# the url leading slash is considered as part of a comment block or part +# of a string (with a quote or double quote after it). In these circumstances, +# previous slashes do not affect libinjection result, making it able to detect +# some SQLi inside the path. +# +SecRule REQUEST_BASENAME|REQUEST_FILENAME "@detectSQLi" \ + "id:942101,\ + phase:1,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,\ + msg:'SQL Injection Attack Detected via libinjection',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ SQL Function Names ]=- +# +# This rule is a stricter sibling of 942151. +# This rule 942152 checks for the same regex in request headers referer and user-agent. +# +# Regular expression generated from regex-assembly/942152.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942152 +# +SecRule REQUEST_HEADERS:Referer|REQUEST_HEADERS:User-Agent "@rx (?i)\b(?:a(?:dd(?:dat|tim)e|es_(?:de|en)crypt|s(?:cii(?:str)?|in)|tan2?)|b(?:enchmark|i(?:n_to_num|t_(?:and|count|length|x?or)))|c(?:har(?:acter)?_length|iel(?:ing)?|o(?:alesce|ercibility|llation|(?:mpres)?s|n(?:cat(?:_ws)?|nection_id|v(?:ert(?:_tz)?)?)|t)|r32|ur(?:(?:dat|tim)e|rent_(?:date|setting|time(?:stamp)?|user)))|d(?:a(?:t(?:abase(?:_to_xml)?|e(?:_(?:add|format|sub)|diff))|y(?:name|of(?:month|week|year)))|count|e(?:code|grees|s_(?:de|en)crypt)|ump)|e(?:lt|n(?:c(?:ode|rypt)|ds_?with)|x(?:p(?:ort_set)?|tract(?:value)?))|f(?:i(?:el|n)d_in_set|ound_rows|rom_(?:base64|days|unixtime))|g(?:e(?:ometrycollection|t(?:_(?:format|lock)|pgusername))|(?:r(?:eates|oup_conca)|tid_subse)t)|hex(?:toraw)?|i(?:fnull|n(?:et6?_(?:aton|ntoa)|s(?:ert|tr)|terval)|s(?:_(?:(?:free|used)_lock|ipv(?:4(?:_(?:compat|mapped))?|6)|n(?:ot(?:_null)?|ull)|superuser)|null))|json(?:_(?:a(?:gg|rray(?:_(?:elements(?:_text)?|length))?)|build_(?:array|object)|e(?:ac|xtract_pat)h(?:_text)?|object(?:_(?:agg|keys))?|populate_record(?:set)?|strip_nulls|t(?:o_record(?:set)?|ypeof))|b(?:_(?:array(?:_(?:elements(?:_text)?|length))?|build_(?:array|object)|object(?:_(?:agg|keys))?|e(?:ac|xtract_pat)h(?:_text)?|insert|p(?:ath_(?:(?:exists|match)(?:_tz)?|query(?:_(?:(?:array|first)(?:_tz)?|tz))?)|opulate_record(?:set)?|retty)|s(?:et(?:_lax)?|trip_nulls)|t(?:o_record(?:set)?|ypeof)))?|path)?|l(?:ast_(?:day|inser_id)|case|e(?:as|f)t|i(?:kel(?:ihood|y)|nestring)|o(?:_(?:from_bytea|put)|ad_file|ca(?:ltimestamp|te)|g(?:10|2)|wer)|pad|trim)|m(?:a(?:ke(?:_set|date)|ster_pos_wait)|d5|i(?:crosecon)?d|onthname|ulti(?:linestring|po(?:int|lygon)))|n(?:ame_const|ot_in|ullif)|o(?:ct(?:et_length)?|(?:ld_passwo)?rd)|p(?:eriod_(?:add|diff)|g_(?:client_encoding|(?:databas|read_fil)e|l(?:argeobject|s_dir)|sleep|user)|o(?:(?:lyg|siti)on|w)|rocedure_analyse)|qu(?:arter|ery_to_xml|ote)|r(?:a(?:dians|nd|wtohex)|elease_lock|ow_(?:count|to_json)|pad|trim)|s(?:chema|e(?:c_to_time|ssion_user)|ha[1-2]?|in|oundex|pace|q(?:lite_(?:compileoption_(?:get|used)|source_id)|rt)|t(?:arts_?with|d(?:dev_(?:po|sam)p)?|r(?:_to_date|cmp))|ub(?:(?:dat|tim)e|str(?:ing(?:_index)?)?)|ys(?:date|tem_user))|t(?:ime(?:_(?:format|to_sec)|diff|stamp(?:add|diff)?)|o(?:_(?:base64|jsonb?)|n?char|(?:day|second)s)|r(?:im|uncate))|u(?:case|n(?:compress(?:ed_length)?|hex|i(?:str|x_timestamp)|likely)|(?:pdatexm|se_json_nul)l|tc_(?:date|time(?:stamp)?)|uid(?:_short)?)|var(?:_(?:po|sam)p|iance)|we(?:ek(?:day|ofyear)|ight_string)|xmltype|yearweek)[^0-9A-Z_a-z]*\(" \ + "id:942152,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,t:lowercase,\ + msg:'SQL Injection Attack: SQL function name detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# This rule is a stricter sibling of 942320. +# It checks for the same regex in request headers referer and user-agent. +# +# Regular expression generated from regex-assembly/942321.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 942321 +# +SecRule REQUEST_HEADERS:Referer|REQUEST_HEADERS:User-Agent "@rx (?i)create[\s\v]+(?:function|procedure)[\s\v]*?[0-9A-Z_a-z]+[\s\v]*?\([\s\v]*?\)[\s\v]*?-|d(?:eclare[^0-9A-Z_a-z]+[#@][\s\v]*?[0-9A-Z_a-z]+|iv[\s\v]*?\([\+\-]*[\s\v\.0-9]+,[\+\-]*[\s\v\.0-9]+\))|exec[\s\v]*?\([\s\v]*?@|(?:lo_(?:impor|ge)t|procedure[\s\v]+analyse)[\s\v]*?\(|;[\s\v]*?(?:declare|open)[\s\v]+[\-0-9A-Z_a-z]+|::(?:b(?:igint|ool)|double[\s\v]+precision|int(?:eger)?|numeric|oid|real|(?:tex|smallin)t)" \ + "id:942321,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects MySQL and PostgreSQL stored procedure/function injections',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:942015,phase:1,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:942016,phase:2,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + + +# +# [ SQL HAVING queries ] +# +# This pattern was split off from rule 942250 due to frequent +# false positives in English text. Testing showed that SQL +# injections with HAVING should be detected by libinjection +# (rule 942100). +# +# This is a stricter sibling of rule 942250. +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\W+\d*?\s*?\bhaving\b\s*?[^\s\-]" \ + "id:942251,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects HAVING injections',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# This rule is a stricter sibling of 942330. See that rule for a +# description and overview. +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx [\"'`][\s\d]*?[^\w\s]\W*?\d\W*?.*?[\"'`\d]" \ + "id:942490,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Detects classic SQL injection probings 3/3',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# +# [ SQL Injection Character Anomaly Usage ] +# +# This rule attempts to gauge when there is an excessive use of +# meta-characters within a single parameter payload. +# +# It is similar to 942430, but focuses on Cookies instead of +# GET/POST parameters. +# +# Expect a lot of false positives with this rule. +# The most likely false positive instances will be complex session ids. +# This will make it necessary to disable the rule for certain known cookies. +# The following directive is an example to switch off the rule globally for +# the cookie foo_id. Place this instruction in your configuration after +# the include directive for the Core Rules Set. +# +# SecRuleUpdateTargetById 942420 "!REQUEST_COOKIES:foo_id" +# + +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES "@rx ((?:[~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>][^~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>]*?){8})" \ + "id:942420,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Restricted SQL Character Anomaly Detection (cookies): # of special characters exceeded (8)',\ + logdata:'Matched Data: %{TX.1} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.warning_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.warning_anomaly_score}'" + + +# +# This is a stricter sibling of rule 942430. +# +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# + +SecRule ARGS_NAMES|ARGS|XML:/* "@rx ((?:[~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>][^~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>]*?){6})" \ + "id:942431,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (6)',\ + logdata:'Matched Data: %{TX.1} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.warning_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.warning_anomaly_score}'" + + +# +# [ Repetitive Non-Word Characters ] +# +# This rule attempts to identify when multiple (4 or more) non-word characters +# are repeated in sequence. +# +# The pattern may occur in some normal texts, e.g. "foo...." will match. +# +SecRule ARGS "@rx \W{4}" \ + "id:942460,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Meta-Character Anomaly Detection Alert - Repetitive Non-Word Characters',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'WARNING',\ + setvar:'tx.sql_injection_score=+%{tx.warning_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.warning_anomaly_score}'" + + +# +# -=[ Detect SQLi bypass: quotes ]=- +# +# Quotes and backticks can be used to bypass SQLi detection. +# +# Example: +# GET http://localhost/test.php?id=9999%20or+{`if`(2=(select+2+from+wp_users+where+user_login='admin'))} +# +# The minimum text between the ticks or backticks must be 2 (if, for example) and a maximum of 29. +# 29 is a compromise: The lower this number (29), the lower the probability of FP and the higher the probability of false negatives. +# In tests we got a minimum number of FP with {2,29}. +# +# Base64 encoding detection: +# (?:[A-Za-z0-9+/]{4})+ #match any number of 4-letter blocks of the base64 char set +# (?:[A-Za-z0-9+/]{2}== #match 2-letter block of the base64 char set followed by "==", together forming a 4-letter block +# | # or +# [A-Za-z0-9+/]{3}= #match 3-letter block of the base64 char set followed by "=", together forming a 4-letter block +# )? +# +# The minimal string that triggers this regexp is: 'if' +# +# The rule 942511 is related to 942110 which catches a single ' or ` +# +# The rule 942510 is similar to this rule, but triggers on backticks +# (`if`). That rule runs in paranoia level 2 or higher since the risk of +# false positives in natural text is still present but lower than this +# rule. +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:'(?:(?:[\w\s=_\-+{}()<@]){2,29}|(?:[A-Za-z0-9+/]{4})+(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)')" \ + "id:942511,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQLi bypass attempt by ticks detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# Detects '; +# ' Single quote. Used to delineate a query with an unmatched quote. +# ; Terminate a query. A prematurely terminated query creates an error. +# Explanation source: +# https://hwang.cisdept.cpp.edu/swanew/Text/SQL-Injection.htm +# +# Bug Bounty example: email=admin@juice-sh.op';&password=foo +# +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ';" \ + "id:942530,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'SQLi query termination detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/3',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:942017,phase:1,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:942018,phase:2,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + +# +# [ SQL Injection Character Anomaly Usage ] +# +# This is a stricter sibling of rule 942420. +# + +SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES "@rx ((?:[~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>][^~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>]*?){3})" \ + "id:942421,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Restricted SQL Character Anomaly Detection (cookies): # of special characters exceeded (3)',\ + logdata:'Matched Data: %{TX.1} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/4',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.warning_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.warning_anomaly_score}'" + + +# +# This is a stricter sibling of rule 942430. +# +# This rule is also triggered by the following exploit(s): +# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] +# + +SecRule ARGS_NAMES|ARGS|XML:/* "@rx ((?:[~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>][^~!@#\$%\^&\*\(\)\-\+=\{\}\[\]\|:;\"'´’‘`<>]*?){2})" \ + "id:942432,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (2)',\ + logdata:'Matched Data: %{TX.1} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-sqli',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248/66',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/4',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.warning_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.warning_anomaly_score}'" + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-942-APPLICATION-ATTACK-SQLI" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf similarity index 71% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf index f575d2cf4f..af8ad4f0fb 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -14,10 +14,10 @@ -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:943011,phase:1,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:943012,phase:2,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:943011,phase:1,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:943012,phase:2,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # @@ -43,11 +43,10 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/225/21/593/61',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.session_fixation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule ARGS_NAMES "@rx ^(?:jsessionid|aspsessionid|asp\.net_sessionid|phpsession|phpsessid|weblogicsession|session_id|session-id|cfid|cftoken|cfsid|jservsession|jwsession)$" \ @@ -55,7 +54,7 @@ SecRule ARGS_NAMES "@rx ^(?:jsessionid|aspsessionid|asp\.net_sessionid|phpsessio phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:lowercase,\ + t:none,t:lowercase,\ msg:'Possible Session Fixation Attack: SessionID Parameter Name with Off-Domain Referer',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -65,16 +64,15 @@ SecRule ARGS_NAMES "@rx ^(?:jsessionid|aspsessionid|asp\.net_sessionid|phpsessio tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/225/21/593/61',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" - SecRule REQUEST_HEADERS:Referer "@rx ^(?:ht|f)tps?://(.*?)\/" \ + SecRule REQUEST_HEADERS:Referer "@rx ^(?:ht|f)tps?://(.*?)/" \ "capture,\ chain" SecRule TX:1 "!@endsWith %{request_headers.host}" \ - "ctl:auditLogParts=+E,\ - setvar:'tx.session_fixation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + "setvar:'tx.session_fixation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule ARGS_NAMES "@rx ^(?:jsessionid|aspsessionid|asp\.net_sessionid|phpsession|phpsessid|weblogicsession|session_id|session-id|cfid|cftoken|cfsid|jservsession|jwsession)$" \ @@ -82,7 +80,7 @@ SecRule ARGS_NAMES "@rx ^(?:jsessionid|aspsessionid|asp\.net_sessionid|phpsessio phase:2,\ block,\ capture,\ - t:none,t:urlDecodeUni,t:lowercase,\ + t:none,t:lowercase,\ msg:'Possible Session Fixation Attack: SessionID Parameter Name with No Referer',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ @@ -92,37 +90,36 @@ SecRule ARGS_NAMES "@rx ^(?:jsessionid|aspsessionid|asp\.net_sessionid|phpsessio tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/1000/225/21/593/61',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" SecRule &REQUEST_HEADERS:Referer "@eq 0" \ - "ctl:auditLogParts=+E,\ - setvar:'tx.session_fixation_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + "setvar:'tx.session_fixation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:943013,phase:1,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:943014,phase:2,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:943013,phase:1,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:943014,phase:2,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:943015,phase:1,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:943016,phase:2,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:943015,phase:1,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:943016,phase:2,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:943017,phase:1,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:943018,phase:2,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:943017,phase:1,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:943018,phase:2,pass,nolog,skipAfter:END-REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-944-APPLICATION-ATTACK-JAVA.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf similarity index 60% rename from pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-944-APPLICATION-ATTACK-JAVA.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf index 4075e18f5f..df224f33ae 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/REQUEST-944-APPLICATION-ATTACK-JAVA.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -13,10 +13,10 @@ # # Many rules check request bodies, use "SecRequestBodyAccess On" to enable it on main modsecurity configuration file. -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:944011,phase:1,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:944012,phase:2,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:944011,phase:1,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:944012,phase:2,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # This rule is also triggered by an Apache Struts exploit: # [ Apache Struts vulnerability CVE-2017-5638 - Exploit tested: https://github.com/xsscx/cve-2017-5638 ] @@ -36,7 +36,6 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES phase:2,\ block,\ t:none,t:lowercase,\ - log,\ msg:'Remote Command Execution: Suspicious Java class detected',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -47,10 +46,10 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/137/6',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # This rule is also triggered by the following exploit(s): # [ Apache Struts vulnerability CVE-2017-5638 - Exploit tested: https://github.com/xsscx/cve-2017-5638 ] @@ -70,7 +69,6 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES phase:2,\ block,\ t:none,t:lowercase,\ - log,\ msg:'Remote Command Execution: Java process spawn (CVE-2017-9805)',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -81,12 +79,12 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/248',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_BODY|REQUEST_HEADERS|XML:/*|XML://@* "@rx (?:unmarshaller|base64data|java\.)" \ "setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # Magic bytes detected and payload included possibly RCE vulnerable classes detected and process execution methods detected # anomaly score set to critical as all conditions indicate the request try to perform RCE. @@ -96,7 +94,6 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES phase:2,\ block,\ t:none,t:lowercase,\ - log,\ msg:'Remote Command Execution: Java serialization (CVE-2015-4852)',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -107,13 +104,12 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/248',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ chain" SecRule MATCHED_VARS "@rx (?:runtime|processbuilder)" \ - "t:none,t:lowercase,\ - setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + "setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # This rule is also triggered by the following exploit(s): # [ Apache Struts vulnerability CVE-2017-5638 - Exploit tested: https://github.com/mazen160/struts-pwn ] @@ -129,8 +125,7 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES "id:944130,\ phase:2,\ block,\ - t:none,t:lowercase,\ - log,\ + t:none,\ msg:'Suspicious Java class detected',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -141,17 +136,135 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/248',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/1',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ Java Script Uploads ] +# +# Block file uploads with filenames ending in Java scripts (.jsp, .jspx) +# +# Many application contain Unrestricted File Upload vulnerabilities. +# https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload +# +# Attackers may use such a vulnerability to achieve remote code execution +# by uploading a script file. If the upload storage location is predictable +# and not adequately protected, the attacker may then request the uploaded +# file and have the code within it executed on the server. +# +# Some AJAX uploaders use the nonstandard request headers X-Filename, +# X_Filename, or X-File-Name to transmit the file name to the server; +# scan these request headers as well as multipart/form-data file names. +# +SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X.Filename|REQUEST_HEADERS:X-File-Name "@rx .*\.(?:jsp|jspx)\.*$" \ + "id:944140,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'Java Injection Attack: Java Script File Upload Found',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-java',\ + tag:'platform-multi',\ + tag:'attack-injection-java',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Log4J / Log4Shell Defense +# +# This addresses exploits against the Log4J library described in several CVEs: +# * CVE-2021-44228 +# * CVE-2021-44832 +# * CVE-2021-45046 +# * CVE-2021-45105 +# +# See https://coreruleset.org/20211213/crs-and-log4j-log4shell-cve-2021-44228/ +# +# This rule attempts to detect two things: +# * Nested use of ${ +# * use of ${jndi:... without the closing bracket +# +# Rule 932130 is also essential for defense since there are certain +# bypasses of the log4j rules that can be caught by 932130. +# +# The payload is not displayed in the alert message since log4j could +# potentially be executed on the logviewer. +# +# This rule has stricter siblings: 944151 (PL2), 944152 (PL4) +# +# Regular expression generated from regex-assembly/944150.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 944150 +# +SecRule REQUEST_LINE|ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|XML:/*|XML://@* "@rx (?i)(?:\$|$?)(?:\{|&l(?:brace|cub);?)(?:[^\}]{0,15}(?:\$|$?)(?:\{|&l(?:brace|cub);?)|jndi|ctx)" \ + "id:944150,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,t:jsDecode,t:htmlEntityDecode,\ + log,\ + msg:'Potential Remote Command Execution: Log4j / Log4shell',\ + tag:'application-multi',\ + tag:'language-java',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/137/6',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/1',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:944013,phase:1,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:944014,phase:2,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:944013,phase:1,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:944014,phase:2,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +# This is a stricter sibling of 944150. +# It is a re-iteration of said rule without the curly bracket distance limiter +# between the nested "${". This is prone to backtracking and therefore a potential +# DoS problem for backtracking regular expression engines (e.g. PCRE2), but it also avoids evasions that fill the space between the nested +# elements with arbitrary data. # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# Regular expression generated from regex-assembly/944151.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 944151 # +SecRule REQUEST_LINE|ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|XML:/*|XML://@* "@rx (?i)(?:\$|$?)(?:\{|&l(?:brace|cub);?)(?:[^\}]*(?:\$|$?)(?:\{|&l(?:brace|cub);?)|jndi|ctx)" \ + "id:944151,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,t:jsDecode,t:htmlEntityDecode,\ + log,\ + msg:'Potential Remote Command Execution: Log4j / Log4shell',\ + tag:'application-multi',\ + tag:'language-java',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/137/6',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + # [ Java deserialization vulnerability/Apache Commons (CVE-2015-4852) ] # # Detect exploitation of "Java deserialization" Apache Commons. @@ -169,7 +282,6 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES "id:944200,\ phase:2,\ block,\ - log,\ msg:'Magic bytes Detected, probable java serialization in use',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -180,10 +292,10 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/248',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # Detecting possible base64 text to match encoded magic bytes \xac\xed\x00\x05 with padding encoded in base64 strings are rO0ABQ KztAAU Cs7QAF SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_BODY|REQUEST_HEADERS|XML:/*|XML://@* \ @@ -191,7 +303,6 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES "id:944210,\ phase:2,\ block,\ - log,\ msg:'Magic bytes Detected Base64 Encoded, probable java serialization in use',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -202,10 +313,10 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/248',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_BODY|REQUEST_HEADERS|XML:/*|XML://@* \ "@rx (?:clonetransformer|forclosure|instantiatefactory|instantiatetransformer|invokertransformer|prototypeclonefactory|prototypeserializationfactory|whileclosure|getproperty|filewriter|xmldecoder)" \ @@ -213,7 +324,6 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES phase:2,\ block,\ t:none,t:lowercase,\ - log,\ msg:'Remote Command Execution: Java serialization (CVE-2015-4852)',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -224,10 +334,10 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/248',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # This rule is also triggered by the following exploit(s): # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] @@ -238,7 +348,6 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES phase:2,\ block,\ t:lowercase,\ - log,\ msg:'Remote Command Execution: Suspicious Java method detected',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -249,17 +358,41 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/248',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/2',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This rule is also triggered by the following exploit(s): +# - https://www.rapid7.com/blog/post/2022/03/30/spring4shell-zero-day-vulnerability-in-spring-framework/ +# +SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_BODY|REQUEST_HEADERS|XML:/*|XML://@* \ + "@rx (?:class\.module\.classLoader\.resources\.context\.parent\.pipeline|springframework\.context\.support\.FileSystemXmlApplicationContext)" \ + "id:944260,\ + phase:2,\ + block,\ + t:urlDecodeUni,\ + msg:'Remote Command Execution: Malicious class-loading payload',\ + logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-java',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/248',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/2',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:944015,phase:1,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:944016,phase:2,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:944015,phase:1,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:944016,phase:2,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # # Interesting keywords for possibly RCE on vulnerable classes and methods base64 encoded # Keywords = ['runtime', 'processbuilder', 'clonetransformer', 'forclosure', 'instantiatefactory', 'instantiatetransformer', 'invokertransformer', 'prototypeclonefactory', 'prototypeserializationfactory', 'whileclosure'] @@ -274,7 +407,6 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES phase:2,\ block,\ t:none,\ - log,\ msg:'Base64 encoded string matched suspicious keyword',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ @@ -285,18 +417,46 @@ SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES tag:'capec/1000/152/248',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/3',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ - setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:944017,phase:1,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:944018,phase:2,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:944017,phase:1,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:944018,phase:2,pass,nolog,skipAfter:END-REQUEST-944-APPLICATION-ATTACK-JAVA" # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # +# This is a stricter sibling of 944150. +# It simply checks for the existence of `${`, taking into account the same encoding evasions +# as 944150. +# +# Regular expression generated from regex-assembly/944152.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 944152 +# +SecRule REQUEST_LINE|ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|XML:/*|XML://@* "@rx (?i)(?:\$|$?)(?:\{|&l(?:brace|cub);?)" \ + "id:944152,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,t:jsDecode,t:htmlEntityDecode,\ + log,\ + msg:'Potential Remote Command Execution: Log4j / Log4shell',\ + tag:'application-multi',\ + tag:'language-java',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/152/137/6',\ + tag:'PCI/6.5.2',\ + tag:'paranoia-level/4',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # # -= Paranoia Levels Finished =- diff --git a/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf new file mode 100644 index 0000000000..e8ac6e9d37 --- /dev/null +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf @@ -0,0 +1,223 @@ +# ------------------------------------------------------------------------ +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2023 Core Rule Set project. 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 blocking and detection anomaly scores in phase 1 +# even when early blocking is disabled, we need to sum up the scores in phase 1 +# this prevents bugs in phase 5 if Apache skips phases because of error handling +# See: https://github.com/coreruleset/coreruleset/issues/2319#issuecomment-1047503932 + +SecRule TX:BLOCKING_PARANOIA_LEVEL "@ge 1" \ + "id:949052,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl1}'" +SecRule TX:DETECTION_PARANOIA_LEVEL "@ge 1" \ + "id:949152,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl1}'" + +SecRule TX:BLOCKING_PARANOIA_LEVEL "@ge 2" \ + "id:949053,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl2}'" +SecRule TX:DETECTION_PARANOIA_LEVEL "@ge 2" \ + "id:949153,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl2}'" + +SecRule TX:BLOCKING_PARANOIA_LEVEL "@ge 3" \ + "id:949054,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl3}'" +SecRule TX:DETECTION_PARANOIA_LEVEL "@ge 3" \ + "id:949154,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl3}'" + +SecRule TX:BLOCKING_PARANOIA_LEVEL "@ge 4" \ + "id:949055,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl4}'" +SecRule TX:DETECTION_PARANOIA_LEVEL "@ge 4" \ + "id:949155,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl4}'" + +# at start of phase 2, we reset the aggregate scores to 0 to prevent duplicate counting of per-PL scores +# this is necessary because the per-PL scores are counted across phases +SecAction \ + "id:949059,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=0'" +SecAction \ + "id:949159,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=0'" + +# Summing up the blocking and detection anomaly scores in phase 2 + +SecRule TX:BLOCKING_PARANOIA_LEVEL "@ge 1" \ + "id:949060,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl1}'" +SecRule TX:DETECTION_PARANOIA_LEVEL "@ge 1" \ + "id:949160,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl1}'" + +SecRule TX:BLOCKING_PARANOIA_LEVEL "@ge 2" \ + "id:949061,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl2}'" +SecRule TX:DETECTION_PARANOIA_LEVEL "@ge 2" \ + "id:949161,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl2}'" + +SecRule TX:BLOCKING_PARANOIA_LEVEL "@ge 3" \ + "id:949062,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl3}'" +SecRule TX:DETECTION_PARANOIA_LEVEL "@ge 3" \ + "id:949162,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl3}'" + +SecRule TX:BLOCKING_PARANOIA_LEVEL "@ge 4" \ + "id:949063,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.blocking_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl4}'" +SecRule TX:DETECTION_PARANOIA_LEVEL "@ge 4" \ + "id:949163,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + setvar:'tx.detection_inbound_anomaly_score=+%{tx.inbound_anomaly_score_pl4}'" + + +SecMarker "BEGIN-REQUEST-BLOCKING-EVAL" + +# +# -=[ Anomaly Mode: Overall Transaction Anomaly Score ]=- +# + +# if early blocking is active, check threshold in phase 1 +SecRule TX:BLOCKING_INBOUND_ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" \ + "id:949111,\ + phase:1,\ + deny,\ + t:none,\ + msg:'Inbound Anomaly Score Exceeded in phase 1 (Total Score: %{TX.BLOCKING_INBOUND_ANOMALY_SCORE})',\ + tag:'anomaly-evaluation',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + chain" + SecRule TX:EARLY_BLOCKING "@eq 1" + +# always check threshold in phase 2 +SecRule TX:BLOCKING_INBOUND_ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" \ + "id:949110,\ + phase:2,\ + deny,\ + t:none,\ + msg:'Inbound Anomaly Score Exceeded (Total Score: %{TX.BLOCKING_INBOUND_ANOMALY_SCORE})',\ + tag:'anomaly-evaluation',\ + ver:'OWASP_CRS/4.0.0-rc2'" + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:949011,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:949012,phase:2,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:949013,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:949014,phase:2,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:949015,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:949016,phase:2,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:949017,phase:1,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:949018,phase:2,pass,nolog,skipAfter:END-REQUEST-949-BLOCKING-EVALUATION" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-949-BLOCKING-EVALUATION" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-950-DATA-LEAKAGES.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-950-DATA-LEAKAGES.conf similarity index 67% rename from pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-950-DATA-LEAKAGES.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-950-DATA-LEAKAGES.conf index 0b6f832cc5..4ebb59e15d 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-950-DATA-LEAKAGES.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-950-DATA-LEAKAGES.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -8,10 +8,14 @@ # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ -# The paranoia level skip rules 950020, 950021 and 950022 have odd -# numbers not in sync with other paranoia level skip rules in other -# files. This is done to avoid rule id collisions with CRSv2. -# This is also true for rule 950130. +# We reused paranoia level skip rules 950010, 950011, and 950018. +# These rule identifiers were in use in CRSv2, so we used different +# identifiers in CRSv3 to avoid conflicts (950020, 950021 and 950022). +# In CRSv4, for the sake of a consistent structure, we use these +# identifiers again, so that the skip rules of PL can be defined in the +# same way for all files. +# Rule id 950130 has been kept - this ID also was introduced at first +# rule to avoid the collision. # # -= Paranoia Level 0 (empty) =- (apply unconditionally) @@ -19,23 +23,23 @@ -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:950020,phase:3,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:950021,phase:4,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:950011,phase:3,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:950012,phase:4,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # # -=[ Directory Listing ]=- # -SecRule RESPONSE_BODY "@rx (?:<(?:TITLE>Index of.*?Index of.*?Index of|>\[To Parent Directory\]<\/[Aa]>
)" \ +SecRule RESPONSE_BODY "@rx (?:<(?:TITLE>Index of.*?Index of.*?Index of|>\[To Parent Directory\]
)" \ "id:950130,\ phase:4,\ block,\ capture,\ t:none,\ msg:'Directory Listing',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ @@ -44,11 +48,9 @@ SecRule RESPONSE_BODY "@rx (?:<(?:TITLE>Index of.*?Index of.*?Inde tag:'OWASP_CRS',\ tag:'capec/1000/118/116/54/127',\ tag:'PCI/6.5.6',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" # # -=[ CGI Source Code Leakage ]=- @@ -69,7 +71,7 @@ SecRule RESPONSE_BODY "@rx ^#\!\s?/" \ capture,\ t:none,\ msg:'CGI source code leakage',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ @@ -78,17 +80,15 @@ SecRule RESPONSE_BODY "@rx ^#\!\s?/" \ tag:'OWASP_CRS',\ tag:'capec/1000/118/116',\ tag:'PCI/6.5.6',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:950013,phase:3,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:950014,phase:4,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:950013,phase:3,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:950014,phase:4,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # # @@ -96,12 +96,12 @@ 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,\ msg:'The Application Returned a 500-Level Status Code',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ @@ -110,26 +110,24 @@ SecRule RESPONSE_STATUS "@rx ^5\d{2}$" \ tag:'paranoia-level/2',\ tag:'OWASP_CRS',\ tag:'capec/1000/152',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl2=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl2=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl2=+%{tx.error_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:950015,phase:3,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:950016,phase:4,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:950015,phase:3,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:950016,phase:4,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:950017,phase:3,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:950022,phase:4,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:950017,phase:3,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:950018,phase:4,pass,nolog,skipAfter:END-RESPONSE-950-DATA-LEAKAGES" # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # diff --git a/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf new file mode 100644 index 0000000000..182465489e --- /dev/null +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf @@ -0,0 +1,404 @@ +# ------------------------------------------------------------------------ +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2023 Core Rule Set project. 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) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:951011,phase:3,pass,nolog,skipAfter:END-RESPONSE-951-DATA-LEAKAGES-SQL" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:951012,phase:4,pass,nolog,skipAfter:END-RESPONSE-951-DATA-LEAKAGES-SQL" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# +# -=[ SQL Error Leakages ]=- +# +# Ref: https://github.com/sqlmapproject/sqlmap +# Ref: https://github.com/Arachni/arachni/tree/master/components/checks/active/sql_injection/regexps +# +SecRule RESPONSE_BODY "!@pmFromFile sql-errors.data" \ + "id:951100,\ + phase:4,\ + pass,\ + t:none,\ + nolog,\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-disclosure',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + skipAfter:END-SQL-ERROR-MATCH-PL1" + +SecRule RESPONSE_BODY "@rx (?i:JET Database Engine|Access Database Engine|\[Microsoft\]\[ODBC Microsoft Access Driver\])" \ + "id:951110,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Microsoft Access SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-msaccess',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i:ORA-[0-9][0-9][0-9][0-9]|java\.sql\.SQLException|Oracle error|Oracle.*Driver|Warning.*oci_.*|Warning.*ora_.*)" \ + "id:951120,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Oracle SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-oracle',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i:DB2 SQL error:|\[IBM\]\[CLI Driver\]\[DB2/6000\]|CLI Driver.*DB2|DB2 SQL error|db2_\w+\()" \ + "id:951130,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'DB2 SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-db2',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i:\[DM_QUERY_E_SYNTAX\]|has occurred in the vicinity of:)" \ + "id:951140,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'EMC SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-emc',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i)Dynamic SQL Error" \ + "id:951150,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'firebird SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-firebird',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i)Exception (?:condition )?\d+\. Transaction rollback\." \ + "id:951160,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Frontbase SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-frontbase',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i)org\.hsqldb\.jdbc" \ + "id:951170,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'hsqldb SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-hsqldb',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i:An illegal character has been found in the statement|com\.informix\.jdbc|Exception.*Informix)" \ + "id:951180,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'informix SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-informix',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i:Warning.*ingres_|Ingres SQLSTATE|Ingres\W.*Driver)" \ + "id:951190,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'ingres SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-ingres',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i:Warning: ibase_|Unexpected end of command in statement)" \ + "id:951200,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'interbase SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-interbase',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i:SQL error.*POS[0-9]+.*|Warning.*maxdb.*)" \ + "id:951210,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'maxDB SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-maxdb',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i)(?:System\.Data\.OleDb\.OleDbException|\[Microsoft\]\[ODBC SQL Server Driver\]|\[Macromedia\]\[SQLServer JDBC Driver\]|\[SqlException|System\.Data\.SqlClient\.SqlException|Unclosed quotation mark after the character string|'80040e14'|mssql_query\(\)|Microsoft OLE DB Provider for ODBC Drivers|Microsoft OLE DB Provider for SQL Server|Incorrect syntax near|Sintaxis incorrecta cerca de|Syntax error in string in query expression|Procedure or function .* expects parameter|Unclosed quotation mark before the character string|Syntax error .* in query expression|Data type mismatch in criteria expression\.|ADODB\.Field \(0x800A0BCD\)|the used select statements have different number of columns|OLE DB.*SQL Server|Warning.*mssql_.*|Driver.*SQL[ _-]*Server|SQL Server.*Driver|SQL Server.*[0-9a-fA-F]{8}|Exception.*\WSystem\.Data\.SqlClient\.|Conversion failed when converting the varchar value .*? to data type int\.)" \ + "id:951220,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'mssql SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-mssql',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/951230.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 951230 +# +SecRule RESPONSE_BODY "@rx (?i)(?:supplied argument is not a valid |SQL syntax.*)MySQL|Column count doesn't match(?: value count at row)?|mysql_fetch_array\(\)|on MySQL result index|You have an error in your SQL syntax(?:;| near)|MyS(?:QL server version for the right syntax to use|qlClient\.)|\[MySQL\]\[ODBC|(?:Table '[^']+' doesn't exis|valid MySQL resul)t|Warning.{1,10}mysql_(?:[\(-\)_a-z]{1,26})?|(?:ERROR [0-9]{4} \([0-9a-z]{5}\)|XPATH syntax error):" \ + "id:951230,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'mysql SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-mysql',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/951240.ra. +# To update the regular expression run the following shell script +# (consult https://coreruleset.org/docs/development/regex_assembly/ for details): +# crs-toolchain regex update 951240 +# +SecRule RESPONSE_BODY "@rx (?i)P(?:ostgreSQL(?: query failed:|.{1,20}ERROR)|G::[a-z]*Error)|pg_(?:query|exec)\(\) \[:|Warning.{1,20}\bpg_.*|valid PostgreSQL result|Npgsql\.|Supplied argument is not a valid PostgreSQL .*? resource|(?:Unable to connect to PostgreSQL serv|invalid input syntax for integ)er" \ + "id:951240,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'postgres SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-pgsql',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i)(?:Warning.*sqlite_.*|Warning.*SQLite3::|SQLite/JDBCDriver|SQLite\.Exception|System\.Data\.SQLite\.SQLiteException)" \ + "id:951250,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'sqlite SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-sqlite',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecRule RESPONSE_BODY "@rx (?i)(?:Sybase message:|Warning.{2,20}sybase|Sybase.*Server message.*)" \ + "id:951260,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Sybase SQL Information Leakage',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-sybase',\ + tag:'attack-disclosure',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/118/116/54',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'" + +SecMarker "END-SQL-ERROR-MATCH-PL1" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:951013,phase:3,pass,nolog,skipAfter:END-RESPONSE-951-DATA-LEAKAGES-SQL" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:951014,phase:4,pass,nolog,skipAfter:END-RESPONSE-951-DATA-LEAKAGES-SQL" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:951015,phase:3,pass,nolog,skipAfter:END-RESPONSE-951-DATA-LEAKAGES-SQL" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:951016,phase:4,pass,nolog,skipAfter:END-RESPONSE-951-DATA-LEAKAGES-SQL" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:951017,phase:3,pass,nolog,skipAfter:END-RESPONSE-951-DATA-LEAKAGES-SQL" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:951018,phase:4,pass,nolog,skipAfter:END-RESPONSE-951-DATA-LEAKAGES-SQL" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-RESPONSE-951-DATA-LEAKAGES-SQL" diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-952-DATA-LEAKAGES-JAVA.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf similarity index 69% rename from pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-952-DATA-LEAKAGES-JAVA.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf index 074ad67515..a8191a4915 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-952-DATA-LEAKAGES-JAVA.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -14,10 +14,10 @@ -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:952011,phase:3,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:952012,phase:4,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:952011,phase:3,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:952012,phase:4,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # @@ -30,7 +30,7 @@ SecRule RESPONSE_BODY "@pmFromFile java-code-leakages.data" \ capture,\ t:none,\ msg:'Java Source Code Leakage',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-java',\ tag:'platform-multi',\ @@ -39,11 +39,9 @@ SecRule RESPONSE_BODY "@pmFromFile java-code-leakages.data" \ tag:'OWASP_CRS',\ tag:'capec/1000/118/116',\ tag:'PCI/6.5.6',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" # # -=[ Java Errors ]=- @@ -57,7 +55,7 @@ SecRule RESPONSE_BODY "@pmFromFile java-errors.data" \ capture,\ t:none,\ msg:'Java Errors',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-java',\ tag:'platform-multi',\ @@ -66,34 +64,32 @@ SecRule RESPONSE_BODY "@pmFromFile java-errors.data" \ tag:'OWASP_CRS',\ tag:'capec/1000/118/116',\ tag:'PCI/6.5.6',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:952013,phase:3,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:952014,phase:4,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:952013,phase:3,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:952014,phase:4,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:952015,phase:3,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:952016,phase:4,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:952015,phase:3,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:952016,phase:4,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:952017,phase:3,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:952018,phase:4,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:952017,phase:3,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:952018,phase:4,pass,nolog,skipAfter:END-RESPONSE-952-DATA-LEAKAGES-JAVA" # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # diff --git a/pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-953-DATA-LEAKAGES-PHP.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf similarity index 59% rename from pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-953-DATA-LEAKAGES-PHP.conf rename to pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf index 6f51f433ed..f232372d4f 100644 --- a/pkg/render/applicationlayer/modsec-core-ruleset/RESPONSE-953-DATA-LEAKAGES-PHP.conf +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------ -# OWASP ModSecurity Core Rule Set ver.3.3.5 +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 # Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. # Copyright (c) 2021-2023 Core Rule Set project. All rights reserved. # @@ -14,10 +14,10 @@ -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:953011,phase:3,pass,nolog,skipAfter:END-RESPONSE-953-DATA-LEAKAGES-PHP" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:953012,phase:4,pass,nolog,skipAfter:END-RESPONSE-953-DATA-LEAKAGES-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:953011,phase:3,pass,nolog,skipAfter:END-RESPONSE-953-DATA-LEAKAGES-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:953012,phase:4,pass,nolog,skipAfter:END-RESPONSE-953-DATA-LEAKAGES-PHP" # -# -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) # # @@ -30,7 +30,7 @@ SecRule RESPONSE_BODY "@pmFromFile php-errors.data" \ capture,\ t:none,\ msg:'PHP Information Leakage',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ @@ -39,11 +39,9 @@ SecRule RESPONSE_BODY "@pmFromFile php-errors.data" \ tag:'OWASP_CRS',\ tag:'capec/1000/118/116',\ tag:'PCI/6.5.6',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" # # -=[ PHP source code leakage ]=- @@ -57,7 +55,7 @@ SecRule RESPONSE_BODY "@rx (?:\b(?:f(?:tp_(?:nb_)?f?(?:ge|pu)t|get(?:s?s|c)|scan capture,\ t:none,\ msg:'PHP source code leakage',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ @@ -66,29 +64,24 @@ SecRule RESPONSE_BODY "@rx (?:\b(?:f(?:tp_(?:nb_)?f?(?:ge|pu)t|get(?:s?s|c)|scan tag:'OWASP_CRS',\ tag:'capec/1000/118/116',\ tag:'PCI/6.5.6',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" -# Detect the presence of the PHP open tag ".{1,20}?error '800(?:04005|40e31)'.{1,40}?Timeout expired| \(0x80040e31\)
Timeout expired
)|

internal server error<\/h1>.*?

part of the server has crashed or it has a configuration error\.<\/h2>|cannot connect to the server: timed out)" \ +SecRule RESPONSE_BODY "@rx (?:Microsoft OLE DB Provider for SQL Server(?:.{1,20}?error '800(?:04005|40e31)'.{1,40}?Timeout expired| \(0x80040e31\)
Timeout expired
)|

internal server error

.*?

part of the server has crashed or it has a configuration error\.

|cannot connect to the server: timed out)" \ "id:954110,\ phase:4,\ block,\ capture,\ t:none,\ msg:'Application Availability Error',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-iis',\ @@ -60,23 +58,21 @@ SecRule RESPONSE_BODY "@rx (?:Microsoft OLE DB Provider for SQL Server(?:<\/font tag:'PCI/6.5.6',\ tag:'OWASP_CRS',\ tag:'capec/1000/118/116',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" # # IIS Errors leakage # -SecRule RESPONSE_BODY "@rx (?:\b(?:A(?:DODB\.Command\b.{0,100}?\b(?:Application uses a value of the wrong type for the current operation\b|error')| trappable error occurred in an external object\. The script cannot continue running\b)|Microsoft VBScript (?:compilation (?:\(0x8|error)|runtime (?:Error|\(0x8))\b|Object required: '|error '800)|Version Information:<\/b>(?: |\s)(?:Microsoft \.NET Framework|ASP\.NET) Version:|>error 'ASP\b|An Error Has Occurred|>Syntax error in string in query expression|\/[Ee]rror[Mm]essage\.aspx?\?[Ee]rror\b)" \ +SecRule RESPONSE_BODY "@pmFromFile iis-errors.data" \ "id:954120,\ phase:4,\ block,\ capture,\ t:none,\ msg:'IIS Information Leakage',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-iis',\ @@ -86,11 +82,9 @@ SecRule RESPONSE_BODY "@rx (?:\b(?:A(?:DODB\.Command\b.{0,100}?\b(?:Application tag:'OWASP_CRS',\ tag:'capec/1000/118/116',\ tag:'PCI/6.5.6',\ - ctl:auditLogParts=+E,\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" SecRule RESPONSE_STATUS "!@rx ^404$" \ @@ -100,7 +94,7 @@ SecRule RESPONSE_STATUS "!@rx ^404$" \ capture,\ t:none,\ msg:'IIS Information Leakage',\ - logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-iis',\ @@ -110,38 +104,36 @@ SecRule RESPONSE_STATUS "!@rx ^404$" \ tag:'OWASP_CRS',\ tag:'capec/1000/118/116',\ tag:'PCI/6.5.6',\ - ver:'OWASP_CRS/3.3.5',\ + ver:'OWASP_CRS/4.0.0-rc2',\ severity:'ERROR',\ chain" SecRule RESPONSE_BODY "@rx \bServer Error in.{0,50}?\bApplication\b" \ "capture,\ t:none,\ - ctl:auditLogParts=+E,\ - setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}',\ - setvar:'tx.anomaly_score_pl1=+%{tx.error_anomaly_score}'" + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.error_anomaly_score}'" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:954013,phase:3,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:954014,phase:4,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:954013,phase:3,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:954014,phase:4,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" # -# -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:954015,phase:3,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:954016,phase:4,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:954015,phase:3,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:954016,phase:4,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" # -# -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) # -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:954017,phase:3,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" -SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:954018,phase:4,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:954017,phase:3,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:954018,phase:4,pass,nolog,skipAfter:END-RESPONSE-954-DATA-LEAKAGES-IIS" # -# -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) # diff --git a/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-955-WEB-SHELLS.conf b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-955-WEB-SHELLS.conf new file mode 100644 index 0000000000..48731dc437 --- /dev/null +++ b/pkg/render/applicationlayer/embed/coreruleset/rules/RESPONSE-955-WEB-SHELLS.conf @@ -0,0 +1,548 @@ +# ------------------------------------------------------------------------ +# OWASP ModSecurity Core Rule Set ver.4.0.0-rc2 +# Copyright (c) 2006-2020 Trustwave and contributors. (not) All rights reserved. +# Copyright (c) 2021-2023 Core Rule Set project. 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) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:955011,phase:3,pass,nolog,skipAfter:END-RESPONSE-955-WEB-SHELLS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:955012,phase:4,pass,nolog,skipAfter:END-RESPONSE-955-WEB-SHELLS" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# For performance reasons, most of the shells are matched using this rule. +# This rule is intended for PHP web shells. +SecRule RESPONSE_BODY "@pmFromFile web-shells-php.data" \ + "id:955100,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Web shell detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# r57 web shell +SecRule RESPONSE_BODY "@rx (r57 Shell Version [0-9.]+|r57 shell)" \ + "id:955110,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'r57 web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# WSO web shell +SecRule RESPONSE_BODY "@rx ^.*? - WSO [0-9.]+" \ + "id:955120,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'WSO web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# b4tm4n web shell (https://github.com/k4mpr3t/b4tm4n) +SecRule RESPONSE_BODY "@rx B4TM4N SH3LL.*" \ + "id:955130,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'b4tm4n web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Mini Shell web shell +SecRule RESPONSE_BODY "@rx Mini Shell.*Developed By LameHacker" \ + "id:955140,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Mini Shell web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Ashiyane web shell +SecRule RESPONSE_BODY "@rx \.:: .* ~ Ashiyane V [0-9.]+ ::\." \ + "id:955150,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Ashiyane web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Symlink_Sa web shell +SecRule RESPONSE_BODY "@rx Symlink_Sa [0-9.]+" \ + "id:955160,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Symlink_Sa web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# CasuS web shell +SecRule RESPONSE_BODY "@rx CasuS [0-9.]+ by MafiABoY" \ + "id:955170,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'CasuS web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# GRP WebShell +SecRule RESPONSE_BODY "@rx ^\r\n\r\nGRP WebShell [0-9.]+ " \ + "id:955180,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'GRP WebShell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# NGHshell web shell +SecRule RESPONSE_BODY "@rx <small>NGHshell [0-9.]+ by Cr4sh</body></html>\n$" \ + "id:955190,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'NGHshell web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# SimAttacker web shell +SecRule RESPONSE_BODY "@rx <title>SimAttacker - (?:Version|Vrsion) : [0-9.]+ - " \ + "id:955200,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'SimAttacker web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Unknown web shell +SecRule RESPONSE_BODY "@rx ^<!DOCTYPE html>\n<html>\n<!-- By Artyum .*<title>Web Shell" \ + "id:955210,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Unknown web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# lama's'hell web shell +SecRule RESPONSE_BODY "@rx lama's'hell v. [0-9.]+" \ + "id:955220,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'lama\'s\'hell web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# lostDC web shell +SecRule RESPONSE_BODY "@rx ^ *\n[ ]+\n[ ]+lostDC - " \ + "id:955230,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'lostDC web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Unknown web shell +SecRule RESPONSE_BODY "@rx ^<title>PHP Web Shell\r\n\r\n\r\n " \ + "id:955240,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Unknown web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Unknown web shell +SecRule RESPONSE_BODY "@rx ^\n\n
Input command :
\n
" \ + "id:955250,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Unknown web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Ru24PostWebShell web shell +SecRule RESPONSE_BODY "@rx ^\n\nRu24PostWebShell - " \ + "id:955260,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'Ru24PostWebShell web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# s72 Shell web shell +SecRule RESPONSE_BODY "@rx <title>s72 Shell v[0-9.]+ Codinf by Cr@zy_King" \ + "id:955270,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'s72 Shell web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# PhpSpy web shell +SecRule RESPONSE_BODY "@rx ^\r\n\r\n\r\nPhpSpy Ver [0-9]+" \ + "id:955280,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'PhpSpy web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# g00nshell web shell +SecRule RESPONSE_BODY "@rx ^ \n\n\n\ng00nshell v[0-9.]+ " \ + "id:955290,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'g00nshell web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# PuNkHoLic shell web shell +# Various versions has this text written little differently so we need to do +# t:removeWhitespace and t:lowercase. +SecRule RESPONSE_BODY "@contains <title>punkholicshell" \ + "id:955300,\ + phase:4,\ + block,\ + capture,\ + t:none,t:removeWhitespace,t:lowercase,\ + msg:'PuNkHoLic shell web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# azrail web shell +SecRule RESPONSE_BODY "@rx ^\n \n azrail [0-9.]+ by C-W-M" \ + "id:955310,\ + phase:4,\ + block,\ + capture,\ + t:none,\ + msg:'azrail web shell',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-rce',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'capec/1000/225/122/17/650',\ + ver:'OWASP_CRS/4.0.0-rc2',\ + severity:'CRITICAL',\ + setvar:'tx.outbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# SmEvK_PaThAn Shell web shell +SecRule RESPONSE_BODY "@rx >SmEvK_PaThAn Shell v[0-9]+ coded by \n.*? ~ Shell I\n\n