424 lines
12 KiB
Plaintext
424 lines
12 KiB
Plaintext
# ------------------------------------------------------------------------
|
|
# OWASP ModSecurity Core Rule Set ver.3.2.0
|
|
# Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved.
|
|
#
|
|
# The OWASP ModSecurity Core Rule Set is distributed under
|
|
# Apache Software License (ASL) version 2
|
|
# Please see the enclosed LICENSE file for full details.
|
|
# ------------------------------------------------------------------------
|
|
|
|
#
|
|
# This file REQUEST-901-INITIALIZATION.conf initializes the Core Rules
|
|
# and performs preparatory actions. It also fixes errors and omissions
|
|
# of variable definitions in the file crs-setup.conf.
|
|
# The setup.conf can and should be edited by the user, this file
|
|
# 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/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecComponentSignature
|
|
#
|
|
SecComponentSignature "OWASP_CRS/3.2.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:'ModSecurity Core Rule Set is deployed without configuration! Please copy the crs-setup.conf.example template to crs-setup.conf, and include the crs-setup.conf file in your webserver configuration before including the CRS rules. See the INSTALL file in the CRS directory for detailed instructions.',\
|
|
severity:'CRITICAL'"
|
|
|
|
|
|
#
|
|
# -=[ Default setup values ]=-
|
|
#
|
|
# Some constructs or individual rules will fail if certain parameters
|
|
# are not set in the setup.conf file. The following rules will catch
|
|
# these cases and assign sane default values.
|
|
#
|
|
|
|
# Default Inbound Anomaly Threshold Level (rule 900110 in setup.conf)
|
|
SecRule &TX:inbound_anomaly_score_threshold "@eq 0" \
|
|
"id:901100,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.inbound_anomaly_score_threshold=5'"
|
|
|
|
# Default Outbound Anomaly Threshold Level (rule 900110 in setup.conf)
|
|
SecRule &TX:outbound_anomaly_score_threshold "@eq 0" \
|
|
"id:901110,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.outbound_anomaly_score_threshold=4'"
|
|
|
|
# Default Paranoia Level (rule 900000 in setup.conf)
|
|
SecRule &TX:paranoia_level "@eq 0" \
|
|
"id:901120,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.paranoia_level=1'"
|
|
|
|
# Default Executing Paranoia Level (rule 900000 in setup.conf)
|
|
SecRule &TX:executing_paranoia_level "@eq 0" \
|
|
"id:901125,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.executing_paranoia_level=%{TX.PARANOIA_LEVEL}'"
|
|
|
|
# Default Sampling Percentage (rule 900400 in setup.conf)
|
|
SecRule &TX:sampling_percentage "@eq 0" \
|
|
"id:901130,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.sampling_percentage=100'"
|
|
|
|
# Default Anomaly Scores (rule 900100 in setup.conf)
|
|
SecRule &TX:critical_anomaly_score "@eq 0" \
|
|
"id:901140,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.critical_anomaly_score=5'"
|
|
|
|
SecRule &TX:error_anomaly_score "@eq 0" \
|
|
"id:901141,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.error_anomaly_score=4'"
|
|
|
|
SecRule &TX:warning_anomaly_score "@eq 0" \
|
|
"id:901142,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.warning_anomaly_score=3'"
|
|
|
|
SecRule &TX:notice_anomaly_score "@eq 0" \
|
|
"id:901143,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.notice_anomaly_score=2'"
|
|
|
|
# Default do_reput_block
|
|
SecRule &TX:do_reput_block "@eq 0" \
|
|
"id:901150,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.do_reput_block=0'"
|
|
|
|
# Default block duration
|
|
SecRule &TX:reput_block_duration "@eq 0" \
|
|
"id:901152,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.reput_block_duration=300'"
|
|
|
|
# Default HTTP policy: allowed_methods (rule 900200)
|
|
SecRule &TX:allowed_methods "@eq 0" \
|
|
"id:901160,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'"
|
|
|
|
# Default HTTP policy: allowed_request_content_type (rule 900220)
|
|
SecRule &TX:allowed_request_content_type "@eq 0" \
|
|
"id:901162,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.allowed_request_content_type=application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/soap+xml|application/x-amf|application/json|application/octet-stream|application/csp-report|application/xss-auditor-report|text/plain'"
|
|
|
|
# Default HTTP policy: allowed_request_content_type_charset (rule 900270)
|
|
SecRule &TX:allowed_request_content_type_charset "@eq 0" \
|
|
"id:901168,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
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)
|
|
SecRule &TX:allowed_http_versions "@eq 0" \
|
|
"id:901163,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0'"
|
|
|
|
# Default HTTP policy: restricted_extensions (rule 900240)
|
|
SecRule &TX:restricted_extensions "@eq 0" \
|
|
"id:901164,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'"
|
|
|
|
# Default HTTP policy: restricted_headers (rule 900250)
|
|
SecRule &TX:restricted_headers "@eq 0" \
|
|
"id:901165,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.restricted_headers=/proxy/ /lock-token/ /content-range/ /translate/ /if/'"
|
|
|
|
# Default HTTP policy: static_extensions (rule 900260)
|
|
SecRule &TX:static_extensions "@eq 0" \
|
|
"id:901166,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.static_extensions=/.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/'"
|
|
|
|
# Default enforcing of body processor URLENCODED
|
|
SecRule &TX:enforce_bodyproc_urlencoded "@eq 0" \
|
|
"id:901167,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
setvar:'tx.enforce_bodyproc_urlencoded=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.
|
|
# sql_error_match is used for shortcutting rules for performance reasons.
|
|
|
|
SecAction \
|
|
"id:901200,\
|
|
phase:1,\
|
|
pass,\
|
|
t:none,\
|
|
nolog,\
|
|
setvar:'tx.anomaly_score=0',\
|
|
setvar:'tx.anomaly_score_pl1=0',\
|
|
setvar:'tx.anomaly_score_pl2=0',\
|
|
setvar:'tx.anomaly_score_pl3=0',\
|
|
setvar:'tx.anomaly_score_pl4=0',\
|
|
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.inbound_anomaly_score=0',\
|
|
setvar:'tx.outbound_anomaly_score=0',\
|
|
setvar:'tx.outbound_anomaly_score_pl1=0',\
|
|
setvar:'tx.outbound_anomaly_score_pl2=0',\
|
|
setvar:'tx.outbound_anomaly_score_pl3=0',\
|
|
setvar:'tx.outbound_anomaly_score_pl4=0',\
|
|
setvar:'tx.sql_error_match=0'"
|
|
|
|
|
|
#
|
|
# -=[ Initialize collections ]=-
|
|
#
|
|
# Create both Global and IP collections for rules to use.
|
|
# There are some CRS rules that assume that these two collections
|
|
# have already been initiated.
|
|
#
|
|
|
|
SecRule REQUEST_HEADERS:User-Agent "@rx ^.*$" \
|
|
"id:901318,\
|
|
phase:1,\
|
|
pass,\
|
|
t:none,t:sha1,t:hexEncode,\
|
|
nolog,\
|
|
setvar:'tx.ua_hash=%{MATCHED_VAR}'"
|
|
|
|
SecAction \
|
|
"id:901321,\
|
|
phase:1,\
|
|
pass,\
|
|
t:none,\
|
|
nolog,\
|
|
initcol:global=global,\
|
|
initcol:ip=%{remote_addr}_%{tx.ua_hash},\
|
|
setvar:'tx.real_ip=%{remote_addr}'"
|
|
|
|
#
|
|
# -=[ 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:'paranoia-level/1',\
|
|
ctl:forceRequestBodyVariable=On,\
|
|
ver:'OWASP_CRS/3.2.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',\
|
|
ver:'OWASP_CRS/3.2.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
|
|
# there are no integers in a sha1 hash. We make sure we get two
|
|
# integer numbers by taking the last two digits from the DURATION counter
|
|
# (in microseconds).
|
|
# Finally, leading zeros are removed from the two-digit random number.
|
|
#
|
|
|
|
SecRule TX:sampling_percentage "@eq 100" \
|
|
"id:901400,\
|
|
phase:1,\
|
|
pass,\
|
|
nolog,\
|
|
skipAfter:END-SAMPLING"
|
|
|
|
SecRule UNIQUE_ID "@rx ^." \
|
|
"id:901410,\
|
|
phase:1,\
|
|
pass,\
|
|
t:sha1,t:hexEncode,\
|
|
nolog,\
|
|
setvar:'TX.sampling_rnd100=%{MATCHED_VAR}'"
|
|
|
|
SecRule DURATION "@rx (..)$" \
|
|
"id:901420,\
|
|
phase:1,\
|
|
pass,\
|
|
capture,\
|
|
nolog,\
|
|
setvar:'TX.sampling_rnd100=%{TX.sampling_rnd100}%{TX.1}'"
|
|
|
|
SecRule TX:sampling_rnd100 "@rx ^[a-f]*([0-9])[a-f]*([0-9])" \
|
|
"id:901430,\
|
|
phase:1,\
|
|
pass,\
|
|
capture,\
|
|
nolog,\
|
|
setvar:'TX.sampling_rnd100=%{TX.1}%{TX.2}'"
|
|
|
|
SecRule TX:sampling_rnd100 "@rx ^0([0-9])" \
|
|
"id:901440,\
|
|
phase:1,\
|
|
pass,\
|
|
capture,\
|
|
nolog,\
|
|
setvar:'TX.sampling_rnd100=%{TX.1}'"
|
|
|
|
|
|
#
|
|
# 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}.',\
|
|
ctl:ruleEngine=Off"
|
|
|
|
SecMarker "END-SAMPLING"
|
|
|
|
|
|
#
|
|
# Configuration Plausibility Checks
|
|
#
|
|
|
|
# Make sure executing paranoia level is not lower than paranoia level
|
|
SecRule TX:executing_paranoia_level "@lt %{tx.paranoia_level}" \
|
|
"id:901500,\
|
|
phase:1,\
|
|
deny,\
|
|
status:500,\
|
|
t:none,\
|
|
log,\
|
|
msg:'Executing paranoia level configured is lower than the paranoia level itself. This is illegal. Blocking request. Aborting.'"
|