# ------------------------------------------------------------------------
# OWASP ModSecurity Core Rule Set ver.3.3.9
# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.
# Copyright (c) 2021-2026 Core Rule Set project. All rights reserved.
#
# The OWASP ModSecurity Core Rule Set is distributed under
# Apache Software License (ASL) version 2
# Please see the enclosed LICENSE file for full details.
# ------------------------------------------------------------------------

# These exclusions remedy false positives in a default Drupal install.
# The exclusions are only active if crs_exclusions_drupal=1 is set.
# See rule 900130 in crs-setup.conf.example for instructions.

#
# [ POLICY ]
#
# Drupal is a complex application that is hard to secure with the CRS. This set
# of exclusion rules aims to sanitise the CRS in a way that allows a default
# Drupal setup to be installed and configured without much hassle as far as
# ModSecurity and the CRS are concerned.
#
# The exclusion rules are fairly straight forward in the sense that they
# disable CRS on a set of well-known parameter fields that are often the source
# of false positives / false alarms of the CRS. This includes namely the
# session cookie, the password fields and article/node bodies.
#
# This is based on two assumptions: - You have a basic trust in your
# authenticated users who are allowed to edit nodes.  - Drupal allows html
# content in nodes and it protects your users from attacks via these fields.
#
# If you think these assumptions are wrong or if you would prefer a more
# careful/secure approach, you can disable the exclusion rules handling of said
# node body false positives. Do this by placing the following directive in
# RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.
#
# SecRuleRemoveById 9001200-9001299
#
# This will mean the CRS remain intact for the editing of node bodies.
#
# The exclusion rules in this file work without the need to define a Drupal
# installation path prefix. Instead they look at the URI from the end - or
# they use regular expressions when targeting dynamic URL. This is all not
# totally foolproof. In some cases, an advanced attacker might be able to
# doctor a request in a way that one of these exclusion rules is triggered
# and the request will bypass all further inspection despite not being a
# Drupal request at all. These exclusion rules could thus be leveraged to
# disable the CRS completely. This is why these rules are off by default.
#
# The CRS rules covered by this ruleset are the rules with Paranoia Level 1 and
# 2. If you chose to run Paranoia Level 3 or 4, you will be facing additional
# false positives which you need to handle yourself.
#
# This set of exclusion rules does not cover any additional Drupal modules
# outside of core.
#
# The exclusion rules are based on Drupal 8.1.10.
#
# And finally: This set of exclusion rules is in an experimental state. If you
# encounter false positives with the basic Drupal functionality and they are
# not covered by this rule file, then please report them. The aim is to be able
# to install and run Drupal core in a seamless manner protected by
# ModSecurity / CRS up to the paranoia level 2.


SecRule &TX:crs_exclusions_drupal|TX:crs_exclusions_drupal "@eq 0" \
    "id:9001000,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ver:'OWASP_CRS/3.3.9',\
    skipAfter:END-DRUPAL-RULE-EXCLUSIONS"

SecRule &TX:crs_exclusions_drupal|TX:crs_exclusions_drupal "@eq 0" \
    "id:9001001,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ver:'OWASP_CRS/3.3.9',\
    skipAfter:END-DRUPAL-RULE-EXCLUSIONS"


# [ Table of Contents ]
#
# 9001100 Session Cookie
# 9001110 Password
# 9001120 FREE for use
# 9001130 FREE for use
# 9001140 Content and Descriptions
# 9001150 FREE for use
# 9001160 Form Token
# 9001170 Text Formats and Editors
# 9001180 WYSIWYG/CKEditor Assets and Upload
# 9001190 FREE for use
# 9001200 Content and Descriptions
#
# The rule id range from 9001200 to 9001999 is reserved for future
# use (Drupal plugins / modules).


