diff --git a/.github/crs-version.txt b/.github/crs-version.txt index 8f1e770b8..012caadf7 100644 --- a/.github/crs-version.txt +++ b/.github/crs-version.txt @@ -1 +1 @@ -v4.14.0 \ No newline at end of file +v4.25.0 \ No newline at end of file diff --git a/appsec/crs/4.25.0/REQUEST-901-INITIALIZATION.conf b/appsec/crs/4.25.0/REQUEST-901-INITIALIZATION.conf new file mode 100644 index 000000000..94aa26c0b --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-901-INITIALIZATION.conf @@ -0,0 +1,491 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS is distributed under +# Apache Software License (ASL) version 2 +# Please see the enclosed LICENSE file for full details. +# ------------------------------------------------------------------------ + +# +# 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 crs-setup.conf can and should be edited by the user, this file +# is part of the CRS installation and should not be altered. +# + + +# +# -=[ Rules Version ]=- +# +# Rule version data is added to the "Producer" line of Section H of the Audit log: +# +# - Producer: ModSecurity for Apache/2.9.1 (http://www.modsecurity.org/); OWASP_CRS/3.1.0. +# +# Ref: https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v2.x)#seccomponentsignature +# +SecComponentSignature "OWASP_CRS/4.25.0" + +# +# -=[ Default setup values ]=- +# +# The CRS checks the tx.crs_setup_version variable to ensure that the setup +# file is included at the correct time. This detects situations where +# necessary settings are not defined, for instance if the file +# inclusion order is incorrect, or if the user has forgotten to +# include the crs-setup.conf file. +# +# If you are upgrading from an earlier version of the CRS and you are +# getting this error, please make a new copy of the setup template +# crs-setup.conf.example to crs-setup.conf, and re-apply your policy +# changes. There have been many changes in settings syntax from CRS2 +# to CRS3, so an old setup file may cause unwanted behavior. +# +# If you are not planning to use the crs-setup.conf template, you must +# manually set the tx.crs_setup_version variable before including +# the CRS rules/* files. +# +# The variable is a numerical representation of the CRS version number. +# E.g., v3.0.0 is represented as 300. +# + +SecRule &TX:crs_setup_version "@eq 0" \ + "id:901001,\ + phase:1,\ + deny,\ + status:500,\ + log,\ + auditlog,\ + msg:'CRS 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',\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL'" + + +# +# -=[ Default setup values ]=- +# +# Some constructs or individual rules will fail if certain parameters +# 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 crs-setup.conf) +SecRule &TX:inbound_anomaly_score_threshold "@eq 0" \ + "id:901100,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.inbound_anomaly_score_threshold=5'" + +# 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.outbound_anomaly_score_threshold=4'" + +# Default Reporting Level (rule 900115 in crs-setup.conf) +SecRule &TX:reporting_level "@eq 0" \ + "id:901111,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.blocking_paranoia_level=1'" + +# Default Detection Paranoia Level (rule 900001 in crs-setup.conf) +SecRule &TX:detection_paranoia_level "@eq 0" \ + "id:901125,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.detection_paranoia_level=%{TX.blocking_paranoia_level}'" + +# Default Sampling Percentage (rule 900400 in crs-setup.conf) +SecRule &TX:sampling_percentage "@eq 0" \ + "id:901130,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.sampling_percentage=100'" + +# Default Anomaly Scores (rule 900100 in crs-setup.conf) +SecRule &TX:critical_anomaly_score "@eq 0" \ + "id:901140,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.critical_anomaly_score=5'" + +SecRule &TX:error_anomaly_score "@eq 0" \ + "id:901141,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.error_anomaly_score=4'" + +SecRule &TX:warning_anomaly_score "@eq 0" \ + "id:901142,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.warning_anomaly_score=3'" + +SecRule &TX:notice_anomaly_score "@eq 0" \ + "id:901143,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.notice_anomaly_score=2'" + +# Default HTTP policy: allowed_methods (rule 900200 in crs-setup.conf) +SecRule &TX:allowed_methods "@eq 0" \ + "id:901160,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'" + +# 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |text/xml| |application/xml| |application/soap+xml| |application/json|'" + +# 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + 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 in crs-setup.conf) +SecRule &TX:allowed_http_versions "@eq 0" \ + "id:901163,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + 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 in crs-setup.conf) +SecRule &TX:restricted_extensions "@eq 0" \ + "id:901164,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.restricted_extensions=.ani/ .asa/ .asax/ .ascx/ .back/ .backup/ .bak/ .bck/ .bk/ .bkp/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .cnf/ .com/ .compositefont/ .config/ .conf/ .copy/ .crt/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dist/ .dll/ .dos/ .dpkg-dist/ .drv/ .gadget/ .hta/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .inf/ .ini/ .jks/ .jse/ .key/ .licx/ .lnk/ .log/ .mdb/ .msc/ .ocx/ .old/ .pass/ .pdb/ .pfx/ .pif/ .pem/ .pol/ .prf/ .printer/ .pwd/ .rdb/ .rdp/ .reg/ .resources/ .resx/ .sav/ .save/ .scr/ .sct/ .sh/ .shs/ .sql/ .sqlite/ .sqlite3/ .swap/ .swo/ .swp/ .sys/ .temp/ .tfstate/ .tlb/ .tmp/ .vb/ .vbe/ .vbs/ .vbproj/ .vsdisco/ .vxd/ .webinfo/ .ws/ .wsc/ .wsf/ .wsh/ .xsd/ .xsx/'" + +# 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.restricted_headers_basic=/content-encoding/ /proxy/ /lock-token/ /content-range/ /if/ /x-http-method-override/ /x-http-method/ /x-method-override/ /x-middleware-subrequest/ /expect/'" + +# 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.restricted_headers_extended=/accept-charset/'" + +# +# -=[ Method Override Parameter Configuration ]=- +# +# Initialize the allow_method_override_parameter variable. +# This controls whether the _method parameter is permitted for HTTP method +# override (used by frameworks like Laravel, Rails, Symfony). +# +# To allow _method parameter, set tx.allow_method_override_parameter=1 +# in crs-setup.conf (see rule 900510). +# +SecRule &TX:allow_method_override_parameter "@eq 0" \ + "id:901510,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.allow_method_override_parameter=0'" + +# 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.enforce_bodyproc_urlencoded=0'" + +# 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.crs_validate_utf8_encoding=0'" + +# Default check for skipping response analysis (rule 900500 in crs-setup.conf) +SecRule &TX:crs_skip_response_analysis "@eq 0" \ + "id:901170,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.crs_skip_response_analysis=0'" + +# +# -=[ Initialize internal variables ]=- +# + +# Initialize anomaly scoring variables. +# All _score variables start at 0, and are incremented by the various rules +# upon detection of a possible attack. + +SecAction \ + "id:901200,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + 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',\ + setvar:'tx.lfi_score=0',\ + setvar:'tx.rce_score=0',\ + setvar:'tx.php_injection_score=0',\ + setvar:'tx.http_violation_score=0',\ + setvar:'tx.session_fixation_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.anomaly_score=0'" + + +# +# -=[ Initialize collections ]=- +# +# Create both Global and IP collections for rules to use. +# 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. + +# Disable collection initialization by default (see rule 900130 in crs-setup.conf) +# The creation of the IP and the GLOBAL collection is not being tested as +# of this writing due to limits in ftw and our testing setup. +# Proper testing would involve the checking of a variable in the said collections. +SecRule &TX:ENABLE_DEFAULT_COLLECTIONS "@eq 1" \ + "id:901320,\ + phase:1,\ + pass,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.ua_hash=%{REQUEST_HEADERS.User-Agent}',\ + chain" + SecRule TX:ENABLE_DEFAULT_COLLECTIONS "@eq 1" \ + "chain" + SecRule TX:ua_hash "@unconditionalMatch" \ + "t:none,t:sha1,t:hexEncode,\ + initcol:global=global,\ + initcol:ip=%{remote_addr}_%{MATCHED_VAR}" + +# +# -=[ Initialize Correct Body Processing ]=- +# +# Force request body variable and optionally request body processor +# + +# Force body variable +SecRule REQBODY_PROCESSOR "!@rx (?:URLENCODED|MULTIPART|XML|JSON)" \ + "id:901340,\ + phase:1,\ + pass,\ + nolog,\ + noauditlog,\ + msg:'Enabling body inspection',\ + tag:'OWASP_CRS',\ + ctl:forceRequestBodyVariable=On,\ + ver:'OWASP_CRS/4.25.0'" + +# Force body processor URLENCODED +SecRule TX:enforce_bodyproc_urlencoded "@eq 1" \ + "id:901350,\ + phase:1,\ + pass,\ + t:none,t:urlDecodeUni,\ + nolog,\ + noauditlog,\ + msg:'Enabling forced body inspection for ASCII content',\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + chain" + SecRule REQBODY_PROCESSOR "!@rx (?:URLENCODED|MULTIPART|XML|JSON)" \ + "ctl:requestBodyProcessor=URLENCODED" + + +# +# -=[ Easing In / Sampling Percentage ]=- +# +# This is used to send only a limited percentage of requests into the Core +# Rule Set. The selection is based on TX.sampling_percentage and a pseudo +# random number calculated below. +# +# Use this to ease into a new Core Rules installation with an existing +# productive service. +# +# See +# https://www.netnea.com/cms/2016/04/26/easing-in-conditional-modsecurity-rule-execution-based-on-pseudo-random-numbers/ +# + +# +# Generate the pseudo random number +# +# ATTENTION: This is no cryptographically secure random number. It's just +# a cheap way to get some random number suitable for sampling. +# +# 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 +# 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,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + skipAfter:END-SAMPLING" + +SecRule UNIQUE_ID "@rx ^[a-f]*([0-9])[a-f]*([0-9])" \ + "id:901410,\ + phase:1,\ + pass,\ + capture,\ + t:sha1,t:hexEncode,\ + nolog,\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'TX.sampling_rnd100=%{TX.1}%{TX.2}'" + +# +# Sampling decision +# +# If a request is allowed to pass without being checked by the CRS, there is no +# entry in the audit log (for performance reasons), but an error log entry is +# being written. If you want to disable the error log entry, then issue the +# following directive somewhere after the inclusion of the CRS +# (E.g., RESPONSE-999-EXCEPTIONS.conf). +# +# SecRuleUpdateActionById 901450 "nolog" +# + + +SecRule TX:sampling_rnd100 "!@lt %{tx.sampling_percentage}" \ + "id:901450,\ + phase:1,\ + pass,\ + log,\ + noauditlog,\ + msg:'Sampling: Disable the rule engine based on sampling_percentage %{TX.sampling_percentage} and random number %{TX.sampling_rnd100}',\ + tag:'OWASP_CRS',\ + ctl:ruleRemoveByTag=OWASP_CRS,\ + ver:'OWASP_CRS/4.25.0'" + +SecMarker "END-SAMPLING" + + +# +# Configuration Plausibility Checks +# + +# 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:'Detection paranoia level configured is lower than the paranoia level itself. This is illegal. Blocking request. Aborting',\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0'" diff --git a/appsec/crs/4.25.0/REQUEST-905-COMMON-EXCEPTIONS.conf b/appsec/crs/4.25.0/REQUEST-905-COMMON-EXCEPTIONS.conf new file mode 100644 index 000000000..de1790610 --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-905-COMMON-EXCEPTIONS.conf @@ -0,0 +1,57 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS is distributed under +# Apache Software License (ASL) version 2 +# Please see the enclosed LICENSE file for full details. +# ------------------------------------------------------------------------ + + +# This file is used as an exception mechanism to remove common false positives +# that may be encountered. +# +# Exception for Apache SSL pinger +# +SecRule REQUEST_LINE "@streq GET /" \ + "id:905100,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-apache',\ + tag:'attack-generic',\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + chain" + SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ + "t:none,\ + ctl:ruleRemoveByTag=OWASP_CRS,\ + ctl:auditEngine=Off" + +# +# Exception for Apache internal dummy connection +# +SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ + "id:905110,\ + phase:1,\ + pass,\ + t:none,\ + nolog,\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-apache',\ + tag:'attack-generic',\ + tag:'OWASP_CRS',\ + ver:'OWASP_CRS/4.25.0',\ + 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:ruleRemoveByTag=OWASP_CRS,\ + ctl:auditEngine=Off" diff --git a/appsec/crs/4.25.0/REQUEST-911-METHOD-ENFORCEMENT.conf b/appsec/crs/4.25.0/REQUEST-911-METHOD-ENFORCEMENT.conf new file mode 100644 index 000000000..f8b17fffb --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-911-METHOD-ENFORCEMENT.conf @@ -0,0 +1,76 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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:911011,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:911012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# +# -=[ Allowed Request Methods ]=- +# +# tx.allowed_methods is defined in the crs-setup.conf file +# +SecRule REQUEST_METHOD "!@within %{tx.allowed_methods}" \ + "id:911100,\ + phase:1,\ + block,\ + msg:'Method is not allowed by policy',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-generic',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/METHOD-ENFORCEMENT',\ + tag:'capec/1000/210/272/220/274',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:911013,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:911014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:911015,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:911016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:911017,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:911018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-911-METHOD-ENFORCEMENT" diff --git a/appsec/crs/4.25.0/REQUEST-913-SCANNER-DETECTION.conf b/appsec/crs/4.25.0/REQUEST-913-SCANNER-DETECTION.conf new file mode 100644 index 000000000..aa59137e9 --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-913-SCANNER-DETECTION.conf @@ -0,0 +1,86 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-913-SCANNER-DETECTION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:913012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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:'OWASP_CRS/SCANNER-DETECTION',\ + tag:'capec/1000/118/224/541/310',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-913-SCANNER-DETECTION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:913014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-913-SCANNER-DETECTION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:913016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-913-SCANNER-DETECTION" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:913018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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/appsec/crs/4.25.0/REQUEST-920-PROTOCOL-ENFORCEMENT.conf b/appsec/crs/4.25.0/REQUEST-920-PROTOCOL-ENFORCEMENT.conf new file mode 100644 index 000000000..4a15d1642 --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-920-PROTOCOL-ENFORCEMENT.conf @@ -0,0 +1,2008 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS is distributed under +# Apache Software License (ASL) version 2 +# Please see the enclosed LICENSE file for full details. +# ------------------------------------------------------------------------ + +# +# Some protocol violations are common in application layer attacks. +# Validating HTTP requests eliminates a large number of application layer attacks. +# +# 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.rfc-editor.org/rfc/rfc9110.html + + + +# +# -= Paranoia Level 0 (empty) =- (apply unconditionally) +# + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:920011,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:920012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# +# Validate request line against the format specified in the HTTP RFC +# +# -=[ Rule Logic ]=- +# +# Uses rule negation against the regex for positive security. The regex specifies the proper +# construction of URI request lines such as: +# +# "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.rfc-editor.org/rfc/rfc9110.html#section-4.2.1 +# http://capec.mitre.org/data/definitions/272.html +# +SecRule REQUEST_LINE "!@rx (?i)^(?:get /[^#\?]*(?:\?[^\s\x0b#]*)?(?:#[^\s\x0b]*)?|(?:connect (?:(?:[0-9]{1,3}\.){3}[0-9]{1,3}\.?(?::[0-9]+)?|[\--9A-Z_a-z]+:[0-9]+)|options \*|[a-z]{3,10}[\s\x0b]+(?:[0-9A-Z_a-z]{3,7}?://[\--9A-Z_a-z]*(?::[0-9]+)?)?/[^#\?]*(?:\?[^\s\x0b#]*)?(?:#[^\s\x0b]*)?)[\s\x0b]+[\.-9A-Z_a-z]+)$" \ + "id:920100,\ + phase:1,\ + block,\ + t:none,\ + msg:'Invalid HTTP Request Line',\ + logdata:'%{request_line}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + + +# +# Identify multipart/form-data name evasion attempts +# +# There are possible impedance mismatches between how +# ModSecurity interprets multipart file names and how +# a destination app server such as PHP might parse the +# Content-Disposition data: +# +# filename-parm := "filename" "=" value +# +# -=[ Rule Logic ]=- +# These rules check for the existence of the ' " ; = meta-characters in +# 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 +# Disallow ['\";=\\], except for frequently used HTML entities (see 920120.ra). +# +# 920121: PL2 : FILES_NAMES, FILES +# Disallow ['\";=\\] +# +# -=[ References ]=- +# http://www.ietf.org/rfc/rfc2183.txt +# +# This rule used to use negative look-behind. +# See https://github.com/coreruleset/coreruleset/wiki/Technical-Decisions-and-Best-Practices#avoiding-negative-look-behind-in-regular-expressions +# for an explanation of why it now uses `!@rx` instead to avoid look-around. +# +# Regular expression generated from regex-assembly/920120.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 920120 +# +SecRule FILES|FILES_NAMES "!@rx (?i)^(?:&(?:(?:[acegilnorsuz]acut|[aeiou]grav|[aino]tild)e|[c-elnr-tz]caron|(?:[cgklnr-t]cedi|[aeiouy]um)l|[aceg-josuwy]circ|[au]ring|a(?:mp|pos)|nbsp|oslash);|[^\"';=\x5c])*$" \ + "id:920120,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Attempted multipart/form-data bypass',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# Accept only digits in content length +# +# -=[ Rule Logic ]=- +# This rule uses ModSecurity's rule negation against the regex meaning if the Content-Length header +# is NOT all digits, then it will match. +# +# -=[ References ]=- +# https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6 +# +SecRule REQUEST_HEADERS:Content-Length "!@rx ^\d+$" \ + "id:920160,\ + phase:1,\ + block,\ + t:none,\ + msg:'Content-Length HTTP header is not numeric',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# Do not accept GET or HEAD requests with bodies +# In RCF-9110, "A client SHOULD NOT generate content in a HEAD/GET request +# unless it is made directly to an origin server that has previously indicated" +# +# -=[ Rule Logic ]=- +# The chained rule matches when: +# 1) If the request method is GET or HEAD +# AND +# 2) Header: Content-Length exists and non-zero +# +# -=[ References ]=- +# https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.1 +# https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.2 +# +SecRule REQUEST_METHOD "@rx ^(?:GET|HEAD)$" \ + "id:920170,\ + phase:1,\ + block,\ + t:none,\ + msg:'GET or HEAD Request with Body Content',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule REQUEST_HEADERS:Content-Length "!@rx ^0?$" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# This is a sibling of rule 920170 +# +SecRule REQUEST_METHOD "@rx ^(?:GET|HEAD)$" \ + "id:920171,\ + phase:1,\ + block,\ + t:none,\ + msg:'GET or HEAD Request with Transfer-Encoding',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule &REQUEST_HEADERS:Transfer-Encoding "!@eq 0" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# Require Content-Length or Transfer-Encoding to be provided with +# every POST request if the protocol version is not HTTP/2 or HTTP/3. +# +# In case of HTTP/2, see the RFC7540 8.1 p52: +# HTTP/2 does not use the Transfer-Encoding: chunked anymore, because +# the underlying transport protocol is already using data frames with +# known length. +# +# In case of HTTP/3, see the RFC9114 4.1: +# Transfer codings (see Section 7 of [HTTP/1.1]) are not defined for +# HTTP/3; the Transfer-Encoding header field MUST NOT be used. +# +# -=[ Rule Logic ]=- +# This chained rule checks if the protocol is not HTTP/2 or HTTP/3, +# then checks request method is POST, if so, it checks that a +# Content-Length or Transfer-Encoding headers are also present. +# +SecRule REQUEST_PROTOCOL "!@within HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0" \ + "id:920180,\ + phase:1,\ + block,\ + t:none,\ + msg:'POST without Content-Length and Transfer-Encoding headers',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + chain" + SecRule REQUEST_METHOD "@streq POST" \ + "chain" + SecRule &REQUEST_HEADERS:Content-Length "@eq 0" \ + "chain" + SecRule &REQUEST_HEADERS:Transfer-Encoding "@eq 0" \ + "setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + +# +# As per RFC7230 3.3.2: A sender MUST NOT send a Content-Length +# header field in any message that contains a Transfer-Encoding header +# field. +# +# Related to 920170, 920171 and 920180. +# +SecRule &REQUEST_HEADERS:Transfer-Encoding "!@eq 0" \ + "id:920181,\ + phase:1,\ + block,\ + t:none,\ + msg:'Content-Length and Transfer-Encoding headers present',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + chain" + SecRule &REQUEST_HEADERS:Content-Length "!@eq 0" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + + +# +# Range Header Check +# +# RFC7233 2.1 p6: +# "A byte-range-spec is invalid if the last-byte-pos value is present +# and less than the first-byte-pos." +# +# -=[ Rule Logic ]=- +# This rule compares the first and second byte ranges and flags +# when the first value is greater than the second. +# +# -=[ References ]=- +# https://datatracker.ietf.org/doc/html/rfc7233 +# https://seclists.org/fulldisclosure/2011/Aug/175 +# +SecRule REQUEST_HEADERS:Range "@rx (\d+)-(\d+)" \ + "id:920190,\ + phase:1,\ + block,\ + capture,\ + t:none,\ + msg:'Range: Invalid Last Byte Value',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + chain" + SecRule TX:2 "@lt %{tx.1}" \ + "setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + +# The `Request-Range` header is a legacy/non-standard HTTP header that dates back to Netscape +# Navigator 2-3 and MSIE 3 (~1996-1997). It was never part of any HTTP RFC and has no legitimate +# use in modern web traffic. +# +## Background +# +### Origin of `Request-Range` +# +# The header originated from an early draft of HTTP byte-range requests before standardization: +# +# - **Draft standard**: Defined `Request-Range` header with `multipart/x-byteranges` response type +# - **HTTP/1.1 (RFC 2068/7233/9110)**: Standardized as `Range` header with `multipart/byteranges` response type +# - **Netscape Navigator 2-3**: Sent **both** `Range` and `Request-Range` headers (with the same value) +# - **Netscape Communicator 4+**: Dropped the non-standard `Request-Range` header +# +# Rationale for Blocking +# +# | Factor | Assessment | +# |---------------------------|---------------------------------------------------------------| +# | **Legitimate modern use** | None - header is ~25 years obsolete | +# | **Last known clients** | Netscape Navigator 2-3, MSIE 3 (1996-1997) | +# | **False positive risk** | Essentially zero | +# | **Attack surface** | Servers may still process it; could bypass `Range`-only rules | +# | **RFC status** | Never standardized; not in RFC 9110 | +SecRule &REQUEST_HEADERS:Request-Range "@gt 0" \ + "id:920660,\ + phase:1,\ + block,\ + t:none,\ + msg:'Obsolete Request-Range header detected',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + +# +# Broken/Malicious clients often have duplicate or conflicting headers +# Automated programs and bots often do not obey the HTTP RFC +# +# -=[ Rule Logic ]=- +# This rule inspects the Connection header and looks for duplicates of the +# keep-alive and close options. +# +# -=[ References ]=- +# https://datatracker.ietf.org/doc/html/rfc7233 +# +SecRule REQUEST_HEADERS:Connection "@rx \b(?:keep-alive|close),\s?(?:keep-alive|close)\b" \ + "id:920210,\ + phase:1,\ + block,\ + t:none,\ + msg:'Multiple/Conflicting Connection Header Data Found',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + + +# +# Check UTF encoding +# We only want to apply this check if UTF-8 encoding is actually used by the site, otherwise +# it will result in false positives. +# +# -=[ Rule Logic ]=- +# This chained rule first checks to see if the admin has set the TX:CRS_VALIDATE_UTF8_ENCODING +# variable in the crs-setup.conf file. +# +SecRule TX:CRS_VALIDATE_UTF8_ENCODING "@eq 1" \ + "id:920250,\ + phase:2,\ + block,\ + t:none,\ + msg:'UTF8 Encoding Abuse Attack Attempt',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153/267',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + chain" + SecRule REQUEST_FILENAME|ARGS|ARGS_NAMES "@validateUtf8Encoding" \ + "setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + + +# +# Disallow use of full-width unicode as decoding evasions may be possible. +# +# -=[ Rule Logic ]=- +# This rule looks for full-width encoding by looking for %u followed by 2 'f' +# characters and then 2 hex characters. It is a vulnerability that affected +# IIS circa 2007. +# The rule will trigger on %uXXXX formatted chars that are full or half +# width, as explained above. This %uXXXX format is passed as a raw parameter +# and is (seemingly only) accepted by IIS (5.0, 6.0, 7.0, and 8.0). Other +# webservers will only process unicode chars presented as hex UTF-8 bytes. +# +# -=[ References ]=- +# http://www.kb.cert.org/vuls/id/739224 +# https://www.checkpoint.com/defense/advisories/public/2007/cpai-2007-201.html +# https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/719 +# +# Regular expression generated from regex-assembly/920260.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 920260 +# +SecRule REQUEST_URI|REQUEST_BODY "@rx (?i)%uff[0-9a-f]{2}" \ + "id:920260,\ + phase:2,\ + block,\ + t:none,\ + msg:'Unicode Full/Half Width Abuse Attack Attempt',\ + logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-iis',\ + tag:'platform-windows',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153/267/72',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + + +# +# Restrict type of characters sent +# +# This is a rule with multiple stricter siblings that grows more +# restrictive in higher paranoia levels. +# +# -=[ Rule Logic ]=- +# This rule uses the @validateByteRange operator to restrict the request +# payloads. +# +# -=[ Targets and ASCII Ranges ]=- +# +# 920270: PL1 : REQUEST_URI, REQUEST_HEADERS, ARGS and ARGS_NAMES +# ASCII 1-255 : Full ASCII range without null character +# +# 920271: PL2 : REQUEST_URI, REQUEST_HEADERS, ARGS and ARGS_NAMES +# ASCII 9,10,13,32-126,128-255 : Full visible ASCII range, tab, newline +# +# 920272: PL3 : REQUEST_URI, REQUEST_HEADERS, ARGS, ARGS_NAMES and REQUEST_BODY +# ASCII 32-36,38-126 : Visible lower ASCII range without percent symbol +# +# 920273: PL4 : ARGS, ARGS_NAMES and REQUEST_BODY +# ASCII 38,44-46,48-58,61,65-90,95,97-122 +# A-Z a-z 0-9 = - _ . , : & +# +# 920274: PL4 : REQUEST_HEADERS without User-Agent, Referer, Cookie +# and Structured Header booleans +# ASCII 32,34,38,42-59,61,65-90,95,97-122 +# A-Z a-z 0-9 = - _ . , : & " * + / SPACE +# +# REQUEST_URI and REQUEST_HEADERS User-Agent, Referer and Cookie are very hard +# to restrict beyond the limits in 920272. Structured Header booleans are +# validated separately in 920275. +# +# 920274 generally has few positives. However, it would detect rare attacks +# on Accept request headers and friends. + +SecRule REQUEST_URI_RAW|REQUEST_HEADERS|ARGS|ARGS_NAMES "@validateByteRange 1-255" \ + "id:920270,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Invalid character in request (null character)',\ + 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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# Do not accept requests without common headers. +# All normal web browsers include Host, User-Agent and Accept headers. +# Implies either an attacker or a legitimate automation client. +# + +# +# Missing/Empty Host Header +# +# -=[ Rule Logic ]=- +# These rules will first check to see if a Host header is present. +# The second check is to see if a Host header exists but is empty. +# +SecRule &REQUEST_HEADERS:Host "@eq 0" \ + "id:920280,\ + phase:1,\ + block,\ + t:none,\ + msg:'Request Missing a Host Header',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + skipAfter:END-HOST-CHECK" + + +SecRule REQUEST_HEADERS:Host "@rx ^$" \ + "id:920290,\ + phase:1,\ + block,\ + t:none,\ + msg:'Empty Host Header',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +SecMarker "END-HOST-CHECK" + + +# +# Empty Accept Header +# +# -=[ Rule Logic ]=- +# This rule checks if an Accept header exists, but has an empty value. +# This is only allowed in combination with the OPTIONS method. +# Additionally, there are some clients sending empty Accept headers. +# They are covered in another chained rule checking the User-Agent. +# This technique demands a separate rule to detect an empty +# Accept header if there is no user agent. This is checked via +# the separate rule 920311. +# +# Exclude some common broken clients sending empty Accept header: +# "Business/6.6.1.2 CFNetwork/758.5.3 Darwin/15.6.0" (CRS issue #515) +# "Entreprise/6.5.0.177 CFNetwork/758.4.3 Darwin/15.5.0" (CRS issue #366) +# +# -=[ References ]=- +# https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/366 +# + +SecRule REQUEST_HEADERS:Accept "@rx ^$" \ + "id:920310,\ + phase:1,\ + block,\ + t:none,\ + msg:'Request Has an Empty Accept Header',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'NOTICE',\ + chain" + SecRule REQUEST_METHOD "!@rx ^OPTIONS$" \ + "chain" + SecRule REQUEST_HEADERS:User-Agent "!@pm AppleWebKit Android Business Enterprise Entreprise" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.notice_anomaly_score}'" + +# +# This rule is a sibling of rule 920310. +# +SecRule REQUEST_HEADERS:Accept "@rx ^$" \ + "id:920311,\ + phase:1,\ + block,\ + t:none,\ + msg:'Request Has an Empty Accept Header',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'NOTICE',\ + chain" + SecRule REQUEST_METHOD "!@rx ^OPTIONS$" \ + "chain" + SecRule &REQUEST_HEADERS:User-Agent "@eq 0" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.notice_anomaly_score}'" + + +# +# Empty User-Agent Header +# +# -=[ Rule Logic ]=- +# This rules will check to see if the User-Agent header is empty. +# +# Note that there is a second rule, 920320, which will check for +# the existence of the User-Agent header. +# + +SecRule REQUEST_HEADERS:User-Agent "@rx ^$" \ + "id:920330,\ + phase:1,\ + block,\ + t:none,\ + msg:'Empty User Agent Header',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'NOTICE',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.notice_anomaly_score}'" + +# +# Missing Content-Type Header with Request Body (Phase 1) +# +# -=[ Rule Logic ]=- +# This rule checks if the Content-Length header value is non-zero (indicating +# the client declares a body is present), then verifies the existence of the +# Content-Type header. While RFCs do not mandate a Content-Type header for all +# requests, its absence in requests with a body is a strong indication of a +# non-compliant browser or an evasion attempt. +# +# Omitting the Content-Type header allows bypassing the Request Body Processor +# unless you set the optional tx.enforce_bodyproc_urlencoded variable. This can +# be used to evade detection by preventing proper parsing of XML, JSON, or other +# body formats. +# +# This rule operates in phase:1 (request headers) based on the Content-Length +# header declaration. A complementary rule (920640) operates in phase:2 based +# on the actual REQUEST_BODY_LENGTH to catch cases where the body is present +# but Content-Length was omitted or set to zero. +# +# -=[ References ]=- +# https://httpwg.org/specs/rfc7231.html#header.content-type +# https://httpwg.org/specs/rfc7230.html#header.content-length + +SecRule REQUEST_HEADERS:Content-Length "!@rx ^0$" \ + "id:920340,\ + phase:1,\ + block,\ + t:none,\ + msg:'Content-Type header missing from request with non-zero Content-Length',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule &REQUEST_HEADERS:Content-Type "@eq 0" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Check that the host header is not an IP address +# This is not an HTTP RFC violation but it is indicative of automated client access. +# Many web-based worms propagate by scanning IP address blocks. +# +# -=[ Rule Logic ]=- +# This rule triggers if the Host header contains an IPv4 or IPv6 address, optionally +# extended with a port number. In the case of IPv6 we covering the address with square +# brackets and the address without square brackets. +# +# The regex consists of three main parts and said optional group: +# +# * IPv4 address +# * IPv6 address with square brackets +# * IPv6 address without square brackets +# * optional colon and port number +# +# Please note that the regex does not test the validity of the IP addresses. +# It just tries to detect a potential IP address. +# +# -=[ References ]=- +# https://technet.microsoft.com/en-us/magazine/2005.01.hackerbasher.aspx +# + +SecRule REQUEST_HEADERS:Host "@rx (?:^([\d.]+|\[[\da-f:]+\]|[\da-f:]+)(:[\d]+)?$)" \ + "id:920350,\ + phase:1,\ + block,\ + t:none,\ + msg:'Host header is a numeric IP address',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'" + + +# In most cases, you should expect a certain volume of each a request on your +# website. For example, a request with 400 arguments, can be suspicious. +# This file creates limitations on the request. +# +# TODO Look at the rules in this file, and define the sizes you'd like to enforce. +# Note that most of the rules are commented out by default. +# Uncomment the rules you need +# + + +# +# Maximum number of arguments in request limited +# +SecRule &TX:MAX_NUM_ARGS "@eq 1" \ + "id:920380,\ + phase:2,\ + block,\ + t:none,\ + msg:'Too many arguments in request',\ + 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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule &ARGS "@gt %{tx.max_num_args}" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +## -- Arguments limits -- +# +# Limit argument name length +# +SecRule &TX:ARG_NAME_LENGTH "@eq 1" \ + "id:920360,\ + phase:2,\ + block,\ + t:none,\ + msg:'Argument name too long',\ + 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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule ARGS_NAMES "@gt %{tx.arg_name_length}" \ + "t:none,t:length,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Limit argument value length +# +# This rule is also triggered by an Apache Struts Remote Code Execution exploit: +# [ Apache Struts vulnerability CVE-2017-9791 - Exploit tested: https://www.exploit-db.com/exploits/42324 ] +# +SecRule &TX:ARG_LENGTH "@eq 1" \ + "id:920370,\ + phase:2,\ + block,\ + t:none,\ + msg:'Argument value too long',\ + 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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule ARGS "@gt %{tx.arg_length}" \ + "t:none,t:length,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Limit arguments total length +# +SecRule &TX:TOTAL_ARG_LENGTH "@eq 1" \ + "id:920390,\ + phase:2,\ + block,\ + t:none,\ + msg:'Total arguments size exceeded',\ + 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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule ARGS_COMBINED_SIZE "@gt %{tx.total_arg_length}" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# -- File upload limits -- +# +# Individual file size is limited +SecRule &TX:MAX_FILE_SIZE "@eq 1" \ + "id:920400,\ + phase:1,\ + block,\ + t:none,\ + msg:'Uploaded file size too large',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule REQUEST_HEADERS:Content-Type "@rx ^(?i)multipart/form-data" \ + "chain" + SecRule REQUEST_HEADERS:Content-Length "@gt %{tx.max_file_size}" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Combined file size is limited +# +SecRule &TX:COMBINED_FILE_SIZES "@eq 1" \ + "id:920410,\ + phase:2,\ + block,\ + t:none,\ + msg:'Total uploaded files size too large',\ + 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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule FILES_COMBINED_SIZE "@gt %{tx.combined_file_sizes}" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + + +# +# Restrict which content-types we accept. +# + +# Restrict Content-Type header to established patterns. +# +# This provides generic allow list protection against vulnerabilities like +# Apache Struts Content-Type arbitrary command execution (CVE-2017-5638). +# +# Examples of allowed patterns: +# - text/plain +# - text/plain; charset="UTF-8" +# - multipart/form-data; boundary=----WebKitFormBoundary12345 +# - 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,\ + t:none,t:lowercase,\ + msg:'Illegal Content-Type header',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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:1,\ + block,\ + capture,\ + t:none,\ + msg:'Request content type is not allowed by policy',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.content_type=|%{tx.0}|',\ + chain" + SecRule TX:content_type "!@within %{tx.allowed_request_content_type}" \ + "t:lowercase,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# Restrict charset parameter within the content-type header +# +SecRule REQUEST_HEADERS:Content-Type "@rx charset\s*=\s*[\"']?([^;\"'\s]+)" \ + "id:920480,\ + phase:1,\ + block,\ + capture,\ + t:none,\ + msg:'Request content type charset is not allowed by policy',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.content_type_charset=|%{tx.1}|',\ + chain" + SecRule TX:content_type_charset "!@within %{tx.allowed_request_content_type_charset}" \ + "t:lowercase,\ + ctl:forceRequestBodyVariable=On,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Restrict charset parameter inside content type header to occur max once. +# +SecRule REQUEST_HEADERS:Content-Type "@rx charset.*?charset" \ + "id:920530,\ + phase:1,\ + block,\ + t:none,t:lowercase,\ + msg:'Multiple charsets detected in content type header',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Missing Content-Type Header with Request Body (Phase 2) +# +# -=[ Rule Logic ]=- +# This rule checks if the actual REQUEST_BODY_LENGTH is greater than zero +# (indicating a body was received), then verifies the existence of the +# Content-Type header. This operates in phase:2 (request body) and complements +# rule 920340 which checks in phase:1 based on the Content-Length header. +# +# This rule catches evasion attempts where: +# - The Content-Length header was omitted entirely +# - The Content-Length header was set to zero but a body was sent anyway +# - The request bypassed phase:1 checks but still contains a body +# +# Without a Content-Type header, the Request Body Processor cannot properly +# parse the body content (XML, JSON, multipart, etc.), allowing attackers to +# hide malicious payloads from inspection unless tx.enforce_bodyproc_urlencoded +# is configured. +# +# -=[ References ]=- +# https://httpwg.org/specs/rfc7231.html#header.content-type +# https://httpwg.org/specs/rfc7230.html#message.body +# +SecRule REQUEST_BODY_LENGTH "@gt 0" \ + "id:920640,\ + phase:2,\ + block,\ + t:none,\ + msg:'Content-Type header missing from request with body',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule &REQUEST_HEADERS:Content-Type "@eq 0" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Restrict protocol versions. +# +SecRule REQUEST_PROTOCOL "!@within %{tx.allowed_http_versions}" \ + "id:920430,\ + phase:1,\ + block,\ + t:none,\ + msg:'HTTP protocol version is not allowed by policy',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Restrict file extension +# +SecRule REQUEST_BASENAME "@rx \.([^.]+)$" \ + "id:920440,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'URL file extension is restricted by policy',\ + logdata:'%{TX.0}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.extension=.%{tx.1}/',\ + chain" + SecRule TX:EXTENSION "@within %{tx.restricted_extensions}" \ + "t:none,t:lowercase,\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Backup or "working" file extension +# example: index.php~, /index.php~/foo/ +# +SecRule REQUEST_FILENAME "@rx \.[^.~]+~(?:/.*|)$" \ + "id:920500,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Attempt to access a backup or working file',\ + logdata:'%{TX.0}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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 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__. +# +# 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: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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.header_name_920450_%{tx.0}=/%{tx.0}/',\ + chain" + 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 100 characters. +# The length of 100 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). +# Concatenating all valid values for Accept-Encoding (without q=0.5) resulted in a value of 93: +# aes128gcm, br, compress, deflate, exi, gzip, identity, pack200-gzip, x-compress, x-gzip, zstd +# +# This rule has a stricter sibling: 920521 +# +SecRule REQUEST_HEADERS:Accept-Encoding "@gt 100" \ + "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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# Restrict response charsets that we allow. +# The following rules make sure that the response will be in an ASCII-compatible charset that +# phase 4 rules can properly understand and block. +# + +# +# 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 regex-assembly/920600.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 920600 +# +SecRule REQUEST_HEADERS:Accept "!@rx ^(?:(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)/(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\x0b]*;[\s\x0b]*(?:charset[\s\x0b]*=[\s\x0b]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\x0b-\"\(\),/:-\?\[-\]c\{\}]|c(?:[^!\"\(\),/:-\?\[-\]h\{\}]|h(?:[^!\"\(\),/:-\?\[-\]a\{\}]|a(?:[^!\"\(\),/:-\?\[-\]r\{\}]|r(?:[^!\"\(\),/:-\?\[-\]s\{\}]|s(?:[^!\"\(\),/:-\?\[-\]e\{\}]|e[^!\"\(\),/:-\?\[-\]t\{\}]))))))[^!\"\(\),/:-\?\[-\]\{\}]*[\s\x0b]*=[\s\x0b]*[^!\(\),/:-\?\[-\]\{\}]+);?)*(?:[\s\x0b]*,[\s\x0b]*(?:(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)/(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\x0b]*;[\s\x0b]*(?:charset[\s\x0b]*=[\s\x0b]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\x0b-\"\(\),/:-\?\[-\]c\{\}]|c(?:[^!\"\(\),/:-\?\[-\]h\{\}]|h(?:[^!\"\(\),/:-\?\[-\]a\{\}]|a(?:[^!\"\(\),/:-\?\[-\]r\{\}]|r(?:[^!\"\(\),/:-\?\[-\]s\{\}]|s(?:[^!\"\(\),/:-\?\[-\]e\{\}]|e[^!\"\(\),/:-\?\[-\]t\{\}]))))))[^!\"\(\),/:-\?\[-\]\{\}]*[\s\x0b]*=[\s\x0b]*[^!\(\),/:-\?\[-\]\{\}]+);?)*)*$" \ + "id:920600,\ + phase:1,\ + block,\ + t:none,t:lowercase,\ + msg:'Illegal Accept header: charset parameter',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# This rule disables `920540` if the JSON body processor is not active. This +# check is split into a different rule to allow for specific targets to be excluded. +# Warning: There must be no rules between `920539` and `920540` or they +# will be skipped. This rule must also be kept in the same phase as `920540`. +SecRule REQBODY_PROCESSOR "@streq JSON" \ + "id:920539,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + ver:'OWASP_CRS/4.25.0',\ + skip:1" + +# +# Unicode character bypass check for non JSON requests +# See reported bypass in issue: +# https://github.com/coreruleset/coreruleset/issues/2512 +# +# Warning: There must be no rules between `920539` and `920540` or they +# will be skipped. +SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@rx (?i)\x5cu[0-9a-f]{4}" \ + "id:920540,\ + phase:2,\ + block,\ + capture,\ + 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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153/267/72',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + ver:'OWASP_CRS/4.25.0',\ + 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. +# Content-Type confusion poses a significant security risk to a web application. It occurs when +# the server and client have different interpretations of the Content-Type header, leading to +# miscommunication, potential exploitation and WAF bypass. +# +# Using Apache, when multiple Content-Type request headers are received, the server combines them +# into a single header with the values separated by commas. For example, if a client sends multiple +# Content-Type headers with values "application/json" and "text/plain", Apache will combine them +# into a single header like this: "Content-Type: application/json, text/plain". +# +# On the other hand, Nginx handles multiple Content-Type headers differently. It preserves each +# header as a separate entity without combining them. So, if a client sends multiple Content-Type +# headers, Nginx will keep them separate, maintaining the original values. +# +SecRule &REQUEST_HEADERS:Content-Type "@gt 1" \ + "id:920620,\ + phase:1,\ + block,\ + t:none,\ + msg:'Multiple Content-Type Request Headers',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:920013,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:920014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + +# +# -=[ Rule Logic ]=- +# +# Check the number of range fields in the Range request header. +# +# An excessive number of Range request headers can be used to DoS a server. +# The original CVE proposed an arbitrary upper limit of 5 range fields. +# +# Several clients are known to request PDF fields with up to 62 range +# fields. Therefore the standard rule does not cover PDF files. This is +# performed in two separate (stricter) siblings of this rule. +# +# 920200: PL2: Limit of 5 range header fields for all filenames outside of PDFs +# 920201: PL2: Limit of 62 range header fields for PDFs +# 920202: PL4: Limit of 5 range header fields for PDFs +# +# -=[ References ]=- +# https://httpd.apache.org/security/CVE-2011-3192.txt + + +SecRule REQUEST_HEADERS:Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){6}" \ + "id:920200,\ + phase:1,\ + block,\ + t:none,\ + msg:'Range: Too many fields (6 or more)',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + chain" + SecRule REQUEST_BASENAME "!@endsWith .pdf" \ + "setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'" + +# +# This is a sibling of rule 920200 +# + +SecRule REQUEST_BASENAME "@endsWith .pdf" \ + "id:920201,\ + phase:1,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Range: Too many fields for pdf request (63 or more)',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + chain" + SecRule REQUEST_HEADERS:Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){63}" \ + "setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'" + + +SecRule ARGS "@rx %[0-9a-fA-F]{2}" \ + "id:920230,\ + phase:2,\ + block,\ + t:none,\ + msg:'Multiple URL Encoding Detected',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153/267/120',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'" + + +# +# PL2: This is a stricter sibling of 920270. +# +SecRule REQUEST_URI_RAW|REQUEST_HEADERS|ARGS|ARGS_NAMES "@validateByteRange 9,10,13,32-126,128-255" \ + "id:920271,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Invalid character in request (non printable characters)',\ + logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + + +# +# Missing User-Agent Header +# +# -=[ Rule Logic ]=- +# This rules will check to see if there is a User-Agent header or not. +# + +SecRule &REQUEST_HEADERS:User-Agent "@eq 0" \ + "id:920320,\ + phase:1,\ + block,\ + t:none,\ + msg:'Missing User Agent Header',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'NOTICE',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.notice_anomaly_score}'" + + +# +# PL2: This is a stricter sibling of 920120. +# +SecRule FILES_NAMES|FILES "@rx ['\";=\x5c]" \ + "id:920121,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Attempted multipart/form-data bypass',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + 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}'" + + +# +# Check URL encodings +# +# -=[ References ]=- +# http://www.ietf.org/rfc/rfc1738.txt +# +SecRule REQUEST_HEADERS:Content-Type "@rx ^(?i)application/x-www-form-urlencoded" \ + "id:920240,\ + phase:2,\ + block,\ + t:none,\ + msg:'URL Encoding Abuse Attack Attempt',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153/267/72',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + chain" + SecRule REQUEST_BODY "@rx \x25" \ + "chain" + SecRule REQUEST_BODY "@validateUrlEncoding" \ + "setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'" + +# +# -=[ Rule 920650: HTTP Method Override via _method Parameter ]=- +# +# The _method parameter is used by several web frameworks (Laravel, Rails, +# Symfony, CakePHP, Express.js, Phoenix, etc.) to override the HTTP method. +# This allows HTML forms to simulate PUT, PATCH, DELETE requests which are +# not natively supported by browsers. +# +# While this is legitimate framework behavior, it can be abused to: +# - Bypass WAF rules that inspect based on HTTP method +# - Bypass SameSite=Lax cookie restrictions for CSRF attacks +# - Circumvent method-based access control lists +# +# This rule detects _method parameter in both query string and request body +# when it specifies a potentially dangerous method (DELETE, PUT, PATCH, etc.). +# +# To allow _method parameter for applications that legitimately use it, +# set tx.allow_method_override_parameter=1 in crs-setup.conf (see rule 900210). +# +# References: +# - https://portswigger.net/web-security/csrf/bypassing-samesite-restrictions +# - https://blog.mindedsecurity.com/2016/01/request-parameter-method-may-lead-to.html +# - https://www.sidechannel.blog/en/http-method-override-what-it-is-and-how-a-pentester-can-use-it +# - https://laravel.com/docs/routing#form-method-spoofing +# - https://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-patch-put-or-delete-methods-work +# +SecRule TX:allow_method_override_parameter "@eq 0" \ + "id:920650,\ + phase:2,\ + block,\ + t:none,\ + msg:'HTTP method override attempt via _method parameter',\ + logdata:'Requested method override: %{ARGS._method}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule REQUEST_METHOD "!@streq %{ARGS._method}" \ + "t:none,t:lowercase,\ + chain" + SecRule ARGS:_method "@rx ^[a-z]{3,10}$" \ + "t:none,t:urlDecodeUni,t:lowercase,\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:920015,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:920016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + +# +# PL 3: This is a stricter sibling of 920270. Ascii range: Printable characters in the low range +# +# 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_RAW|REQUEST_HEADERS|ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteRange 32-36,38-126" \ + "id:920272,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Invalid character in request (outside of printable chars below ascii 127)',\ + logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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,\ + block,\ + t:none,\ + msg:'Request Missing an Accept Header',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + 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}'" + + +# +# PL3: The little known x-up-devcap-post-charset request header can be used to submit +# a request with a different encoding as an alternative to the charset parameter in +# the Content-Type header. This can be used to circumvent charset restrictions on +# the Content-Type header in ASP.NET. +# 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.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,\ + phase:1,\ + block,\ + t:none,\ + msg:'Request header x-up-devcap-post-charset detected in combination with prefix \'UP\' to User-Agent',\ + logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ + tag:'language-aspnet',\ + tag:'platform-windows',\ + tag:'attack-protocol',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule REQUEST_HEADERS:User-Agent "@rx ^(?i)up" \ + "t:none,\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# +# Cache-Control Request Header allow list +# +# -=[ Rule Logic ]=- +# 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. +# +# The regular expression used on this rule tries to match multiple directives +# in a single value, for example: "max-stale=1, max-age=2". This leads us to +# use a regular expression that accepts a trailing comma to keep compatibility +# with all regex engines and not PCRE only. For example: "max-stale=1, max-age=2, " +# +# Moreover, this regular expression allows duplicate directives sequence like: +# "max-stale, max-stale=1, no-cache, no-cache". +# +# Standard Cache-Control directives that can be used by the client: +# - max-age= +# - max-stale[=] +# - min-fresh= +# - no-cache +# - no-store +# - no-transform +# - only-if-cached +# +# References: +# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control +# - https://regex101.com/r/CZ0Hxu/22 +# +SecRule &REQUEST_HEADERS:Cache-Control "@gt 0" \ + "id:920510,\ + phase:1,\ + block,\ + t:none,\ + msg:'Invalid Cache-Control request header',\ + logdata:'Invalid Cache-Control value in request found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'header-allowlist',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + 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.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:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:920017,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:920018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + +# +# This is a stricter sibling of rule 920200 +# + +SecRule REQUEST_BASENAME "@endsWith .pdf" \ + "id:920202,\ + phase:1,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Range: Too many fields for pdf request (6 or more)',\ + logdata:'%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/4',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'WARNING',\ + chain" + SecRule REQUEST_HEADERS:Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){6}" \ + "setvar:'tx.inbound_anomaly_score_pl4=+%{tx.warning_anomaly_score}'" + + +# +# This is a stricter sibling of 920270. +# +# 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|ARGS_NAMES|REQUEST_BODY "@validateByteRange 38,44-46,48-58,61,65-90,95,97-122" \ + "id:920273,\ + phase:2,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Invalid character in request (outside of very strict set)',\ + logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/4',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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|!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:1,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Invalid character in request headers (outside of very strict set)',\ + logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/4',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" + +# +# This is a stricter sibling of 920270. +# 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|REQUEST_HEADERS:Sec-CH-UA-Mobile "!@rx ^(?:\?[01])?$" \ + "id:920275,\ + phase:1,\ + block,\ + t:none,t:urlDecodeUni,\ + msg:'Invalid character in request headers (outside of very strict set)',\ + logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/4',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/210/272',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" + +# -=[ Abnormal Character Escapes ]=- +# +# [ Rule Logic ] +# Consider the following payload: arg=cat+/e\tc/pa\ssw\d +# Here, \s and \d were only used to obfuscate the string passwd and a lot of +# parsers will silently ignore the non-necessary escapes. The case with \t is +# a bit different though, as \t is a natural escape for the TAB character, +# so we will avoid this (and \n, \r, etc.). +# +# This rule aims to detect non-necessary, abnormal escapes. You could say it is +# a nice way to forbid the backslash character where it is not needed. +# +# This is a new rule at paranoia level 4. We expect quite a few false positives +# for this rule and we will later evaluate if the rule makes any sense at all. +# The rule is redundant with 920273 and 920274 in PL4. But if the rule proofs +# to be useful and false positives remain at a reasonable level, then it might +# be shifted to PL3 in a future release, where it would be the only rule +# covering the backslash escape. +# +# We forbid backslashes followed by a list of basic ascii characters - unless +# the backslash is preceded by another backslash. +# +# 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 (?:^|[^\x5c])\x5c[cdeghijklmpqwxyz123456789]" \ + "id:920460,\ + phase:2,\ + block,\ + capture,\ + 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',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/4',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ENFORCEMENT',\ + tag:'capec/1000/153/267',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-920-PROTOCOL-ENFORCEMENT" diff --git a/appsec/crs/4.25.0/REQUEST-921-PROTOCOL-ATTACK.conf b/appsec/crs/4.25.0/REQUEST-921-PROTOCOL-ATTACK.conf new file mode 100644 index 000000000..de11b1e84 --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-921-PROTOCOL-ATTACK.conf @@ -0,0 +1,628 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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:921011,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:921012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# +# -=[ HTTP Request Smuggling ]=- +# +# [ Rule Logic ] +# This rule looks for a HTTP / WEBDAV method name in combination with the word http/\d or a CR/LF character. +# This would point to an attempt to inject a 2nd request into the request, thus bypassing +# tests carried out on the primary request. +# +# [ References ] +# http://projects.webappsec.org/HTTP-Request-Smuggling +# +# Regular expression generated from regex-assembly/921110.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 921110 +# +SecRule ARGS_NAMES|ARGS|REQUEST_BODY|XML:/* "@rx (?:get|p(?:(?:os|u)t|atch|rop(?:find|atch))|head|options|co(?:nnect|py)|delete|trac[ek]|m(?:kcol|ove)|(?:un)?lock)[\s\x0b]+[^\s\x0b]+[\s\x0b]+http/[0-9]" \ + "id:921110,\ + phase:2,\ + block,\ + capture,\ + 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',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/33',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{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 response header and +# may be interpreted by an intermediary proxy server and treated as two separate +# responses. +# +# [ References ] +# http://projects.webappsec.org/HTTP-Response-Splitting +# +# Regular expression generated from regex-assembly/921120.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 921120 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx [\n\r][^0-9A-Z_a-z]*?(?:content-(?:type|length)|set-cookie|location):[\s\x0b]*[0-9A-Z_a-z]" \ + "id:921120,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'HTTP Response Splitting Attack',\ + 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:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/34',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:\bhttp/\d|<(?:html|meta)\b)" \ + "id:921130,\ + phase:2,\ + block,\ + capture,\ + 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',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/34',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# -=[ HTTP Header Injection ]=- +# +# [ Rule Logic ] +# These rules look for Carriage Return (CR) %0d and Linefeed (LF) %0a characters, +# on their own or in combination with header field names. +# These characters may cause problems if the data is returned in a response header +# and interpreted by the client. +# The rules are similar to rules defending against the HTTP Request Splitting and +# Request Smuggling rules. +# +# [ References ] +# https://en.wikipedia.org/wiki/HTTP_header_injection +# +SecRule REQUEST_HEADERS_NAMES|REQUEST_HEADERS "@rx [\n\r]" \ + "id:921140,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'HTTP Header Injection Attack via headers',\ + 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:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/273',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# Detect newlines in argument names. +# Checking for GET arguments has been moved to paranoia level 2 (921151) +# in order to mitigate possible false positives. +# +# 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 "@rx [\n\r]" \ + "id:921150,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + 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',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/33',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# Regular expression generated from regex-assembly/921160.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 921160 +# +SecRule ARGS_GET_NAMES|ARGS_GET "@rx [\n\r]+(?:[\s\x0b]|location|re(?:fresh|mote-(?:ip|addr))|(?:set-)?cookie|forwarded-(?:(?:fo|serve)r|host)|host|via|originating-IP|x-(?:forwarded-(?:(?:fo|serve)r|host)|host|via|remote-(?:ip|addr)|originating-IP))[\s\x0b]*:" \ + "id:921160,\ + phase:1,\ + block,\ + capture,\ + t:none,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',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/33',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{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://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,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'HTTP Splitting (CR/LF in request filename detected)',\ + 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:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/34',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# -=[ LDAP Injection ]=- +# +# [ Rule Logic ] +# +# This is a rule trying to prevent LDAP injection. It is based on a BlackHat presentation by Alonso Parada +# and regex writing by Denis Kolegov. +# +# [ References ] +# * https://www.blackhat.com/presentations/bh-europe-08/Alonso-Parada/Whitepaper/bh-eu-08-alonso-parada-WP.pdf +# * 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 + +# Regular expression generated from regex-assembly/921200.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 921200 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ^[^!&\(\):<>\|~]*\)[\s\x0b]*(?:\((?:[^!&\(\),<->\|~]+[<>~]?=|[\s\x0b]*[!&\|][\s\x0b]*[\(\)]?[\s\x0b]*)|\)[\s\x0b]*\([\s\x0b]*[!&\|][\s\x0b]*|[!&\|][\s\x0b]*\([^!&\(\),<->\|~]+[<>~]?=[^!&\(\):<>\|~]*)" \ + "id:921200,\ + phase:2,\ + block,\ + capture,\ + t:none,t:htmlEntityDecode,\ + msg:'LDAP Injection Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-ldap',\ + tag:'platform-multi',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/152/248/136',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# -=[ Body Processor Bypass ]=- +# +# [ Rule Logic ] +# +# 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 regex-assembly/921421.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 921421 +# +SecRule REQUEST_HEADERS:Content-Type "@rx ^[^\s\x0b,;]+[\s\x0b,;].*?(?:application/(?:.+\+)?json|(?:application/(?:soap\+)?|text/)xml)" \ + "id:921421,\ + phase:1,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'Content-Type header: Dangerous content type outside the mime type declaration',\ + 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:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# 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_RAW "@rx unix:[^|]*\|" \ + "id:921240,\ + phase:1,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,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:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/33',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# Detection for old V1 cookie format from RFC 2109. +# +# This has been abused by the cookie sandwich technique, in diverse issues affecting Apache Tomcat, Python, and maybe others. +# RFC 6265 deprecated and replaced RFCs 2109 and 2965. +# It completely removed "$Version", meaning user agents and servers no longer use this attribute. +# See: +# - https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique +# - https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-%28v2.x%29#seccookieformat +SecRule REQUEST_COOKIES:/\x22?\x24Version/ "@streq 1" \ + "id:921250,\ + phase:1,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'Old Cookies V1 usage attempt detected',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/33',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:921014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + + +# Detect newlines in GET argument values. +# These may point to a HTTP header injection attack, but can also sometimes +# occur in benign query parameters. +# +# See also: rule 921140, 921150 +# +SecRule ARGS_GET "@rx [\n\r]" \ + "id:921151,\ + phase:1,\ + block,\ + capture,\ + t:none,\ + 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',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220/33',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# +# -=[ Body Processor Bypass ]=- +# +# [ Rule Logic ] +# +# This rule intends to detect content types in the Content-Type header outside of the actual content type declaration. +# +# [ References ] +# * See rule 921422 +# +# Regular expression generated from regex-assembly/921422.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 921422 +# +SecRule REQUEST_HEADERS:Content-Type "@rx ^[^\s\x0b,;]+[\s\x0b,;].*?\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,\ + capture,\ + t:none,t:lowercase,\ + msg:'Content-Type header: Dangerous content type outside the mime type declaration',\ + 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:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:921015,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:921016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# +# + +# Forbid Request Range Header +# +# It is possible abuse the HTTP Request Range Header to leak error pages +# and other information in very small snippets. +# The easiest way to fight this is to deny the use of this header. +# This is a viable option since the header is only used in rare circumstances +# anymore. +# If it is necessary to use it in a certain setup, then it is best to +# create a rule exclusion for a given URI and this rule ID as a workaround. +# +SecRule &REQUEST_HEADERS:Range "@gt 0" \ + "id:921230,\ + phase:1,\ + block,\ + t:none,\ + msg:'HTTP Range Header detected',\ + logdata:'Matched Data: Header %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/210/272/220',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# -=[ HTTP Parameter Pollution ]=- +# +# [ Rule Logic ] +# These rules look for multiple parameters with the same name. +# 921170 counts the occurrences of the individual parameters. +# 921180 checks if any counter is > 1. +# +# One HPP attack vector is to try evade signature filters by distributing the +# attack payload across multiple parameters with the same name. +# This works as many security devices only apply signatures to individual +# parameter payloads, however the back-end web application may (in the case +# of ASP.NET) consolidate all of the payloads into one thus making the +# attack payload active. +# +# This rule is not compatible with application endpoints that accept this +# kind of input: /foo.php?test[]=1&test[]=2 +# +# [ References ] +# http://tacticalwebappsec.blogspot.com/2009/05/http-parameter-pollution.html +# https://capec.mitre.org/data/definitions/460.html +# +SecRule ARGS_NAMES "@rx ." \ + "id:921170,\ + phase:2,\ + pass,\ + nolog,\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/152/137/15/460',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'TX.paramcounter_%{MATCHED_VAR_NAME}=+1'" + +SecRule TX:/paramcounter_.*/ "@gt 1" \ + "id:921180,\ + phase:2,\ + block,\ + msg:'HTTP Parameter Pollution (%{MATCHED_VAR_NAME})',\ + logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-protocol',\ + tag:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/152/137/15/460',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{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 921210 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,\ + block,\ + capture,\ + 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:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/152/137/15/460',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:921017,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:921018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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 ]=- +# +# [ 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 - which is the case for almost +# all CMS - this rule should be disabled. Otherwise, be prepared to handle +# a high volume of exclusions to configure, particularly on administration +# panels. +# +# [ 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,\ + block,\ + capture,\ + 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:'paranoia-level/4',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/PROTOCOL-ATTACK',\ + tag:'capec/1000/152/137/15/460',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'" + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-921-PROTOCOL-ATTACK" diff --git a/appsec/crs/4.25.0/REQUEST-922-MULTIPART-ATTACK.conf b/appsec/crs/4.25.0/REQUEST-922-MULTIPART-ATTACK.conf new file mode 100644 index 000000000..a2f139ed4 --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-922-MULTIPART-ATTACK.conf @@ -0,0 +1,157 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS is distributed under +# Apache Software License (ASL) version 2 +# Please see the enclosed LICENSE file for full details. +# ------------------------------------------------------------------------ + +# +# -= Paranoia Level 0 (empty) =- (apply unconditionally) +# + +# This file is to address the 3UWMWA6W vulnerability. +# It requires ModSecurity version 2.9.6 or 3.0.8 (or an updated version with backports +# of the security fixes in these versions) or a compatible engine supporting these changes. +# +# If you cannot upgrade ModSecurity, this file will cause ModSecurity to fail to start. +# In that case, you can temporarily delete this file. However, you will be missing +# protection from these rules. Therefore, we recommend upgrading your engine instead. + +# The rules in this file will be part of the 920 / 921 in the future. + +# Only allow specific charsets when using "_charset_" +# Note: this is in phase:2 because these are headers that come in the body +SecRule &MULTIPART_PART_HEADERS:_charset_ "!@eq 0" \ + "id:922100,\ + phase:2,\ + block,\ + t:none,\ + msg:'Multipart content type global _charset_ definition is not allowed by policy',\ + logdata:'Matched Data: %{ARGS._charset_}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-multipart-header',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/MULTIPART-ATTACK',\ + tag:'capec/1000/255/153',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.922100_charset=|%{ARGS._charset_}|',\ + chain" + SecRule TX:922100_CHARSET "!@within %{tx.allowed_request_content_type_charset}" \ + "t:lowercase,\ + 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 +# +# How do these rules work: +# * rule 922140 sets the multipart counter TX variable to 0 +# note that this is why does not matter if more parts have the same name - see rule's test +# * rule 922150 collects all multipart headers' 'Content-Type' value +# eg. 'text/plain; charset=utf-8' +# * rule 922110 checks all the collected headers' content type and charset +# +SecRule &MULTIPART_PART_HEADERS "@gt 0" \ + "id:922140,\ + phase:2,\ + pass,\ + t:none,\ + nolog,\ + tag:'attack-multipart-header',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/MULTIPART-ATTACK',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.multipart_headers_content_counter=0'" + +SecRule MULTIPART_PART_HEADERS "@rx ^content-type\s*:\s*(.*)$" \ + "id:922150,\ + phase:2,\ + pass,\ + capture,\ + t:none,t:lowercase,\ + nolog,\ + tag:'attack-multipart-header',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/MULTIPART-ATTACK',\ + ver:'OWASP_CRS/4.25.0',\ + setvar:'tx.multipart_headers_content_types_%{tx.multipart_headers_content_counter}=%{tx.1}',\ + setvar:'tx.multipart_headers_content_counter=+1'" + +# Regular expression generated from regex-assembly/922110.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 922110 +SecRule TX:/MULTIPART_HEADERS_CONTENT_TYPES_*/ "!@rx ^(?:(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)/(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\x0b]*;[\s\x0b]*(?:charset[\s\x0b]*=[\s\x0b]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\x0b-\"\(\),/:-\?\[-\]c\{\}]|c(?:[^!\"\(\),/:-\?\[-\]h\{\}]|h(?:[^!\"\(\),/:-\?\[-\]a\{\}]|a(?:[^!\"\(\),/:-\?\[-\]r\{\}]|r(?:[^!\"\(\),/:-\?\[-\]s\{\}]|s(?:[^!\"\(\),/:-\?\[-\]e\{\}]|e[^!\"\(\),/:-\?\[-\]t\{\}]))))))[^!\"\(\),/:-\?\[-\]\{\}]*[\s\x0b]*=[\s\x0b]*[^!\(\),/:-\?\[-\]\{\}]+);?)*(?:[\s\x0b]*,[\s\x0b]*(?:(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)/(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\x0b]*;[\s\x0b]*(?:charset[\s\x0b]*=[\s\x0b]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\x0b-\"\(\),/:-\?\[-\]c\{\}]|c(?:[^!\"\(\),/:-\?\[-\]h\{\}]|h(?:[^!\"\(\),/:-\?\[-\]a\{\}]|a(?:[^!\"\(\),/:-\?\[-\]r\{\}]|r(?:[^!\"\(\),/:-\?\[-\]s\{\}]|s(?:[^!\"\(\),/:-\?\[-\]e\{\}]|e[^!\"\(\),/:-\?\[-\]t\{\}]))))))[^!\"\(\),/:-\?\[-\]\{\}]*[\s\x0b]*=[\s\x0b]*[^!\(\),/:-\?\[-\]\{\}]+);?)*)*$" \ + "id:922110,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'Illegal MIME Multipart Header content-type: charset parameter',\ + logdata:'Matched Data: %{MATCHED_VAR} found within Content-Type multipart form',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-multipart-header',\ + tag:'attack-protocol',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/MULTIPART-ATTACK',\ + tag:'capec/272/220',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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 +SecRule MULTIPART_PART_HEADERS "@rx content-transfer-encoding:(.*)" \ + "id:922120,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'Content-Transfer-Encoding was deprecated by rfc7578 in 2015 and should not be used',\ + logdata:'Matched Data: %{TX.0}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-multipart-header',\ + tag:'attack-deprecated-header',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/MULTIPART-ATTACK',\ + tag:'capec/272/220',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Multipart header names can't contain any characters outside of range 33 and 126, +# excluding 58 (':') which is the separator. +# RFC 2045 refers RFC 822 about the header syntax. +# Note: this is in phase:2 because these are headers that come in the body +SecRule MULTIPART_PART_HEADERS "@rx [^\x21-\x7E][\x21-\x39\x3B-\x7E]*:" \ + "id:922130,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'Multipart header contains characters outside of valid range',\ + logdata:'Matched Data: %{TX.0}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-multipart-header',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/MULTIPART-ATTACK',\ + tag:'capec/272/220',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" diff --git a/appsec/crs/4.25.0/REQUEST-930-APPLICATION-ATTACK-LFI.conf b/appsec/crs/4.25.0/REQUEST-930-APPLICATION-ATTACK-LFI.conf new file mode 100644 index 000000000..311b99c3c --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-930-APPLICATION-ATTACK-LFI.conf @@ -0,0 +1,239 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:930012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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[56]|EFC8|F025|002f)|%3(?:2(?:%(?:%6|4)6|F)|5%%63)|1u)|0x(?:2f|5c))(?:\.(?:%0[01]|\?)?|\?\.?|%(?:2(?:(?:5(?:2|c0%25a))?e|%45)|c0(?:\.|%[256aef]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[56]|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:'OWASP_CRS/ATTACK-LFI',\ + tag:'capec/1000/255/153/126',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# +# Regular expression generated from regex-assembly/930110.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 930110 +# +SecRule REQUEST_URI_RAW|ARGS|REQUEST_HEADERS|!REQUEST_HEADERS:Referer|FILES|XML:/* "@rx (?:^|[/;\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:'OWASP_CRS/ATTACK-LFI',\ + tag:'capec/1000/255/153/126',\ + ver:'OWASP_CRS/4.25.0',\ + 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_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:'OWASP_CRS/ATTACK-LFI',\ + tag:'capec/1000/255/153/126',\ + ver:'OWASP_CRS/4.25.0',\ + 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:'OWASP_CRS/ATTACK-LFI',\ + tag:'capec/1000/255/153/126',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# -=[ Restricted AI Artifact Access ]=- +# +# Detects attempts to access AI coding assistant configuration directories and +# proprietary config files. These paths can contain API keys, MCP server definitions, +# and credentials reachable if in a web root. +# +# Ref: https://github.com/coreruleset/coreruleset/issues/4474 +# +SecRule REQUEST_FILENAME "@pmFromFile ai-critical-artifacts.data" \ + "id:930140,\ + phase:1,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,\ + msg:'Restricted File Access Attempt: AI Coding Assistant Artifact',\ + 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:'OWASP_CRS/ATTACK-LFI',\ + tag:'capec/1000/255/153/126',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:930014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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:'OWASP_CRS/ATTACK-LFI',\ + tag:'capec/1000/255/153/126',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:930016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:930018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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/appsec/crs/4.25.0/REQUEST-931-APPLICATION-ATTACK-RFI.conf b/appsec/crs/4.25.0/REQUEST-931-APPLICATION-ATTACK-RFI.conf new file mode 100644 index 000000000..adbc142fa --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-931-APPLICATION-ATTACK-RFI.conf @@ -0,0 +1,206 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:931012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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 +# +# Note: brackets around IPv6 literals are mandatory per RFC 2732, +# but have been made optional here - just in case - to account for rare +# non-standard implementations or parsing inconsistencies. +# +# -=[ References ]=- +# http://projects.webappsec.org/Remote-File-Inclusion +# http://tacticalwebappsec.blogspot.com/2009/06/generic-remote-file-inclusion-attack.html +# https://datatracker.ietf.org/doc/html/rfc2732 +# +# Regular expression generated from regex-assembly/931100.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 931100 +# +SecRule ARGS|XML:/* "@rx (?i)^(f(?:ile|tps?)|https?|ssh)://(?:\[?[0-9a-f]+:[0-:a-f]+\]?|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})" \ + "id:931100,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + 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:'OWASP_CRS/ATTACK-RFI',\ + tag:'capec/1000/152/175/253',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# Regular expression generated from regex-assembly/931110.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 931110 +# +SecRule QUERY_STRING|REQUEST_BODY "@rx (?i)(?:\binclude[\s\x0b]*\([^\)]*|mosConfig_absolute_path|(?:_(?:CONF\[path|SERVER\[DOCUMENT_ROOT)|path\[docroot|config\[root_dir)\]|GALLERY_BASEDIR|appserv_root)=(?:f(?:ile|tps?)|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:'OWASP_CRS/ATTACK-RFI',\ + tag:'capec/1000/152/175/253',\ + ver:'OWASP_CRS/4.25.0',\ + 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:'OWASP_CRS/ATTACK-RFI',\ + tag:'capec/1000/152/175/253',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:931014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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 %{tx.original_target}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-rfi',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-RFI',\ + tag:'capec/1000/152/175/253',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rfi_parameter_%{MATCHED_VAR_NAME}=.%{tx.1}',\ + setvar:'tx.original_target=%{MATCHED_VAR_NAME}',\ + 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 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',\ + 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/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-RFI',\ + tag:'capec/1000/152/175/253',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:931015,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:931016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:931018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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/appsec/crs/4.25.0/REQUEST-932-APPLICATION-ATTACK-RCE.conf b/appsec/crs/4.25.0/REQUEST-932-APPLICATION-ATTACK-RCE.conf new file mode 100644 index 000000000..527891c16 --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-932-APPLICATION-ATTACK-RCE.conf @@ -0,0 +1,2276 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:932012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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)) +# \$\[ $[2+2] +# ` `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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:7[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[arx][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?|(?:b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z|c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[89][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?9|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)|d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?f|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|q[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)|f[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:g|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b|j[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:j[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s|q)|[kz][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b|(?:k[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?g|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z)|r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|(?:s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?h|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n)|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:3[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m|c)|x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|z)|y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|l[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:4[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?))[\s\x0b&\),<>\|].*|a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?-[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[&\),<>\|]{1,10}|(?:[\-\.0-9A-Z_a-z][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?){1,10}[\s\x0b&\),<>\|\}]{1,10})|r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?j[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*)|g[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[&\),<>\|]{1,10}|(?:[\-\.0-9A-Z_a-z][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?){1,10}[\s\x0b&\),<>\|\}]{1,10})|(?:d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b|[hr][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?g)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*))\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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:HEAD|POST|y(?:arn|elp))[\s\x0b&\),<>\|]|a(?:dd(?:group|user)|getty|(?:l(?:ias|pine)|tobm|xel)[\s\x0b&\),<>\|]|nsible|p(?:parmor_[^\s\x0b]{1,10}\b|t(?:-get|itude[\s\x0b&\),<>\|]))|r(?:ch[\s\x0b&\),<>\|]|ia2c|j(?:-register|disp))|s(?:cii(?:-xfr|85)|pell)|u(?:ditctl|repot|search))|b(?:a(?:s(?:e(?:32|64|n(?:ame[\s\x0b&\),<>\|]|c))|h[\s\x0b&\),<>\|])|tch[\s\x0b&\),<>\|])|lkid[\s\x0b&\),<>\|]|pftrace|r(?:eaksw|(?:idge|wap)[\s\x0b&\),<>\|])|sd(?:cat|iff|tar)|u(?:iltin|n(?:dler[\s\x0b&\),<>\|]|zip2)|s(?:ctl|ybox))|y(?:ebug|obu[\s\x0b&\),<>\|])|z(?:c(?:at|mp)[\s\x0b&\),<>\|]|diff|e(?:grep|xe[\s\x0b&\),<>\|])|f?grep|ip2(?:[\s\x0b&\),<>\|]|recover)|less|more))|c(?:[89]9-gcc|a(?:(?:ncel|psh)[\s\x0b&\),<>\|]|rgo(?:[\s\x0b&\),<>\|]|-(?:audit|miri|watch)))|ertbot|h(?:(?:(?:att|di)r|mod|o(?:om|wn)|root|sh)[\s\x0b&\),<>\|]|e(?:ck_(?:by_ssh|cups|log|memory|raid|s(?:sl_cert|tatusfile))|f[\s\x0b&\),\-<>\|])|(?:flag|pas)s|g(?:passwd|rp[\s\x0b&\),<>\|]))|l(?:ang(?:\+\+|[\s\x0b&\),<>\|])|ippy-driver)|o(?:bc(?:[\s\x0b&\),<>\|]|run)|(?:lumn|m(?:m(?:and)?|p(?:oser|ress)))[\s\x0b&\),<>\|]|proc|w(?:say|think))|p(?:(?:an|io)[\s\x0b&\),<>\|]|ulimit)|r(?:ash[\s\x0b&\),<>\|]|on(?:[\s\x0b&\),<>\|]|tab))|s(?:cli[\s\x0b&\),<>\|]|plit|vtool)|u(?:psfilter|rl[\s\x0b&\),<>\|]))|d(?:(?:ash|i(?:alog|ff)|vips)[\s\x0b&\),<>\|]|hclient|m(?:esg[\s\x0b&\),<>\|]|idecode|setup)|o(?:(?:as|ne)[\s\x0b&\),<>\|]|cker[\s\x0b&\),\-<>\|]|sbox)|pkg[\s\x0b&\),\-<>\|])|e(?:2fsck|asy_install|(?:cho|fax|grep|macs|sac|val)[\s\x0b&\),<>\|]|n(?:d(?:if|sw)[\s\x0b&\),<>\|]|v-update)|x(?:(?:ec|p(?:and|(?:ec|or)t|r))[\s\x0b&\),<>\|]|iftool))|f(?:acter|d(?:(?:find|isk)[\s\x0b&\),<>\|]|u?mount)|(?:etch|grep|lock|unction)[\s\x0b&\),<>\|]|i(?:le(?:[\s\x0b&\),<>\|]|test)|(?:n(?:d|ger)|sh)[\s\x0b&\),<>\|])|o(?:ld[\s\x0b&\),<>\|]|reach)|ping[\s\x0b&\),6<>\|]|tp(?:stats|who))|g(?:(?:awk|core|i(?:mp|nsh)|z(?:cat|exe|ip))[\s\x0b&\),<>\|]|e(?:ni(?:e[\s\x0b&\),<>\|]|soimage)|t(?:cap|facl[\s\x0b&\),<>\|]))|hc(?:-[\s\x0b&\),<>\|]|i[\s\x0b&\),\-<>\|])|r(?:(?:cat|ep)[\s\x0b&\),<>\|]|oupmod)|tester|unzip)|h(?:(?:ash|i(?:ghlight|story))[\s\x0b&\),<>\|]|e(?:ad[\s\x0b&\),<>\|]|xdump)|ost(?:id|name)|ping3|t(?:digest|op[\s\x0b&\),<>\|]|passwd))|i(?:(?:conv|nstall)[\s\x0b&\),<>\|]|f(?:config|top[\s\x0b&\),<>\|])|onice|p(?:6?tables|config|p(?:eveprinter|find|tool))|spell)|j(?:(?:ava|exec)[\s\x0b&\),<>\|]|o(?:in[\s\x0b&\),<>\|]|urnalctl)|runscript)|k(?:ill(?:[\s\x0b&\),<>\|]|all)|nife[\s\x0b&\),<>\|]|sshell)|l(?:a(?:st(?:comm[\s\x0b&\),<>\|]|log(?:in)?)|tex[\s\x0b&\),<>\|])|dconfig|ess(?:echo|(?:fil|pip)e)|ftp(?:[\s\x0b&\),<>\|]|get)|o(?:(?:cate|ok)[\s\x0b&\),<>\|]|g(?:inctl|(?:nam|sav)e)|setup)|s(?:(?:-F|cpu|hw|mod|of|pci|usb)[\s\x0b&\),<>\|]|b_release)|trace|ua(?:la)?tex|wp-(?:d(?:ownload|ump)|mirror|request)|ynx[\s\x0b&\),<>\|]|z(?:4c(?:[\s\x0b&\),<>\|]|at)|c(?:at|mp)[\s\x0b&\),<>\|]|diff|[ef]?grep|less|m(?:a(?:[\s\x0b&\),<>\|]|dec|info)|ore)))|m(?:(?:a(?:il[qx]?|ke|wk)|utt)[\s\x0b&\),<>\|]|k(?:(?:dir|nod)[\s\x0b&\),<>\|]|fifo|temp)|locate|o(?:squitto|unt[\s\x0b&\),<>\|])|sg(?:attrib|c(?:at|onv)|filter|merge|uniq)|ysql(?:[\s\x0b&\),<>\|]|admin|dump(?:slow)?|hotcopy|show))|n(?:(?:a(?:no|sm|wk)|ice|map|o(?:de|hup)|ping|roff)[\s\x0b&\),<>\|]|c(?:\.(?:openbsd|traditional)|at[\s\x0b&\),<>\|])|e(?:ofetch|t(?:(?:c|st)at|kit-ftp|plan))|s(?:enter|lookup|tat[\s\x0b&\),<>\|]))|o(?:ctave[\s\x0b&\),<>\|]|nintr|p(?:en(?:ssl|v(?:pn|t))|kg[\s\x0b&\),<>\|]))|p(?:a(?:(?:cman|rted|tch)[\s\x0b&\),<>\|]|s(?:swd|te[\s\x0b&\),<>\|]))|d(?:b(?:2mb|3[\s\x0b&\),\.<>\|])|f(?:la)?tex|ksh[\s\x0b&\),<>\|])|er(?:(?:f|ms)[\s\x0b&\),<>\|]|l(?:5?[\s\x0b&\),<>\|]|sh))|i(?:co(?:nv|[\s\x0b&\),<>\|])|dstat|(?:gz|ng6?)[\s\x0b&\),<>\|])|(?:(?:ft|gre)p|opd|u(?:ppet|shd))[\s\x0b&\),<>\|]|hp(?:-cgi|[57][\s\x0b&\),<>\|])|k(?:exec|g_?info|ill[\s\x0b&\),<>\|])|rint(?:env|f[\s\x0b&\),<>\|])|s(?:(?:ed|ql)[\s\x0b&\),<>\|]|ftp)|tar(?:[\s\x0b&\),<>\|]|diff|grep)|y(?:3?versions|thon(?:[23]|[^\s\x0b]{1,10}\b)))|r(?:(?:ak[eu]|bash|nano|oute|vi(?:ew|m))[\s\x0b&\),<>\|]|e(?:a(?:delf|lpath)|(?:(?:boo|dcarpe)t|name|p(?:eat|lace))[\s\x0b&\),<>\|]|stic)|l(?:ogin|wrap)|m(?:dir[\s\x0b&\),<>\|]|t-(?:dump|tar)|user)|pm(?:db[\s\x0b&\),<>\|]|(?:quer|verif)y)|sync(?:-ssl|[\s\x0b&\),<>\|])|u(?:by[^\s\x0b]{1,10}\b|n(?:-(?:mailcap|parts)|c[\s\x0b&\),<>\|])|st(?:-(?:analyzer|(?:g|ll)db)|c[\s\x0b&\),<>\|]|doc|fmt|up)))|s(?:(?:ash|c(?:hed|r(?:een|ipt))|diff|(?:ft|na)p|l(?:eep|sh)|plit)[\s\x0b&\),<>\|]|e(?:(?:ndmail|rvice)[\s\x0b&\),<>\|]|t(?:arch|cap|env|facl[\s\x0b&\),<>\|]|sid))|h(?:\.distrib|(?:red|u(?:f|tdown))[\s\x0b&\),<>\|])|mbclient|o(?:(?:ca|r)t[\s\x0b&\),<>\|]|elim)|qlite3|sh(?:-(?:a(?:dd|gent)|copy-id|key(?:ge|sca)n)|pass)|t(?:art-stop-daemon|dbuf|r(?:ace|ings[\s\x0b&\),<>\|]))|udo(?:-rs|[\s\x0b&\),<>_\|]|edit|replay)|vn(?:a(?:dmin|uthz)|bench|dumpfilter|fsfs|look|mucc|rdump|s(?:erve|ync)|version)|ys(?:ctl|tem(?:ctl|d-resolve)))|t(?:a(?:ilf?[\s\x0b&\),<>\|]|sk(?:[\s\x0b&\),<>\|]|set))|c(?:l?sh[\s\x0b&\),<>\|]|p(?:dump|ing|traceroute))|elnet|(?:ftp|mux|ouch)[\s\x0b&\),<>\|]|ime(?:datectl|out[\s\x0b&\),<>\|])|r(?:a(?:ceroute6?|p[\s\x0b&\),<>\|])|off[\s\x0b&\),<>\|])|shark)|u(?:limit[\s\x0b&\),<>\|]|n(?:(?:ame|compress|iq|rar|s(?:et|hare)|xz)[\s\x0b&\),<>\|]|expand|l(?:ink[\s\x0b&\),<>\|]|z(?:4[\s\x0b&\),<>\|]|ma))|pigz|z(?:ip[\s\x0b&\),<>\|]|std))|conv|p(?:2date[\s\x0b&\),<>\|]|date-alternatives)|ser(?:(?:ad|mo)d|del)|u(?:de|en)code)|v(?:algrind|i(?:(?:[ep]w|gr|rsh)[\s\x0b&\),<>\|]|mdiff|sudo(?:-rs)?)|olatility[\s\x0b&\),<>\|])|w(?:(?:all|get)[\s\x0b&\),<>\|]|h(?:iptail[\s\x0b&\),<>\|]|o(?:ami|is[\s\x0b&\),<>\|]))|i(?:reshark|sh[\s\x0b&\),<>\|]))|x(?:(?:args|pad|term)[\s\x0b&\),<>\|]|e(?:latex|tex[\s\x0b&\),<>\|])|mo(?:dmap|re[\s\x0b&\),<>\|])|z(?:c(?:at|mp)[\s\x0b&\),<>\|]|d(?:ec[\s\x0b&\),<>\|]|iff)|[ef]?grep|less|more))|z(?:athura|(?:c(?:at|mp)|diff|grep|less|run)[\s\x0b&\),<>\|]|[ef]grep|ip(?:c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|mo(?:dload|re[\s\x0b&\),<>\|])|s(?:oelim|td(?:[\s\x0b&\),<>\|]|(?: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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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_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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:[\n\r;`\{]|\|\|?|&&?)[\s\x0b]*[\s\x0b\"'\(,@]*(?:[\"'\.-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[\"\^]*(?:[dpv]|o[\"\^]*u[\"\^]*n[\"\^]*t)|o[\"\^]*g[\"\^]*v|p[\"\^]*(?:o[\"\^]*p|u[\"\^]*s[\"\^]*h)[\"\^]*d|t[\"\^]*r[\"\^]*c[\"\^]*m|w[\"\^]*j[\"\^]*b)[\"\^]*[\s\x0b,\./;<>].*|c[\"\^]*(?:(?:(?:d|h[\"\^]*d[\"\^]*i[\"\^]*r|v[\"\^]*p[\"\^]*a)[\"\^]*|p[\"\^]*(?:[ip][\"\^]*)?)[\s\x0b,\./;<>].*|l[\"\^]*(?:(?:[cipv]|h[\"\^]*y)[\"\^]*[\s\x0b,\./;<>].*|s)|n[\"\^]*s[\"\^]*n)|d[\"\^]*(?:(?:b[\"\^]*p|e[\"\^]*l|i[\"\^]*(?:f[\"\^]*f|r))[\"\^]*[\s\x0b,\./;<>].*|n[\"\^]*s[\"\^]*n)|g[\"\^]*(?:(?:(?:(?:a[\"\^]*)?l|b[\"\^]*p|d[\"\^]*r|h[\"\^]*y|(?:w[\"\^]*m[\"\^]*)?i|j[\"\^]*b|[uv])[\"\^]*|c[\"\^]*(?:[ims][\"\^]*)?|m[\"\^]*(?:o[\"\^]*)?|s[\"\^]*(?:n[\"\^]*(?:p[\"\^]*)?|v[\"\^]*))[\s\x0b,\./;<>].*|e[\"\^]*r[\"\^]*r|p[\"\^]*(?:(?:s[\"\^]*)?[\s\x0b,\./;<>].*|v))|l[\"\^]*s|n[\"\^]*(?:(?:a[\"\^]*l|d[\"\^]*r|[iv]|m[\"\^]*o|s[\"\^]*n)[\"\^]*[\s\x0b,\./;<>].*|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\x0b,\./;<>].*|c[\"\^]*(?:j[\"\^]*b[\"\^]*[\s\x0b,\./;<>].*|s[\"\^]*n)|u[\"\^]*j[\"\^]*b)|s[\"\^]*(?:(?:(?:a[\"\^]*(?:j[\"\^]*b|l|p[\"\^]*s|s[\"\^]*v)|b[\"\^]*p|[cv]|w[\"\^]*m[\"\^]*i)[\"\^]*|l[\"\^]*(?:s[\"\^]*)?|p[\"\^]*(?:(?:j[\"\^]*b|p[\"\^]*s|s[\"\^]*v)[\"\^]*)?)[\s\x0b,\./;<>].*|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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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 +# $[2+2] Arithmetic expansion +# /e[t]c Shell glob expression to bypass wordlists +# +# 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) +# +# 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 +# +SecRule REQUEST_COOKIES|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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \b(?:for(?:/[dflr].*)? %+[^ ]+ in\(.*\)[\s\x0b]?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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Unix shell expressions - Bash Tilde expansion ] +# This rule has a stricter sibling: 932271 +# +# Detects the following patterns which are common in Unix shell scripts +# and one-liners: +# +# ~+ $PWD +# ~- $OLDPWD +# ~-2 second directory entry on the stack from the top +# ~+2 second directory entry on the stack from the bottom +# +# Reference - https://linuxsimply.com/bash-scripting-tutorial/expansion/tilde-expansion/ +# +# Regular expression generated from regex-assembly/932270.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 932270 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ~[\+\-](?:$|[0-9]+)" \ + "id:932270,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# [ Unix shell expressions - brace expansion ] +# +# Detects the following patterns which are common in Unix shell scripts +# and one-liners: +# +# {,ip,a} +# c{a,oun}t +# {,ifconfig} +# {,ifconfig,eth0} +# {l,-lh}s +# +# +# Regular expression generated from regex-assembly/932280.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 932280 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \{[0-9A-Z_a-z]*,[,\-0-9A-Z_a-z]*\}" \ + "id:932280,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Brace Expansion 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:^|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:7[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[arx][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?|(?:b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z|c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[89][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?9|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)|d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?f|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|q[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)|f[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:g|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b|j[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:j[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s|q)|[kz][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b|(?:k[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?g|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z)|r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|(?:s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?h|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n)|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:3[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m|c)|x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|z)|y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|l[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:4[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?))[\s\x0b&\),<>\|].*|a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?-[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[&\),<>\|]{1,10}|(?:[\-\.0-9A-Z_a-z][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?){1,10}[\s\x0b&\),<>\|\}]{1,10})|r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?j[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*)|g[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[&\),<>\|]{1,10}|(?:[\-\.0-9A-Z_a-z][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?){1,10}[\s\x0b&\),<>\|\}]{1,10})|(?:d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b|[hr][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?g)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*))" \ + "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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:^|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:a(?:ddgroup|nsible|pparmor_[^\s\x0b]{1,10}\b|rj(?:-register|disp)|tobm[\s\x0b&\),<>\|]|u(?:ditctl|repot|search))|b(?:ase(?:32|64|nc)|(?:lkid|rwap|yobu)[\s\x0b&\),<>\|]|sd(?:cat|iff|tar)|u(?:iltin|nzip2|sybox)|z(?:c(?:at|mp)[\s\x0b&\),<>\|]|diff|e(?:grep|xe[\s\x0b&\),<>\|])|f?grep|ip2(?:[\s\x0b&\),<>\|]|recover)|less|more))|c(?:[89]9-gcc|argo-(?:audit|miri|watch)|h(?:(?:attr|mod|o(?:om|wn)|sh)[\s\x0b&\),<>\|]|ef-|g(?:passwd|rp[\s\x0b&\),<>\|])|pass)|l(?:ang\+\+|ippy-driver)|o(?:bc(?:[\s\x0b&\),<>\|]|run)|mm[\s\x0b&\),<>\|]|proc)|(?:p(?:an|io)|scli)[\s\x0b&\),<>\|])|d(?:(?:iff|mesg|vips)[\s\x0b&\),<>\|]|o(?:as[\s\x0b&\),<>\|]|cker-)|pkg[\s\x0b&\),\-<>\|])|e(?:2fsck|(?:fax|grep|macs|nd(?:if|sw)|sac|xpr)[\s\x0b&\),<>\|])|f(?:d(?:(?:find|isk)[\s\x0b&\),<>\|]|u?mount)|grep[\s\x0b&\),<>\|]|iletest|ping[\s\x0b&\),6<>\|]|tp(?:stats|who))|g(?:(?:core|insh|z(?:cat|exe|ip))[\s\x0b&\),<>\|]|(?:etca|unzi)p|hc(?:-[\s\x0b&\),<>\|]|i[\s\x0b&\),\-<>\|])|r(?:(?:cat|ep)[\s\x0b&\),<>\|]|oupmod))|(?:htop|jexec)[\s\x0b&\),<>\|]|i(?:(?:conv|ftop)[\s\x0b&\),<>\|]|pp(?:eveprinter|find|tool))|l(?:ast(?:comm[\s\x0b&\),<>\|]|log(?:in)?)|ess(?:echo|(?:fil|pip)e)|ftp(?:[\s\x0b&\),<>\|]|get)|osetup|s(?:(?:-F|cpu|hw|mod|of|pci|usb)[\s\x0b&\),<>\|]|b_release)|wp-download|z(?:4c(?:[\s\x0b&\),<>\|]|at)|c(?:at|mp)[\s\x0b&\),<>\|]|diff|[ef]?grep|less|m(?:a(?:[\s\x0b&\),<>\|]|dec|info)|ore)))|m(?:a(?:ilq|wk)[\s\x0b&\),<>\|]|k(?:fifo|nod[\s\x0b&\),<>\|]|temp)|locate|ysql(?:[\s\x0b&\),<>\|]|admin|dump(?:slow)?|hotcopy|show))|n(?:(?:a(?:sm|wk)|(?:ma|ohu)p|ping|roff|stat)[\s\x0b&\),<>\|]|c(?:\.(?:openbsd|traditional)|at[\s\x0b&\),<>\|])|et(?:(?:c|st)at|kit-ftp|plan))|o(?:nintr|pkg[\s\x0b&\),<>\|])|p(?:d(?:b(?:2mb|3[\s\x0b&\),\.<>\|])|ksh[\s\x0b&\),<>\|])|(?:er(?:f|l5?)|(?:ft|gre)p|(?:op|ush)d|s(?:ed|ql))[\s\x0b&\),<>\|]|i(?:conv|(?:gz|ng6)[\s\x0b&\),<>\|])|hp(?:-cgi|[57][\s\x0b&\),<>\|])|k(?:exec|ill[\s\x0b&\),<>\|])|rint(?:env|f[\s\x0b&\),<>\|])|tar(?:[\s\x0b&\),<>\|]|diff|grep)|y(?:3?versions|thon[23]))|r(?:(?:aku|bash|nano|pmdb|vi(?:ew|m))[\s\x0b&\),<>\|]|e(?:alpath|boot[\s\x0b&\),<>\|])|m(?:dir[\s\x0b&\),<>\|]|t-(?:dump|tar)|user)|sync(?:-ssl|[\s\x0b&\),<>\|])|u(?:nc[\s\x0b&\),<>\|]|st(?:-(?:analyzer|(?:g|ll)db)|c[\s\x0b&\),<>\|]|doc|fmt|up)))|s(?:(?:diff|ftp|lsh|ocat)[\s\x0b&\),<>\|]|e(?:ndmail[\s\x0b&\),<>\|]|t(?:cap|env|sid))|h(?:\.distrib|uf[\s\x0b&\),<>\|])|sh-(?:a(?:dd|gent)|copy-id)|udo(?:-rs|[\s\x0b&\),<>_\|]|edit|replay)|vn(?:a(?:dmin|uthz)|bench|dumpfilter|fsfs|look|mucc|rdump|s(?:erve|ync)|version)|ysctl)|t(?:(?:ailf|ftp|imeout|mux)[\s\x0b&\),<>\|]|c(?:l?sh[\s\x0b&\),<>\|]|p(?:ing|traceroute))|elnet|r(?:a(?:ceroute6?|p[\s\x0b&\),<>\|])|off[\s\x0b&\),<>\|]))|u(?:n(?:(?:ame|iq|rar|xz)[\s\x0b&\),<>\|]|lz(?:4[\s\x0b&\),<>\|]|ma)|pigz|zstd)|conv|ser(?:(?:ad|mo)d|del))|vi(?:(?:gr|pw|rsh)[\s\x0b&\),<>\|]|sudo(?:-rs)?)|w(?:get[\s\x0b&\),<>\|]|ho(?:ami|is[\s\x0b&\),<>\|]))|x(?:(?:args|etex|more|pad|term)[\s\x0b&\),<>\|]|z(?:c(?:at|mp)[\s\x0b&\),<>\|]|d(?:ec[\s\x0b&\),<>\|]|iff)|[ef]?grep|less|more))|z(?:(?:c(?:at|mp)|diff|grep|less|run)[\s\x0b&\),<>\|]|[ef]grep|ip(?:c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|mo(?:dload|re[\s\x0b&\),<>\|])|std(?:[\s\x0b&\),<>\|]|(?: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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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 is meant to block the execution of commands with no arguments when it's possible to meaningfully do so. +# False positive prone commands are not detected at PL-1. +# +# 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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/932340.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 932340 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:aptitude|d(?:f|mesg)|env|h(?:ostname|top)|(?:(?:io|vm)sta|reboo)t|l(?:ast|s)|mysql(?:[^\s\x0b]{1,10}\b)?|ps(?:ql)?|s(?:et|hutdown|u)|w(?:ho(?:ami|is)?)?)$" \ + "id:932340,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Direct Unix Command Execution (No Arguments)',\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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_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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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_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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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: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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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: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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \ba[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s\b[\s\x0b]+(?:[\+\-][a-z]+\+?[\s\x0b]+)?[!\"%',-\.0-9@-Z_a-z]+=[^\s\x0b]" \ + "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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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. +# +# The inverted chained rule enforces a word boundary for some entries that are prone to +# being detected as false positives. This can't be enforced for all entries since some are intentionally meant to match permutations. +# +# +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,t:removeWhitespace,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule MATCHED_VARS "!@rx (?i)(?:\.boto|buddyinfo|mtrr|acpi|zoneinfo)\B" \ + "t:none,\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:[\n\r;`\{]|\|\|?|&&?)[\s\x0b]*[\s\x0b\"'\(,@]*(?:[\"'\.-9A-Z_a-z]+/|(?:[\"'\x5c\^]*[0-9A-Z_a-z][\"'\x5c\^]*:[^\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|t[\"\^]*b[\"\^]*r[\"\^]*o[\"\^]*k)[\"\^]*e)[\"\^]*r|p[\"\^]*p[\"\^]*(?:i[\"\^]*n[\"\^]*s[\"\^]*t[\"\^]*a[\"\^]*l[\"\^]*l[\"\^]*e[\"\^]*r|v[\"\^]*l[\"\^]*p))|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\x0b,\./;<>].*|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\x0b,\./;<>].*|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\x0b,\./;<>].*|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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:[\n\r;`\{]|\|\|?|&&?)[\s\x0b]*[\s\x0b\"'\(,@]*(?:[\"'\.-9A-Z_a-z]+/|(?:[\"'\x5c\^]*[0-9A-Z_a-z][\"'\x5c\^]*:[^\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|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[\"\^]*[qr])|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[\"\^]*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[\"\^]*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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:932014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + +# This rule is a stricter sibling to 932370 +# +# This rule contains additional commands that are not matched at PL-1 due to being false positive prone or common english words. +# Regular expression generated from regex-assembly/932371.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 932371 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:[\n\r;`\{]|\|\|?|&&?)[\s\x0b]*[\s\x0b\"'\(,@]*(?:[\"'\.-9A-Z_a-z]+/|(?:[\"'\x5c\^]*[0-9A-Z_a-z][\"'\x5c\^]*:[^\x5c]*|[ \"'\.-9A-Z\x5c\^_a-z]*)\x5c)?[\"\^]*a[\"\^]*t[\"\^]*[\s\x0b,\./;<>].*(?:\.[\"\^]*[0-9A-Z_a-z]+)?\b" \ + "id:932371,\ + 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/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# [ 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*\.[\s\x0b].*\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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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. +# +# Regular expression generated from regex-assembly/932131.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 932131 +# +SecRule REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer "@rx \$(?:\((?:[^\)]+|\([^\)]+\))\)|\{[^\}]+\}|\[[^\]]*\])|[<>]\([^\)]+\)|/[0-9A-Z_a-z]*\[[^\]]+\]" \ + "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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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 +# +# The two chain rules looking for `/` and `\s` prevent FPs for strings such as +# - pa$word +# - Price: $24.99 +# - rando$mstr.in/g. +# The regular expression does not include this requirement, but we're looking for a unix command +# separated by space, followed by an absolute path, e.g., `cat /etc/passwd`. +# +# 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_NAMES|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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.932200_matched_var_name=%{matched_var_name}',\ + chain" + SecRule MATCHED_VARS "@rx /" \ + "t:none,\ + chain" + SecRule MATCHED_VARS "@rx \s" \ + "t:none,\ + 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 932205-chain1 +# +SecRule REQUEST_HEADERS:Referer "@rx ^[^#]+" \ + "id:932205,\ + phase:1,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.932205_matched_var_name=%{matched_var_name}',\ + chain" + SecRule TX:0 "@rx ^[^\.]+\.[^;\?]+[;\?](.*(['\*\?\x5c`][^\n/]+/|/[^/]+?['\*\?\x5c`]|\$[!#\$\(\*\-0-9\?-\[_a-\{]))" \ + "capture,\ + t:none,\ + chain" + SecRule TX:1 "@rx /" \ + "t:none,\ + chain" + SecRule TX:1 "@rx \s" \ + "t:none,\ + 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:1,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.932206_matched_var_name=%{matched_var_name}',\ + chain" + SecRule MATCHED_VARS "@rx /" \ + "t:none,\ + chain" + SecRule MATCHED_VARS "@rx \s" \ + "t:none,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# +# -=[ Rule 932207 ]=- +# +# Sibling of 932200 targeting fragments in the Referer header. +# +# The last chain prevents FPs against the "Scroll to text fragment" browser feature +# (https://wicg.github.io/scroll-to-text-fragment/). +# +# Regular expression generated from regex-assembly/932207.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 932207 932207-chain1 +# +SecRule REQUEST_HEADERS:Referer "@rx #.*" \ + "id:932207,\ + phase:1,\ + block,\ + capture,\ + t:none,t:lowercase,t:urlDecodeUni,\ + msg:'RCE Bypass Technique',\ + logdata:'Matched Data: %{TX.0} found within %{TX.932207_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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.932207_matched_var_name=%{matched_var_name}',\ + chain" + SecRule TX:0 "@rx ['\*\?\x5c`][^\n/]+/|/[^/]+?['\*\?\x5c`]|\$[!#\$\(\*\-0-9\?-\[_a-\{]" \ + "capture,\ + t:none,\ + chain" + SecRule MATCHED_VAR "@rx /" \ + "t:none,\ + chain" + SecRule MATCHED_VAR "@rx \s" \ + "t:none,\ + chain" + SecRule MATCHED_VAR "!@beginsWith #:~:text=" \ + "t:none,\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i).\|(?:[\s\x0b]*|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:7[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[arx][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?|(?:G[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?E[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?T|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z|c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[89][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?9|[au][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t|c|(?:m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?p|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)|d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[dfu]|i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[gr])|f[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[cgi]|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p)|h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:d|u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p)|i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[dp]|r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b)|j[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:j[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s|q)|k[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r|v)|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[cl]|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t|(?:p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?m)|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[cr]|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[ex]|i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p)|u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:3[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m|c)|x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|z)|y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s|u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m)|z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h))[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:(?:[bdx]|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|q[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?)|l[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:(?:(?:u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?a|[lnps])[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?|z[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:4[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?)?|r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[dv]|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?|m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?)|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[dt]|[ghu]|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?))[\s\x0b&\),<>\|].*|a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?-[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[&\),<>\|]{1,10}|(?:[\-\.0-9A-Z_a-z][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?){1,10}[\s\x0b&\),<>\|\}]{1,10})|(?:(?:b|(?:p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?t|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[ks])[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[jp][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?|s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?)[\s\x0b&\),<>\|].*)|g[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[&\),<>\|]{1,10}|(?:[\-\.0-9A-Z_a-z][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?){1,10}[\s\x0b&\),<>\|\}]{1,10})|(?:d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m|[hr][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c|i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t|o|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?g)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*)|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:(?:(?:[at][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b|f|(?:k[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?g|h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|x[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?z)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?|r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?)?)[\s\x0b&\),<>\|].*|i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|[&\),<>\|]{1,10}|(?:[\-\.0-9A-Z_a-z][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?){1,10}[\s\x0b&\),<>\|\}]{1,10}))))" \ + "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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS|XML:/* "@rx (?i)[\-0-9_a-z]+(?:[\s\x0b]*[\"'][^\s\x0b\"',:]+[\"']|(?:[\"'][\"']+|[\[-\]]+|\$+[!#\*\-0-9\?@\x5c_a-\{]+|``|[\$<>]\(\))[\s\x0b]*)[\-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 %{TX.932240_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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.932240_matched_var_name=%{matched_var_name}',\ + chain" + SecRule MATCHED_VARS "!@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}'" + + +# [ Unix shell expressions - Bash Brace expansion ] +# +# This rule is a stricter sibling of rule 932280. It matches non-whitespace characters between braces, +# as an extension of rule 932280, which only detects alphanumeric and underscore characters. This rule detects the following +# patterns which are used in Unix shell scripts and one-liners: +# +# {,echo,#test} +# {,cd,/etc,} +# {,$'whoami',} +# {,$"whoami",} +# {,/?s?/?i?/c?t,/e??/p??s??,} +# +# +# Regular expression generated from regex-assembly/932281.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 932281 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \{[^\s\x0b,:\}]*,[^\s\x0b]*\}" \ + "id:932281,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Brace Expansion 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ;[\s\x0b]*\.[\s\x0b]*[\"']?(?: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,\ + capture,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# [ Unix shell expressions - Bash Tilde expansion ] +# This rule is a sibling of rule 932270 +# +# Detects the following patterns which are common in Unix shell scripts +# and one-liners: +# +# ~4 fourth directory entry on the stack from the top +# +# Reference - https://linuxsimply.com/bash-scripting-tutorial/expansion/tilde-expansion/ +# +# Regular expression generated from regex-assembly/932271.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 932271 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ~[0-9]+" \ + "id:932271,\ + 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/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\r\n.*?\b(?:E(?:HLO[\s\x0b][\-\.a-z]{1,255}|XPN[\s\x0b].{1,64})|HELO[\s\x0b][\-\.a-z]{1,255}|MAIL[\s\x0b]FROM:<.{1,64}@.{1,255}>|R(?:CPT[\s\x0b]TO:(?:<.{1,64}@.{1,255}>| )?<.{1,64}>|SET\b)|VRFY[\s\x0b].{1,64}(?:[\s\x0b]<.{1,64}@.{1,255}>|@.{1,255})|AUTH[\s\x0b][\-0-9_a-z]{1,20}[\s\x0b](?:(?:[\+/-9A-Z_a-z]{4})*(?:[\+/-9A-Z_a-z]{2}=|[\+/-9A-Z_a-z]{3}))?=|STARTTLS\b|NOOP\b(?:[\s\x0b].{1,255})?)" \ + "id:932300,\ + phase:2,\ + block,\ + capture,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/137/134',\ + ver:'OWASP_CRS/4.25.0',\ + 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_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-eiklpr-twx]+?)|UID (?:COPY|FETCH|STORE) (?:[\*,0-:]+)?|(?:(?:DELETE|GET)ACL|MYRIGHTS) (?:[\"%&\*\--9A-Z\x5c_a-z]+)?)" \ + "id:932310,\ + phase:2,\ + block,\ + capture,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/137/134',\ + ver:'OWASP_CRS/4.25.0',\ + 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_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-9_a-z]{1,20} (?:(?:[\+/-9A-Z_a-z]{4})*(?:[\+/-9A-Z_a-z]{2}=|[\+/-9A-Z_a-z]{3}))?=))" \ + "id:932320,\ + phase:2,\ + block,\ + capture,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/137/134',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:^|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:7z[arx]?|(?:GE|POS)T|y(?:e(?:s|lp)|um|arn)|HEAD)[\s\x0b&\),<>\|]|a(?:a-[^\s\x0b]{1,10}\b|(?:b|w[ks]|l(?:ias|pine)|tobm|xel)[\s\x0b&\),<>\|]|p(?:t(?:[\s\x0b&\),<>\|]|-get)|parmor_[^\s\x0b]{1,10}\b)|r(?:(?:p|ch)?[\s\x0b&\),<>\|]|j(?:[\s\x0b&\),<>\|]|-register|disp)|ia2c)|s(?:h[\s\x0b&\),<>\|]|cii(?:-xfr|85)|pell)|dd(?:group|user)|getty|nsible|u(?:ditctl|repot|search))|b(?:z(?:(?:z|c(?:at|mp))[\s\x0b&\),<>\|]|diff|e(?:grep|xe[\s\x0b&\),<>\|])|f?grep|ip2(?:[\s\x0b&\),<>\|]|recover)|less|more)|a(?:s(?:e(?:32|64|n(?:ame[\s\x0b&\),<>\|]|c))|h[\s\x0b&\),<>\|])|tch[\s\x0b&\),<>\|])|lkid[\s\x0b&\),<>\|]|pftrace|r(?:eaksw|(?:idge|wap)[\s\x0b&\),<>\|])|sd(?:cat|iff|tar)|u(?:iltin|n(?:dler[\s\x0b&\),<>\|]|zip2)|s(?:ctl|ybox))|y(?:ebug|obu[\s\x0b&\),<>\|]))|c(?:[89]9(?:[\s\x0b&\),<>\|]|-gcc)|a(?:(?:t|ncel|psh)[\s\x0b&\),<>\|]|rgo(?:[\s\x0b&\),<>\|]|-(?:audit|miri|watch)))|(?:c|mp)[\s\x0b&\),<>\|]|p(?:(?:an|io)?[\s\x0b&\),<>\|]|ulimit)|s(?:(?:h|cli)[\s\x0b&\),<>\|]|plit|vtool)|u(?:(?:t|rl)[\s\x0b&\),<>\|]|psfilter)|ertbot|h(?:(?:(?:att|di)r|mod|o(?:om|wn)|root|sh)[\s\x0b&\),<>\|]|e(?:ck_(?:by_ssh|cups|log|memory|raid|s(?:sl_cert|tatusfile))|f[\s\x0b&\),\-<>\|])|(?:flag|pas)s|g(?:passwd|rp[\s\x0b&\),<>\|]))|l(?:ang(?:\+\+|[\s\x0b&\),<>\|])|ippy-driver)|o(?:bc(?:[\s\x0b&\),<>\|]|run)|(?:lumn|m(?:m(?:and)?|p(?:oser|ress)))[\s\x0b&\),<>\|]|proc|w(?:say|think))|r(?:ash[\s\x0b&\),<>\|]|on(?:[\s\x0b&\),<>\|]|tab)))|d(?:(?:[dfu]|i(?:(?:alo)?g|r|ff)|a(?:sh|te)|vips)[\s\x0b&\),<>\|]|hclient|m(?:esg[\s\x0b&\),<>\|]|idecode|setup)|o(?:(?:as|ne)[\s\x0b&\),<>\|]|cker[\s\x0b&\),\-<>\|]|sbox)|pkg[\s\x0b&\),\-<>\|])|e(?:(?:[bd]|qn|s(?:h|ac)?|cho|fax|grep|macs|val)[\s\x0b&\),<>\|]|n(?:v(?:[\s\x0b&\),<>\|]|-update)|d(?:if|sw)[\s\x0b&\),<>\|])|x(?:(?:ec|p(?:and|(?:ec|or)t|r))?[\s\x0b&\),<>\|]|iftool)|2fsck|asy_install)|f(?:(?:c|g(?:rep)?|mt|etch|lock|unction)[\s\x0b&\),<>\|]|i(?:(?:n(?:d|ger)|sh)?[\s\x0b&\),<>\|]|le(?:[\s\x0b&\),<>\|]|test))|tp(?:[\s\x0b&\),<>\|]|stats|who)|acter|d(?:(?:find|isk)[\s\x0b&\),<>\|]|u?mount)|o(?:ld[\s\x0b&\),<>\|]|reach)|ping[\s\x0b&\),6<>\|])|g(?:c(?:c[^\s\x0b]{1,10}\b|ore[\s\x0b&\),<>\|])|(?:db|i(?:t|mp|nsh)|o|pg|awk|z(?:cat|exe|ip))[\s\x0b&\),<>\|]|e(?:m[\s\x0b&\),<>\|]|ni(?:e[\s\x0b&\),<>\|]|soimage)|t(?:cap|facl[\s\x0b&\),<>\|]))|hc(?:-?[\s\x0b&\),<>\|]|i[\s\x0b&\),\-<>\|])|r(?:(?:c(?:at)?|ep)[\s\x0b&\),<>\|]|oupmod)|tester|unzip)|h(?:(?:d|up|ash|i(?:ghlight|story))[\s\x0b&\),<>\|]|e(?:ad[\s\x0b&\),<>\|]|xdump)|ost(?:id|name)|ping3|t(?:digest|op[\s\x0b&\),<>\|]|passwd))|i(?:(?:d|rb|conv|nstall)[\s\x0b&\),<>\|]|p(?:[\s\x0b&\),<>\|]|6?tables|config|p(?:eveprinter|find|tool))|f(?:config|top[\s\x0b&\),<>\|])|onice|spell)|j(?:(?:js|q|ava|exec)[\s\x0b&\),<>\|]|o(?:(?:bs|in)[\s\x0b&\),<>\|]|urnalctl)|runscript)|k(?:s(?:h[\s\x0b&\),<>\|]|shell)|ill(?:[\s\x0b&\),<>\|]|all)|nife[\s\x0b&\),<>\|])|l(?:(?:[lnp]|inks|ynx)?[\s\x0b&\),<>\|]|a(?:(?:tex)?[\s\x0b&\),<>\|]|st(?:(?:comm)?[\s\x0b&\),<>\|]|log(?:in)?))|d(?:d?[\s\x0b&\),<>\|]|config)|s(?:(?:-F|cpu|hw|mod|of|pci|usb)?[\s\x0b&\),<>\|]|b_release)|ua(?:[\s\x0b&\),<>\|]|(?:la)?tex)|z(?:4(?:[\s\x0b&\),<>\|]|c(?:[\s\x0b&\),<>\|]|at))|(?:c(?:at|mp))?[\s\x0b&\),<>\|]|diff|[ef]?grep|less|m(?:a(?:[\s\x0b&\),<>\|]|dec|info)|ore))|ess(?:[\s\x0b&\),<>\|]|echo|(?:fil|pip)e)|ftp(?:[\s\x0b&\),<>\|]|get)|o(?:(?:ca(?:l|te)|ok)[\s\x0b&\),<>\|]|g(?:inctl|(?:nam|sav)e)|setup)|trace|wp-(?:d(?:ownload|ump)|mirror|request))|m(?:(?:a(?:n|il[qx]?|ke|wk)|tr|v|utt)[\s\x0b&\),<>\|]|k(?:(?:dir|nod)[\s\x0b&\),<>\|]|fifo|temp)|locate|o(?:squitto|unt[\s\x0b&\),<>\|])|sg(?:attrib|c(?:at|onv)|filter|merge|uniq)|ysql(?:[\s\x0b&\),<>\|]|admin|dump(?:slow)?|hotcopy|show))|n(?:c(?:(?:at)?[\s\x0b&\),<>\|]|\.(?:openbsd|traditional))|e(?:t(?:[\s\x0b&\),<>\|]|(?:c|st)at|kit-ftp|plan)|ofetch)|(?:l|m(?:ap)?|p(?:m|ing)|a(?:no|sm|wk)|ice|o(?:de|hup)|roff)[\s\x0b&\),<>\|]|s(?:enter|lookup|tat[\s\x0b&\),<>\|]))|o(?:(?:d|ctave)[\s\x0b&\),<>\|]|nintr|p(?:en(?:ssl|v(?:pn|t))|kg[\s\x0b&\),<>\|]))|p(?:a(?:(?:x|rted|tch)[\s\x0b&\),<>\|]|s(?:swd|te[\s\x0b&\),<>\|]))|d(?:b(?:[\s\x0b&\),<>\|]|2mb|3[\s\x0b&\),\.<>\|])|f(?:la)?tex|ksh[\s\x0b&\),<>\|])|(?:f(?:tp)?|g(?:rep)?|(?:w|op)d|xz|u(?:ppet|shd))[\s\x0b&\),<>\|]|hp(?:[57]?[\s\x0b&\),<>\|]|-cgi)|i(?:c(?:[\s\x0b&\),<>\|]|o(?:nv|[\s\x0b&\),<>\|]))|p(?:[\s\x0b&\),<>\|]|[^\s\x0b]{1,10}\b)|dstat|(?:gz|ng6?)[\s\x0b&\),<>\|])|k(?:g(?:[\s\x0b&\),<>\|]|_?info)|exec|ill[\s\x0b&\),<>\|])|r(?:y?[\s\x0b&\),<>\|]|int(?:env|f[\s\x0b&\),<>\|]))|t(?:x[\s\x0b&\),<>\|]|ar(?:[\s\x0b&\),<>\|]|diff|grep))|er(?:(?:f|ms)[\s\x0b&\),<>\|]|l(?:5?[\s\x0b&\),<>\|]|sh))|s(?:(?:ed|ql)[\s\x0b&\),<>\|]|ftp)|y(?:3?versions|thon(?:[23]|[^\s\x0b]{1,10}\b)))|r(?:(?:a(?:r|k[eu])|cp?|bash|nano|oute|vi(?:ew|m))[\s\x0b&\),<>\|]|e(?:(?:d(?:carpet)?|v|boot|name|p(?:eat|lace))[\s\x0b&\),<>\|]|a(?:delf|lpath)|stic)|m(?:(?:dir)?[\s\x0b&\),<>\|]|t(?:[\s\x0b&\),<>\|]|-(?:dump|tar))|user)|pm(?:(?:db)?[\s\x0b&\),<>\|]|(?:quer|verif)y)|l(?:ogin|wrap)|sync(?:-ssl|[\s\x0b&\),<>\|])|u(?:by[^\s\x0b]{1,10}\b|n(?:-(?:mailcap|parts)|c[\s\x0b&\),<>\|])|st(?:-(?:analyzer|(?:g|ll)db)|c[\s\x0b&\),<>\|]|doc|fmt|up)))|s(?:(?:c(?:p|hed|r(?:een|ipt))|g|ash|diff|(?:ft|na)p|l(?:eep|sh)|plit)[\s\x0b&\),<>\|]|e(?:(?:d|ndmail|rvice)[\s\x0b&\),<>\|]|t(?:(?:facl)?[\s\x0b&\),<>\|]|arch|cap|env|sid))|h(?:(?:red|u(?:f|tdown))?[\s\x0b&\),<>\|]|\.distrib)|s(?:[\s\x0b&\),<>\|]|h(?:[\s\x0b&\),<>\|]|-(?:a(?:dd|gent)|copy-id|key(?:ge|sca)n)|pass))|u(?:[\s\x0b&\),<>\|]|do(?:-rs|[\s\x0b&\),<>_\|]|edit|replay))|vn(?:[\s\x0b&\),<>\|]|a(?:dmin|uthz)|bench|dumpfilter|fsfs|look|mucc|rdump|s(?:erve|ync)|version)|mbclient|o(?:(?:(?:ca|r)t|urce)[\s\x0b&\),<>\|]|elim)|qlite3|t(?:art-stop-daemon|dbuf|r(?:ace|ings[\s\x0b&\),<>\|]))|ys(?:ctl|tem(?:ctl|d-resolve)))|t(?:a(?:(?:[cr]|ilf?)[\s\x0b&\),<>\|]|sk(?:[\s\x0b&\),<>\|]|set))|(?:bl|o(?:p|uch)|ftp|mux)[\s\x0b&\),<>\|]|e(?:[ex][\s\x0b&\),<>\|]|lnet)|i(?:c[\s\x0b&\),<>\|]|me(?:datectl|out[\s\x0b&\),<>\|]))|c(?:l?sh[\s\x0b&\),<>\|]|p(?:dump|ing|traceroute))|r(?:a(?:ceroute6?|p[\s\x0b&\),<>\|])|off[\s\x0b&\),<>\|])|shark)|u(?:l(?:imit)?[\s\x0b&\),<>\|]|n(?:(?:ame|compress|iq|rar|s(?:et|hare)|xz)[\s\x0b&\),<>\|]|expand|l(?:ink[\s\x0b&\),<>\|]|z(?:4[\s\x0b&\),<>\|]|ma))|pigz|z(?:ip[\s\x0b&\),<>\|]|std))|conv|pdate-alternatives|ser(?:(?:ad|mo)d|del)|u(?:de|en)code)|v(?:i(?:m(?:[\s\x0b&\),<>\|]|diff)|(?:[ep]w|gr|rsh)[\s\x0b&\),<>\|]|sudo(?:-rs)?)|algrind|olatility[\s\x0b&\),<>\|])|w(?:(?:3m|c|a(?:ll|tch)|get)[\s\x0b&\),<>\|]|h(?:iptail[\s\x0b&\),<>\|]|o(?:ami|is[\s\x0b&\),<>\|]))|i(?:reshark|sh[\s\x0b&\),<>\|]))|x(?:(?:(?:x|pa)d|args|term)[\s\x0b&\),<>\|]|z(?:(?:c(?:at|mp))?[\s\x0b&\),<>\|]|d(?:ec[\s\x0b&\),<>\|]|iff)|[ef]?grep|less|more)|e(?:latex|tex[\s\x0b&\),<>\|])|mo(?:dmap|re[\s\x0b&\),<>\|]))|z(?:ip(?:[\s\x0b&\),<>\|]|c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|s(?:h[\s\x0b&\),<>\|]|oelim|td(?:[\s\x0b&\),<>\|]|(?:ca|m)t|grep|less))|athura|(?:c(?:at|mp)|diff|grep|less|run)[\s\x0b&\),<>\|]|[ef]grep|mo(?:dload|re[\s\x0b&\),<>\|])|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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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:User-Agent|REQUEST_HEADERS:Referer "@rx (?i)(?:^|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:7z[arx]?|(?:GE|POS)T|y(?:e(?:s|lp)|um|arn)|HEAD)[\s\x0b&\),<>\|]|a(?:a-[^\s\x0b]{1,10}\b|(?:b|w[ks]|l(?:ias|pine)|tobm|xel)[\s\x0b&\),<>\|]|p(?:t(?:[\s\x0b&\),<>\|]|-get)|parmor_[^\s\x0b]{1,10}\b)|r(?:(?:p|ch)?[\s\x0b&\),<>\|]|j(?:[\s\x0b&\),<>\|]|-register|disp)|ia2c)|s(?:h[\s\x0b&\),<>\|]|cii(?:-xfr|85)|pell)|dd(?:group|user)|getty|nsible|u(?:ditctl|repot|search))|b(?:z(?:(?:z|c(?:at|mp))[\s\x0b&\),<>\|]|diff|e(?:grep|xe[\s\x0b&\),<>\|])|f?grep|ip2(?:[\s\x0b&\),<>\|]|recover)|less|more)|a(?:s(?:e(?:32|64|n(?:ame[\s\x0b&\),<>\|]|c))|h[\s\x0b&\),<>\|])|tch[\s\x0b&\),<>\|])|lkid[\s\x0b&\),<>\|]|pftrace|r(?:eaksw|(?:idge|wap)[\s\x0b&\),<>\|])|sd(?:cat|iff|tar)|u(?:iltin|n(?:dler[\s\x0b&\),<>\|]|zip2)|s(?:ctl|ybox))|y(?:ebug|obu[\s\x0b&\),<>\|]))|c(?:[89]9(?:[\s\x0b&\),<>\|]|-gcc)|a(?:(?:t|ncel|psh)[\s\x0b&\),<>\|]|rgo(?:[\s\x0b&\),<>\|]|-(?:audit|miri|watch)))|(?:c|mp)[\s\x0b&\),<>\|]|p(?:(?:an|io)?[\s\x0b&\),<>\|]|ulimit)|s(?:(?:h|cli)[\s\x0b&\),<>\|]|plit|vtool)|u(?:t[\s\x0b&\),<>\|]|psfilter)|ertbot|h(?:(?:(?:att|di)r|mod|o(?:om|wn)|root|sh)[\s\x0b&\),<>\|]|e(?:ck_(?:by_ssh|cups|log|memory|raid|s(?:sl_cert|tatusfile))|f[\s\x0b&\),\-<>\|])|(?:flag|pas)s|g(?:passwd|rp[\s\x0b&\),<>\|]))|l(?:ang(?:\+\+|[\s\x0b&\),<>\|])|ippy-driver)|o(?:bc(?:[\s\x0b&\),<>\|]|run)|(?:lumn|m(?:m(?:and)?|p(?:oser|ress)))[\s\x0b&\),<>\|]|proc|w(?:say|think))|r(?:ash[\s\x0b&\),<>\|]|on(?:[\s\x0b&\),<>\|]|tab)))|d(?:(?:[dfu]|i(?:(?:alo)?g|r|ff)|a(?:sh|te)|vips)[\s\x0b&\),<>\|]|hclient|m(?:esg[\s\x0b&\),<>\|]|idecode|setup)|o(?:(?:as|ne)[\s\x0b&\),<>\|]|cker[\s\x0b&\),\-<>\|]|sbox)|pkg[\s\x0b&\),\-<>\|])|e(?:(?:[bd]|qn|s(?:h|ac)?|cho|fax|grep|macs|val)[\s\x0b&\),<>\|]|n(?:v(?:[\s\x0b&\),<>\|]|-update)|d(?:if|sw)[\s\x0b&\),<>\|])|x(?:(?:ec|p(?:and|(?:ec|or)t|r))?[\s\x0b&\),<>\|]|iftool)|2fsck|asy_install)|f(?:(?:c|g(?:rep)?|mt|etch|lock|unction)[\s\x0b&\),<>\|]|i(?:(?:n(?:d|ger)|sh)?[\s\x0b&\),<>\|]|le(?:[\s\x0b&\),<>\|]|test))|tp(?:[\s\x0b&\),<>\|]|stats|who)|acter|d(?:(?:find|isk)[\s\x0b&\),<>\|]|u?mount)|o(?:ld[\s\x0b&\),<>\|]|reach)|ping[\s\x0b&\),6<>\|])|g(?:c(?:c[^\s\x0b]{1,10}\b|ore[\s\x0b&\),<>\|])|(?:db|i(?:t|mp|nsh)|o|pg|awk|z(?:cat|exe|ip))[\s\x0b&\),<>\|]|e(?:m[\s\x0b&\),<>\|]|ni(?:e[\s\x0b&\),<>\|]|soimage)|t(?:cap|facl[\s\x0b&\),<>\|]))|hc(?:-?[\s\x0b&\),<>\|]|i[\s\x0b&\),\-<>\|])|r(?:(?:c(?:at)?|ep)[\s\x0b&\),<>\|]|oupmod)|tester|unzip)|h(?:(?:d|up|ash|i(?:ghlight|story))[\s\x0b&\),<>\|]|e(?:ad[\s\x0b&\),<>\|]|xdump)|ost(?:id|name)|ping3|t(?:digest|op[\s\x0b&\),<>\|]|passwd))|i(?:(?:d|rb|conv|nstall)[\s\x0b&\),<>\|]|p(?:[\s\x0b&\),<>\|]|6?tables|config|p(?:eveprinter|find|tool))|f(?:config|top[\s\x0b&\),<>\|])|onice|spell)|j(?:(?:js|q|ava|exec)[\s\x0b&\),<>\|]|o(?:(?:bs|in)[\s\x0b&\),<>\|]|urnalctl)|runscript)|k(?:s(?:h[\s\x0b&\),<>\|]|shell)|ill(?:[\s\x0b&\),<>\|]|all)|nife[\s\x0b&\),<>\|])|l(?:(?:[lnp]|ynx)?[\s\x0b&\),<>\|]|a(?:(?:tex)?[\s\x0b&\),<>\|]|st(?:(?:comm)?[\s\x0b&\),<>\|]|log(?:in)?))|d(?:d?[\s\x0b&\),<>\|]|config)|s(?:(?:-F|cpu|hw|mod|of|pci|usb)?[\s\x0b&\),<>\|]|b_release)|ua(?:[\s\x0b&\),<>\|]|(?:la)?tex)|z(?:4(?:[\s\x0b&\),<>\|]|c(?:[\s\x0b&\),<>\|]|at))|(?:c(?:at|mp))?[\s\x0b&\),<>\|]|diff|[ef]?grep|less|m(?:a(?:[\s\x0b&\),<>\|]|dec|info)|ore))|ess(?:[\s\x0b&\),<>\|]|echo|(?:fil|pip)e)|ftp(?:[\s\x0b&\),<>\|]|get)|o(?:(?:ca(?:l|te)|ok)[\s\x0b&\),<>\|]|g(?:inctl|(?:nam|sav)e)|setup)|trace|wp-(?:d(?:ownload|ump)|mirror|request))|m(?:(?:a(?:n|il[qx]?|ke|wk)|tr|v|utt)[\s\x0b&\),<>\|]|k(?:(?:dir|nod)[\s\x0b&\),<>\|]|fifo|temp)|locate|o(?:squitto|unt[\s\x0b&\),<>\|])|sg(?:attrib|c(?:at|onv)|filter|merge|uniq)|ysql(?:[\s\x0b&\),<>\|]|admin|dump(?:slow)?|hotcopy|show))|n(?:c(?:(?:at)?[\s\x0b&\),<>\|]|\.(?:openbsd|traditional))|e(?:t(?:[\s\x0b&\),<>\|]|(?:c|st)at|kit-ftp|plan)|ofetch)|(?:l|m(?:ap)?|p(?:m|ing)|a(?:no|sm|wk)|ice|o(?:de|hup)|roff)[\s\x0b&\),<>\|]|s(?:enter|lookup|tat[\s\x0b&\),<>\|]))|o(?:(?:d|ctave)[\s\x0b&\),<>\|]|nintr|p(?:en(?:ssl|v(?:pn|t))|kg[\s\x0b&\),<>\|]))|p(?:a(?:(?:x|rted|tch)[\s\x0b&\),<>\|]|s(?:swd|te[\s\x0b&\),<>\|]))|d(?:b(?:[\s\x0b&\),<>\|]|2mb|3[\s\x0b&\),\.<>\|])|f(?:la)?tex|ksh[\s\x0b&\),<>\|])|(?:f(?:tp)?|g(?:rep)?|(?:w|op)d|xz|u(?:ppet|shd))[\s\x0b&\),<>\|]|hp(?:[57]?[\s\x0b&\),<>\|]|-cgi)|i(?:c(?:[\s\x0b&\),<>\|]|o(?:nv|[\s\x0b&\),<>\|]))|p(?:[\s\x0b&\),<>\|]|[^\s\x0b]{1,10}\b)|dstat|(?:gz|ng6?)[\s\x0b&\),<>\|])|k(?:g(?:[\s\x0b&\),<>\|]|_?info)|exec|ill[\s\x0b&\),<>\|])|r(?:y?[\s\x0b&\),<>\|]|int(?:env|f[\s\x0b&\),<>\|]))|t(?:x[\s\x0b&\),<>\|]|ar(?:[\s\x0b&\),<>\|]|diff|grep))|er(?:(?:f|ms)[\s\x0b&\),<>\|]|l(?:5?[\s\x0b&\),<>\|]|sh))|s(?:(?:ed|ql)[\s\x0b&\),<>\|]|ftp)|y(?:3?versions|thon[23]))|r(?:(?:a(?:r|k[eu])|cp?|bash|nano|oute|vi(?:ew|m))[\s\x0b&\),<>\|]|e(?:(?:d(?:carpet)?|v|boot|name|p(?:eat|lace))[\s\x0b&\),<>\|]|a(?:delf|lpath)|stic)|m(?:(?:dir)?[\s\x0b&\),<>\|]|t(?:[\s\x0b&\),<>\|]|-(?:dump|tar))|user)|pm(?:(?:db)?[\s\x0b&\),<>\|]|(?:quer|verif)y)|l(?:ogin|wrap)|sync(?:-ssl|[\s\x0b&\),<>\|])|u(?:by[^\s\x0b]{1,10}\b|n(?:-(?:mailcap|parts)|c[\s\x0b&\),<>\|])|st(?:-(?:analyzer|(?:g|ll)db)|c[\s\x0b&\),<>\|]|doc|fmt|up)))|s(?:(?:c(?:p|hed|r(?:een|ipt))|g|ash|diff|ftp|l(?:eep|sh)|plit)[\s\x0b&\),<>\|]|e(?:(?:d|ndmail|rvice)[\s\x0b&\),<>\|]|t(?:(?:facl)?[\s\x0b&\),<>\|]|arch|cap|env|sid))|h(?:(?:red|u(?:f|tdown))?[\s\x0b&\),<>\|]|\.distrib)|s(?:[\s\x0b&\),<>\|]|h(?:[\s\x0b&\),<>\|]|-(?:a(?:dd|gent)|copy-id|key(?:ge|sca)n)|pass))|u(?:[\s\x0b&\),<>\|]|do(?:-rs|[\s\x0b&\),<>_\|]|edit|replay))|vn(?:[\s\x0b&\),<>\|]|a(?:dmin|uthz)|bench|dumpfilter|fsfs|look|mucc|rdump|s(?:erve|ync)|version)|mbclient|o(?:(?:(?:ca|r)t|urce)[\s\x0b&\),<>\|]|elim)|qlite3|t(?:art-stop-daemon|dbuf|r(?:ace|ings[\s\x0b&\),<>\|]))|ys(?:ctl|tem(?:ctl|d-resolve)))|t(?:a(?:(?:[cr]|ilf?)[\s\x0b&\),<>\|]|sk(?:[\s\x0b&\),<>\|]|set))|(?:bl|o(?:p|uch)|ftp|mux)[\s\x0b&\),<>\|]|e(?:[ex][\s\x0b&\),<>\|]|lnet)|i(?:c[\s\x0b&\),<>\|]|me(?:datectl|out[\s\x0b&\),<>\|]))|c(?:l?sh[\s\x0b&\),<>\|]|p(?:dump|ing|traceroute))|r(?:a(?:ceroute6?|p[\s\x0b&\),<>\|])|off[\s\x0b&\),<>\|])|shark)|u(?:l(?:imit)?[\s\x0b&\),<>\|]|n(?:(?:ame|compress|iq|rar|s(?:et|hare)|xz)[\s\x0b&\),<>\|]|expand|l(?:ink[\s\x0b&\),<>\|]|z(?:4[\s\x0b&\),<>\|]|ma))|pigz|z(?:ip[\s\x0b&\),<>\|]|std))|conv|pdate-alternatives|ser(?:(?:ad|mo)d|del)|u(?:de|en)code)|v(?:i(?:m(?:[\s\x0b&\),<>\|]|diff)|(?:[ep]w|gr|rsh)[\s\x0b&\),<>\|]|sudo(?:-rs)?)|algrind|olatility[\s\x0b&\),<>\|])|w(?:(?:c|a(?:ll|tch))[\s\x0b&\),<>\|]|h(?:iptail[\s\x0b&\),<>\|]|o(?:ami|is[\s\x0b&\),<>\|]))|i(?:reshark|sh[\s\x0b&\),<>\|]))|x(?:(?:(?:x|pa)d|args|term)[\s\x0b&\),<>\|]|z(?:(?:c(?:at|mp))?[\s\x0b&\),<>\|]|d(?:ec[\s\x0b&\),<>\|]|iff)|[ef]?grep|less|more)|e(?:latex|tex[\s\x0b&\),<>\|])|mo(?:dmap|re[\s\x0b&\),<>\|]))|z(?:ip(?:[\s\x0b&\),<>\|]|c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|s(?:h[\s\x0b&\),<>\|]|oelim|td(?:[\s\x0b&\),<>\|]|(?:ca|m)t|grep|less))|athura|(?:c(?:at|mp)|diff|grep|less|run)[\s\x0b&\),<>\|]|[ef]grep|mo(?:dload|re[\s\x0b&\),<>\|])|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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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:1,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# [ Shell fork bomb detection ] +# +# This rule detects shell fork bomb patterns, where a function is defined +# whose body recursively calls itself via pipe and / or background process, +# causing exponential process creation that exhausts system resources. +# +# Examples: +# :(){ :|:& };: +# f(){ f|f& };f +# test() { test | test & }; test +# +# The detection targets the structural pattern: +# () { <| or &> }; +# where can be any identifier including bash builtins like : or . +# +# Regular expression generated from regex-assembly/932390.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 932390 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|!REQUEST_HEADERS:Cookie|ARGS_NAMES|ARGS|XML:/* "@rx [\.0-:A-Z_a-z]+[\s\x0b]*\([\s\x0b]*\)[\s\x0b]*\{[^\}]+[&\|][^\}]+\}" \ + "id:932390,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'Remote Command Execution: Shell Fork Bomb',\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:932016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?2[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n|s)|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?f|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o|[\s\x0b&\),<>\|].*))\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:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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|y(?:e(?:s|lp)|um|arn)|HEAD)[\s\x0b&\),<>\|]|a(?:a-[^\s\x0b]{1,10}\b|(?:b|t(?:obm)?|w[ks]|l(?:ias|pine)|xel)[\s\x0b&\),<>\|]|p(?:t(?:(?:itude)?[\s\x0b&\),<>\|]|-get)|parmor_[^\s\x0b]{1,10}\b)|r(?:(?:p|ch)?[\s\x0b&\),<>\|]|j(?:[\s\x0b&\),<>\|]|-register|disp)|ia2c)|s(?:h?[\s\x0b&\),<>\|]|cii(?:-xfr|85)|pell)|dd(?:group|user)|getty|nsible|u(?:ditctl|repot|search))|b(?:z(?:(?:z|c(?:at|mp))[\s\x0b&\),<>\|]|diff|e(?:grep|xe[\s\x0b&\),<>\|])|f?grep|ip2(?:[\s\x0b&\),<>\|]|recover)|less|more)|a(?:s(?:e(?:32|64|n(?:ame[\s\x0b&\),<>\|]|c))|h[\s\x0b&\),<>\|])|tch[\s\x0b&\),<>\|])|lkid[\s\x0b&\),<>\|]|pftrace|r(?:eaksw|(?:idge|wap)[\s\x0b&\),<>\|])|sd(?:cat|iff|tar)|u(?:iltin|n(?:dler[\s\x0b&\),<>\|]|zip2)|s(?:ctl|ybox))|y(?:ebug|obu[\s\x0b&\),<>\|]))|c(?:[89]9(?:[\s\x0b&\),<>\|]|-gcc)|a(?:(?:t|ncel|psh)[\s\x0b&\),<>\|]|rgo(?:[\s\x0b&\),<>\|]|-(?:audit|miri|watch)))|(?:c|mp)[\s\x0b&\),<>\|]|p(?:(?:an|io)?[\s\x0b&\),<>\|]|ulimit)|s(?:(?:h|cli)[\s\x0b&\),<>\|]|plit|vtool)|u(?:t[\s\x0b&\),<>\|]|psfilter)|ertbot|h(?:(?:(?:att|di)r|mod|o(?:om|wn)|root|sh)[\s\x0b&\),<>\|]|e(?:ck_(?:by_ssh|cups|log|memory|raid|s(?:sl_cert|tatusfile))|f[\s\x0b&\),\-<>\|])|(?:flag|pas)s|g(?:passwd|rp[\s\x0b&\),<>\|]))|l(?:ang(?:\+\+|[\s\x0b&\),<>\|])|ippy-driver)|o(?:bc(?:[\s\x0b&\),<>\|]|run)|(?:lumn|m(?:m(?:and)?|p(?:oser|ress)))[\s\x0b&\),<>\|]|proc|w(?:say|think))|r(?:ash[\s\x0b&\),<>\|]|on(?:[\s\x0b&\),<>\|]|tab)))|d(?:(?:[dfu]|i(?:(?:alo)?g|r|ff)|a(?:sh|te)|vips)[\s\x0b&\),<>\|]|nf[\s\x0b&\),<>\|]?|hclient|m(?:esg[\s\x0b&\),<>\|]|idecode|setup)|o(?:(?:as|ne)[\s\x0b&\),<>\|]|cker[\s\x0b&\),\-<>\|]|sbox)|pkg[\s\x0b&\),\-<>\|])|e(?:(?:[bd]|qn|s(?:h|ac)?|cho|fax|grep|macs|val)[\s\x0b&\),<>\|]|n(?:v(?:[\s\x0b&\),<>\|]|-update)|d(?:if|sw)[\s\x0b&\),<>\|])|x(?:(?:ec|p(?:and|(?:ec|or)t|r))?[\s\x0b&\),<>\|]|iftool)|2fsck|asy_install)|f(?:(?:c|g(?:rep)?|mt|etch|lock|unction)[\s\x0b&\),<>\|]|i(?:(?:n(?:d|ger)|sh)?[\s\x0b&\),<>\|]|le(?:[\s\x0b&\),<>\|]|test))|tp(?:[\s\x0b&\),<>\|]|stats|who)|acter|d(?:(?:find|isk)[\s\x0b&\),<>\|]|u?mount)|o(?:ld[\s\x0b&\),<>\|]|reach)|ping[\s\x0b&\),6<>\|])|g(?:c(?:c[^\s\x0b]{1,10}\b|ore[\s\x0b&\),<>\|])|(?:db|i(?:t|mp|nsh)|o|pg|awk|z(?:cat|exe|ip))[\s\x0b&\),<>\|]|e(?:m[\s\x0b&\),<>\|]|ni(?:e[\s\x0b&\),<>\|]|soimage)|t(?:cap|facl[\s\x0b&\),<>\|]))|hc(?:-?[\s\x0b&\),<>\|]|i[\s\x0b&\),\-<>\|])|r(?:(?:c(?:at)?|ep)[\s\x0b&\),<>\|]|oupmod)|tester|unzip)|h(?:(?:d|up|ash|i(?:ghlight|story))[\s\x0b&\),<>\|]|e(?:ad[\s\x0b&\),<>\|]|xdump)|ost(?:id|name)|ping3|t(?:digest|op[\s\x0b&\),<>\|]|passwd))|i(?:(?:d|rb|conv|nstall)[\s\x0b&\),<>\|]|p(?:[\s\x0b&\),<>\|]|6?tables|config|p(?:eveprinter|find|tool))|f(?:config|top[\s\x0b&\),<>\|])|onice|spell)|j(?:(?:js|q|ava|exec)[\s\x0b&\),<>\|]|o(?:(?:bs|in)[\s\x0b&\),<>\|]|urnalctl)|runscript)|k(?:s(?:h[\s\x0b&\),<>\|]|shell)|ill(?:[\s\x0b&\),<>\|]|all)|nife[\s\x0b&\),<>\|])|l(?:(?:[lnp]|ynx)?[\s\x0b&\),<>\|]|a(?:(?:tex)?[\s\x0b&\),<>\|]|st(?:(?:comm)?[\s\x0b&\),<>\|]|log(?:in)?))|d(?:d?[\s\x0b&\),<>\|]|config)|s(?:(?:-F|cpu|hw|mod|of|pci|usb)?[\s\x0b&\),<>\|]|b_release)|ua(?:[\s\x0b&\),<>\|]|(?:la)?tex)|z(?:4(?:[\s\x0b&\),<>\|]|c(?:[\s\x0b&\),<>\|]|at))|(?:c(?:at|mp))?[\s\x0b&\),<>\|]|diff|[ef]?grep|less|m(?:a(?:[\s\x0b&\),<>\|]|dec|info)|ore))|ess(?:[\s\x0b&\),<>\|]|echo|(?:fil|pip)e)|ftp(?:[\s\x0b&\),<>\|]|get)|o(?:(?:ca(?:l|te)|ok)[\s\x0b&\),<>\|]|g(?:inctl|(?:nam|sav)e)|setup)|trace|wp-(?:d(?:ownload|ump)|mirror|request))|m(?:(?:a(?:n|il[qx]?|ke|wk)|tr|v|utt)[\s\x0b&\),<>\|]|k(?:(?:dir|nod)[\s\x0b&\),<>\|]|fifo|temp)|locate|o(?:(?:re|unt)[\s\x0b&\),<>\|]|squitto)|sg(?:attrib|c(?:at|onv)|filter|merge|uniq)|ysql(?:[\s\x0b&\),<>\|]|admin|dump(?:slow)?|hotcopy|show))|n(?:c(?:(?:at)?[\s\x0b&\),<>\|]|\.(?:openbsd|traditional))|e(?:t(?:[\s\x0b&\),<>\|]|(?:c|st)at|kit-ftp|plan)|ofetch)|(?:l|m(?:ap)?|p(?:m|ing)|a(?:no|sm|wk)|ice|o(?:de|hup)|roff)[\s\x0b&\),<>\|]|s(?:enter|lookup|tat[\s\x0b&\),<>\|]))|o(?:(?:d|ctave)[\s\x0b&\),<>\|]|nintr|p(?:en(?:ssl|v(?:pn|t))|kg[\s\x0b&\),<>\|]))|p(?:a(?:(?:x|cman|rted|tch)[\s\x0b&\),<>\|]|s(?:swd|te[\s\x0b&\),<>\|]))|d(?:b(?:[\s\x0b&\),<>\|]|2mb|3[\s\x0b&\),\.<>\|])|f(?:la)?tex|ksh[\s\x0b&\),<>\|])|(?:f(?:tp)?|g(?:rep)?|(?:w|op)d|xz|u(?:ppet|shd))[\s\x0b&\),<>\|]|hp(?:[57]?[\s\x0b&\),<>\|]|-cgi)|i(?:c(?:[\s\x0b&\),<>\|]|o(?:nv|[\s\x0b&\),<>\|]))|p(?:[\s\x0b&\),<>\|]|[^\s\x0b]{1,10}\b)|dstat|(?:gz|ng6?)[\s\x0b&\),<>\|])|k(?:g(?:[\s\x0b&\),<>\|]|_?info)|exec|ill[\s\x0b&\),<>\|])|r(?:y?[\s\x0b&\),<>\|]|int(?:env|f[\s\x0b&\),<>\|]))|s(?:(?:ed|ql)?[\s\x0b&\),<>\|]|ftp)|t(?:x[\s\x0b&\),<>\|]|ar(?:[\s\x0b&\),<>\|]|diff|grep))|er(?:(?:f|ms)[\s\x0b&\),<>\|]|l(?:5?[\s\x0b&\),<>\|]|sh))|y(?:3?versions|thon[23]))|r(?:(?:a(?:r|k[eu])|cp?|bash|nano|oute|vi(?:ew|m))[\s\x0b&\),<>\|]|e(?:(?:d(?:carpet)?|v|boot|name|p(?:eat|lace))[\s\x0b&\),<>\|]|a(?:delf|lpath)|stic)|m(?:(?:dir)?[\s\x0b&\),<>\|]|t(?:[\s\x0b&\),<>\|]|-(?:dump|tar))|user)|pm(?:(?:db)?[\s\x0b&\),<>\|]|(?:quer|verif)y)|l(?:ogin|wrap)|sync(?:-ssl|[\s\x0b&\),<>\|])|u(?:by[^\s\x0b]{1,10}\b|n(?:-(?:mailcap|parts)|c[\s\x0b&\),<>\|])|st(?:-(?:analyzer|(?:g|ll)db)|c[\s\x0b&\),<>\|]|doc|fmt|up)))|s(?:(?:c(?:p|hed|r(?:een|ipt))|g|ash|diff|ftp|l(?:eep|sh)|plit)[\s\x0b&\),<>\|]|e(?:(?:d|ndmail|rvice)[\s\x0b&\),<>\|]|t(?:(?:facl)?[\s\x0b&\),<>\|]|arch|cap|env|sid))|h(?:(?:red|u(?:f|tdown))?[\s\x0b&\),<>\|]|\.distrib)|s(?:[\s\x0b&\),<>\|]|h(?:[\s\x0b&\),<>\|]|-(?:a(?:dd|gent)|copy-id|key(?:ge|sca)n)|pass))|u(?:[\s\x0b&\),<>\|]|do(?:-rs|[\s\x0b&\),<>_\|]|edit|replay))|vn(?:[\s\x0b&\),<>\|]|a(?:dmin|uthz)|bench|dumpfilter|fsfs|look|mucc|rdump|s(?:erve|ync)|version)|mbclient|o(?:(?:(?:ca|r)t|urce)[\s\x0b&\),<>\|]|elim)|qlite3|t(?:art-stop-daemon|dbuf|r(?:ace|ings[\s\x0b&\),<>\|]))|ys(?:ctl|tem(?:ctl|d-resolve)))|t(?:a(?:(?:[cr]|ilf?)[\s\x0b&\),<>\|]|sk(?:[\s\x0b&\),<>\|]|set))|(?:bl|o(?:p|uch)|ftp|mux)[\s\x0b&\),<>\|]|e(?:[ex][\s\x0b&\),<>\|]|lnet)|i(?:c[\s\x0b&\),<>\|]|me(?:(?:out)?[\s\x0b&\),<>\|]|datectl))|c(?:l?sh[\s\x0b&\),<>\|]|p(?:dump|ing|traceroute))|r(?:a(?:ceroute6?|p[\s\x0b&\),<>\|])|off[\s\x0b&\),<>\|])|shark)|u(?:l(?:imit)?[\s\x0b&\),<>\|]|n(?:(?:ame|compress|iq|rar|s(?:et|hare)|xz)[\s\x0b&\),<>\|]|expand|l(?:ink[\s\x0b&\),<>\|]|z(?:4[\s\x0b&\),<>\|]|ma))|pigz|z(?:ip[\s\x0b&\),<>\|]|std))|conv|p(?:2date[\s\x0b&\),<>\|]|date-alternatives)|ser(?:(?:ad|mo)d|del)|u(?:de|en)code)|v(?:i(?:(?:[ep]w|gr|rsh)?[\s\x0b&\),<>\|]|m(?:[\s\x0b&\),<>\|]|diff)|sudo(?:-rs)?)|algrind|olatility[\s\x0b&\),<>\|])|w(?:(?:c|a(?:ll|tch))?[\s\x0b&\),<>\|]|h(?:o(?:(?:is)?[\s\x0b&\),<>\|]|ami)?|iptail[\s\x0b&\),<>\|])|i(?:reshark|sh[\s\x0b&\),<>\|]))|x(?:(?:(?:x|pa)d|args|term)[\s\x0b&\),<>\|]|z(?:(?:c(?:at|mp))?[\s\x0b&\),<>\|]|d(?:ec[\s\x0b&\),<>\|]|iff)|[ef]?grep|less|more)|e(?:latex|tex[\s\x0b&\),<>\|])|mo(?:dmap|re[\s\x0b&\),<>\|]))|z(?:ip(?:[\s\x0b&\),<>\|]|c(?:loak|mp)|details|grep|info|(?:merg|not)e|split|tool)|s(?:h[\s\x0b&\),<>\|]|oelim|td(?:[\s\x0b&\),<>\|]|(?:ca|m)t|grep|less))|athura|(?:c(?:at|mp)|diff|grep|less|run)[\s\x0b&\),<>\|]|[ef]grep|mo(?:dload|re[\s\x0b&\),<>\|])|ypper))(?:\b|[^0-9A-Z_a-z])" \ + "id:932237,\ + phase:1,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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_NAMES|ARGS_NAMES|ARGS|XML:/*|REQUEST_HEADERS:Referer|REQUEST_HEADERS:User-Agent "@rx (?i)(?:^|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?2[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|p[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n|s)|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|d[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?f|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o|[\s\x0b&\),<>\|].*))" \ + "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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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 + +# Regular expression generated from regex-assembly/932190.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 932190 +# +SecRule ARGS "@rx (?i)/(?:[\*\?]+[/-9A-Z_a-z]|[/-9A-Z_a-z]+[\*\?])" \ + "id:932190,\ + phase:2,\ + block,\ + capture,\ + t:none,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:'paranoia-level/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + +# [ Unix command injection ] +# +# This rule is meant to block the execution of commands with no arguments when it's possible to meaningfully do so. +# +# 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) +# .932340 (PL-1, matches commands with no arguments) +# .932350 (PL-3, matches commands with no arguments) +# +# .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/932350.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 932350 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:^|b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?s[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?y[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?b[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?x|(?:c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?d|e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?v|v[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?l)|w[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h)[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?[\s\x0b&\),<>\|].*|[ls][\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?r[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?a[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?c[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e|n[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?h[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?p|t[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?i[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?m[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?e[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?(?:[\s\x0b&\),<>\|].*|o[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?u[\"'\)\[\x5c]*(?:(?:(?:\|\||&&)[\s\x0b]*)?\$[!#\(\*\-0-9\?@_a-\{]*)?\x5c?t)|[\n\r;=`\{]|\|\|?|&&?|\$(?:\(\(?|[\[\{])|<(?:\(|<<)|>\(|\([\s\x0b]*\))[\s\x0b]*(?:[\$\{]|(?:[\s\x0b]*\(|!)[\s\x0b]*|[0-9A-Z_a-z]+=(?:[^\s\x0b]*|\$(?:.*|.*)|[<>].*|'[^']*'|\"[^\"]*\")[\s\x0b]+)*[\s\x0b]*[\"']*(?:[\"'-\+\--9\?A-\]_a-z\|]+/)?[\"'\x5c]*(?:(?:aptitud|unam)e|d(?:f|ir|mesg)|env|h(?:istory|ostname|top)|i(?:d|ostat)|l(?:ast|s)|mysql(?:[^\s\x0b]{1,10}\b)?|p(?:s(?:ql)?|wd)|(?:reboo|vmsta)t|s(?:(?:cree|hutdow)n|et|u)|top|w(?:ho(?:ami|is)?)?)$" \ + "id:932350,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Remote Command Execution: Direct Unix Command Execution (No Arguments)',\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \r\n.*?\b(?:DATA|QUIT|HELP(?: .{1,255})?)" \ + "id:932301,\ + phase:2,\ + block,\ + capture,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/137/134',\ + ver:'OWASP_CRS/4.25.0',\ + 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_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,\ + capture,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/137/134',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \r\n.*?\b(?:(?:QUI|STA|RSE)T|NOOP|CAPA)" \ + "id:932321,\ + phase:2,\ + block,\ + capture,\ + 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:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/137/134',\ + ver:'OWASP_CRS/4.25.0',\ + 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 932250. +# +# 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx !(?:\d|!)" \ + "id:932331,\ + 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/3',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-RCE',\ + tag:'capec/1000/152/248/88',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:932018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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/appsec/crs/4.25.0/REQUEST-933-APPLICATION-ATTACK-PHP.conf b/appsec/crs/4.25.0/REQUEST-933-APPLICATION-ATTACK-PHP.conf new file mode 100644 index 000000000..716601c31 --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-933-APPLICATION-ATTACK-PHP.conf @@ -0,0 +1,959 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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:933011,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:933012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +# +# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher) +# + +# +# -=[ PHP Injection Attacks ]=- +# +# [ References ] +# https://rips-scanner.sourceforge.net/ +# https://wiki.owasp.org/index.php/PHP_Top_5#P1:_Remote_Code_Executionh +# + +# +# [ PHP Open Tag Found ] +# +# Detects PHP open tags "', but +# this resulted in false positives which were difficult to prevent. +# Therefore, that pattern is now checked by rule 933190 in paranoia levels +# 3 or higher. +# +# Regular expression generated from regex-assembly/933100.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 933100 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)<\?(?:php[\s\x0b]|[\s\x0b=]|xml(?:[\s\x0b]+[^a-z]|:)|$)|\[[/\x5c]?php\]|\{/?php\}" \ + "id:933100,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: PHP Open Tag 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# +# [ PHP Script Uploads ] +# +# Block file uploads with filenames ending in PHP related extensions +# (.php, .phps, .phtml, .php5 etc). +# +# 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 .php file. If the upload storage location is predictable +# and not adequately protected, the attacker may then request the uploaded +# .php file and have the code within it executed on the server. +# +# Also block files with just dot (.) characters after the extension: +# 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 .*\.ph(?:p\d*|tml|ar|ps|t|pt)\.*$" \ + "id:933110,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,t:removeWhitespace,\ + msg:'PHP Injection Attack: PHP Script File Upload 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Configuration Directives ] +# +# Regular expression generated from regex-assembly/933120.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 933120 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:a(?:llow_url_(?:fopen|include)|pc.(?:coredump_unmap|en(?:able(?:_cli|d)|tries_hint)|(?:gc_)?ttl|mmap_file_mask|preload_path|s(?:erializer|hm_s(?:egments|ize)|lam_defense)|use_request_time)|rg_separator.(?:in|out)put|ssert.(?:active|(?:bai|quiet_eva)l|callback|exception|warning)|uto_(?:(?:ap|pre)pend_file|detect_line_endings|globals_jit))|b(?:cmath.scale|rowscap)|c(?:gi.(?:check_shebang_line|(?:discard_pat|np)h|f(?:ix_pathinfo|orce_redirect)|r(?:edirect_status_env|fc2616_headers))|hild_terminate|li(?:_server.color|.p(?:ager|rompt))|om.(?:a(?:llow_dcom|utoregister_(?:(?:casesensitiv|verbos)e|typelib))|(?:code_pag|typelib_fil)e|dotnet_version)|url.cainfo)|d(?:ate.(?:(?:default_l(?:at|ong)itud|timezon)e|sun(?:rise|set)_zenith)|ba.default_handler|efault_(?:(?:charse|socket_timeou)t|mimetype)|is(?:able_(?:classe|function)|play_(?:startup_)?error)s|oc(?:_roo|ref_(?:ex|roo))t)|e(?:n(?:able_(?:dl|post_data_reading)|gine)|rror_(?:(?:(?:ap|pre)pend_str|report)in|lo)g|x(?:i(?:f.(?:decode_(?:jis|unicode)_(?:intel|motorola)|encode_(?:jis|unicode))|t_on_timeout)|tension(?:_dir)?|p(?:ect.(?:log(?:file|user)|match_max|timeout)|ose_php)))|f(?:astcgi.(?:impersonate|logging)|fi.(?:enable|preload)|il(?:e_uploads|ter.default(?:_flags)?))|g(?:d.jpeg_ignore_warning|eoip.custom_directory)|h(?:ard_timeout|ighlight.(?:(?:commen|defaul)t|html|keyword|string)|tml_errors)|i(?:b(?:ase.(?:(?:allow_persisten|time(?:stamp)?forma)t|d(?:ateformat|efault_(?:charset|db|password|user))|max_(?:links|persistent))|m_db2.(?:binmode|i(?:5_(?:all(?:_pconnec|ow_commi)t|dbcs_alloc|ignore_userid)|nstance_name)))|conv.(?:in(?:put|ternal)|output)_encoding|g(?:binary.compact_strings|nore_(?:repeated_(?:errors|source)|user_abort))|m(?:a(?:gick.(?:locale_fix|progress_monitor|skip_version_check)|p.enable_insecure_rsh)|plicit_flush)|n(?:clude_path|put_encoding|t(?:ernal_encoding|l.(?:default_locale|error_level|use_exceptions))))|l(?:dap.max_links|og_errors(?:_max_len)?)|m(?:a(?:gic_quotes_(?:gpc|runtime)|il(?:.(?:add_x_header|force_extra_parameters|log)|parse.def_charset)|x_(?:execution_time|file_uploads|input_(?:nesting_level|time|vars)))|bstring.(?:detect_order|encoding_translation|func_overload|http_(?:input|output(?:_conv_mimetypes)?)|internal_encoding|language|regex_(?:retry|stack)_limit|s(?:trict_detection|ubstitute_character))|crypt.(?:algorithm|mode)s_dir|em(?:cache(?:.(?:allow_failover|c(?:hunk_size|ompress_threshold)|(?:default_por|lock_timeou)t|hash_(?:function|strategy)|max_failover_attempts|protocol|(?:session_)?redundancy)|d.(?:compression_(?:factor|t(?:hreshold|ype))|default_(?:binary_protocol|con(?:nect_timeout|sistent_hash))|s(?:e(?:rializer|ss_(?:binary(?:_protocol)?|con(?:nect_timeout|sistent_hash(?:_type)?)|lock(?:_(?:expire|retries|wait(?:_m(?:ax|in))?)|ing)|number_of_replicas|p(?:ersistent|refix)|r(?:andomize_replica_read|emove_failed(?:_servers)?)|s(?:asl_(?:password|username)|erver_failure_limit)))|tore_retry_count)|use_sasl))|ory_limit)|ysql(?:.(?:allow_(?:local_infile|persistent)|connect_timeout|default_(?:(?:hos|socke)t|p(?:assword|ort)|user)|max_(?:links|persistent)|trace_mode)|i.(?:allow_(?:local_infile|persistent)|default_(?:(?:hos|socke)t|p(?:ort|w)|user)|local_infile_directory|max_(?:links|persistent)|r(?:econnect|ollback_on_cached_plink))|nd.(?:collect_(?:memory_)?statistics|debug|(?:fetch_data_cop|sha256_server_public_ke)y|log_mask|mempool_default_size|net_(?:cmd_buffer_size|read_(?:buffer_size|timeout))|trace_alloc)))|o(?:ci8.(?:(?:connection_clas|event|old_oci_close_semantic)s|default_prefetch|max_persistent|p(?:ersistent_timeout|ing_interval|r(?:efetch_lob_size|ivileged_connect))|statement_cache_size)|dbc.(?:(?:allow|check)_persistent|default(?:_(?:cursortype|db|pw|user)|binmode|lrl)|max_(?:links|persistent))|p(?:cache.(?:blacklist_filename|c(?:ache_id|onsistency_checks)|dups_fix|e(?:nable(?:_(?:cli|file_override))?|rror_log)|f(?:ast_shutdown|ile_(?:cache(?:_(?:consistency_checks|fallback|only))?|update_protection)|orce_restart_timeout)|(?:huge_code_page|save_comment)s|in(?:herited_hack|terned_strings_buffer)|jit(?:_(?:b(?:isect_limit|(?:lacklist_(?:root|side)_trac|uffer_siz)e)|debug|hot_(?:func|loop|return|side_exit)|max_(?:exit_counter|(?:loop_unro|polymorphic_ca)ll|r(?:ecursive_(?:call|return)|oot_trace)|side_trace)s|prof_threshold))?|lo(?:ckfile_path|g_verbosity_level)|m(?:ax_(?:accelerated_files|(?:file_siz|wasted_percentag)e)|emory_consumption|map_base)|opt(?:_debug|imization)_level|pr(?:e(?:ferred_memory_model|load(?:_user)?)|otect_memory)|re(?:cord_warnings|strict_api|validate_(?:freq|path))|use_cwd|validate_(?:permission|root|timestamps))|en(?:_basedir|ssl.ca(?:file|path)))|utput_(?:(?:buffer|encod)ing|handler))|p(?:cre.(?:(?:backtrack|recursion)_lim|j)it|do(?:_odbc.(?:connection_pooling|db2_instance_name)|.dsn)|gsql.(?:a(?:llow|uto_reset)_persistent|(?:ignore|log)_notice|max_(?:links|persistent))|h(?:ar.(?:cache_list|re(?:adonly|quire_hash))|pdbg.(?:eol|path))|recision|ost_max_size)|r(?:e(?:alpath_cache_(?:size|ttl)|gister_argc_argv|port_(?:memleaks|zend_debug)|quest_order)|unkit.(?:internal_override|superglobal))|s(?:e(?:aslog.(?:appender(?:_retry)?|buffer_(?:disabled_in_cli|size)|d(?:efault_(?:basepath|datetime_format|logger|template)|isting_(?:(?:by_hou|folde)r|type))|ignore_warning|level|re(?:call_depth|mote_(?:hos|por|timeou)t)|t(?:hrow_exception|r(?:ace_(?:e(?:rror|xception)|notice|warning)|im_wrap))|use_buffer)|ndmail_(?:from|path)|rialize_precision|ssion.(?:auto_start|c(?:ache_(?:expire|limiter)|ookie_(?:domain|httponly|(?:lifetim|s(?:amesit|ecur))e|path))|entropy_(?:file|length)|gc_(?:divisor|maxlifetime|probability)|hash_(?:bits_per_character|function)|(?:lazy_writ|nam)e|referer_check|s(?:ave_(?:handler|path)|erialize_handler|id_(?:bits_per_character|length))|trans_sid_(?:host|tag)s|u(?:pload_progress.(?:cleanup|enabled|(?:min_)?freq|name|prefix)|se_(?:(?:only_)?cookies|strict_mode|trans_sid))))|hort_open_tag|mtp(?:_port)?|oap.wsdl_cache(?:_(?:dir|enabled|limit|ttl))?|ql(?:.safe_mode|ite3.(?:defensive|extension_dir))|tomp.default_(?:broker|(?:connection|read)_timeout_u?sec)|woole.(?:aio_thread_num|display_errors|enable_(?:coroutine|library|preemptive_scheduler)|(?:fast_serializ|u(?:nixsock_buffer_siz|se_(?:namespac|shortnam)))e)|ys(?:_temp_dir|log.(?:f(?:acility|ilter)|ident)|vshm.init_mem))|t(?:aint.e(?:nable|rror_level)|idy.(?:clean_output|default_config)|ra(?:ck_errors|der.real_(?:precision|round_mode)))|u(?:nserialize_(?:callback_func|max_depth)|opz.(?:disable|exit|overloads)|pload(?:_(?:max_filesize|tmp_dir)|progress.file.filename_template)|rl_rewriter.(?:host|tag)s|ser_(?:agent|dir|ini.(?:cache_ttl|filename)))|v(?:8js.(?:flag|max_disposed_context)s|ariables_order|ld.(?:(?:activ|execut)e|skip_(?:ap|pre)pend))|w(?:in(?:cache.(?:chkinterval|enablecli|f(?:c(?:achesize|enabled(?:filter)?|ndetect)|ile(?:count|mapdir))|(?:ignorelis|namesal)t|maxfilesize|oc(?:achesize|enabled(?:filter)?)|reroute(?:_enabled|ini)|s(?:cachesize|rwlocks)|ttlmax|uc(?:achesize|enabled))|dows.show_crt_warning)|khtmltox.graphics)|x(?:bithack|hprof.output_dir|mlrpc_error(?:_number|s))|ya(?:c(?:.(?:compress_threshold|debug|enable(?:_cli)?|(?:key|value)s_memory_size|serializer)|onf.(?:check_dela|director)y)|f.(?:action_prefer|cache_config|environ|forward_limit|l(?:ibrary|owcase_path)|name_s(?:eparator|uffix)|use_(?:namespace|spl_autoload))|ml.(?:decode_(?:binary|(?:ph|timestam)p)|output_(?:canonical|indent|width))|r.(?:(?:connect_)?timeout|debug|expose_info|packager)|z.(?:keepalive|log_mask))|z(?:end(?:_extension|.(?:assertions|(?:detect_unicod|multibyt)e|e(?:nable_gc|xception_(?:ignore_args|string_param_max_len))|s(?:cript_encoding|ignal_check)))|lib.output_(?:compression(?:_level)?|handler)|ookeeper.(?:recv_timeout|sess(?:_lock_wait|ion_lock))))[\s\x0b]*=[^=]" \ + "id:933120,\ + phase:2,\ + block,\ + capture,\ + t:none,t:normalizePath,\ + msg:'PHP Injection Attack: Configuration Directive 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Variables ] +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-variables.data" \ + "id:933130,\ + phase:2,\ + block,\ + capture,\ + t:none,t:normalizePath,t:urlDecodeUni,\ + msg:'PHP Injection Attack: Variables 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Variables ] +# +# Prevent accessing PHP variables using these methods: +# ${'VARIABLE_NAME'} +# $ {"VARIABLE_NAME"} +# $ {'_VAR'.'IABLE_NAME'} +# $ { $var} +# $ { CONSTANT } +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx \$\s*\{\s*\S[^\{\}]*\}" \ + "id:933135,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: Variable Access 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP I/O Streams ] +# +# The "php://" syntax can be used to refer to various objects, such as local files (for LFI), +# remote urls (for RFI), or standard input/request body. Its occurrence indicates a possible attempt +# to either inject PHP code or exploit a file inclusion vulnerability in a PHP web app. +# +# Examples: +# php://filter/resource=./../../../wp-config.php +# php://filter/resource=http://www.example.com +# php://stdin +# php://input +# +# http://php.net/manual/en/wrappers.php.php +# +# Regular expression generated from regex-assembly/933140.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 933140 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)php://(?:std(?:in|out|err)|(?:in|out)put|f(?:d|ilter)|memory|temp)" \ + "id:933140,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: I/O Stream 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Wrappers ] +# +# PHP comes with many built-in wrappers for various URL-style protocols for use with the filesystem +# functions such as fopen(), copy(), file_exists() and filesize(). Abusing of PHP wrappers like phar:// +# 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. +# +# 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_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,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,t:cmdLine,\ + msg:'PHP Injection Attack: Wrapper scheme detected',\ + logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ + tag:'application-multi',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-injection-php',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Functions ] +# +# Detecting PHP function names is useful to block PHP code injection attacks. +# There are many PHP functions. We have to strike a balance between robust detection +# of PHP code in content, and the risk of false positives. +# +# The list of PHP functions is divided into four groups of varying attack/false positive risk. +# Four separate rules are used to detect these groups of functions: +# +# - Rule 933150: ~234 words highly common to PHP injection payloads and extremely rare in +# natural language or other contexts. +# Examples: 'base64_decode', 'file_get_contents'. +# These words are detected as a match directly using @pmFromFile. +# Function names are defined in php-function-names-933150.data +# +# - Rule 933160: ~39 words which are common in PHP code, but have a higher chance to cause +# 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 /regexp-assemble/data/933160.ra +# +# - Rule 933151: ~2200 words of lesser importance. This includes most PHP functions and keywords. +# Examples: 'addslashes', 'array_diff'. +# For performance reasons, the @pmFromFile operator is used, and many functions from lesser +# used PHP extensions are removed. +# To mitigate false positives, we only match when the '(' character is also found. +# This rule only runs in paranoia level 2 or higher. +# Function names are defined in php-function-names-933151.data +# +# - Rule 933161: ~95 words with short or trivial names, possibly leading to false positives. +# 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 /regexp-assemble/data/933161.ra +# + + +# +# [ PHP Functions: High-Risk PHP Function Names ] +# +# Rule 933150 contains a small list of function names which are highly indicative of a PHP +# injection attack, for example 'base64_decode'. +# The rule uses a chained rule to require parentheses after function names. +# This prevents false positives from substring matches (e.g., "intval" in "PaintValdosta"). +# Functions that commonly appear as English words/substrings are handled by rule 933160 +# with stricter regex-based function call syntax validation. +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-function-names-933150.data" \ + "id:933150,\ + phase:2,\ + block,\ + capture,\ + 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',\ + tag:'language-php',\ + tag:'platform-multi',\ + tag:'attack-injection-php',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + chain" + SecRule MATCHED_VARS "@pm ( )" \ + "t:none,\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Functions: High-Risk PHP Function Calls ] +# +# Some PHP function names have a certain risk of false positives, due to short +# names, full or partial overlap with common natural language terms, uses in +# other contexts, et cetera. Some examples are 'eval', 'exec', 'system'. +# +# For these function names, we apply a regexp to look for PHP function syntax. +# The regexp looks for a word boundary and adjoining parentheses. +# For instance, we want to block 'eval()', but we want to allow 'medieval()'. +# +# We have to be careful of possible bypasses using comment syntax. Examples: +# +# system(...) +# system (...) +# system\t(...) +# system /*comment*/ (...) +# system /*multiline \n comment*/ (...) +# system //comment \n (...) +# system #comment \n (...) +# +# This rule is triggered by the following exploits as well, as they include the string 'exec(...)': +# [ Apache Struts vulnerability CVE-2017-9791 - Exploit tested: https://www.exploit-db.com/exploits/42324 ] +# [ 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 ] +# +# 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 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b\(?[\"']*(?:assert(?:_options)?|c(?:hr|reate_function)|e(?:val|x(?:ec|p))|f(?:ile(?:group)?|open|puts)|glob|i(?:mage(?:gif|(?:jpe|pn)g|wbmp|xbm)|s_a|ntval)|m(?:d5|kdir)|o(?:pendir|rd)|p(?:assthru|hpinfo|open|r(?:intf|ev))|r(?:eadfile|trim)|s(?:t(?:rip_tags|at)|ubstr|ystem)|tmpfile|u(?:n(?:(?:pac|lin)k|serialize)|sort))(?:/(?:\*.*?\*/|/[^\n\r]*)|#[^\n\r]*|[\s\x0b\"])*[\"']*\)?[\s\x0b]*\([^\)]*\)" \ + "id:933160,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: High-Risk PHP 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Object Injection ] +# +# PHP Object Injection is an application level vulnerability that could allow +# an attacker to perform different kinds of malicious attacks, such as +# Code Injection, SQL Injection, Path Traversal and Application Denial of Service, +# depending on the context. +# +# The vulnerability occurs when user-supplied input is not properly sanitized +# before being passed to the unserialize() PHP function. Since PHP allows object +# serialization, attackers could pass ad-hoc serialized strings to a vulnerable +# unserialize() call, resulting in an arbitrary PHP object(s) injection into the +# application scope. +# +# https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection +# +# In serialized form, PHP objects have the following format: +# +# O:8:"stdClass":1:{s:1:"a";i:2;} +# O:3:"Foo":0:{} +# +# Also detected are PHP objects with a custom unserializer: +# 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:{}} +# C:3:"Foo":23:{s:15:"My private data";} +# +# HTTP headers are inspected, since PHP object injection vulnerabilities have been +# found in applications parsing them: +# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-8562 (User-Agent header) +# https://www.exploit-db.com/exploits/39033/ (X-Forwarded-For header) +# http://karmainsecurity.com/KIS-2015-10 (Host header) +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|ARGS_NAMES|ARGS|XML:/* "@rx [oOcC]:\d+:\".+?\":\d+:\{.*}" \ + "id:933170,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: Serialized Object Injection',\ + 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + + +# +# [ PHP Functions: Variable Function Calls ] +# +# PHP 'variable functions' provide an alternate syntax for calling PHP functions. +# http://php.net/manual/en/functions.variable-functions.php +# +# An attacker may use variable function syntax to evade detection of function +# names during exploitation of a remote code execution vulnerability. +# An example to use the 'file_get_contents' function while evading rule 933150: +# +# $fn = 'file_' . 'get_' . 'contents'; +# echo $fn('wp-co' . 'nfig.php'); +# +# Some examples from obfuscated malware: +# +# $OOO0000O0(...) +# @$b374k(...) +# $_[@-_]($_[@!+_] ) +# +# A breakdown of the regular expression: +# +# \$+ +# The variable's '$' char, or multiple '$' for 'variable variables': +# http://php.net/manual/en/language.variables.variable.php +# (?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*|\s*{.+}) +# One of the following: +# - A variable name; regexp from http://php.net/language.variables.basics +# - A nonempty expression for variable variables: ${'fn'} or $ {'fn'} +# (?:\s|\[.+\]|{.+}|/\*.*\*/|//.*|#.*)* +# Optional whitespace, array access, or comments +# \(.*\) +# Parentheses optionally containing function parameters +# +# Regular expression generated from regex-assembly/933180.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 933180 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx \$+(?:[A-Z_a-z\x7f-\x{ff}][0-9A-Z_a-z\x7f-\x{ff}]*|[\s\x0b]*\{.+\})(?:[\s\x0b]|\[.+\]|\{.+\}|/(?:\*.*\*/|/.*)|#.*)*\(.*\)" \ + "id:933180,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{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'); +# - define('z', [['sys' .'tem']]);(z)[0][0]('uname'); +# - (system)(ls); +# - (/**/system)(ls/**/); +# - (['system'])[0]('uname'); +# - (++[++system++][++0++])++{/*dsasd*/0}++(++ls++); +# +# This rule blocks all payloads above and avoids to block values like: +# +# - [ACME] this is a test (just a test) +# - Test (with two) rounded (brackets) +# +# 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_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:\((?:.+\)(?:[\"'][\-0-9A-Z_a-z]+[\"'])?\(.+|[^\)]*string[^\)]*\)[\s\x0b\"'\-\.0-9A-\[\]_a-\{\}]+\([^\)]*)|(?:\[[0-9]+\]|\{[0-9]+\}|\$[^\(\),\./;\x5c]+|[\"'][\-0-9A-Z\x5c_a-z]+[\"'])\(.+)\);" \ + "id:933210,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Session File Upload Protection ] +# +# Detects attempts to upload files matching PHP session naming patterns. +# PHP session files typically follow the pattern: sess_ +# where session_id is typically 20-256 characters (varies by PHP version). +# Example sizes: +# 32 chars — MD5 hash (legacy default) +# 40 chars — SHA-1 hash +# 26 chars — MD5 with 5 bits/character encoding +# +# Modern PHP (7.1+) +# PHP 7.1+ uses session.sid_length (default 32, range 22–256) and session.sid_bits_per_character: +# +# | Bits/char | Character set | Regex | +# | 4 | 0-9a-f | [0-9a-f]{22,256} | +# | 5 | 0-9a-v | [0-9a-v]{22,256} | +# | 6 | 0-9a-zA-Z,- | [0-9a-zA-Z,-]{22,256} | +# +# Attackers can upload malicious serialized PHP objects with session filenames, +# then trigger deserialization by presenting a matching PHPSESSID cookie, leading +# to Remote Code Execution through PHP object injection. +# +# References: +# - CVE-2025-54236 (Magento - Session Reaper) +# - https://slcyber.io/assetnote-security-research-center/why-nested-deserialization-is-still-harmful-magento-rce-cve-2025-54236/ +# +# This rule blocks: +# - sess_abcdef1234567890opqrstxyz (standard session file) +# - /tmp/sess_d8ew88tqmabdcokhumchy8htqm (with path) +# - C:\temp\sess_maliciousfilename1234567890 (Windows path) +# +# 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. +# +# Regular expression generated from regex-assembly/933220.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 933220 +# +SecRule FILES|FILES_NAMES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X.Filename|REQUEST_HEADERS:X-File-Name "@rx (?:^|[/\x5c])sess_[,\-0-9a-z]{20,256}$" \ + "id:933220,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'PHP Injection Attack: PHP Session File Upload Attempt',\ + 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/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:933013,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:933014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + +# +# [ PHP Functions: Medium-Risk PHP Function Names ] +# +# In paranoia level 2, we add additional checks for most PHP functions. +# +# The size of the PHP function list is considerable. +# Even after excluding the more obscure PHP extensions, 1300+ functions remain. +# For performance reasons, this rule now uses a singular regex, without any capturing. +# Due to regex size limitations in Modsecurity 2 with httpd, this is currently split +# out into 3 seperate regex assembly includes: php-function-names-933151, +# php-function-names-933152, and php-function-names-933153, which correspond +# to 933151, 933152, and 933153 respectively. +# +# This approach carries some risk for false positives. Therefore, the function list +# has been curated to remove words closely matching natural language and terms often +# used in other contexts. +# +# This rule is a stricter sibling of rule 933150. +# +# Regular expression generated from regex-assembly/933151.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 933151 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:a(?:c(?:cel_chdir|osh?)|ddc?slashes|pache_(?:child_terminate|get(?:_(?:modules|version)|env)|lookup_uri|note |re(?:quest|sponse)_headers|setenv)|r(?:ray_(?:c(?:h(?:ange_key_case|unk)|o(?:lumn|mbine|unt_values))|diff(?:_(?:assoc|key|u(?:assoc|key)))?|f(?:ill(?:_keys)?|lip)|i(?:ntersect(?:_(?:assoc|key|u(?:assoc|key)))?|s_list)|key(?:_(?:fir|la)st|s)|m(?:ap|erge(?:_recursive)?|ultisort)|p(?:ad|op|roduct)|r(?:and|e(?:(?:duc|vers)e|place(?:_recursive)?))|s(?:earch|p?lice|um)|u(?:(?:diff|intersect)(?:_u?assoc)?|n(?:ique|shift))|walk(?:_recursive)?)|sort)|s(?:inh|ort|sert_options)|tan[2h]?)|b(?:ase(?:64_(?:de|en)code|_convert)|c(?:add|comp|div|m(?:od|ul)|pow(?:mod)?|s(?:cale|qrt|ub))|in(?:2hex|d(?:_textdomain_codeset|ec|textdomain))|oolval|z(?:(?:de)?compress|err(?:no|(?:o|st)r)|open|read))|c(?:al(?:_(?:days_in_month|(?:from|to)_jd|info)|l_user_func_array)|eil|h(?:(?:di)?r|grp|mod|own|unk_split)|l(?:ass_(?:alia|(?:implem|par)ent|use)s|earstatcache|ose(?:dir|log))|o(?:llator_(?:asort|c(?:ompar|reat)e|get_(?:(?:attribut|error_(?:cod|messag)|local)e|s(?:ort_key|trength))|s(?:et_(?:attribute|strength)|ort(?:_with_sort_keys)?))|m_(?:create_guid|event_sink|get_active_object|load_typelib|message_pump|print_typeinfo)|n(?:fig_get_hash|nection_(?:aborted|status)|vert_uu(?:de|en)code)|unt_chars)|rc32|type_(?:al(?:num|pha)|cntrl|(?:x?digi|p(?:rin|unc))t|graph|(?:low|upp)er|space)|url_(?:(?:c(?:los|opy_handl)|file_creat|paus)e|e(?:rr(?:no|or)|scape|xec)|getinfo|(?:ini|rese)t|multi_(?:(?:(?:add|remove)_handl|clos)e|e(?:rrno|xec)|getcontent|in(?:fo_read|it)|s(?:e(?:lec|top)t|trerror))|s(?:etopt(?:_array)?|hare_(?:close|errno|init|s(?:etopt|trerror))|trerror)|u(?:nescape|pkeep)|version))|d(?:ate(?:_(?:add|create(?:_(?:from_format|immutable(?:_from_format)?))?|d(?:(?:ate_s|efault_timezone_[gs])et|iff)|(?:forma|(?:offset_g|time(?:_s|(?:stamp|zone)_[gs]))e)t|get_last_errors|i(?:nterval_(?:create_from_date_string|format)|sodate_set)|modify|parse(?:_from_format)?|su(?:b|n(?:_info|rise|set)))|fmt_(?:(?:creat|localtim|pars)e|format(?:_object)?|get_(?:calendar(?:_object)?|(?:datetyp|error_(?:cod|messag)|local)e|pattern|time(?:type|zone(?:_id)?))|is_lenient|set_(?:calendar|lenient|pattern|timezone)))|ba_(?:(?:clos|delet|replac)e|(?:exist|handler)s|f(?:etch|irstkey)|(?:inser|key_spli|lis)t|nextkey|op(?:en|timize)|popen|sync)|(?:cn?)?gettext|e(?:bug_(?:(?:print_)?backtrace|zval_dump)|c(?:bin|hex)|flate_(?:add|init)|g2rad)|isk_(?:free|total)_space|l_test_test[12]|n(?:gettext|s_(?:check_record|get_(?:mx|record)))|om_import_simplexml)|e(?:aster_da(?:te|ys)|n(?:chant_(?:broker_(?:d(?:escribe|ict_exists)|free(?:_dict)?|get_(?:dict_path|error)|(?:ini|request_(?:pwl_)?dic)t|list_dicts|set_(?:dict_path|ordering))|dict_(?:add(?:_to_session)?|(?:quick_)?check|describe|get_error|is_added|s(?:tore_replacemen|ugges)t))|um_exists)|rror_(?:(?:clear|get)_last|(?:lo|reportin)g)|scapeshell(?:arg|cmd)|x(?:if_(?:imagetype|read_data|t(?:agname|humbnail))|pm1|tension_loaded))|f(?:astcgi_finish_request|d(?:atasync|iv)|eof|f(?:i_trampoline|lush)|get(?:c(?:sv)?|s)|i(?:l(?:e_put_contents|ter_(?:has_var|i(?:d|nput(?:_array)?)|list|var(?:_array)?))|nfo_(?:buffer|(?:clos|fil)e|open|set_flags))|loatval|(?:mo|re(?:a|nchtoj))d|nmatch|orward_static_call(?:_array)?|p(?:assthru|m_get_status|rintf|utcsv)|s(?:canf|eek|ockopen|tat|ync)|t(?:ell|ok|p_(?:a(?:lloc|ppend)|c(?:dup|h(?:dir|mod)|lose|onnect)|delete|exec|f(?:ge|pu)t|get(?:_option)?|login|m(?:dtm|kdir|lsd)|n(?:b_(?:continue|(?:f(?:ge|pu)|ge|pu)t)|list)|p(?:asv|ut|wd)|r(?:aw(?:list)?|ename|mdir)|s(?:et_option|(?:i[tz]|ystyp)e|sl_connect))|runcate)|unc_(?:get_args?|num_args)|write)|g(?:c_(?:(?:(?:collect_cycl|mem_cach)e|statu)s|disable|enabled?)|d_info|et(?:_(?:browser|c(?:(?:alled_clas|lass_(?:method|var))s|(?:fg_va|urrent_use)r)|de(?:bug_type|(?:clared_(?:(?:class|interfac)e|trait)|fined_(?:constant|function|var))s)|(?:extension_func|loaded_extension|m(?:angled_object_var|eta_tag)|parent_clas)s|h(?:eaders|tml_translation_table)|include(?:_path|d_files)|o(?:bject_vars|pen_basedir)|resource(?:_(?:id|type)|s))|(?:cw|lastmo)d|(?:dat|rusag)e|env|host(?:by(?:addr|namel?)|name)|imagesize(?:fromstring)?|my(?:[gpu]id|inode)|opt|protobyn(?:ame|umber)|servby(?:name|port)|t(?:ext|imeofday|ype))|m(?:(?:dat|(?:mk|strf)tim)e|p_(?:a(?:bs|[dn]d)|binomial|c(?:lrbit|mp|om)|div(?:_(?:qr?|r)|exact)|(?:expor|fac|hamdis|testbi)t|gcd(?:ext)?|i(?:mport|n(?:(?:i|ver)t|tval))|jacobi|(?:kronecke|x?o)r|l(?:cm|egendre)|m(?:od|ul)|ne(?:g|xtprime)|p(?:erfect_(?:power|square)|o(?:pcount|wm?)|rob_prime)|r(?:andom_(?:bits|range|seed)|oot(?:rem)?)|s(?:can[01]|etbit|ign|qrt(?:rem)?|trval|ub)))|r(?:apheme_(?:extract|s(?:tr(?:i(?:pos|str)|len|(?:ri?)?pos|str)|ubstr))|egoriantojd)|z(?:(?:un)?compress|(?:de(?:cod|flat)|encod|fil|inflat)e|open))|h(?:ash_(?:(?:algo|equal)s|copy|fi(?:le|nal)|h(?:kdf|mac(?:_(?:algos|file))?)|init|pbkdf2|update(?:_(?:file|stream))?)|e(?:ader(?:_re(?:gister_callback|move)|s_(?:lis|sen)t)|brev|x(?:2bin|dec))|ighlight_(?:file|string)|rtime|t(?:ml(?:(?:_entity|specialchars)_decode|entities)|tp_(?:build_query|response_code))|ypot)|i(?:conv(?:_(?:get_encoding|mime_(?:decode(?:_headers)?|encode)|s(?:et_encoding|tr(?:len|r?pos)|ubstr)))?|dn_to_(?:ascii|utf8)|gnore_user_abort|ma(?:ge(?:_type_to_(?:extension|mime_type)|a(?:ffine(?:matrix(?:conca|ge)t)?|lphablending|ntialias|rc|vif)|(?:bm|w(?:bm|eb))p|c(?:har(?:up)?|o(?:lor(?:a(?:llocate(?:alpha)?|t)|closest(?:alpha|hwb)?|deallocate|(?:exact|resolve)(?:alpha)?|match|s(?:et|forindex|total)|transparent)|nvolution|py(?:merge(?:gray)?|res(?:ampl|iz)ed)?)|r(?:eate(?:from(?:avif|(?:bm|w(?:bm|eb))p|g(?:d(?:2(?:part)?)?|if)|(?:jpe|(?:p|stri)n)g|tga|x[bp]m)|truecolor)?|op(?:auto)?))|d(?:ashedline|estroy)|ellipse|f(?:il(?:l(?:ed(?:arc|(?:ellips|rectangl)e|polygon)|toborder)?|ter)|lip|ont(?:height|width)|t(?:bbox|text))|g(?:ammacorrect|d2?|et(?:clip|interpolation)|if|rab(?:screen|window))|i(?:nterlace|struecolor)|jpeg|l(?:(?:ayereffec|oadfon)t|ine)|openpolygon|p(?:alette(?:copy|totruecolor)|ng|olygon)|r(?:e(?:ctangle|solution)|otate)|s(?:avealpha|cale|et(?:brush|clip|interpolation|pixel|style|t(?:hickness|ile))|tring(?:up)?|[xy])|t(?:ruecolortopalette|ypes)|xbm)|p_(?:(?:8bi|qprin)t|a(?:lerts|ppend)|b(?:ase64|inary|ody(?:struct)?)|c(?:heck|l(?:earflag_full|ose)|reatemailbox)|delete(?:mailbox)?|e(?:rrors|xpunge)|fetch(?:_overview|body|header|(?:mim|structur)e)|g(?:c|et(?:_quota(?:root)?|acl|mailboxes|subscribed))|header(?:info|s)|(?:is_)?open|l(?:ast_error|ist(?:scan)?|sub)|m(?:ail(?:_(?:co(?:mpose|py)|move)|boxmsginfo)?|ime_header_decode|sgno|utf7_to_utf8)|num_(?:msg|recent)|ping|r(?:e(?:namemailbox|open)|fc822_(?:parse_(?:adrlist|headers)|write_address))|s(?:avebody|e(?:arch|t(?:_quota|(?:ac|flag_ful)l))|ort|tatus|ubscribe)|t(?:hread|imeout)|u(?:id|n(?:delet|subscrib)e|tf(?:7_(?:de|en)code|8(?:_to_mutf7)?))))|n(?:_array|et_(?:ntop|pton)|flate_(?:add|get_(?:read_len|status)|init)|i_(?:get(?:_all)?|parse_quantity|restore|set)|t(?:div|erface_exists|l(?:_(?:error_nam|get_error_(?:cod|messag)|is_failur)e|cal_(?:a(?:dd|fter)|(?:befor|f(?:ield_differenc|rom_date_tim)|to_date_tim)e|c(?:lear|reate_instance)|equals|get(?:_(?:a(?:ctual_m(?:ax|in)imum|vailable_locales)|(?:day_of_week_typ|error_(?:cod|messag)|keyword_values_for_local)e|first_day_of_week|greatest_minimum|l(?:east_maximum|ocale)|m(?:aximum|inim(?:al_days_in_first_week|um))|now|(?:(?:repeat|skipp)ed_wall_time_op|weekend_transi)tion|t(?:ime(?:_zone)?|ype)))?|i(?:n_daylight_time|s_(?:equivalent_to|(?:lenien|se)t|weekend))|roll|set(?:_(?:(?:first_day_of|minimal_days_in_first)_week|lenient|(?:repeat|skipp)ed_wall_time_option|time(?:_zone)?))?)|gregcal_(?:(?:create_instanc|[gs]et_gregorian_chang)e|is_leap_year)|tz_(?:c(?:ount_equivalent_ids|reate_(?:default|enumeration|time_zone(?:_id_enumeration)?))|(?:(?:from|to)_date_time_zon|use_daylight_tim)e|get_(?:(?:canonical|windows)_id|d(?:isplay_name|st_savings)|e(?:quivalent_id|rror_(?:cod|messag)e)|(?:gm|offse)t|id(?:_for_windows_id)?|r(?:aw_offset|egion)|(?:tz_data_versio|unknow)n)|has_same_rules))))|p(?:2long|tc(?:embed|parse))|s_(?:bool|(?:(?:(?:c(?:all|ount)|(?:execu|wri)t)ab|uploaded_fi)l|i(?:nfinit|terabl)|re(?:adabl|sourc))e|f(?:i(?:l|nit)e|loat)|link|nan|s(?:calar|oap_fault|tring|ubclass_of))|terator_(?:(?:appl|to_arra)y|count))|j(?:d(?:dayofweek|monthname|to(?:french|gregorian|j(?:ewish|ulian)|unix))|(?:ewish|ulian)tojd|son_(?:last_error(?:_msg)?|validate)))[\s\x0b]*\(" \ + "id:933151,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: Medium-Risk PHP Function Name 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/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This rule is a sibling of rule 933151. +# +# Regular expression generated from regex-assembly/933152.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 933152 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:kr?sort|l(?:c(?:first|g_value|h(?:grp|own))|dap_(?:8859_to_t61|(?:ad|bin)d(?:_ext)?|co(?:mpare|nnect(?:_wallet)?|unt_(?:entri|referenc)es)|d(?:elete(?:_ext)?|n2ufn)|e(?:rr(?:(?:2st|o)r|no)|scape|x(?:op(?:_(?:passwd|refresh|sync|whoami))?|plode_dn))|f(?:irst_(?:(?:attribut|referenc)e|entry)|ree_result)|get_(?:(?:attribut|entri)es|(?:d|optio|values_le)n)|list|mod(?:_(?:add|del|replace)(?:_ext)?|ify_batch)|next_(?:(?:attribut|referenc)e|entry)|parse_(?:exop|re(?:ference|sult))|re(?:ad|name(?:_ext)?)|s(?:asl_bind|e(?:arch|t_(?:option|rebind_proc))|tart_tls)|t61_to_8859|unbind)|evenshtein|i(?:bxml_(?:(?:clear|use_internal)_errors|disable_entity_loader|get_(?:e(?:rrors|xternal_entity_loader)|last_error)|set_(?:external_entity_loader|streams_context))|nkinfo|tespeed_(?:finish_request|re(?:quest|sponse)_headers))|o(?:cal(?:e(?:_(?:(?:accept_from_htt|looku)p|(?:c(?:anonicaliz|ompos)|pars)e|filter_matches|get_(?:(?:all_variant|keyword)s|d(?:efault|isplay_(?:(?:languag|nam)e|region|(?:scrip|varian)t))|primary_language|region|script)|set_default)|conv)|time)|g1[0p]|ng2ip)|stat|trim)|m(?:b_(?:c(?:h(?:eck_encoding|r)|onvert_(?:case|encoding|kana|variables))|de(?:code_(?:mimeheader|numericentity)|tect_(?:encoding|order))|e(?:ncod(?:e_(?:mimeheader|numericentity)|ing_aliases)|reg(?:_(?:match|replace(?:_callback)?|search(?:_(?:(?:get(?:po|reg)|(?:set)?po|reg)s|init))?)|i(?:_replace)?)?)|get_info|http_(?:in|out)put|internal_encoding|l(?:anguage|ist_encodings)|o(?:rd|utput_handler)|p(?:arse_str|referred_mime_name)|regex_(?:encoding|set_options)|s(?:crub|end_mail|plit|tr(?:_(?:pad|split)|cut|i(?:mwidth|pos|str)|len|pos|r(?:chr|i(?:chr|pos)|pos)|(?:st|to(?:low|upp)e)r|width)|ubst(?:itute_character|r(?:_count)?)))|(?:(?:d5|ove_uploaded)_fil|e(?:mory_(?:get_(?:peak_)?|reset_peak_)usag|taphon)|i(?:crotim|me_content_typ))e|hash(?:_(?:count|get_(?:block_siz|hash_nam)e|keygen_s2k))?|k(?:dir|time)|sg(?:_(?:(?:get_queu|re(?:ceiv|move_queu))e|queue_exists|s(?:e(?:nd|t_queue)|tat_queue))|fmt_(?:create|(?:format|parse)(?:_message)?|get_(?:(?:error_(?:cod|messag)|local)e|pattern)|set_pattern))|t_(?:getrandmax|s?rand)|ysqli_(?:a(?:ffected_rows|utocommit)|begin_transaction|c(?:ha(?:nge_user|racter_set_name)|lose|o(?:mmit|nnect(?:_err(?:no|or))?))|d(?:ata_seek|ebug|ump_debug_info)|e(?:rr(?:no|or(?:_list)?)|xecute_query)|f(?:etch_(?:a(?:ll|rray|ssoc)|column|field(?:_direct|s)?|lengths|object|row)|ield_(?:count|seek|tell)|ree_result)|get_(?:c(?:harset|lient_(?:info|stats|version)|onnection_stats)|(?:host|proto)_info|(?:links_stat|warning)s|server_(?:info|version))|in(?:fo|it|sert_id)|kill|m(?:ore_results|ulti_query)|n(?:ext_result|um_(?:field|row)s)|options|p(?:ing|oll|repare)|query|r(?:e(?:a(?:l_(?:connect|escape_string|query)|p_async_query)|fresh|(?:lease_savepoin|por)t)|ollback)|s(?:(?:avepoin|sl_se)t|e(?:lect_db|t_charset)|qlstate|t(?:(?:a|ore_resul)t|mt_(?:a(?:ffected_rows|ttr_[gs]et)|bind_(?:param|result)|close|data_seek|e(?:rr(?:no|or(?:_list)?)|xecute)|f(?:etch|(?:ield_coun|ree_resul)t)|get_(?:result|warnings)|in(?:it|sert_id)|more_results|n(?:ext_result|um_rows)|p(?:aram_count|repare)|res(?:et|ult_metadata)|s(?:end_long_data|qlstate|tore_result))))|thread_(?:id|safe)|(?:use_resul|warning_coun)t))|n(?:(?:at(?:case)?sor|gettex)t|et_get_interfaces|l(?:2br|_langinfo)|ormalizer_(?:get_raw_decomposition|is_normalized|normalize)|umfmt_(?:create|(?:format|parse)(?:_currency)?|get_(?:(?:(?:text_)?attribut|error_(?:cod|messag)|local)e|pattern|symbol)|set_(?:(?:text_)?attribute|pattern|symbol)))|o(?:b_(?:clean|end_(?:clean|flush)|(?:implicit_)?flush|g(?:et_(?:c(?:lean|ontents)|flush|le(?:ngth|vel)|status)|zhandler)|list_handlers)|c(?:i(?:_(?:(?:bind_(?:array_)?|define_)by_name|c(?:ancel|l(?:ient_version|ose)|o(?:llection_(?:a(?:ppend|ssign)|element_(?:assign|get)|max|size|trim)|(?:mmi|nnec)t))|e(?:rror|xecute)|f(?:etch(?:_(?:a(?:ll|rray|ssoc)|object|row))?|ield_(?:is_null|(?:nam|s(?:cal|iz))e|precision|type(?:_raw)?)|ree_(?:collection|descriptor|statement))|get_implicit_resultset|lob_(?:(?:appen|loa|re(?:a|win))d|copy|e(?:of|rase|xport)|flush|i(?:mport|s_equal)|s(?:(?:av|iz)e|eek)|t(?:ell|runcate)|write)|n(?:ew_(?:c(?:o(?:llection|nnect)|ursor)|descriptor)|um_(?:field|row)s)|p(?:a(?:rs|ssword_chang)e|connect)|r(?:e(?:gister_taf_callback|sult)|ollback)|s(?:e(?:rver_version|t_(?:(?:ac|db_opera|edi)tion|c(?:all_timeout|lient_i(?:dentifier|nfo))|module_name|prefetch(?:_lob)?))|tatement_type)|unregister_taf_callback)|fetchinto|[gs]etbufferinglob)|tdec)|dbc_(?:autocommit|(?:binmod|data_sourc)e|c(?:lose(?:_all)?|o(?:lumn(?:privilege)?s|mmit|nnect(?:ion_string_(?:is_quoted|(?:should_)?quote))?)|ursor)|e(?:rror(?:msg)?|xec(?:ute)?)|f(?:etch_(?:array|into|object|row)|ield_(?:len|n(?:ame|um)|(?:scal|typ)e)|oreignkeys|ree_result)|gettypeinfo|longreadlen|n(?:ext_result|um_(?:field|row)s)|p(?:connect|r(?:epare|(?:imarykey|ocedure(?:column)?)s))|r(?:esult(?:_all)?|ollback)|s(?:etoption|(?:pecialcolumn|tatistic)s)|table(?:privilege)?s)|p(?:cache_(?:compile_file|get_(?:configuration|status)|i(?:nvalidate|s_script_cached)|reset)|en(?:dir|log|ssl_(?:c(?:ipher_(?:iv|key)_length|ms_(?:(?:de|en)crypt|read|sign|verify)|sr_(?:export(?:_to_file)?|get_(?:public_key|subject)|new|sign))|d(?:(?:ecryp|iges)t|h_compute_key)|e(?:ncrypt|rror_string)|(?:get_(?:c(?:ert_location|ipher_method|urve_name)|md_method)|random_pseudo_byte)s|open|p(?:bkdf2|k(?:cs(?:12_(?:export(?:_to_file)?|read)|7_(?:(?:de|en)crypt|read|sign|verify))|ey_(?:(?:deriv|fre)e|export(?:_to_file)?|get_(?:details|p(?:rivate|ublic))|new))|(?:rivate|ublic)_(?:de|en)crypt)|s(?:eal|ign|pki_(?:export(?:_challenge)?|new|verify))|verify|x509_(?:check(?:_private_key|purpose)|export(?:_to_file)?|f(?:ingerprint|ree)|parse|read|verify))))|utput_(?:add_rewrite_var|reset_rewrite_vars))|p(?:a(?:rse_(?:ini_(?:file|string)|str)|ss(?:thru|word_(?:algos|get_info|(?:needs_re)?hash|verify))|thinfo)|c(?:lose|ntl_(?:a(?:larm|sync_signals)|exec|forkx?|get(?:_last_error|priority)|rfork|s(?:etpriority|ig(?:nal(?:_(?:dispatch|get_handler))?|procmask|timedwait|waitinfo)|trerror)|unshare|w(?:ait(?:pid)?|exitstatus|if(?:continu|exit|s(?:ignal|topp))ed|(?:stop|term)sig)))|do_drivers|fsockopen|g_(?:(?:affected_row|num_(?:field|row)|option)s|c(?:ancel_query|l(?:ient_encoding|ose)|o(?:n(?:nect(?:_poll|ion_(?:busy|reset|status))?|(?:sume_inpu|ver)t)|py_(?:from|to)))|d(?:bnam|elet)e|e(?:n(?:d_copy|ter_pipeline_mode)|scape_(?:bytea|identifier|literal|string)|x(?:ecut|it_pipeline_mod)e)|f(?:etch_(?:a(?:ll(?:_columns)?|rray|ssoc)|object|r(?:esult|ow))|ield(?:_(?:is_null|n(?:ame|um)|prtlen|size|t(?:able|ype(?:_oid)?))|isnull|prtlen)|lush|ree_result)|get_(?:notify|pid|result)|(?:hos|inser)t|l(?:ast_(?:error|notice|oid)|o_(?:(?:c(?:los|reat)|writ)e|(?:ex|im)port|open|read(?:_all)?|(?:see|unlin)k|t(?:ell|runcate)))|meta_data|p(?:arameter_status|(?:connec|or)t|i(?:ng|peline_s(?:tatus|ync))|(?:repar|ut_lin)e)|query(?:_params)?|result_(?:error(?:_field)?|s(?:eek|tatus))|s(?:e(?:lect|nd_(?:(?:execut|prepar)e|query(?:_params)?)|t_(?:client_encoding|error_(?:context_visibil|verbos)ity))|ocket)|t(?:ra(?:ce|nsaction_status)|ty)|u(?:n(?:escape_bytea|trace)|pdate)|version)|hp(?:_(?:ini_(?:loaded_file|scanned_files)|(?:s(?:api_nam|trip_whitespac)|unam)e)|credits|dbg_(?:break_(?:f(?:ile|unction)|method|next)|c(?:lea|olo)r|e(?:nd_oplog|xec)|get_executable|prompt|start_oplog)|info|version)|osix_(?:e?access|ctermid|f?pathconf|get(?:_last_error|(?:cw|(?:e[gu]|[su])i)d|g(?:id|r(?:gid|nam|oups))|login|p(?:g(?:id|rp)|p?id|w(?:nam|uid))|rlimit)|i(?:nitgroups|satty)|kill|mk(?:fifo|nod)|s(?:et(?:(?:e[gu]|p?g|[su])id|rlimit)|trerror|ysconf)|t(?:imes|tyname)|uname)|r(?:eg_(?:filter|grep|last_error(?:_msg)?|match_all|quote|replace_callback(?:_array)?|split)|o(?:c_(?:(?:clos|nic|terminat)e|get_status|open)|perty_exists))|spell_(?:add_to_(?:personal|session)|c(?:heck|lear_session|onfig_(?:(?:creat|ignor|mod)e|d(?:ata|ict)_dir|(?:persona|save_rep)l|r(?:epl|untogether)))|new(?:_(?:config|personal))?|s(?:(?:ave_wordli|ugge)s|tore_replacemen)t)|utenv)|quote(?:d_printable_(?:de|en)code|meta))[\s\x0b]*\(" \ + "id:933152,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: Medium-Risk PHP Function Name 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/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# This rule is a sibling of rule 933151. +# +# Regular expression generated from regex-assembly/933153.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 933153 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:r(?:a(?:d2deg|ndom_(?:bytes|int)|wurl(?:de|en)code)|e(?:a(?:d(?:dir|(?:gz)?file|lin(?:e(?:_(?:(?:(?:add|list|write)_histor|re(?:ad_histor|displa))y|c(?:allback_(?:handler_(?:install|remove)|read_char)|lear_history|ompletion_function)|info|on_new_line))?|k))|lpath(?:_cache_(?:get|size))?)|gister_(?:shutdown|tick)_function|s(?:ourcebundle_(?:c(?:ount|reate)|get(?:_error_(?:cod|messag)e)?|locales)|tore_e(?:rror|xception)_handler)|wind(?:dir)?)|mdir|sort)|s(?:api_windows_(?:cp_(?:conv|[gs]et|is_utf8)|(?:generate_ctrl_even|vt100_suppor)t|set_ctrl_handler)|candir|e(?:m_(?:(?:acquir|re(?:leas|mov))e|get)|ssion_(?:(?:abor|unse)t|c(?:ache_(?:expire|limiter)|reate_id)|de(?:code|stroy)|(?:encod|(?:module_)?nam|write_clos)e|g(?:c|et_cookie_params)|id|re(?:g(?:enerate_id|ister_shutdown)|set)|s(?:ave_path|et_(?:cookie_params|save_handler)|ta(?:rt|tus)))|t(?:_(?:e(?:rror|xception)_handler|include_path|time_limit)|(?:(?:raw)?cooki|local)e))|h(?:a1(?:_file)?|ell_exec|m(?:_(?:(?:at|de)tach|(?:(?:ge|pu)t|has)_var|remove(?:_var)?)|op_(?:(?:clos|(?:dele|wri)t|siz)e|open|read)))|i(?:m(?:ilar_text|plexml_(?:import_dom|load_(?:file|string)))|nh)|nmp(?:[23]_(?:get(?:next)?|(?:real_)?walk|set)|_(?:get_(?:quick_print|valueretrieval)|read_mib|set_(?:(?:(?:enum|quick)_prin|oid_output_forma)t|valueretrieval))|get(?:next)?|(?:real)?walk|set)|o(?:cket_(?:a(?:ccept|ddrinfo_(?:bind|connect|explain|lookup)|tmark)|bind|c(?:l(?:ear_error|ose)|msg_space|onnect|reate(?:_(?:listen|pair))?)|(?:ex|im)port_stream|get(?:_option|(?:peer|sock)name)|l(?:ast_error|isten)|re(?:ad|cv(?:from|msg)?)|s(?:e(?:lect|nd(?:msg|to)?|t_(?:(?:non)?block|option))|hutdown|trerror)|w(?:rite|saprotocol_info_(?:(?:ex|im)port|release)))|dium_(?:(?:ad|(?:un)?pa)d|b(?:ase642bin|in2(?:base64|hex))|c(?:ompare|rypto_(?:a(?:ead_(?:aes256gcm_(?:(?:de|en)crypt|is_available|keygen)|chacha20poly1305_(?:(?:de|en)crypt|ietf_(?:(?:de|en)crypt|keygen)|keygen)|xchacha20poly1305_ietf_(?:(?:de|en)crypt|keygen))|uth(?:_(?:keygen|verify))?)|box(?:_(?:keypair(?:_from_secretkey_and_publickey)?|open|publickey(?:_from_secretkey)?|se(?:al(?:_open)?|cretkey|ed_keypair)))?|core_ristretto255_(?:add|from_hash|is_valid_point|random|s(?:calar_(?:add|(?:complemen|inver)t|mul|negate|r(?:andom|educe)|sub)|ub))|generichash(?:_(?:final|init|keygen|update))?|k(?:df_(?:derive_from_key|keygen)|x_(?:client_session_keys|keypair|publickey|se(?:cretkey|ed_keypair|rver_session_keys)))|pwhash(?:_s(?:cryptsalsa208sha256(?:_str(?:_verify)?)?|tr(?:_(?:needs_rehash|verify))?))?|s(?:calarmult(?:_ristretto255(?:_base)?)?|ecret(?:box(?:_(?:keyg|op)en)?|stream_xchacha20poly1305_(?:(?:init_)?pu(?:ll|sh)|keygen|rekey))|horthash(?:_keygen)?|ign(?:_(?:(?:verify_)?detached|ed25519_[ps]k_to_curve25519|keypair(?:_from_secretkey_and_publickey)?|open|publickey(?:_from_secretkey)?|se(?:cretkey|ed_keypair)))?|tream(?:_(?:keygen|x(?:chacha20(?:_(?:keygen|xor(?:_ic)?))?|or)))?)))|hex2bin|increment|mem(?:cmp|zero))|undex)|p(?:l_(?:autoload(?:_(?:call|(?:extens|funct)ions|(?:un)?register))?|classes|object_(?:hash|id))|rintf)|qrt|scanf|tr(?:_(?:contains|(?:decreme|word_cou)nt|ends_with|getcsv|i(?:ncrement|replace)|pad|r(?:epeat|ot13)|s(?:huffle|plit|tarts_with))|c(?:(?:asec)?mp|oll|spn)|eam_(?:bucket_(?:(?:ap|pre)pend|make_writeable|new)|co(?:ntext_(?:create|get_(?:default|(?:option|param)s)|set_(?:default|options?|params))|py_to_stream)|filter_(?:(?:ap|pre)pend|re(?:gister|move))|get_(?:(?:(?:conten|transpor)t|(?:filt|wrapp)er)s|line|meta_data)|is(?:_local|atty)|resolve_include_path|s(?:e(?:lect|t_(?:blocking|chunk_size|(?:read|write)_buffer|timeout))|ocket_(?:(?:accep|clien)t|enable_crypto|get_name|pair|recvfrom|s(?:e(?:ndto|rver)|hutdown))|upports_lock)|wrapper_(?:re(?:gister|store)|unregister))|ftime|i(?:p(?:c?slashe|o)s|str)|n(?:at)?c(?:asec)?mp|p(?:brk|time)|r(?:chr|ev|i?pos)|s(?:pn|tr)|t(?:ok|r)|val)|ubstr_(?:co(?:mpare|unt)|replace)|ys_get(?:_temp_dir|loadavg))|t(?:anh|e(?:mpnam|st[12]|xtdomain)|i(?:dy_(?:(?:access|error|warning)_count|c(?:lean_repair|onfig_count)|diagnose|get(?:_(?:body|config|error_buffer|h(?:ead|tml(?:_ver)?)|o(?:pt_doc|utput)|r(?:elease|oot)|status)|opt)|is_x(?:ht)?ml|(?:parse|repair)_(?:file|string))|me(?:_(?:nanosleep|sleep_until)|zone_(?:(?:(?:abbreviation|identifier)s_lis|(?:(?:locat|vers)ion|transitions)_ge)t|name_(?:from_abbr|get)|o(?:ffset_get|pen))))|mpfile|oken_(?:get_all|name)|r(?:a(?:it_exists|nsliterator_(?:create(?:_(?:from_rules|inverse))?|(?:get_error_(?:cod|messag)|transliterat)e|list_ids))|igger_error))|u(?:[ak]sort|cwords|mask|n(?:i(?:qi|xtoj)d|register_tick_function)|(?:rlde|tf8_(?:de|en))code|s(?:e_soap_error_handler|leep|ort))|v(?:ar(?:_(?:dump|export)|iant_(?:a(?:bs|[dn]d)|c(?:as?t|mp)|d(?:ate_(?:from|to)_timestamp|iv)|eqv|fix|get_type|i(?:div|mp|nt)|m(?:od|ul)|n(?:eg|ot)|x?or|pow|round|s(?:et(?:_type)?|ub)))|ersion_compare|[fs]?printf)|wordwrap|xml(?:_(?:error_string|get_(?:current_(?:byte_index|(?:column|line)_number)|error_code)|parse(?:_into_struct|r_(?:create(?:_ns)?|free|[gs]et_option))?|set_(?:(?:character_data|default|e(?:lement|nd_namespace_decl|xternal_entity_ref)|(?:notation|start_namespace|unparsed_entity)_decl|processing_instruction)_handler|object))|writer_(?:end_(?:attribute|c(?:data|omment)|d(?:ocument|td(?:_(?:attlist|e(?:lement|ntity)))?)|element|pi)|f(?:lush|ull_end_element)|o(?:pen_(?:memory|uri)|utput_memory)|s(?:et_indent(?:_string)?|tart_(?:(?:attribute|element)(?:_ns)?|c(?:data|omment)|d(?:ocument|td(?:_(?:attlist|e(?:lement|ntity)))?)|pi))|text|write_(?:(?:attribute|element)(?:_ns)?|c(?:data|omment)|dtd(?:_(?:attlist|e(?:lement|ntity)))?|pi|raw)))|z(?:end_(?:c(?:all_method|reate_unterminated_string)|get_(?:current_func_name|map_ptr_last|unit_enum)|iterable(?:_legacy)?|leak_(?:bytes|variable)|(?:number_or_string|string_or_(?:object|stdclass))(?:_or_null)?|t(?:e(?:rminate_string|st_(?:(?:(?:nullable_)?array|void)_return|c(?:ompile_string|r(?:ash|eate_throwing_resource))|deprecated|f(?:ill_packed_array|unc)|is_string_marked_as_valid_utf8|(?:override_libxml_global_sta|parameter_with_attribu)te|zend_(?:call_stack_(?:get|use_all)|ini_(?:parse_u?quantity|str))))|hread_id)|version|weakmap_(?:attach|dump|remove))|ip_(?:close|entry_(?:c(?:lose|ompress(?:edsize|ionmethod))|(?:filesiz|nam)e|open|read)|open|read)|lib_(?:(?:de|en)cod|get_coding_typ)e)|ZendTestNS2_(?:ZendSubNS_)?namespaced_(?:deprecated_)?func)[\s\x0b]*\(" \ + "id:933153,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: Medium-Risk PHP Function Name 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/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:933015,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:933016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +# +# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher) +# + +# +# [ PHP Variables: Common Variable Indexes ] +# +# In paranoia level 3, we add additional checks for parameters to many PHP variables. +# +# +# One of the more common variables used within attacks on PHP is $_SERVER. Because +# of how many different ways PHP has for executing variables (variable variables, +# etc) often just looking for $_SERVER will be less effective than looking for the +# various indexes within $_SERVER. This rule checks for these indexes. +# This rule is located in PL 3 because often developers will use these names as +# parameter names or values and this will lead to false positives. +# Because this list is not expected to change and it is limited in size we use a +# regex in this case to look for these values whereas in its sibling rule we use +# @pmFromFile for flexibility and performance. +# +# 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_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,\ + capture,\ + t:none,t:normalizePath,t:urlDecodeUni,\ + msg:'PHP Injection Attack: Variables 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:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Functions: Low-Value PHP Function Calls ] +# +# In paranoia level 3, we add additional checks for the remaining PHP functions. +# +# Most of these function names are likely to cause false positives in natural text +# or common parameter values, such as 'abs', 'copy', 'date', 'key', 'max', 'min'. +# Therefore, these function names are not scanned in lower paranoia levels. +# +# To mitigate the risk of false positives somewhat, a regexp is used to look for +# PHP function syntax. (See rule 933160 for a description.) +# +# This rule is a stricter sibling of rule 933160. +# +# This rule is also triggered by the following exploit(s): +# [ 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 ] +# +# 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_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\x0b]|/\*.*\*/|(?:#|//).*)*\(.*\)" \ + "id:933161,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'PHP Injection Attack: Low-Value PHP 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:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# +# [ PHP Script Uploads: Superfluous extension ] +# +# Block file uploads with PHP related extensions (.php, .phps, .phtml, +# .php5 etc) anywhere in the name, followed by a dot. +# +# Example: index.php.tmp +# +# Uploading of such files can lead to remote code execution if +# Apache is configured with AddType and MultiViews, as Apache will +# automatically do a filename match when the extension is unknown. +# This configuration is fortunately not common in modern installs. +# +# Blocking these file names might lead to more false positives. +# +# 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. +# +# This rule is a stricter sibling of rule 933110. +# +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:933111,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,t:removeWhitespace,\ + msg:'PHP Injection Attack: PHP Script File Upload 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:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +# [ PHP Closing Tag Found ] +# +# http://www.php.net/manual/en/language.basic-syntax.phptags.php +# +# This check was extracted from 933100 (paranoia level 1), since the +# checked sequence '?>' commonly causes false positives. +# See issue #654 for discussion. +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pm ?>" \ + "id:933190,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,\ + msg:'PHP Injection Attack: PHP Closing Tag 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:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:\((?:.+\)(?:[\"'][\-0-9A-Z_a-z]+[\"'])?\(.+|[^\)]*string[^\)]*\)[\s\x0b\"'\-\.0-9A-\[\]_a-\{\}]+\([^\)]*)|(?:\[[0-9]+\]|\{[0-9]+\}|\$[^\(\),\./;\x5c]+|[\"'][\-0-9A-Z\x5c_a-z]+[\"'])\(.+)\)(?:;|$)?" \ + "id:933211,\ + phase:2,\ + block,\ + capture,\ + t:none,t:urlDecodeUni,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:'OWASP_CRS/ATTACK-PHP',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'" + + +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:933017,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:933018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" +# +# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher) +# + + + +# +# -= Paranoia Levels Finished =- +# +SecMarker "END-REQUEST-933-APPLICATION-ATTACK-PHP" diff --git a/appsec/crs/4.25.0/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf b/appsec/crs/4.25.0/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf new file mode 100644 index 000000000..8b51dfe5f --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf @@ -0,0 +1,442 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:934012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx _(?:\$\$ND_FUNC\$\$_|_js_function)|(?:\beval|new[\s\x0b]+Function[\s\x0b]*)\(|(?:String\.fromCharCod|Module:prototyp)e|function\(\)\{|this\.constructor|module\.exports=|\([\s\x0b]*[^0-9A-Z_a-z]child_process[^0-9A-Z_a-z][\s\x0b]*\)|cons(?:tructor:constructor|ole(?:\.(?:(?:debu|lo)g|error|info|trace|warn)(?:\.call)?\(|\[[\"'`](?:(?:debu|lo)g|error|info|trace|warn)[\"'`]\]))|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)\[|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:'platform-nodejs',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + 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_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:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/225/664',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + +# This rule detects SSRF attempts using hostnames without schemes. +# Some frameworks and libraries add implicit 'http://' or 'https://' schemes +# when processing URLs, making scheme-less hostnames effective attack vectors. +# +# Examples: +# - localhost/ +# - host.docker.internal/ +# - kubernetes.default.svc.cluster.local/ +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@pmFromFile ssrf-no-scheme.data" \ + "id:934190,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'Possible Server Side Request Forgery (SSRF) Attack: Scheme-less localhost or internal hostname detected',\ + 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:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/225/664',\ + ver:'OWASP_CRS/4.25.0',\ + 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. + +# Regular expression generated from regex-assembly/934130.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 934130 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx __proto__|constructor[\s\x0b]*(?:\.|\]?\[)[\s\x0b]*prototype" \ + "id:934130,\ + phase:2,\ + block,\ + capture,\ + t:none,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:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1/180/77',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx Process[\s\x0b]*\.[\s\x0b]*spawn[\s\x0b]*\(" \ + "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:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx while[\s\x0b]*\([\s\x0b\(]*(?:!+(?: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-nodejs',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ^data:(?:(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)/(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\x0b]*;[\s\x0b]*(?:charset[\s\x0b]*=[\s\x0b]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\x0b-\"\(\),/:-\?\[-\]c\{\}]|c(?:[^!\"\(\),/:-\?\[-\]h\{\}]|h(?:[^!\"\(\),/:-\?\[-\]a\{\}]|a(?:[^!\"\(\),/:-\?\[-\]r\{\}]|r(?:[^!\"\(\),/:-\?\[-\]s\{\}]|s(?:[^!\"\(\),/:-\?\[-\]e\{\}]|e[^!\"\(\),/:-\?\[-\]t\{\}]))))))[^!\"\(\),/:-\?\[-\]\{\}]*[\s\x0b]*=[\s\x0b]*[^!\(\),/:-\?\[-\]\{\}]+);?)*(?:[\s\x0b]*,[\s\x0b]*(?:(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)/(?:\*|[^!\"\(\),/:-\?\[-\]\{\}]+)|\*)(?:[\s\x0b]*;[\s\x0b]*(?:charset[\s\x0b]*=[\s\x0b]*\"?(?:iso-8859-15?|utf-8|windows-1252)\b\"?|(?:[^\s\x0b-\"\(\),/:-\?\[-\]c\{\}]|c(?:[^!\"\(\),/:-\?\[-\]h\{\}]|h(?:[^!\"\(\),/:-\?\[-\]a\{\}]|a(?:[^!\"\(\),/:-\?\[-\]r\{\}]|r(?:[^!\"\(\),/:-\?\[-\]s\{\}]|s(?:[^!\"\(\),/:-\?\[-\]e\{\}]|e[^!\"\(\),/:-\?\[-\]t\{\}]))))))[^!\"\(\),/:-\?\[-\]\{\}]*[\s\x0b]*=[\s\x0b]*[^!\(\),/:-\?\[-\]\{\}]+);?)*)*" \ + "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:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:934014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +# +# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher) +# + +# This rule is a stricter sibling of 934100. +# Regular expression generated from regex-assembly/934101.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 934101 +# +SecRule REQUEST_FILENAME|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:close|exists|fork|(?:ope|spaw)n|re(?:ad|quire)|w(?:atch|rite))[\s\x0b]*\(" \ + "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-nodejs',\ + tag:'attack-rce',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + multiMatch,\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + +# -=[ 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_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]{7,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\x0b]*&?@(?:(?:[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}(?:\x{e2}(?:\x91[\xa0-\x{bf}]|\x92[\x80-\x{bf}]|\x93[\x80-\x{a9}\x{ab}-\x{bf}])|\x{e3}\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:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/225/664',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + 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_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx @+\{[\s\x0b]*\[" \ + "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:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'" + + +# [ Generic RCE signatures ] +# +# Detects General SSTI attacks. +# Example: <%= File.open('/etc/passwd').read %> +# Note: there is another rule 941380 that checks for {{.*}} regex. +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:\{%[^%}]*%}|<%=?[^%>]*%>)" \ + "id:934180,\ + phase:2,\ + block,\ + capture,\ + t:none,\ + msg:'SSTI Attack',\ + logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'platform-multi',\ + tag:'attack-ssti',\ + tag:'attack-injection-generic',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-GENERIC',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + 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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:934016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-934-APPLICATION-ATTACK-GENERIC" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:934018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',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/appsec/crs/4.25.0/REQUEST-941-APPLICATION-ATTACK-XSS.conf b/appsec/crs/4.25.0/REQUEST-941-APPLICATION-ATTACK-XSS.conf new file mode 100644 index 000000000..7f12704f2 --- /dev/null +++ b/appsec/crs/4.25.0/REQUEST-941-APPLICATION-ATTACK-XSS.conf @@ -0,0 +1,1161 @@ +# ------------------------------------------------------------------------ +# OWASP CRS ver.4.25.0 +# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved. +# Copyright (c) 2021-2026 CRS project. All rights reserved. +# +# The OWASP CRS 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:941011,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" +SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:941012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0',skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" +# +# -= 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 make use of a special tag to 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,\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + ctl:ruleRemoveTargetByTag=xss-perf-disable;REQUEST_FILENAME,\ + ver:'OWASP_CRS/4.25.0'" + + +# +# -=[ Libinjection - XSS Detection ]=- +# +# Ref: https://github.com/client9/libinjection +# Ref: https://speakerdeck.com/ngalbreath/libinjection-from-sqli-to-xss +# +# -=[ Targets ]=- +# +# 941100: PL1 : REQUEST_COOKIES| +# REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent| +# ARGS_NAMES|ARGS|XML:/* +# +# 941101: PL2 : REQUEST_FILENAME|REQUEST_HEADERS:Referer +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@detectXSS" \ + "id:941100,\ + phase:2,\ + block,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ + msg:'XSS Attack Detected via libinjection',\ + logdata:'Matched Data: XSS data found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-xss',\ + tag:'xss-perf-disable',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# -=[ XSS Filters - Category 1 ]=- +# http://xssplayground.net23.net/xssfilter.html +# script tag based XSS vectors, e.g., +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|REQUEST_HEADERS|!REQUEST_HEADERS:Cookie|ARGS_NAMES|ARGS|XML:/* "@rx (?i)]*>[\s\S]*?" \ + "id:941110,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ + msg:'XSS Filter - Category 1: Script Tag 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:'xss-perf-disable',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{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-50 characters after the prefix ("on"). +# +# The shortest known event is "onget". The longest known event is "onwebkitplaybacktargetavailabilitychanged" +# with 39 chars after the prefix. 50 chars adds a little bit of safety. +# +# The regex requires the equals sign to be followed by a non-equals character (=[^=]) +# to prevent false positives with base64-encoded strings (which often end in = or ==). +# This improvement allows the rule to be placed at PL1 despite having previously been +# moved to PL2 in v3.4 due to base64-related false positives with the older regex. +# +# Regular expression generated from regex-assembly/941120.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 941120 +# +SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|!REQUEST_HEADERS:Cookie|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)[\t-\r \"'\(,/-9;=`]on[a-z]{3,50}[\t-\r \(,;]*?=[^=]" \ + "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:'xss-perf-disable',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# -=[ XSS Filters - Category 3 ]=- +# +# 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_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i).(?:\b(?:(?:x(?:link:href|html|mlns)|data:text/html|formaction)\b|pattern[\s\x0b]*=)|(?:!ENTITY[\s\x0b]+(?:%[\s\x0b]+)?[^\s\x0b]+[\s\x0b]+(?:SYSTEM|PUBLIC)|@import|;base64)\b)" \ + "id:941130,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ + msg:'XSS Filter - Category 3: Attribute 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:'xss-perf-disable',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{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_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:removeWhitespace,\ + msg:'XSS Filter - Category 4: Javascript URI 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:'xss-perf-disable',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# -=[ NoScript XSS Filters ]=- +# Ref: http://noscript.net/ +# +# [NoScript InjectionChecker] HTML injection +# +# 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_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx (?i)<[^0-9<>A-Z_a-z]*(?:[^\s\x0b\"'<>]*:)?[^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|d[^0-9A-Z_a-z]*?i[^0-9A-Z_a-z]*?a[^0-9A-Z_a-z]*?l[^0-9A-Z_a-z]*?o[^0-9A-Z_a-z]*?g|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\x0b/]*[\s\x0b/]|[\"'](?:[^\s\x0b/]*[\s\x0b/])?)(?: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)|(?:playbacktargetavailabilitychange|transitionen)d)|heel)|zoom)|ping|s(?:rc|tyle))[\x08-\n\f\r ]*?=" \ + "id:941160,\ + phase:2,\ + block,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ + msg:'NoScript XSS InjectionChecker: HTML Injection',\ + 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:'xss-perf-disable',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [NoScript InjectionChecker] Attributes injection +# +SecRule REQUEST_COOKIES|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,\ + capture,\ + t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ + msg:'NoScript XSS InjectionChecker: Attribute Injection',\ + 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:'xss-perf-disable',\ + tag:'paranoia-level/1',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" + + +# +# [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_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@pm document.cookie document.domain document.querySelector document.body.appendChild document.write .parentnode .innerhtml window.location -moz-binding " \ + "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:'xss-perf-disable',\ + tag:'paranoia-level/2',\ + tag:'OWASP_CRS',\ + tag:'OWASP_CRS/ATTACK-XSS',\ + tag:'capec/1000/152/242',\ + ver:'OWASP_CRS/4.25.0',\ + severity:'CRITICAL',\ + setvar:'tx.xss_score=+%{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. +# +# +# +# +#