2026-01-08 06:51:04 +03:00
|
|
|
## Log destination
|
2026-01-07 14:27:55 +03:00
|
|
|
SecDefaultAction "phase:1,log,auditlog,pass"
|
|
|
|
|
SecDefaultAction "phase:2,log,auditlog,pass"
|
|
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Paranoia level
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900000,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.blocking_crs_paranoia_level={{ site.crs_paranoia_level | default(caddy_sites_defaults.crs_paranoia_level) }}"
|
|
|
|
|
{% if site.crs_detection_paranoia_level | default(caddy_sites_defaults.crs_detection_paranoia_level) != None %}
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Detection paranoia level
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900001,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_detection_paranoia_level={{ site.crs_detection_paranoia_level | default(caddy_sites_defaults.crs_detection_paranoia_level) }}"
|
2026-01-08 06:51:04 +03:00
|
|
|
{% endif %}
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Enforce Body Processor URLENCODED
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900010,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_enforce_bodyproc_urlencoded={{ site.crs_enforce_bodyproc_urlencoded | default(caddy_sites_defaults.crs_enforce_bodyproc_urlencoded) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Anomaly Scoring Mode Severity Levels
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900100,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_critical_anomaly_score={{ site.crs_critical_anomaly_score | default(caddy_sites_defaults.crs_critical_anomaly_score) }},\
|
|
|
|
|
setvar:tx.crs_error_anomaly_score={{ site.crs_error_anomaly_score | default(caddy_sites_defaults.crs_error_anomaly_score) }},\
|
|
|
|
|
setvar:tx.crs_warning_anomaly_score={{ site.crs_warning_anomaly_score | default(caddy_sites_defaults.crs_warning_anomaly_score) }},\
|
|
|
|
|
setvar:tx.crs_notice_anomaly_score={{ site.crs_notice_anomaly_score | default(caddy_sites_defaults.crs_notice_anomaly_score) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Anomaly Scoring Mode Blocking Threshold Levels
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900110,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_inbound_anomaly_score_threshold={% if site.crs_log_only | default(caddy_sites_defaults.crs_log_only) %}1000{% else %}{{ site.crs_inbound_anomaly_score_threshold | default(caddy_sites_defaults.crs_inbound_anomaly_score_threshold) }}{% endif %},\
|
|
|
|
|
setvar:tx.crs_outbound_anomaly_score_threshold={% if site.crs_log_only | default(caddy_sites_defaults.crs_log_only) %}1000{% else %}{{ site.crs_outbound_anomaly_score_threshold | default(caddy_sites_defaults.crs_outbound_anomaly_score_threshold) }}{% endif %}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Application Specific Rule Exclusions
|
|
|
|
|
# FIXME
|
2026-01-07 14:27:55 +03:00
|
|
|
# In CRS 4, these are no longer part of the CRS itself, but they are available
|
|
|
|
|
# as "CRS plugins". Some plugins improve support for web applications, and others
|
|
|
|
|
# may bring new functionality. Plugins are not installed by default, but can be
|
|
|
|
|
# downloaded from the plugin registry:
|
|
|
|
|
# https://github.com/coreruleset/plugin-registry
|
|
|
|
|
# For detailed information about using and installing plugins, please see:
|
|
|
|
|
# https://coreruleset.org/docs/concepts/plugins/
|
|
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Anomaly Score Reporting Level
|
2026-01-07 14:27:55 +03:00
|
|
|
# 0 - Reporting disabled
|
|
|
|
|
# 1 - Reporting for requests with a blocking anomaly score >= a threshold
|
|
|
|
|
# 2 - Reporting for requests with a detection anomaly score >= a threshold
|
|
|
|
|
# 3 - Reporting for requests with a blocking anomaly score greater than 0
|
|
|
|
|
# 4 - Reporting for requests with a detection anomaly score greater than 0
|
|
|
|
|
# 5 - Reporting for all requests
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900115,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_reporting_level={{ site.crs_reporting_level | default(caddy_sites_defaults.crs_reporting_level) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Early Anomaly Scoring Mode Blocking
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900120,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
2026-01-08 06:51:04 +03:00
|
|
|
setvar:tx.early_blocking=0"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Initialize Default Collections
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900130,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
2026-01-08 06:51:04 +03:00
|
|
|
setvar:tx.enable_default_collections=1"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## HTTP Policy Settings
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900200,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:'tx.crs_allowed_methods={{ site.crs_allowed_methods | default(caddy_sites_defaults.crs_allowed_methods) | join(" ") }}'"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-20 17:40:16 +03:00
|
|
|
## Content-Types that a client is allowed to send in a request
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900220,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:'tx.crs_allowed_request_content_type={{ site.crs_allowed_request_content_type | default(caddy_sites_defaults.crs_allowed_request_content_type) | join(" ") }}'"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Allowed HTTP versions
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900230,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:'tx.crs_allowed_http_versions={{ site.crs_allowed_http_versions | default(caddy_sites_defaults.crs_allowed_http_versions) | join(" ") }}'"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Forbidden file extensions
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900240,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:'tx.crs_restricted_extensions={{ site.crs_restricted_extensions | default(caddy_sites_defaults.crs_restricted_extensions) | join(" ") }}'"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Restricted request headers
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900250,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:'tx.crs_restricted_headers_basic={{ site.crs_restricted_headers_basic | default(caddy_sites_defaults.crs_restricted_headers_basic) | join(" ") }}'"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Extended restricted request headers (forbidden at a higher paranoia level)
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900255,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:'tx.crs_restricted_headers_extended={{ site.crs_restricted_headers_extended | default(caddy_sites_defaults.crs_restricted_headers_extended) | join(" ") }}'"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-20 17:40:16 +03:00
|
|
|
## Content-Types charsets that a client is allowed to send in a request
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900280,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:'tx.crs_allowed_request_content_type_charset={{ caddy_sites_defaults.crs_allowed_request_content_type_charset | default(caddy_sites_defaults.crs_allowed_request_content_type_charset) | join(" ") }}'"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-20 17:40:16 +03:00
|
|
|
## Block request if number of arguments is too high
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900300,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_max_num_args={{ site.crs_max_num_args | default(caddy_sites_defaults.crs_max_num_args) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-20 17:40:16 +03:00
|
|
|
## Block request if the length of any argument name is too high
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900310,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_arg_name_length={{ site.crs_arg_name_length | default(caddy_sites_defaults.crs_arg_name_length) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-20 17:40:16 +03:00
|
|
|
## Block request if the length of any argument value is too high
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900320,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_arg_length={{ site.crs_arg_length | default(caddy_sites_defaults.crs_arg_length) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-20 17:40:16 +03:00
|
|
|
## Block request if the total length of all combined arguments is too high
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900330,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_total_arg_length={{ site.crs_total_arg_length | default(caddy_sites_defaults.crs_total_arg_length) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-20 17:40:16 +03:00
|
|
|
## Block request if the file size of any individual uploaded file is too high
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900340,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_max_file_size={{ site.crs_max_file_size | default(caddy_sites_defaults.crs_max_file_size) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-20 17:40:16 +03:00
|
|
|
## Block request if the total size of all combined uploaded files is too high
|
2026-01-08 06:51:04 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900350,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_combined_file_sizes={{ site.crs_combined_file_sizes | default(caddy_sites_defaults.crs_combined_file_sizes) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Easing In / Sampling Percentage
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900400,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_sampling_percentage={{ site.crs_sampling_percentage | default(caddy_sites_defaults.crs_sampling_percentage) }}"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Check UTF-8 encoding
|
|
|
|
|
SecAction \
|
|
|
|
|
"id:900950,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
2026-01-08 06:51:04 +03:00
|
|
|
setvar:tx.crs_validate_utf8_encoding=1"
|
2026-01-07 14:27:55 +03:00
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## Skip Checking Responses
|
2026-01-07 14:27:55 +03:00
|
|
|
# CRS will perform analysis of the response contents if this is enabled and you have
|
|
|
|
|
# the directive `SecResponseBodyAccess On`.
|
|
|
|
|
# Warning: this feature is _enabled_ by default, but depending on your applications
|
|
|
|
|
# you might be targeted in a Request Filter Denial of Service (RFDoS) attack.
|
|
|
|
|
# References: https://blog.sicuranext.com/response-filter-denial-of-service-a-new-way-to-shutdown-a-website/
|
|
|
|
|
# Uncomment this rule to _skip checking responses_.
|
|
|
|
|
#SecAction \
|
|
|
|
|
# "id:900500,\
|
|
|
|
|
# phase:1,\
|
|
|
|
|
# pass,\
|
|
|
|
|
# t:none,\
|
|
|
|
|
# nolog,\
|
|
|
|
|
# tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
# ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
2026-01-07 14:27:55 +03:00
|
|
|
# setvar:tx.crs_skip_response_analysis=1"
|
|
|
|
|
|
2026-01-08 06:51:04 +03:00
|
|
|
## End of setup
|
2026-01-07 14:27:55 +03:00
|
|
|
SecAction \
|
|
|
|
|
"id:900990,\
|
|
|
|
|
phase:1,\
|
|
|
|
|
pass,\
|
|
|
|
|
t:none,\
|
|
|
|
|
nolog,\
|
|
|
|
|
tag:'OWASP_CRS',\
|
2026-01-23 11:20:54 +03:00
|
|
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
|
|
|
|
setvar:tx.crs_setup_version={{ site.crs_version | default(caddy_sites_defaults.crs_version) | regex_replace('\.', '') }}"
|