# [ Session Cookie ]
#
# Giving the session cookie a dynamic name is most unfortunate
# from a ModSecurity perspective. The rule language does not allow
# us to disable rules in a granular way for individual cookies with
# dynamic names. So we need to disable rule causing false positives
# for all cookies and their names.
#
# Rule Exclusion Session Cookie: 942450 SQL Hex Encoding Identified
#
SecAction "id:9001100,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetById=942450;REQUEST_COOKIES_NAMES,\
    ctl:ruleRemoveTargetById=942450;REQUEST_COOKIES,\
    ver:'OWASP_CRS/3.3.9'"


#
# [ Password ]
#
# Disable the CRS completely for all occurrences of passwords.
#
SecRule REQUEST_FILENAME "@endsWith /core/install.php" \
    "id:9001110,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:account[pass][pass1],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:account[pass][pass2],\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /user/login" \
    "id:9001112,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass,\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /admin/people/create" \
    "id:9001114,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass[pass1],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass[pass2],\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@rx /user/[0-9]+/edit$" \
    "id:9001116,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:current_pass,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass[pass1],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass[pass2],\
    ver:'OWASP_CRS/3.3.9'"


#
# [ Admin Settings (general) ]
#
# Disable known false positives for various fields used on admin pages.
#
# Rule Exclusion: 920271 Invalid character in request on multiple fields/paths
# Rule Exclusion: 942430 Restricted SQL Character Anomaly Detection (args)
#                        Disabled completely for admin/config pages
# For the people/accounts page, we disable the CRS completely for a number of
# freeform text fields.
#
SecRule REQUEST_FILENAME "@contains /admin/config/" \
    "id:9001122,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveById=942430,\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /admin/config/people/accounts" \
    "id:9001124,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveById=920271,\
    ctl:ruleRemoveById=942440,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_cancel_confirm_body,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_password_reset_body,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_register_admin_created_body,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_register_no_approval_required_body,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_register_pending_approval_body,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_status_activated_body,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_status_blocked_body,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_status_canceled_body,\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /admin/config/development/configuration/single/import" \
    "id:9001126,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveById=920271,\
    ctl:ruleRemoveById=942440,\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /admin/config/development/maintenance" \
    "id:9001128,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveById=942440,\
    ver:'OWASP_CRS/3.3.9'"


#
#
# [ Content and Descriptions ]
#
# Disable known false positives for field "ids[]".
#
# Rule Exclusion: 942130 SQL Injection Attack: SQL Tautology Detected
#
SecRule REQUEST_FILENAME "@endsWith /contextual/render" \
    "id:9001140,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetById=942130;ARGS:ids[],\
    ver:'OWASP_CRS/3.3.9'"


#
# [ Form Token / Build ID ]
#
# Rule Exclusion for form_build_id: 942440 SQL Comment Sequence Detected on ...
# Rule Exclusion for form_token:    942450 SQL Hex Encoding
# Rule Exclusion for form_build_id: 942450 SQL Hex Encoding
#
# This is applied site-wide.
#
SecAction "id:9001160,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetById=942440;ARGS:form_build_id,\
    ctl:ruleRemoveTargetById=942450;ARGS:form_token,\
    ctl:ruleRemoveTargetById=942450;ARGS:form_build_id,\
    ver:'OWASP_CRS/3.3.9'"


#
# [ Text Formats and Editors ]
#
# Disable the CRS completely for two fields triggering many, many rules
#
# Rule Exclusion for two fields: 942440 SQL Comment Sequence Detected
#
SecRule REQUEST_FILENAME "@endsWith /admin/config/content/formats/manage/full_html" \
    "id:9001170,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:editor[settings][toolbar][button_groups],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:filters[filter_html][settings][allowed_html],\
    ver:'OWASP_CRS/3.3.9'"


#
# [ WYSIWYG/CKEditor Assets and Upload ]
#
# Disable the unnecessary requestBodyAccess and for binary uploads
# bigger than an arbitrary limit of 31486341 bytes.
#
# Extensive checks make sure these uploads are really legitimate.
#
# Rule 9001180 was commented out in 2021 in order to fight CVE-2021-35368.
#
#SecRule REQUEST_METHOD "@streq POST" \
#    "id:9001180,\
#    phase:1,\
#    pass,\
#    t:none,\
#    nolog,\
#    noauditlog,\
#    ver:'OWASP_CRS/3.3.9',\
#    chain"
#    SecRule REQUEST_FILENAME "@rx /admin/content/assets/add/[a-z]+$" \
#        "chain"
#        SecRule REQUEST_COOKIES:/S?SESS[a-f0-9]+/ "@rx ^[a-zA-Z0-9_-]+" \
#            "ctl:requestBodyAccess=Off"

# Rule 9001182 was commented out in 2021 in order to fight CVE-2021-35368.
#
#SecRule REQUEST_METHOD "@streq POST" \
#    "id:9001182,\
#    phase:1,\
#    pass,\
#    t:none,\
#    nolog,\
#    noauditlog,\
#    ver:'OWASP_CRS/3.3.9',\
#    chain"
#    SecRule REQUEST_FILENAME "@rx /admin/content/assets/manage/[0-9]+$" \
#        "chain"
#        SecRule ARGS:destination "@streq admin/content/assets" \
#            "chain"
#            SecRule REQUEST_HEADERS:Content-Length "@gt 31486341" \
#                "chain"
#                SecRule REQUEST_COOKIES:/S?SESS[a-f0-9]+/ "@rx ^[a-zA-Z0-9_-]+" \
#                    "ctl:requestBodyAccess=Off"

# Rule 9001184 was commented out in 2021 in order to fight CVE-2021-35368.
#
#SecRule REQUEST_METHOD "@streq POST" \
#    "id:9001184,\
#    phase:1,\
#    pass,\
#    t:none,\
#    nolog,\
#    noauditlog,\
#    ver:'OWASP_CRS/3.3.9',\
#    chain"
#    SecRule REQUEST_FILENAME "@rx /file/ajax/field_asset_[a-z0-9_]+/[ua]nd/0/form-[a-z0-9A-Z_-]+$" \
#        "chain"
#        SecRule REQUEST_HEADERS:Content-Length "@gt 31486341" \
#            "chain"
#            SecRule REQUEST_HEADERS:Content-Type "@rx ^(?i)multipart/form-data" \
#                "chain"
#                SecRule REQUEST_COOKIES:/S?SESS[a-f0-9]+/ "@rx ^[a-zA-Z0-9_-]+" \
#                    "ctl:requestBodyAccess=Off"


#
# [ Content and Descriptions ]
#
# Disable the CRS completely for node bodies and other free text fields.
# Other rules are disabled individually.
#
# Rule Exclusion for ARGS:uid[0][target_id]: 942410 SQL Injection Attack
# Rule Exclusion for ARGS:destination:       932110 RCE: Windows Command Inj.
#
SecRule REQUEST_FILENAME "@endsWith /node/add/article" \
    "id:9001200,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:body[0][value],\
    ctl:ruleRemoveTargetById=942410;ARGS:uid[0][target_id],\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /node/add/page" \
    "id:9001202,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:body[0][value],\
    ctl:ruleRemoveTargetById=942410;ARGS:uid[0][target_id],\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@rx /node/[0-9]+/edit$" \
    "id:9001204,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:body[0][value],\
    ctl:ruleRemoveTargetById=942410;ARGS:uid[0][target_id],\
    ctl:ruleRemoveTargetById=932110;ARGS:destination,\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /block/add" \
    "id:9001206,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:body[0][value],\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /admin/structure/block/block-content/manage/basic" \
    "id:9001208,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:description,\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@rx /editor/filter_xss/(?:full|basic)_html$" \
    "id:9001210,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:value,\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@rx /user/[0-9]+/contact$" \
    "id:9001212,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message[0][value],\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /admin/config/development/maintenance" \
    "id:9001214,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:maintenance_mode_message,\
    ver:'OWASP_CRS/3.3.9'"

SecRule REQUEST_FILENAME "@endsWith /admin/config/services/rss-publishing" \
    "id:9001216,\
    phase:2,\
    pass,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:feed_description,\
    ver:'OWASP_CRS/3.3.9'"


SecMarker "END-DRUPAL-RULE-EXCLUSIONS"
