@abtnode/router-provider 1.16.38-beta-20250115-235439-bb5a1c1b → 1.16.38-beta-20250118-033334-2da05ae8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/nginx/includes/security/crs4/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example +200 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-901-INITIALIZATION.conf +470 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-905-COMMON-EXCEPTIONS.conf +57 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-911-METHOD-ENFORCEMENT.conf +76 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-913-SCANNER-DETECTION.conf +86 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf +1915 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-921-PROTOCOL-ATTACK.conf +558 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-922-MULTIPART-ATTACK.conf +120 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf +203 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf +189 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf +1875 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf +774 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf +366 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf +1071 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf +1978 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf +132 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf +463 -0
- package/lib/nginx/includes/security/crs4/rules/REQUEST-949-BLOCKING-EVALUATION.conf +270 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-950-DATA-LEAKAGES.conf +156 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf +417 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf +108 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf +158 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf +152 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-955-WEB-SHELLS.conf +558 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-959-BLOCKING-EVALUATION.conf +280 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-980-CORRELATION.conf +138 -0
- package/lib/nginx/includes/security/crs4/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example +76 -0
- package/lib/nginx/includes/security/crs4/rules/iis-errors.data +59 -0
- package/lib/nginx/includes/security/crs4/rules/java-classes.data +64 -0
- package/lib/nginx/includes/security/crs4/rules/java-code-leakages.data +17 -0
- package/lib/nginx/includes/security/crs4/rules/java-errors.data +10 -0
- package/lib/nginx/includes/security/crs4/rules/lfi-os-files.data +722 -0
- package/lib/nginx/includes/security/crs4/rules/php-config-directives.data +571 -0
- package/lib/nginx/includes/security/crs4/rules/php-errors-pl2.data +7 -0
- package/lib/nginx/includes/security/crs4/rules/php-errors.data +2147 -0
- package/lib/nginx/includes/security/crs4/rules/php-function-names-933150.data +245 -0
- package/lib/nginx/includes/security/crs4/rules/php-function-names-933151.data +2201 -0
- package/lib/nginx/includes/security/crs4/rules/php-variables.data +30 -0
- package/lib/nginx/includes/security/crs4/rules/restricted-files.data +284 -0
- package/lib/nginx/includes/security/crs4/rules/restricted-upload.data +177 -0
- package/lib/nginx/includes/security/crs4/rules/scanners-user-agents.data +119 -0
- package/lib/nginx/includes/security/crs4/rules/sql-errors.data +172 -0
- package/lib/nginx/includes/security/crs4/rules/ssrf.data +177 -0
- package/lib/nginx/includes/security/crs4/rules/unix-shell.data +670 -0
- package/lib/nginx/includes/security/crs4/rules/web-shells-php.data +167 -0
- package/lib/nginx/includes/security/crs4/rules/windows-powershell-commands.data +425 -0
- package/lib/nginx/includes/security/unicode.mapping +96 -0
- package/lib/nginx/index.js +50 -3
- package/lib/nginx/templates/security/crs4/crs-setup.conf.js +857 -0
- package/lib/nginx/templates/security/modsecurity.conf.js +244 -0
- package/package.json +7 -6
|
@@ -0,0 +1,1915 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------
|
|
2
|
+
# OWASP CRS ver.4.9.0
|
|
3
|
+
# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.
|
|
4
|
+
# Copyright (c) 2021-2024 CRS project. All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# The OWASP CRS is distributed under
|
|
7
|
+
# Apache Software License (ASL) version 2
|
|
8
|
+
# Please see the enclosed LICENSE file for full details.
|
|
9
|
+
# ------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
# Some protocol violations are common in application layer attacks.
|
|
13
|
+
# Validating HTTP requests eliminates a large number of application layer attacks.
|
|
14
|
+
#
|
|
15
|
+
# The purpose of this rules file is to enforce HTTP RFC requirements that state how
|
|
16
|
+
# the client is supposed to interact with the server.
|
|
17
|
+
# https://www.rfc-editor.org/rfc/rfc9110.html
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# -= Paranoia Level 0 (empty) =- (apply unconditionally)
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:920011,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.9.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|
|
27
|
+
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 1" "id:920012,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.9.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|
|
28
|
+
#
|
|
29
|
+
# -= Paranoia Level 1 (default) =- (apply only when tx.detection_paranoia_level is sufficiently high: 1 or higher)
|
|
30
|
+
#
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# Validate request line against the format specified in the HTTP RFC
|
|
34
|
+
#
|
|
35
|
+
# -=[ Rule Logic ]=-
|
|
36
|
+
#
|
|
37
|
+
# Uses rule negation against the regex for positive security. The regex specifies the proper
|
|
38
|
+
# construction of URI request lines such as:
|
|
39
|
+
#
|
|
40
|
+
# "http" "://" authority path-abempty [ "?" query ]
|
|
41
|
+
#
|
|
42
|
+
# It also outlines proper construction for CONNECT, OPTIONS and GET requests.
|
|
43
|
+
#
|
|
44
|
+
# Regular expression generated from regex-assembly/920100.ra.
|
|
45
|
+
# To update the regular expression run the following shell script
|
|
46
|
+
# (consult https://coreruleset.org/docs/development/regex_assembly/ for details):
|
|
47
|
+
# crs-toolchain regex update 920100
|
|
48
|
+
#
|
|
49
|
+
# -=[ References ]=-
|
|
50
|
+
# https://www.rfc-editor.org/rfc/rfc9110.html#section-4.2.1
|
|
51
|
+
# http://capec.mitre.org/data/definitions/272.html
|
|
52
|
+
#
|
|
53
|
+
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]+)$" \
|
|
54
|
+
"id:920100,\
|
|
55
|
+
phase:1,\
|
|
56
|
+
block,\
|
|
57
|
+
t:none,\
|
|
58
|
+
msg:'Invalid HTTP Request Line',\
|
|
59
|
+
logdata:'%{request_line}',\
|
|
60
|
+
tag:'application-multi',\
|
|
61
|
+
tag:'language-multi',\
|
|
62
|
+
tag:'platform-multi',\
|
|
63
|
+
tag:'attack-protocol',\
|
|
64
|
+
tag:'paranoia-level/1',\
|
|
65
|
+
tag:'OWASP_CRS',\
|
|
66
|
+
tag:'capec/1000/210/272',\
|
|
67
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
68
|
+
severity:'WARNING',\
|
|
69
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# Identify multipart/form-data name evasion attempts
|
|
74
|
+
#
|
|
75
|
+
# There are possible impedance mismatches between how
|
|
76
|
+
# ModSecurity interprets multipart file names and how
|
|
77
|
+
# a destination app server such as PHP might parse the
|
|
78
|
+
# Content-Disposition data:
|
|
79
|
+
#
|
|
80
|
+
# filename-parm := "filename" "=" value
|
|
81
|
+
#
|
|
82
|
+
# -=[ Rule Logic ]=-
|
|
83
|
+
# These rules check for the existence of the ' " ; = meta-characters in
|
|
84
|
+
# either the "name" (FILES) and "filename" (FILES_NAMES) variables.
|
|
85
|
+
# HTML entities may lead to false positives, which is why
|
|
86
|
+
# frequently used ones, such as "ä", are allowed at PL1.
|
|
87
|
+
#
|
|
88
|
+
# -=[ Targets, characters and html entities ]=-
|
|
89
|
+
#
|
|
90
|
+
# 920120: PL1 : FILES_NAMES, FILES
|
|
91
|
+
# Disallow ['\";=\\], except for frequently used HTML entities (see 920120.ra).
|
|
92
|
+
#
|
|
93
|
+
# 920121: PL2 : FILES_NAMES, FILES
|
|
94
|
+
# Disallow ['\";=\\]
|
|
95
|
+
#
|
|
96
|
+
# -=[ References ]=-
|
|
97
|
+
# http://www.ietf.org/rfc/rfc2183.txt
|
|
98
|
+
#
|
|
99
|
+
# This rule used to use negative look-behind.
|
|
100
|
+
# See https://github.com/coreruleset/coreruleset/wiki/Technical-Decisions-and-Best-Practices#avoiding-negative-look-behind-in-regular-expressions
|
|
101
|
+
# for an explanation of why it now uses `!@rx` instead to avoid look-around.
|
|
102
|
+
#
|
|
103
|
+
# Regular expression generated from regex-assembly/920120.ra.
|
|
104
|
+
# To update the regular expression run the following shell script
|
|
105
|
+
# (consult https://coreruleset.org/docs/development/regex_assembly/ for details):
|
|
106
|
+
# crs-toolchain regex update 920120
|
|
107
|
+
#
|
|
108
|
+
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])*$" \
|
|
109
|
+
"id:920120,\
|
|
110
|
+
phase:2,\
|
|
111
|
+
block,\
|
|
112
|
+
t:none,t:urlDecodeUni,\
|
|
113
|
+
msg:'Attempted multipart/form-data bypass',\
|
|
114
|
+
logdata:'%{MATCHED_VAR}',\
|
|
115
|
+
tag:'application-multi',\
|
|
116
|
+
tag:'language-multi',\
|
|
117
|
+
tag:'platform-multi',\
|
|
118
|
+
tag:'attack-protocol',\
|
|
119
|
+
tag:'paranoia-level/1',\
|
|
120
|
+
tag:'OWASP_CRS',\
|
|
121
|
+
tag:'capec/1000/210/272',\
|
|
122
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
123
|
+
severity:'CRITICAL',\
|
|
124
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
#
|
|
128
|
+
# Accept only digits in content length
|
|
129
|
+
#
|
|
130
|
+
# -=[ Rule Logic ]=-
|
|
131
|
+
# This rule uses ModSecurity's rule negation against the regex meaning if the Content-Length header
|
|
132
|
+
# is NOT all digits, then it will match.
|
|
133
|
+
#
|
|
134
|
+
# -=[ References ]=-
|
|
135
|
+
# https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6
|
|
136
|
+
#
|
|
137
|
+
SecRule REQUEST_HEADERS:Content-Length "!@rx ^\d+$" \
|
|
138
|
+
"id:920160,\
|
|
139
|
+
phase:1,\
|
|
140
|
+
block,\
|
|
141
|
+
t:none,\
|
|
142
|
+
msg:'Content-Length HTTP header is not numeric',\
|
|
143
|
+
logdata:'%{MATCHED_VAR}',\
|
|
144
|
+
tag:'application-multi',\
|
|
145
|
+
tag:'language-multi',\
|
|
146
|
+
tag:'platform-multi',\
|
|
147
|
+
tag:'attack-protocol',\
|
|
148
|
+
tag:'paranoia-level/1',\
|
|
149
|
+
tag:'OWASP_CRS',\
|
|
150
|
+
tag:'capec/1000/210/272',\
|
|
151
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
152
|
+
severity:'CRITICAL',\
|
|
153
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
#
|
|
157
|
+
# Do not accept GET or HEAD requests with bodies
|
|
158
|
+
# In RCF-9110, "A client SHOULD NOT generate content in a HEAD/GET request
|
|
159
|
+
# unless it is made directly to an origin server that has previously indicated"
|
|
160
|
+
#
|
|
161
|
+
# -=[ Rule Logic ]=-
|
|
162
|
+
# The chained rule matches when:
|
|
163
|
+
# 1) If the request method is GET or HEAD
|
|
164
|
+
# AND
|
|
165
|
+
# 2) Header: Content-Length exists and non-zero
|
|
166
|
+
#
|
|
167
|
+
# -=[ References ]=-
|
|
168
|
+
# https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.1
|
|
169
|
+
# https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.2
|
|
170
|
+
#
|
|
171
|
+
SecRule REQUEST_METHOD "@rx ^(?:GET|HEAD)$" \
|
|
172
|
+
"id:920170,\
|
|
173
|
+
phase:1,\
|
|
174
|
+
block,\
|
|
175
|
+
t:none,\
|
|
176
|
+
msg:'GET or HEAD Request with Body Content',\
|
|
177
|
+
logdata:'%{MATCHED_VAR}',\
|
|
178
|
+
tag:'application-multi',\
|
|
179
|
+
tag:'language-multi',\
|
|
180
|
+
tag:'platform-multi',\
|
|
181
|
+
tag:'attack-protocol',\
|
|
182
|
+
tag:'paranoia-level/1',\
|
|
183
|
+
tag:'OWASP_CRS',\
|
|
184
|
+
tag:'capec/1000/210/272',\
|
|
185
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
186
|
+
severity:'CRITICAL',\
|
|
187
|
+
chain"
|
|
188
|
+
SecRule REQUEST_HEADERS:Content-Length "!@rx ^0?$" \
|
|
189
|
+
"t:none,\
|
|
190
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
#
|
|
194
|
+
# This is a sibling of rule 920170
|
|
195
|
+
#
|
|
196
|
+
SecRule REQUEST_METHOD "@rx ^(?:GET|HEAD)$" \
|
|
197
|
+
"id:920171,\
|
|
198
|
+
phase:1,\
|
|
199
|
+
block,\
|
|
200
|
+
t:none,\
|
|
201
|
+
msg:'GET or HEAD Request with Transfer-Encoding',\
|
|
202
|
+
logdata:'%{MATCHED_VAR}',\
|
|
203
|
+
tag:'application-multi',\
|
|
204
|
+
tag:'language-multi',\
|
|
205
|
+
tag:'platform-multi',\
|
|
206
|
+
tag:'attack-protocol',\
|
|
207
|
+
tag:'paranoia-level/1',\
|
|
208
|
+
tag:'OWASP_CRS',\
|
|
209
|
+
tag:'capec/1000/210/272',\
|
|
210
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
211
|
+
severity:'CRITICAL',\
|
|
212
|
+
chain"
|
|
213
|
+
SecRule &REQUEST_HEADERS:Transfer-Encoding "!@eq 0" \
|
|
214
|
+
"t:none,\
|
|
215
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
#
|
|
219
|
+
# Require Content-Length or Transfer-Encoding to be provided with
|
|
220
|
+
# every POST request if the protocol version is not HTTP/2 or HTTP/3.
|
|
221
|
+
#
|
|
222
|
+
# In case of HTTP/2, see the RFC7540 8.1 p52:
|
|
223
|
+
# HTTP/2 does not use the Transfer-Encoding: chunked anymore, because
|
|
224
|
+
# the underlying transport protocol is already using data frames with
|
|
225
|
+
# known length.
|
|
226
|
+
#
|
|
227
|
+
# In case of HTTP/3, see the RFC9114 4.1:
|
|
228
|
+
# Transfer codings (see Section 7 of [HTTP/1.1]) are not defined for
|
|
229
|
+
# HTTP/3; the Transfer-Encoding header field MUST NOT be used.
|
|
230
|
+
#
|
|
231
|
+
# -=[ Rule Logic ]=-
|
|
232
|
+
# This chained rule checks if the protocol is not HTTP/2 or HTTP/3,
|
|
233
|
+
# then checks request method is POST, if so, it checks that a
|
|
234
|
+
# Content-Length or Transfer-Encoding headers are also present.
|
|
235
|
+
#
|
|
236
|
+
SecRule REQUEST_PROTOCOL "!@within HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0" \
|
|
237
|
+
"id:920180,\
|
|
238
|
+
phase:1,\
|
|
239
|
+
block,\
|
|
240
|
+
t:none,\
|
|
241
|
+
msg:'POST without Content-Length or Transfer-Encoding headers',\
|
|
242
|
+
logdata:'%{MATCHED_VAR}',\
|
|
243
|
+
tag:'application-multi',\
|
|
244
|
+
tag:'language-multi',\
|
|
245
|
+
tag:'platform-multi',\
|
|
246
|
+
tag:'attack-protocol',\
|
|
247
|
+
tag:'paranoia-level/1',\
|
|
248
|
+
tag:'OWASP_CRS',\
|
|
249
|
+
tag:'capec/1000/210/272',\
|
|
250
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
251
|
+
severity:'WARNING',\
|
|
252
|
+
chain"
|
|
253
|
+
SecRule REQUEST_METHOD "@streq POST" \
|
|
254
|
+
"chain"
|
|
255
|
+
SecRule &REQUEST_HEADERS:Content-Length "@eq 0" \
|
|
256
|
+
"chain"
|
|
257
|
+
SecRule &REQUEST_HEADERS:Transfer-Encoding "@eq 0" \
|
|
258
|
+
"setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
|
|
259
|
+
|
|
260
|
+
#
|
|
261
|
+
# As per RFC7230 3.3.2: A sender MUST NOT send a Content-Length
|
|
262
|
+
# header field in any message that contains a Transfer-Encoding header
|
|
263
|
+
# field.
|
|
264
|
+
#
|
|
265
|
+
# Related to 920170, 920171 and 920180.
|
|
266
|
+
#
|
|
267
|
+
SecRule &REQUEST_HEADERS:Transfer-Encoding "!@eq 0" \
|
|
268
|
+
"id:920181,\
|
|
269
|
+
phase:1,\
|
|
270
|
+
block,\
|
|
271
|
+
t:none,\
|
|
272
|
+
msg:'Content-Length and Transfer-Encoding headers present',\
|
|
273
|
+
tag:'application-multi',\
|
|
274
|
+
tag:'language-multi',\
|
|
275
|
+
tag:'platform-multi',\
|
|
276
|
+
tag:'attack-protocol',\
|
|
277
|
+
tag:'paranoia-level/1',\
|
|
278
|
+
tag:'OWASP_CRS',\
|
|
279
|
+
tag:'capec/1000/210/272',\
|
|
280
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
281
|
+
severity:'WARNING',\
|
|
282
|
+
chain"
|
|
283
|
+
SecRule &REQUEST_HEADERS:Content-Length "!@eq 0" \
|
|
284
|
+
"t:none,\
|
|
285
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
#
|
|
289
|
+
# Range Header Check
|
|
290
|
+
#
|
|
291
|
+
# RFC7233 2.1 p6:
|
|
292
|
+
# "A byte-range-spec is invalid if the last-byte-pos value is present
|
|
293
|
+
# and less than the first-byte-pos."
|
|
294
|
+
#
|
|
295
|
+
# -=[ Rule Logic ]=-
|
|
296
|
+
# This rule compares the first and second byte ranges and flags
|
|
297
|
+
# when the first value is greater than the second.
|
|
298
|
+
#
|
|
299
|
+
# -=[ References ]=-
|
|
300
|
+
# https://datatracker.ietf.org/doc/html/rfc7233
|
|
301
|
+
# https://seclists.org/fulldisclosure/2011/Aug/175
|
|
302
|
+
#
|
|
303
|
+
SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx (\d+)-(\d+)" \
|
|
304
|
+
"id:920190,\
|
|
305
|
+
phase:1,\
|
|
306
|
+
block,\
|
|
307
|
+
capture,\
|
|
308
|
+
t:none,\
|
|
309
|
+
msg:'Range: Invalid Last Byte Value',\
|
|
310
|
+
logdata:'%{MATCHED_VAR}',\
|
|
311
|
+
tag:'application-multi',\
|
|
312
|
+
tag:'language-multi',\
|
|
313
|
+
tag:'platform-multi',\
|
|
314
|
+
tag:'attack-protocol',\
|
|
315
|
+
tag:'paranoia-level/1',\
|
|
316
|
+
tag:'OWASP_CRS',\
|
|
317
|
+
tag:'capec/1000/210/272',\
|
|
318
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
319
|
+
severity:'WARNING',\
|
|
320
|
+
chain"
|
|
321
|
+
SecRule TX:2 "@lt %{tx.1}" \
|
|
322
|
+
"setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
#
|
|
326
|
+
# Broken/Malicious clients often have duplicate or conflicting headers
|
|
327
|
+
# Automated programs and bots often do not obey the HTTP RFC
|
|
328
|
+
#
|
|
329
|
+
# -=[ Rule Logic ]=-
|
|
330
|
+
# This rule inspects the Connection header and looks for duplicates of the
|
|
331
|
+
# keep-alive and close options.
|
|
332
|
+
#
|
|
333
|
+
# -=[ References ]=-
|
|
334
|
+
# https://datatracker.ietf.org/doc/html/rfc7233
|
|
335
|
+
#
|
|
336
|
+
SecRule REQUEST_HEADERS:Connection "@rx \b(?:keep-alive|close),\s?(?:keep-alive|close)\b" \
|
|
337
|
+
"id:920210,\
|
|
338
|
+
phase:1,\
|
|
339
|
+
block,\
|
|
340
|
+
t:none,\
|
|
341
|
+
msg:'Multiple/Conflicting Connection Header Data Found',\
|
|
342
|
+
logdata:'%{MATCHED_VAR}',\
|
|
343
|
+
tag:'application-multi',\
|
|
344
|
+
tag:'language-multi',\
|
|
345
|
+
tag:'platform-multi',\
|
|
346
|
+
tag:'attack-protocol',\
|
|
347
|
+
tag:'paranoia-level/1',\
|
|
348
|
+
tag:'OWASP_CRS',\
|
|
349
|
+
tag:'capec/1000/210/272',\
|
|
350
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
351
|
+
severity:'WARNING',\
|
|
352
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
|
|
353
|
+
|
|
354
|
+
#
|
|
355
|
+
# Check URL encodings
|
|
356
|
+
#
|
|
357
|
+
# -=[ Rule Logic ]=-
|
|
358
|
+
# There are two different chained rules. We need to separate them as we are inspecting two
|
|
359
|
+
# different variables - REQUEST_URI_RAW and REQUEST_BODY. For REQUEST_BODY, we only want to
|
|
360
|
+
# run the @validateUrlEncoding operator if the content-type is application/x-www-form-urlencoding.
|
|
361
|
+
#
|
|
362
|
+
# We exclude the last path segment from validation because it could be a file name, which could
|
|
363
|
+
# easily contain a '%' character that is not part of a URI encoded sequence.
|
|
364
|
+
#
|
|
365
|
+
# -=[ References ]=-
|
|
366
|
+
# http://www.ietf.org/rfc/rfc1738.txt
|
|
367
|
+
#
|
|
368
|
+
# -=[ Example payload ]=-
|
|
369
|
+
# http://localhost/?s=a%20b%20c%'/
|
|
370
|
+
# reason: %'/ is not a valid url encoding
|
|
371
|
+
#
|
|
372
|
+
# Regular expression generated from regex-assembly/920220-chain1.ra.
|
|
373
|
+
# To update the regular expression run the following shell script
|
|
374
|
+
# (consult https://coreruleset.org/docs/development/regex_assembly/ for details):
|
|
375
|
+
# crs-toolchain regex update 920220-chain1
|
|
376
|
+
#
|
|
377
|
+
SecRule REQUEST_URI_RAW "@rx \x25" \
|
|
378
|
+
"id:920220,\
|
|
379
|
+
phase:1,\
|
|
380
|
+
block,\
|
|
381
|
+
t:none,t:urlDecodeUni,\
|
|
382
|
+
msg:'URL Encoding Abuse Attack Attempt',\
|
|
383
|
+
logdata:'%{REQUEST_URI_RAW}',\
|
|
384
|
+
tag:'application-multi',\
|
|
385
|
+
tag:'language-multi',\
|
|
386
|
+
tag:'platform-multi',\
|
|
387
|
+
tag:'attack-protocol',\
|
|
388
|
+
tag:'paranoia-level/1',\
|
|
389
|
+
tag:'OWASP_CRS',\
|
|
390
|
+
tag:'capec/1000/255/153/267/72',\
|
|
391
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
392
|
+
severity:'CRITICAL',\
|
|
393
|
+
chain"
|
|
394
|
+
SecRule REQUEST_URI_RAW "@rx ^(.*)/(?:[^\?]+)?(\?.*)?$" \
|
|
395
|
+
"capture,\
|
|
396
|
+
chain"
|
|
397
|
+
SecRule TX:1|TX:2 "@validateUrlEncoding" \
|
|
398
|
+
"t:none,t:urlDecodeUni,\
|
|
399
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
# Validate URI encoding of the last path segment, only if it does not look like a file name.
|
|
403
|
+
# A file name could easily contain a '%' character that is not part of a URI encoded sequence.
|
|
404
|
+
#
|
|
405
|
+
# Regular expression generated from regex-assembly/920221.ra.
|
|
406
|
+
# To update the regular expression run the following shell script
|
|
407
|
+
# (consult https://coreruleset.org/docs/development/regex_assembly/ for details):
|
|
408
|
+
# crs-toolchain regex update 920221
|
|
409
|
+
#
|
|
410
|
+
SecRule REQUEST_BASENAME "!@rx ^.*%.*\.[^\s\x0b\.]+$" \
|
|
411
|
+
"id:920221,\
|
|
412
|
+
phase:1,\
|
|
413
|
+
block,\
|
|
414
|
+
capture,\
|
|
415
|
+
t:none,t:urlDecodeUni,\
|
|
416
|
+
msg:'URL Encoding Abuse Attack Attempt',\
|
|
417
|
+
logdata:'%{REQUEST_BASENAME}',\
|
|
418
|
+
tag:'application-multi',\
|
|
419
|
+
tag:'language-multi',\
|
|
420
|
+
tag:'platform-multi',\
|
|
421
|
+
tag:'attack-protocol',\
|
|
422
|
+
tag:'paranoia-level/1',\
|
|
423
|
+
tag:'OWASP_CRS',\
|
|
424
|
+
tag:'capec/1000/255/153/267/72',\
|
|
425
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
426
|
+
severity:'CRITICAL',\
|
|
427
|
+
chain"
|
|
428
|
+
SecRule TX:0 "@validateUrlEncoding" \
|
|
429
|
+
"t:none,t:urlDecodeUni,\
|
|
430
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
#
|
|
434
|
+
# Check UTF encoding
|
|
435
|
+
# We only want to apply this check if UTF-8 encoding is actually used by the site, otherwise
|
|
436
|
+
# it will result in false positives.
|
|
437
|
+
#
|
|
438
|
+
# -=[ Rule Logic ]=-
|
|
439
|
+
# This chained rule first checks to see if the admin has set the TX:CRS_VALIDATE_UTF8_ENCODING
|
|
440
|
+
# variable in the crs-setup.conf file.
|
|
441
|
+
#
|
|
442
|
+
SecRule TX:CRS_VALIDATE_UTF8_ENCODING "@eq 1" \
|
|
443
|
+
"id:920250,\
|
|
444
|
+
phase:2,\
|
|
445
|
+
block,\
|
|
446
|
+
t:none,\
|
|
447
|
+
msg:'UTF8 Encoding Abuse Attack Attempt',\
|
|
448
|
+
logdata:'%{MATCHED_VAR}',\
|
|
449
|
+
tag:'application-multi',\
|
|
450
|
+
tag:'language-multi',\
|
|
451
|
+
tag:'platform-multi',\
|
|
452
|
+
tag:'attack-protocol',\
|
|
453
|
+
tag:'paranoia-level/1',\
|
|
454
|
+
tag:'OWASP_CRS',\
|
|
455
|
+
tag:'capec/1000/255/153/267',\
|
|
456
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
457
|
+
severity:'WARNING',\
|
|
458
|
+
chain"
|
|
459
|
+
SecRule REQUEST_FILENAME|ARGS|ARGS_NAMES "@validateUtf8Encoding" \
|
|
460
|
+
"setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
#
|
|
464
|
+
# Disallow use of full-width unicode as decoding evasions may be possible.
|
|
465
|
+
#
|
|
466
|
+
# -=[ Rule Logic ]=-
|
|
467
|
+
# This rule looks for full-width encoding by looking for %u followed by 2 'f'
|
|
468
|
+
# characters and then 2 hex characters. It is a vulnerability that affected
|
|
469
|
+
# IIS circa 2007.
|
|
470
|
+
# The rule will trigger on %uXXXX formatted chars that are full or half
|
|
471
|
+
# width, as explained above. This %uXXXX format is passed as a raw parameter
|
|
472
|
+
# and is (seemingly only) accepted by IIS (5.0, 6.0, 7.0, and 8.0). Other
|
|
473
|
+
# webservers will only process unicode chars presented as hex UTF-8 bytes.
|
|
474
|
+
#
|
|
475
|
+
# -=[ References ]=-
|
|
476
|
+
# http://www.kb.cert.org/vuls/id/739224
|
|
477
|
+
# https://www.checkpoint.com/defense/advisories/public/2007/cpai-2007-201.html
|
|
478
|
+
# https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/719
|
|
479
|
+
#
|
|
480
|
+
# Regular expression generated from regex-assembly/920260.ra.
|
|
481
|
+
# To update the regular expression run the following shell script
|
|
482
|
+
# (consult https://coreruleset.org/docs/development/regex_assembly/ for details):
|
|
483
|
+
# crs-toolchain regex update 920260
|
|
484
|
+
#
|
|
485
|
+
SecRule REQUEST_URI|REQUEST_BODY "@rx (?i)%uff[0-9a-f]{2}" \
|
|
486
|
+
"id:920260,\
|
|
487
|
+
phase:2,\
|
|
488
|
+
block,\
|
|
489
|
+
t:none,\
|
|
490
|
+
msg:'Unicode Full/Half Width Abuse Attack Attempt',\
|
|
491
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
492
|
+
tag:'application-multi',\
|
|
493
|
+
tag:'language-multi',\
|
|
494
|
+
tag:'platform-iis',\
|
|
495
|
+
tag:'platform-windows',\
|
|
496
|
+
tag:'attack-protocol',\
|
|
497
|
+
tag:'paranoia-level/1',\
|
|
498
|
+
tag:'OWASP_CRS',\
|
|
499
|
+
tag:'capec/1000/255/153/267/72',\
|
|
500
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
501
|
+
severity:'WARNING',\
|
|
502
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
#
|
|
506
|
+
# Restrict type of characters sent
|
|
507
|
+
#
|
|
508
|
+
# This is a rule with multiple stricter siblings that grows more
|
|
509
|
+
# restrictive in higher paranoia levels.
|
|
510
|
+
#
|
|
511
|
+
# -=[ Rule Logic ]=-
|
|
512
|
+
# This rule uses the @validateByteRange operator to restrict the request
|
|
513
|
+
# payloads.
|
|
514
|
+
#
|
|
515
|
+
# -=[ Targets and ASCII Ranges ]=-
|
|
516
|
+
#
|
|
517
|
+
# 920270: PL1 : REQUEST_URI, REQUEST_HEADERS, ARGS and ARGS_NAMES
|
|
518
|
+
# ASCII 1-255 : Full ASCII range without null character
|
|
519
|
+
#
|
|
520
|
+
# 920271: PL2 : REQUEST_URI, REQUEST_HEADERS, ARGS and ARGS_NAMES
|
|
521
|
+
# ASCII 9,10,13,32-126,128-255 : Full visible ASCII range, tab, newline
|
|
522
|
+
#
|
|
523
|
+
# 920272: PL3 : REQUEST_URI, REQUEST_HEADERS, ARGS, ARGS_NAMES and REQUEST_BODY
|
|
524
|
+
# ASCII 32-36,38-126 : Visible lower ASCII range without percent symbol
|
|
525
|
+
#
|
|
526
|
+
# 920273: PL4 : ARGS, ARGS_NAMES and REQUEST_BODY
|
|
527
|
+
# ASCII 38,44-46,48-58,61,65-90,95,97-122
|
|
528
|
+
# A-Z a-z 0-9 = - _ . , : &
|
|
529
|
+
#
|
|
530
|
+
# 920274: PL4 : REQUEST_HEADERS without User-Agent, Referer, Cookie
|
|
531
|
+
# and Structured Header booleans
|
|
532
|
+
# ASCII 32,34,38,42-59,61,65-90,95,97-122
|
|
533
|
+
# A-Z a-z 0-9 = - _ . , : & " * + / SPACE
|
|
534
|
+
#
|
|
535
|
+
# REQUEST_URI and REQUEST_HEADERS User-Agent, Referer and Cookie are very hard
|
|
536
|
+
# to restrict beyond the limits in 920272. Structured Header booleans are
|
|
537
|
+
# validated separately in 920275.
|
|
538
|
+
#
|
|
539
|
+
# 920274 generally has few positives. However, it would detect rare attacks
|
|
540
|
+
# on Accept request headers and friends.
|
|
541
|
+
|
|
542
|
+
SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@validateByteRange 1-255" \
|
|
543
|
+
"id:920270,\
|
|
544
|
+
phase:2,\
|
|
545
|
+
block,\
|
|
546
|
+
t:none,t:urlDecodeUni,\
|
|
547
|
+
msg:'Invalid character in request (null character)',\
|
|
548
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
549
|
+
tag:'application-multi',\
|
|
550
|
+
tag:'language-multi',\
|
|
551
|
+
tag:'platform-multi',\
|
|
552
|
+
tag:'attack-protocol',\
|
|
553
|
+
tag:'paranoia-level/1',\
|
|
554
|
+
tag:'OWASP_CRS',\
|
|
555
|
+
tag:'capec/1000/210/272',\
|
|
556
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
557
|
+
severity:'CRITICAL',\
|
|
558
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
#
|
|
562
|
+
# Do not accept requests without common headers.
|
|
563
|
+
# All normal web browsers include Host, User-Agent and Accept headers.
|
|
564
|
+
# Implies either an attacker or a legitimate automation client.
|
|
565
|
+
#
|
|
566
|
+
|
|
567
|
+
#
|
|
568
|
+
# Missing/Empty Host Header
|
|
569
|
+
#
|
|
570
|
+
# -=[ Rule Logic ]=-
|
|
571
|
+
# These rules will first check to see if a Host header is present.
|
|
572
|
+
# The second check is to see if a Host header exists but is empty.
|
|
573
|
+
#
|
|
574
|
+
SecRule &REQUEST_HEADERS:Host "@eq 0" \
|
|
575
|
+
"id:920280,\
|
|
576
|
+
phase:1,\
|
|
577
|
+
pass,\
|
|
578
|
+
t:none,\
|
|
579
|
+
msg:'Request Missing a Host Header',\
|
|
580
|
+
tag:'application-multi',\
|
|
581
|
+
tag:'language-multi',\
|
|
582
|
+
tag:'platform-multi',\
|
|
583
|
+
tag:'attack-protocol',\
|
|
584
|
+
tag:'paranoia-level/1',\
|
|
585
|
+
tag:'OWASP_CRS',\
|
|
586
|
+
tag:'capec/1000/210/272',\
|
|
587
|
+
tag:'PCI/6.5.10',\
|
|
588
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
589
|
+
severity:'WARNING',\
|
|
590
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}',\
|
|
591
|
+
skipAfter:END-HOST-CHECK"
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
SecRule REQUEST_HEADERS:Host "@rx ^$" \
|
|
595
|
+
"id:920290,\
|
|
596
|
+
phase:1,\
|
|
597
|
+
block,\
|
|
598
|
+
t:none,\
|
|
599
|
+
msg:'Empty Host Header',\
|
|
600
|
+
tag:'application-multi',\
|
|
601
|
+
tag:'language-multi',\
|
|
602
|
+
tag:'platform-multi',\
|
|
603
|
+
tag:'attack-protocol',\
|
|
604
|
+
tag:'paranoia-level/1',\
|
|
605
|
+
tag:'OWASP_CRS',\
|
|
606
|
+
tag:'capec/1000/210/272',\
|
|
607
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
608
|
+
severity:'CRITICAL',\
|
|
609
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
610
|
+
|
|
611
|
+
SecMarker "END-HOST-CHECK"
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
#
|
|
615
|
+
# Empty Accept Header
|
|
616
|
+
#
|
|
617
|
+
# -=[ Rule Logic ]=-
|
|
618
|
+
# This rule checks if an Accept header exists, but has an empty value.
|
|
619
|
+
# This is only allowed in combination with the OPTIONS method.
|
|
620
|
+
# Additionally, there are some clients sending empty Accept headers.
|
|
621
|
+
# They are covered in another chained rule checking the User-Agent.
|
|
622
|
+
# This technique demands a separate rule to detect an empty
|
|
623
|
+
# Accept header if there is no user agent. This is checked via
|
|
624
|
+
# the separate rule 920311.
|
|
625
|
+
#
|
|
626
|
+
# Exclude some common broken clients sending empty Accept header:
|
|
627
|
+
# "Business/6.6.1.2 CFNetwork/758.5.3 Darwin/15.6.0" (CRS issue #515)
|
|
628
|
+
# "Entreprise/6.5.0.177 CFNetwork/758.4.3 Darwin/15.5.0" (CRS issue #366)
|
|
629
|
+
#
|
|
630
|
+
# -=[ References ]=-
|
|
631
|
+
# https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/366
|
|
632
|
+
#
|
|
633
|
+
|
|
634
|
+
SecRule REQUEST_HEADERS:Accept "@rx ^$" \
|
|
635
|
+
"id:920310,\
|
|
636
|
+
phase:1,\
|
|
637
|
+
pass,\
|
|
638
|
+
t:none,\
|
|
639
|
+
msg:'Request Has an Empty Accept Header',\
|
|
640
|
+
tag:'application-multi',\
|
|
641
|
+
tag:'language-multi',\
|
|
642
|
+
tag:'platform-multi',\
|
|
643
|
+
tag:'attack-protocol',\
|
|
644
|
+
tag:'paranoia-level/1',\
|
|
645
|
+
tag:'OWASP_CRS',\
|
|
646
|
+
tag:'capec/1000/210/272',\
|
|
647
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
648
|
+
severity:'NOTICE',\
|
|
649
|
+
chain"
|
|
650
|
+
SecRule REQUEST_METHOD "!@rx ^OPTIONS$" \
|
|
651
|
+
"chain"
|
|
652
|
+
SecRule REQUEST_HEADERS:User-Agent "!@pm AppleWebKit Android Business Enterprise Entreprise" \
|
|
653
|
+
"t:none,\
|
|
654
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.notice_anomaly_score}'"
|
|
655
|
+
|
|
656
|
+
#
|
|
657
|
+
# This rule is a sibling of rule 920310.
|
|
658
|
+
#
|
|
659
|
+
SecRule REQUEST_HEADERS:Accept "@rx ^$" \
|
|
660
|
+
"id:920311,\
|
|
661
|
+
phase:1,\
|
|
662
|
+
pass,\
|
|
663
|
+
t:none,\
|
|
664
|
+
msg:'Request Has an Empty Accept Header',\
|
|
665
|
+
tag:'application-multi',\
|
|
666
|
+
tag:'language-multi',\
|
|
667
|
+
tag:'platform-multi',\
|
|
668
|
+
tag:'attack-protocol',\
|
|
669
|
+
tag:'paranoia-level/1',\
|
|
670
|
+
tag:'OWASP_CRS',\
|
|
671
|
+
tag:'capec/1000/210/272',\
|
|
672
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
673
|
+
severity:'NOTICE',\
|
|
674
|
+
chain"
|
|
675
|
+
SecRule REQUEST_METHOD "!@rx ^OPTIONS$" \
|
|
676
|
+
"chain"
|
|
677
|
+
SecRule &REQUEST_HEADERS:User-Agent "@eq 0" \
|
|
678
|
+
"t:none,\
|
|
679
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.notice_anomaly_score}'"
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
#
|
|
683
|
+
# Empty User-Agent Header
|
|
684
|
+
#
|
|
685
|
+
# -=[ Rule Logic ]=-
|
|
686
|
+
# This rules will check to see if the User-Agent header is empty.
|
|
687
|
+
#
|
|
688
|
+
# Note that there is a second rule, 920320, which will check for
|
|
689
|
+
# the existence of the User-Agent header.
|
|
690
|
+
#
|
|
691
|
+
|
|
692
|
+
SecRule REQUEST_HEADERS:User-Agent "@rx ^$" \
|
|
693
|
+
"id:920330,\
|
|
694
|
+
phase:1,\
|
|
695
|
+
pass,\
|
|
696
|
+
t:none,\
|
|
697
|
+
msg:'Empty User Agent Header',\
|
|
698
|
+
tag:'application-multi',\
|
|
699
|
+
tag:'language-multi',\
|
|
700
|
+
tag:'platform-multi',\
|
|
701
|
+
tag:'attack-protocol',\
|
|
702
|
+
tag:'paranoia-level/1',\
|
|
703
|
+
tag:'OWASP_CRS',\
|
|
704
|
+
tag:'capec/1000/210/272',\
|
|
705
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
706
|
+
severity:'NOTICE',\
|
|
707
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.notice_anomaly_score}'"
|
|
708
|
+
|
|
709
|
+
#
|
|
710
|
+
# Missing Content-Type Header with Request Body
|
|
711
|
+
#
|
|
712
|
+
# -=[ Rule Logic ]=-
|
|
713
|
+
# This rule will first check to see if the value of the Content-Length header is
|
|
714
|
+
# non-equal to 0. The chained rule is then checking the existence of the
|
|
715
|
+
# Content-Type header. The RFCs do not state there must be a
|
|
716
|
+
# Content-Type header. However, a request missing a Content-Header is a
|
|
717
|
+
# strong indication of a non-compliant browser.
|
|
718
|
+
#
|
|
719
|
+
# Also, omitting the CT header allows to bypass the Request Body Processor
|
|
720
|
+
# unless you set the optional tx.enforce_bodyproc_urlencoded variable.
|
|
721
|
+
#
|
|
722
|
+
# Note: in default settings, this behavior only provides a NOTICE and will
|
|
723
|
+
# not cause a request to be blocked. However, in paranoia level 2 or
|
|
724
|
+
# higher, we run sibling 920341, which DOES block these requests.
|
|
725
|
+
#
|
|
726
|
+
# -=[ References ]=-
|
|
727
|
+
# http://httpwg.org/specs/rfc7231.html#header.content-type
|
|
728
|
+
|
|
729
|
+
SecRule REQUEST_HEADERS:Content-Length "!@rx ^0$" \
|
|
730
|
+
"id:920340,\
|
|
731
|
+
phase:1,\
|
|
732
|
+
pass,\
|
|
733
|
+
t:none,\
|
|
734
|
+
msg:'Request Containing Content, but Missing Content-Type header',\
|
|
735
|
+
tag:'application-multi',\
|
|
736
|
+
tag:'language-multi',\
|
|
737
|
+
tag:'platform-multi',\
|
|
738
|
+
tag:'attack-protocol',\
|
|
739
|
+
tag:'paranoia-level/1',\
|
|
740
|
+
tag:'OWASP_CRS',\
|
|
741
|
+
tag:'capec/1000/210/272',\
|
|
742
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
743
|
+
severity:'NOTICE',\
|
|
744
|
+
chain"
|
|
745
|
+
SecRule &REQUEST_HEADERS:Content-Type "@eq 0" \
|
|
746
|
+
"t:none,\
|
|
747
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.notice_anomaly_score}'"
|
|
748
|
+
|
|
749
|
+
# Check that the host header is not an IP address
|
|
750
|
+
# This is not an HTTP RFC violation but it is indicative of automated client access.
|
|
751
|
+
# Many web-based worms propagate by scanning IP address blocks.
|
|
752
|
+
#
|
|
753
|
+
# -=[ Rule Logic ]=-
|
|
754
|
+
# This rule triggers if the Host header contains an IPv4 or IPv6 address, optionally
|
|
755
|
+
# extended with a port number. In the case of IPv6 we covering the address with square
|
|
756
|
+
# brackets and the address without square brackets.
|
|
757
|
+
#
|
|
758
|
+
# The regex consists of three main parts and said optional group:
|
|
759
|
+
#
|
|
760
|
+
# * IPv4 address
|
|
761
|
+
# * IPv6 address with square brackets
|
|
762
|
+
# * IPv6 address without square brackets
|
|
763
|
+
# * optional colon and port number
|
|
764
|
+
#
|
|
765
|
+
# Please note that the regex does not test the validity of the IP addresses.
|
|
766
|
+
# It just tries to detect a potential IP address.
|
|
767
|
+
#
|
|
768
|
+
# -=[ References ]=-
|
|
769
|
+
# https://technet.microsoft.com/en-us/magazine/2005.01.hackerbasher.aspx
|
|
770
|
+
#
|
|
771
|
+
|
|
772
|
+
SecRule REQUEST_HEADERS:Host "@rx (?:^([\d.]+|\[[\da-f:]+\]|[\da-f:]+)(:[\d]+)?$)" \
|
|
773
|
+
"id:920350,\
|
|
774
|
+
phase:1,\
|
|
775
|
+
block,\
|
|
776
|
+
t:none,\
|
|
777
|
+
msg:'Host header is a numeric IP address',\
|
|
778
|
+
logdata:'%{MATCHED_VAR}',\
|
|
779
|
+
tag:'application-multi',\
|
|
780
|
+
tag:'language-multi',\
|
|
781
|
+
tag:'platform-multi',\
|
|
782
|
+
tag:'attack-protocol',\
|
|
783
|
+
tag:'paranoia-level/1',\
|
|
784
|
+
tag:'OWASP_CRS',\
|
|
785
|
+
tag:'capec/1000/210/272',\
|
|
786
|
+
tag:'PCI/6.5.10',\
|
|
787
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
788
|
+
severity:'WARNING',\
|
|
789
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
# In most cases, you should expect a certain volume of each a request on your
|
|
793
|
+
# website. For example, a request with 400 arguments, can be suspicious.
|
|
794
|
+
# This file creates limitations on the request.
|
|
795
|
+
#
|
|
796
|
+
# TODO Look at the rules in this file, and define the sizes you'd like to enforce.
|
|
797
|
+
# Note that most of the rules are commented out by default.
|
|
798
|
+
# Uncomment the rules you need
|
|
799
|
+
#
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
#
|
|
803
|
+
# Maximum number of arguments in request limited
|
|
804
|
+
#
|
|
805
|
+
SecRule &TX:MAX_NUM_ARGS "@eq 1" \
|
|
806
|
+
"id:920380,\
|
|
807
|
+
phase:2,\
|
|
808
|
+
block,\
|
|
809
|
+
t:none,\
|
|
810
|
+
msg:'Too many arguments in request',\
|
|
811
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
812
|
+
tag:'application-multi',\
|
|
813
|
+
tag:'language-multi',\
|
|
814
|
+
tag:'platform-multi',\
|
|
815
|
+
tag:'attack-protocol',\
|
|
816
|
+
tag:'paranoia-level/1',\
|
|
817
|
+
tag:'OWASP_CRS',\
|
|
818
|
+
tag:'capec/1000/210/272',\
|
|
819
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
820
|
+
severity:'CRITICAL',\
|
|
821
|
+
chain"
|
|
822
|
+
SecRule &ARGS "@gt %{tx.max_num_args}" \
|
|
823
|
+
"t:none,\
|
|
824
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
825
|
+
|
|
826
|
+
## -- Arguments limits --
|
|
827
|
+
#
|
|
828
|
+
# Limit argument name length
|
|
829
|
+
#
|
|
830
|
+
SecRule &TX:ARG_NAME_LENGTH "@eq 1" \
|
|
831
|
+
"id:920360,\
|
|
832
|
+
phase:2,\
|
|
833
|
+
block,\
|
|
834
|
+
t:none,\
|
|
835
|
+
msg:'Argument name too long',\
|
|
836
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
837
|
+
tag:'application-multi',\
|
|
838
|
+
tag:'language-multi',\
|
|
839
|
+
tag:'platform-multi',\
|
|
840
|
+
tag:'attack-protocol',\
|
|
841
|
+
tag:'paranoia-level/1',\
|
|
842
|
+
tag:'OWASP_CRS',\
|
|
843
|
+
tag:'capec/1000/210/272',\
|
|
844
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
845
|
+
severity:'CRITICAL',\
|
|
846
|
+
chain"
|
|
847
|
+
SecRule ARGS_NAMES "@gt %{tx.arg_name_length}" \
|
|
848
|
+
"t:none,t:length,\
|
|
849
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
850
|
+
|
|
851
|
+
#
|
|
852
|
+
# Limit argument value length
|
|
853
|
+
#
|
|
854
|
+
# This rule is also triggered by an Apache Struts Remote Code Execution exploit:
|
|
855
|
+
# [ Apache Struts vulnerability CVE-2017-9791 - Exploit tested: https://www.exploit-db.com/exploits/42324 ]
|
|
856
|
+
#
|
|
857
|
+
SecRule &TX:ARG_LENGTH "@eq 1" \
|
|
858
|
+
"id:920370,\
|
|
859
|
+
phase:2,\
|
|
860
|
+
block,\
|
|
861
|
+
t:none,\
|
|
862
|
+
msg:'Argument value too long',\
|
|
863
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
864
|
+
tag:'application-multi',\
|
|
865
|
+
tag:'language-multi',\
|
|
866
|
+
tag:'platform-multi',\
|
|
867
|
+
tag:'attack-protocol',\
|
|
868
|
+
tag:'paranoia-level/1',\
|
|
869
|
+
tag:'OWASP_CRS',\
|
|
870
|
+
tag:'capec/1000/210/272',\
|
|
871
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
872
|
+
severity:'CRITICAL',\
|
|
873
|
+
chain"
|
|
874
|
+
SecRule ARGS "@gt %{tx.arg_length}" \
|
|
875
|
+
"t:none,t:length,\
|
|
876
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
877
|
+
|
|
878
|
+
#
|
|
879
|
+
# Limit arguments total length
|
|
880
|
+
#
|
|
881
|
+
SecRule &TX:TOTAL_ARG_LENGTH "@eq 1" \
|
|
882
|
+
"id:920390,\
|
|
883
|
+
phase:2,\
|
|
884
|
+
block,\
|
|
885
|
+
t:none,\
|
|
886
|
+
msg:'Total arguments size exceeded',\
|
|
887
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
888
|
+
tag:'application-multi',\
|
|
889
|
+
tag:'language-multi',\
|
|
890
|
+
tag:'platform-multi',\
|
|
891
|
+
tag:'attack-protocol',\
|
|
892
|
+
tag:'paranoia-level/1',\
|
|
893
|
+
tag:'OWASP_CRS',\
|
|
894
|
+
tag:'capec/1000/210/272',\
|
|
895
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
896
|
+
severity:'CRITICAL',\
|
|
897
|
+
chain"
|
|
898
|
+
SecRule ARGS_COMBINED_SIZE "@gt %{tx.total_arg_length}" \
|
|
899
|
+
"t:none,\
|
|
900
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
#
|
|
904
|
+
# -- File upload limits --
|
|
905
|
+
#
|
|
906
|
+
# Individual file size is limited
|
|
907
|
+
SecRule &TX:MAX_FILE_SIZE "@eq 1" \
|
|
908
|
+
"id:920400,\
|
|
909
|
+
phase:1,\
|
|
910
|
+
block,\
|
|
911
|
+
t:none,\
|
|
912
|
+
msg:'Uploaded file size too large',\
|
|
913
|
+
tag:'application-multi',\
|
|
914
|
+
tag:'language-multi',\
|
|
915
|
+
tag:'platform-multi',\
|
|
916
|
+
tag:'attack-protocol',\
|
|
917
|
+
tag:'paranoia-level/1',\
|
|
918
|
+
tag:'OWASP_CRS',\
|
|
919
|
+
tag:'capec/1000/210/272',\
|
|
920
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
921
|
+
severity:'CRITICAL',\
|
|
922
|
+
chain"
|
|
923
|
+
SecRule REQUEST_HEADERS:Content-Type "@rx ^(?i)multipart/form-data" \
|
|
924
|
+
"chain"
|
|
925
|
+
SecRule REQUEST_HEADERS:Content-Length "@gt %{tx.max_file_size}" \
|
|
926
|
+
"t:none,\
|
|
927
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
928
|
+
|
|
929
|
+
#
|
|
930
|
+
# Combined file size is limited
|
|
931
|
+
#
|
|
932
|
+
SecRule &TX:COMBINED_FILE_SIZES "@eq 1" \
|
|
933
|
+
"id:920410,\
|
|
934
|
+
phase:2,\
|
|
935
|
+
block,\
|
|
936
|
+
t:none,\
|
|
937
|
+
msg:'Total uploaded files size too large',\
|
|
938
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
939
|
+
tag:'application-multi',\
|
|
940
|
+
tag:'language-multi',\
|
|
941
|
+
tag:'platform-multi',\
|
|
942
|
+
tag:'attack-protocol',\
|
|
943
|
+
tag:'paranoia-level/1',\
|
|
944
|
+
tag:'OWASP_CRS',\
|
|
945
|
+
tag:'capec/1000/210/272',\
|
|
946
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
947
|
+
severity:'CRITICAL',\
|
|
948
|
+
chain"
|
|
949
|
+
SecRule FILES_COMBINED_SIZE "@gt %{tx.combined_file_sizes}" \
|
|
950
|
+
"t:none,\
|
|
951
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
#
|
|
956
|
+
# Restrict which content-types we accept.
|
|
957
|
+
#
|
|
958
|
+
|
|
959
|
+
# Restrict Content-Type header to established patterns.
|
|
960
|
+
#
|
|
961
|
+
# This provides generic allow list protection against vulnerabilities like
|
|
962
|
+
# Apache Struts Content-Type arbitrary command execution (CVE-2017-5638).
|
|
963
|
+
#
|
|
964
|
+
# Examples of allowed patterns:
|
|
965
|
+
# - text/plain
|
|
966
|
+
# - text/plain; charset="UTF-8"
|
|
967
|
+
# - multipart/form-data; boundary=----WebKitFormBoundary12345
|
|
968
|
+
# - application/soap+xml; charset=utf-8; action="urn:localhost-hwh#getQuestions"
|
|
969
|
+
# - application/*+json
|
|
970
|
+
|
|
971
|
+
SecRule REQUEST_HEADERS:Content-Type "!@rx ^[\w/.+*-]+(?:\s?;\s*(?:action|boundary|charset|component|start(?:-info)?|type|version)\s?=\s?['\"\w.()+,/:=?<>@#*-]+)*$" \
|
|
972
|
+
"id:920470,\
|
|
973
|
+
phase:1,\
|
|
974
|
+
block,\
|
|
975
|
+
t:none,t:lowercase,\
|
|
976
|
+
msg:'Illegal Content-Type header',\
|
|
977
|
+
logdata:'%{MATCHED_VAR}',\
|
|
978
|
+
tag:'application-multi',\
|
|
979
|
+
tag:'language-multi',\
|
|
980
|
+
tag:'platform-multi',\
|
|
981
|
+
tag:'attack-protocol',\
|
|
982
|
+
tag:'paranoia-level/1',\
|
|
983
|
+
tag:'OWASP_CRS',\
|
|
984
|
+
tag:'capec/1000/255/153',\
|
|
985
|
+
tag:'PCI/12.1',\
|
|
986
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
987
|
+
severity:'CRITICAL',\
|
|
988
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
989
|
+
|
|
990
|
+
# In case Content-Type header can be parsed, check the mime-type against
|
|
991
|
+
# the policy defined in the 'allowed_request_content_type' variable.
|
|
992
|
+
# To change your policy, edit crs-setup.conf and activate rule 900220.
|
|
993
|
+
SecRule REQUEST_HEADERS:Content-Type "@rx ^[^;\s]+" \
|
|
994
|
+
"id:920420,\
|
|
995
|
+
phase:1,\
|
|
996
|
+
block,\
|
|
997
|
+
capture,\
|
|
998
|
+
t:none,\
|
|
999
|
+
msg:'Request content type is not allowed by policy',\
|
|
1000
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1001
|
+
tag:'application-multi',\
|
|
1002
|
+
tag:'language-multi',\
|
|
1003
|
+
tag:'platform-multi',\
|
|
1004
|
+
tag:'attack-protocol',\
|
|
1005
|
+
tag:'paranoia-level/1',\
|
|
1006
|
+
tag:'OWASP_CRS',\
|
|
1007
|
+
tag:'capec/1000/255/153',\
|
|
1008
|
+
tag:'PCI/12.1',\
|
|
1009
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1010
|
+
severity:'CRITICAL',\
|
|
1011
|
+
setvar:'tx.content_type=|%{tx.0}|',\
|
|
1012
|
+
chain"
|
|
1013
|
+
SecRule TX:content_type "!@within %{tx.allowed_request_content_type}" \
|
|
1014
|
+
"t:lowercase,\
|
|
1015
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
#
|
|
1019
|
+
# Restrict charset parameter within the content-type header
|
|
1020
|
+
#
|
|
1021
|
+
SecRule REQUEST_HEADERS:Content-Type "@rx charset\s*=\s*[\"']?([^;\"'\s]+)" \
|
|
1022
|
+
"id:920480,\
|
|
1023
|
+
phase:1,\
|
|
1024
|
+
block,\
|
|
1025
|
+
capture,\
|
|
1026
|
+
t:none,\
|
|
1027
|
+
msg:'Request content type charset is not allowed by policy',\
|
|
1028
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1029
|
+
tag:'application-multi',\
|
|
1030
|
+
tag:'language-multi',\
|
|
1031
|
+
tag:'platform-multi',\
|
|
1032
|
+
tag:'attack-protocol',\
|
|
1033
|
+
tag:'paranoia-level/1',\
|
|
1034
|
+
tag:'OWASP_CRS',\
|
|
1035
|
+
tag:'capec/1000/255/153',\
|
|
1036
|
+
tag:'PCI/12.1',\
|
|
1037
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1038
|
+
severity:'CRITICAL',\
|
|
1039
|
+
setvar:'tx.content_type_charset=|%{tx.1}|',\
|
|
1040
|
+
chain"
|
|
1041
|
+
SecRule TX:content_type_charset "!@within %{tx.allowed_request_content_type_charset}" \
|
|
1042
|
+
"t:lowercase,\
|
|
1043
|
+
ctl:forceRequestBodyVariable=On,\
|
|
1044
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1045
|
+
|
|
1046
|
+
#
|
|
1047
|
+
# Restrict charset parameter inside content type header to occur max once.
|
|
1048
|
+
#
|
|
1049
|
+
SecRule REQUEST_HEADERS:Content-Type "@rx charset.*?charset" \
|
|
1050
|
+
"id:920530,\
|
|
1051
|
+
phase:1,\
|
|
1052
|
+
block,\
|
|
1053
|
+
t:none,t:lowercase,\
|
|
1054
|
+
msg:'Multiple charsets detected in content type header',\
|
|
1055
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1056
|
+
tag:'application-multi',\
|
|
1057
|
+
tag:'language-multi',\
|
|
1058
|
+
tag:'platform-multi',\
|
|
1059
|
+
tag:'attack-protocol',\
|
|
1060
|
+
tag:'paranoia-level/1',\
|
|
1061
|
+
tag:'OWASP_CRS',\
|
|
1062
|
+
tag:'capec/1000/255/153',\
|
|
1063
|
+
tag:'PCI/12.1',\
|
|
1064
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1065
|
+
severity:'CRITICAL',\
|
|
1066
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1067
|
+
|
|
1068
|
+
#
|
|
1069
|
+
# Restrict protocol versions.
|
|
1070
|
+
#
|
|
1071
|
+
SecRule REQUEST_PROTOCOL "!@within %{tx.allowed_http_versions}" \
|
|
1072
|
+
"id:920430,\
|
|
1073
|
+
phase:1,\
|
|
1074
|
+
block,\
|
|
1075
|
+
t:none,\
|
|
1076
|
+
msg:'HTTP protocol version is not allowed by policy',\
|
|
1077
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1078
|
+
tag:'application-multi',\
|
|
1079
|
+
tag:'language-multi',\
|
|
1080
|
+
tag:'platform-multi',\
|
|
1081
|
+
tag:'attack-protocol',\
|
|
1082
|
+
tag:'paranoia-level/1',\
|
|
1083
|
+
tag:'OWASP_CRS',\
|
|
1084
|
+
tag:'capec/1000/210/272',\
|
|
1085
|
+
tag:'PCI/6.5.10',\
|
|
1086
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1087
|
+
severity:'CRITICAL',\
|
|
1088
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1089
|
+
|
|
1090
|
+
#
|
|
1091
|
+
# Restrict file extension
|
|
1092
|
+
#
|
|
1093
|
+
SecRule REQUEST_BASENAME "@rx \.([^.]+)$" \
|
|
1094
|
+
"id:920440,\
|
|
1095
|
+
phase:1,\
|
|
1096
|
+
block,\
|
|
1097
|
+
capture,\
|
|
1098
|
+
t:none,t:urlDecodeUni,\
|
|
1099
|
+
msg:'URL file extension is restricted by policy',\
|
|
1100
|
+
logdata:'%{TX.0}',\
|
|
1101
|
+
tag:'application-multi',\
|
|
1102
|
+
tag:'language-multi',\
|
|
1103
|
+
tag:'platform-multi',\
|
|
1104
|
+
tag:'attack-protocol',\
|
|
1105
|
+
tag:'paranoia-level/1',\
|
|
1106
|
+
tag:'OWASP_CRS',\
|
|
1107
|
+
tag:'capec/1000/210/272',\
|
|
1108
|
+
tag:'PCI/6.5.10',\
|
|
1109
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1110
|
+
severity:'CRITICAL',\
|
|
1111
|
+
setvar:'tx.extension=.%{tx.1}/',\
|
|
1112
|
+
chain"
|
|
1113
|
+
SecRule TX:EXTENSION "@within %{tx.restricted_extensions}" \
|
|
1114
|
+
"t:none,t:lowercase,\
|
|
1115
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1116
|
+
|
|
1117
|
+
#
|
|
1118
|
+
# Backup or "working" file extension
|
|
1119
|
+
# example: index.php~, /index.php~/foo/
|
|
1120
|
+
#
|
|
1121
|
+
SecRule REQUEST_FILENAME "@rx \.[^.~]+~(?:/.*|)$" \
|
|
1122
|
+
"id:920500,\
|
|
1123
|
+
phase:1,\
|
|
1124
|
+
block,\
|
|
1125
|
+
t:none,t:urlDecodeUni,\
|
|
1126
|
+
msg:'Attempt to access a backup or working file',\
|
|
1127
|
+
logdata:'%{TX.0}',\
|
|
1128
|
+
tag:'application-multi',\
|
|
1129
|
+
tag:'language-multi',\
|
|
1130
|
+
tag:'platform-multi',\
|
|
1131
|
+
tag:'attack-protocol',\
|
|
1132
|
+
tag:'paranoia-level/1',\
|
|
1133
|
+
tag:'OWASP_CRS',\
|
|
1134
|
+
tag:'capec/1000/210/272',\
|
|
1135
|
+
tag:'PCI/6.5.10',\
|
|
1136
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1137
|
+
severity:'CRITICAL',\
|
|
1138
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1139
|
+
|
|
1140
|
+
#
|
|
1141
|
+
# Restricted HTTP headers
|
|
1142
|
+
#
|
|
1143
|
+
# -=[ Rule Logic ]=-
|
|
1144
|
+
# The use of certain headers is restricted. They are listed in two variables:
|
|
1145
|
+
# - TX.restricted_headers_basic: Known security risks, always forbidden (rule
|
|
1146
|
+
# 920450)
|
|
1147
|
+
# - TX.restricted_headers_extended: Possible false positives, possible security
|
|
1148
|
+
# risks, may be forbidden (rule 920451)
|
|
1149
|
+
#
|
|
1150
|
+
# The headers are transformed into lowercase before the match. In order to make
|
|
1151
|
+
# sure that only complete header names match, the names in the
|
|
1152
|
+
# TX.restricted_headers_* variables are wrapped in slashes. This guarantees that
|
|
1153
|
+
# the Range header (which becomes /range/) will not match the restricted
|
|
1154
|
+
# /content-range/ header, for example.
|
|
1155
|
+
#
|
|
1156
|
+
# This is a chained rule, where the first rule fills a set of variables of the
|
|
1157
|
+
# form TX.header_name_<RULE_ID>_<HEADER_NAME>. The second rule is then executed
|
|
1158
|
+
# for all variables of the form TX.header_name_<RULE_ID>_<HEADER_NAME>.
|
|
1159
|
+
#
|
|
1160
|
+
# As a consequence of the construction of the rule, the alert message and the
|
|
1161
|
+
# alert data will not display the original header name Content-Range, but
|
|
1162
|
+
# /content-range/ instead.
|
|
1163
|
+
#
|
|
1164
|
+
# This rule has a stricter sibling, 920451, which matches against the variable
|
|
1165
|
+
# TX.restricted_headers_extended. It handles deprecated headers that are still
|
|
1166
|
+
# in use (so false positives are possible, hence unsuitable for blocking in a
|
|
1167
|
+
# default paranoia level 1 installation) and headers with possible security
|
|
1168
|
+
# risks.
|
|
1169
|
+
#
|
|
1170
|
+
# -=[ References ]=-
|
|
1171
|
+
# https://access.redhat.com/security/vulnerabilities/httpoxy (Header Proxy)
|
|
1172
|
+
# https://www.sidechannel.blog/en/http-method-override-what-it-is-and-how-a-pentester-can-use-it
|
|
1173
|
+
#
|
|
1174
|
+
SecRule REQUEST_HEADERS_NAMES "@rx ^.*$" \
|
|
1175
|
+
"id:920450,\
|
|
1176
|
+
phase:1,\
|
|
1177
|
+
block,\
|
|
1178
|
+
capture,\
|
|
1179
|
+
t:none,t:lowercase,\
|
|
1180
|
+
msg:'HTTP header is restricted by policy (%{MATCHED_VAR})',\
|
|
1181
|
+
logdata:'Restricted header detected: %{MATCHED_VAR}',\
|
|
1182
|
+
tag:'application-multi',\
|
|
1183
|
+
tag:'language-multi',\
|
|
1184
|
+
tag:'platform-multi',\
|
|
1185
|
+
tag:'attack-protocol',\
|
|
1186
|
+
tag:'paranoia-level/1',\
|
|
1187
|
+
tag:'OWASP_CRS',\
|
|
1188
|
+
tag:'capec/1000/210/272',\
|
|
1189
|
+
tag:'PCI/12.1',\
|
|
1190
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1191
|
+
severity:'CRITICAL',\
|
|
1192
|
+
setvar:'tx.header_name_920450_%{tx.0}=/%{tx.0}/',\
|
|
1193
|
+
chain"
|
|
1194
|
+
SecRule TX:/^header_name_920450_/ "@within %{tx.restricted_headers_basic}" \
|
|
1195
|
+
"setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1196
|
+
|
|
1197
|
+
#
|
|
1198
|
+
# Rule against CVE-2022-21907
|
|
1199
|
+
# This rule blocks Accept-Encoding headers longer than 100 characters.
|
|
1200
|
+
# The length of 100 is a heuristic based on the length of values from
|
|
1201
|
+
# the RFC (https://datatracker.ietf.org/doc/rfc9110/)
|
|
1202
|
+
# and the respective values assigned by IANA
|
|
1203
|
+
# (https://www.iana.org/assignments/http-parameters/http-parameters.xml#content-coding).
|
|
1204
|
+
# Concatenating all valid values for Accept-Encoding (without q=0.5) resulted in a value of 93:
|
|
1205
|
+
# aes128gcm, br, compress, deflate, exi, gzip, identity, pack200-gzip, x-compress, x-gzip, zstd
|
|
1206
|
+
#
|
|
1207
|
+
# This rule has a stricter sibling: 920521
|
|
1208
|
+
#
|
|
1209
|
+
SecRule REQUEST_HEADERS:Accept-Encoding "@gt 100" \
|
|
1210
|
+
"id:920520,\
|
|
1211
|
+
phase:1,\
|
|
1212
|
+
block,\
|
|
1213
|
+
t:none,t:lowercase,t:length,\
|
|
1214
|
+
msg:'Accept-Encoding header exceeded sensible length',\
|
|
1215
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1216
|
+
tag:'application-multi',\
|
|
1217
|
+
tag:'language-multi',\
|
|
1218
|
+
tag:'platform-multi',\
|
|
1219
|
+
tag:'attack-protocol',\
|
|
1220
|
+
tag:'paranoia-level/1',\
|
|
1221
|
+
tag:'OWASP_CRS',\
|
|
1222
|
+
tag:'capec/1000/255/153',\
|
|
1223
|
+
tag:'PCI/12.1',\
|
|
1224
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1225
|
+
severity:'CRITICAL',\
|
|
1226
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1227
|
+
|
|
1228
|
+
#
|
|
1229
|
+
# Restrict response charsets that we allow.
|
|
1230
|
+
# The following rules make sure that the response will be in an ASCII-compatible charset that
|
|
1231
|
+
# phase 4 rules can properly understand and block.
|
|
1232
|
+
#
|
|
1233
|
+
|
|
1234
|
+
#
|
|
1235
|
+
# Some servers rely on the request Accept header to determine what charset to respond with.
|
|
1236
|
+
# This rule restricts these to familiar charsets.
|
|
1237
|
+
#
|
|
1238
|
+
# Regular expression generated from regex-assembly/920600.ra.
|
|
1239
|
+
# To update the regular expression run the following shell script
|
|
1240
|
+
# (consult https://coreruleset.org/docs/development/regex_assembly/ for details):
|
|
1241
|
+
# crs-toolchain regex update 920600
|
|
1242
|
+
#
|
|
1243
|
+
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]*[^!\(\),/:-\?\[-\]\{\}]+);?)*)*$" \
|
|
1244
|
+
"id:920600,\
|
|
1245
|
+
phase:1,\
|
|
1246
|
+
block,\
|
|
1247
|
+
t:none,t:lowercase,\
|
|
1248
|
+
msg:'Illegal Accept header: charset parameter',\
|
|
1249
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1250
|
+
tag:'application-multi',\
|
|
1251
|
+
tag:'language-multi',\
|
|
1252
|
+
tag:'platform-multi',\
|
|
1253
|
+
tag:'attack-protocol',\
|
|
1254
|
+
tag:'paranoia-level/1',\
|
|
1255
|
+
tag:'OWASP_CRS',\
|
|
1256
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1257
|
+
severity:'CRITICAL',\
|
|
1258
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1259
|
+
|
|
1260
|
+
#
|
|
1261
|
+
# Unicode character bypass check for non JSON requests
|
|
1262
|
+
# See reported bypass in issue:
|
|
1263
|
+
# https://github.com/coreruleset/coreruleset/issues/2512
|
|
1264
|
+
#
|
|
1265
|
+
SecRule REQBODY_PROCESSOR "!@streq JSON" \
|
|
1266
|
+
"id:920540,\
|
|
1267
|
+
phase:2,\
|
|
1268
|
+
block,\
|
|
1269
|
+
t:none,\
|
|
1270
|
+
msg:'Possible Unicode character bypass detected',\
|
|
1271
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
1272
|
+
tag:'application-multi',\
|
|
1273
|
+
tag:'language-multi',\
|
|
1274
|
+
tag:'platform-multi',\
|
|
1275
|
+
tag:'attack-protocol',\
|
|
1276
|
+
tag:'paranoia-level/1',\
|
|
1277
|
+
tag:'OWASP_CRS',\
|
|
1278
|
+
tag:'capec/1000/255/153/267/72',\
|
|
1279
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1280
|
+
severity:'CRITICAL',\
|
|
1281
|
+
chain"
|
|
1282
|
+
SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@rx (?i)\x5cu[0-9a-f]{4}" \
|
|
1283
|
+
"setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1284
|
+
|
|
1285
|
+
#
|
|
1286
|
+
# Disallow any raw URL fragments. The '#' character should be omitted or URL-encoded.
|
|
1287
|
+
# CRS rules generally do not check REQUEST_URI_RAW, but some servers accept the fragment as part of the URL path/query.
|
|
1288
|
+
# This creates false negative evasions.
|
|
1289
|
+
#
|
|
1290
|
+
SecRule REQUEST_URI_RAW "@contains #" \
|
|
1291
|
+
"id:920610,\
|
|
1292
|
+
phase:1,\
|
|
1293
|
+
block,\
|
|
1294
|
+
t:none,\
|
|
1295
|
+
msg:'Raw (unencoded) fragment in request URI',\
|
|
1296
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1297
|
+
tag:'application-multi',\
|
|
1298
|
+
tag:'language-multi',\
|
|
1299
|
+
tag:'platform-multi',\
|
|
1300
|
+
tag:'attack-protocol',\
|
|
1301
|
+
tag:'paranoia-level/1',\
|
|
1302
|
+
tag:'OWASP_CRS',\
|
|
1303
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1304
|
+
severity:'CRITICAL',\
|
|
1305
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1306
|
+
|
|
1307
|
+
#
|
|
1308
|
+
# The following rule (920620) checks for the presence of 2 or more request Content-Type headers.
|
|
1309
|
+
# Content-Type confusion poses a significant security risk to a web application. It occurs when
|
|
1310
|
+
# the server and client have different interpretations of the Content-Type header, leading to
|
|
1311
|
+
# miscommunication, potential exploitation and WAF bypass.
|
|
1312
|
+
#
|
|
1313
|
+
# Using Apache, when multiple Content-Type request headers are received, the server combines them
|
|
1314
|
+
# into a single header with the values separated by commas. For example, if a client sends multiple
|
|
1315
|
+
# Content-Type headers with values "application/json" and "text/plain", Apache will combine them
|
|
1316
|
+
# into a single header like this: "Content-Type: application/json, text/plain".
|
|
1317
|
+
#
|
|
1318
|
+
# On the other hand, Nginx handles multiple Content-Type headers differently. It preserves each
|
|
1319
|
+
# header as a separate entity without combining them. So, if a client sends multiple Content-Type
|
|
1320
|
+
# headers, Nginx will keep them separate, maintaining the original values.
|
|
1321
|
+
#
|
|
1322
|
+
SecRule &REQUEST_HEADERS:Content-Type "@gt 1" \
|
|
1323
|
+
"id:920620,\
|
|
1324
|
+
phase:1,\
|
|
1325
|
+
block,\
|
|
1326
|
+
t:none,\
|
|
1327
|
+
msg:'Multiple Content-Type Request Headers',\
|
|
1328
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1329
|
+
tag:'application-multi',\
|
|
1330
|
+
tag:'language-multi',\
|
|
1331
|
+
tag:'platform-multi',\
|
|
1332
|
+
tag:'attack-protocol',\
|
|
1333
|
+
tag:'paranoia-level/1',\
|
|
1334
|
+
tag:'OWASP_CRS',\
|
|
1335
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1336
|
+
severity:'CRITICAL',\
|
|
1337
|
+
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:920013,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.9.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|
|
1341
|
+
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 2" "id:920014,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.9.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|
|
1342
|
+
#
|
|
1343
|
+
# -= Paranoia Level 2 =- (apply only when tx.detection_paranoia_level is sufficiently high: 2 or higher)
|
|
1344
|
+
#
|
|
1345
|
+
|
|
1346
|
+
#
|
|
1347
|
+
# -=[ Rule Logic ]=-
|
|
1348
|
+
#
|
|
1349
|
+
# Check the number of range fields in the Range request header.
|
|
1350
|
+
#
|
|
1351
|
+
# An excessive number of Range request headers can be used to DoS a server.
|
|
1352
|
+
# The original CVE proposed an arbitrary upper limit of 5 range fields.
|
|
1353
|
+
#
|
|
1354
|
+
# Several clients are known to request PDF fields with up to 62 range
|
|
1355
|
+
# fields. Therefore the standard rule does not cover PDF files. This is
|
|
1356
|
+
# performed in two separate (stricter) siblings of this rule.
|
|
1357
|
+
#
|
|
1358
|
+
# 920200: PL2: Limit of 5 range header fields for all filenames outside of PDFs
|
|
1359
|
+
# 920201: PL2: Limit of 62 range header fields for PDFs
|
|
1360
|
+
# 920202: PL4: Limit of 5 range header fields for PDFs
|
|
1361
|
+
#
|
|
1362
|
+
# -=[ References ]=-
|
|
1363
|
+
# https://httpd.apache.org/security/CVE-2011-3192.txt
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){6}" \
|
|
1367
|
+
"id:920200,\
|
|
1368
|
+
phase:1,\
|
|
1369
|
+
block,\
|
|
1370
|
+
t:none,\
|
|
1371
|
+
msg:'Range: Too many fields (6 or more)',\
|
|
1372
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1373
|
+
tag:'application-multi',\
|
|
1374
|
+
tag:'language-multi',\
|
|
1375
|
+
tag:'platform-multi',\
|
|
1376
|
+
tag:'attack-protocol',\
|
|
1377
|
+
tag:'paranoia-level/2',\
|
|
1378
|
+
tag:'OWASP_CRS',\
|
|
1379
|
+
tag:'capec/1000/210/272',\
|
|
1380
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1381
|
+
severity:'WARNING',\
|
|
1382
|
+
chain"
|
|
1383
|
+
SecRule REQUEST_BASENAME "!@endsWith .pdf" \
|
|
1384
|
+
"setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'"
|
|
1385
|
+
|
|
1386
|
+
#
|
|
1387
|
+
# This is a sibling of rule 920200
|
|
1388
|
+
#
|
|
1389
|
+
|
|
1390
|
+
SecRule REQUEST_BASENAME "@endsWith .pdf" \
|
|
1391
|
+
"id:920201,\
|
|
1392
|
+
phase:1,\
|
|
1393
|
+
block,\
|
|
1394
|
+
t:none,t:urlDecodeUni,\
|
|
1395
|
+
msg:'Range: Too many fields for pdf request (63 or more)',\
|
|
1396
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1397
|
+
tag:'application-multi',\
|
|
1398
|
+
tag:'language-multi',\
|
|
1399
|
+
tag:'platform-multi',\
|
|
1400
|
+
tag:'attack-protocol',\
|
|
1401
|
+
tag:'paranoia-level/2',\
|
|
1402
|
+
tag:'OWASP_CRS',\
|
|
1403
|
+
tag:'capec/1000/210/272',\
|
|
1404
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1405
|
+
severity:'WARNING',\
|
|
1406
|
+
chain"
|
|
1407
|
+
SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){63}" \
|
|
1408
|
+
"setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'"
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
SecRule ARGS "@rx %[0-9a-fA-F]{2}" \
|
|
1412
|
+
"id:920230,\
|
|
1413
|
+
phase:2,\
|
|
1414
|
+
block,\
|
|
1415
|
+
t:none,\
|
|
1416
|
+
msg:'Multiple URL Encoding Detected',\
|
|
1417
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1418
|
+
tag:'application-multi',\
|
|
1419
|
+
tag:'language-multi',\
|
|
1420
|
+
tag:'platform-multi',\
|
|
1421
|
+
tag:'attack-protocol',\
|
|
1422
|
+
tag:'paranoia-level/2',\
|
|
1423
|
+
tag:'OWASP_CRS',\
|
|
1424
|
+
tag:'capec/1000/255/153/267/120',\
|
|
1425
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1426
|
+
severity:'WARNING',\
|
|
1427
|
+
setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'"
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
#
|
|
1431
|
+
# PL2: This is a stricter sibling of 920270.
|
|
1432
|
+
#
|
|
1433
|
+
SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@validateByteRange 9,10,13,32-126,128-255" \
|
|
1434
|
+
"id:920271,\
|
|
1435
|
+
phase:2,\
|
|
1436
|
+
block,\
|
|
1437
|
+
t:none,t:urlDecodeUni,\
|
|
1438
|
+
msg:'Invalid character in request (non printable characters)',\
|
|
1439
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
1440
|
+
tag:'application-multi',\
|
|
1441
|
+
tag:'language-multi',\
|
|
1442
|
+
tag:'platform-multi',\
|
|
1443
|
+
tag:'attack-protocol',\
|
|
1444
|
+
tag:'paranoia-level/2',\
|
|
1445
|
+
tag:'OWASP_CRS',\
|
|
1446
|
+
tag:'capec/1000/210/272',\
|
|
1447
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1448
|
+
severity:'CRITICAL',\
|
|
1449
|
+
setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'"
|
|
1450
|
+
|
|
1451
|
+
|
|
1452
|
+
|
|
1453
|
+
#
|
|
1454
|
+
# Missing User-Agent Header
|
|
1455
|
+
#
|
|
1456
|
+
# -=[ Rule Logic ]=-
|
|
1457
|
+
# This rules will check to see if there is a User-Agent header or not.
|
|
1458
|
+
#
|
|
1459
|
+
|
|
1460
|
+
SecRule &REQUEST_HEADERS:User-Agent "@eq 0" \
|
|
1461
|
+
"id:920320,\
|
|
1462
|
+
phase:1,\
|
|
1463
|
+
pass,\
|
|
1464
|
+
t:none,\
|
|
1465
|
+
msg:'Missing User Agent Header',\
|
|
1466
|
+
tag:'application-multi',\
|
|
1467
|
+
tag:'language-multi',\
|
|
1468
|
+
tag:'platform-multi',\
|
|
1469
|
+
tag:'attack-protocol',\
|
|
1470
|
+
tag:'paranoia-level/2',\
|
|
1471
|
+
tag:'OWASP_CRS',\
|
|
1472
|
+
tag:'capec/1000/210/272',\
|
|
1473
|
+
tag:'PCI/6.5.10',\
|
|
1474
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1475
|
+
severity:'NOTICE',\
|
|
1476
|
+
setvar:'tx.inbound_anomaly_score_pl2=+%{tx.notice_anomaly_score}'"
|
|
1477
|
+
|
|
1478
|
+
|
|
1479
|
+
#
|
|
1480
|
+
# PL2: This is a stricter sibling of 920120.
|
|
1481
|
+
#
|
|
1482
|
+
SecRule FILES_NAMES|FILES "@rx ['\";=\x5c]" \
|
|
1483
|
+
"id:920121,\
|
|
1484
|
+
phase:2,\
|
|
1485
|
+
block,\
|
|
1486
|
+
t:none,t:urlDecodeUni,\
|
|
1487
|
+
msg:'Attempted multipart/form-data bypass',\
|
|
1488
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1489
|
+
tag:'application-multi',\
|
|
1490
|
+
tag:'language-multi',\
|
|
1491
|
+
tag:'platform-multi',\
|
|
1492
|
+
tag:'attack-protocol',\
|
|
1493
|
+
tag:'paranoia-level/2',\
|
|
1494
|
+
tag:'OWASP_CRS',\
|
|
1495
|
+
tag:'capec/1000/210/272',\
|
|
1496
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1497
|
+
severity:'CRITICAL',\
|
|
1498
|
+
setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'"
|
|
1499
|
+
|
|
1500
|
+
|
|
1501
|
+
#
|
|
1502
|
+
# PL2: Block on Missing Content-Type Header with Request Body
|
|
1503
|
+
# This is a stricter sibling of rule 920340.
|
|
1504
|
+
#
|
|
1505
|
+
# -=[ References ]=-
|
|
1506
|
+
# http://httpwg.org/specs/rfc7231.html#header.content-type
|
|
1507
|
+
|
|
1508
|
+
SecRule REQUEST_HEADERS:Content-Length "!@rx ^0$" \
|
|
1509
|
+
"id:920341,\
|
|
1510
|
+
phase:1,\
|
|
1511
|
+
block,\
|
|
1512
|
+
t:none,\
|
|
1513
|
+
msg:'Request Containing Content Requires Content-Type header',\
|
|
1514
|
+
tag:'application-multi',\
|
|
1515
|
+
tag:'language-multi',\
|
|
1516
|
+
tag:'platform-multi',\
|
|
1517
|
+
tag:'attack-protocol',\
|
|
1518
|
+
tag:'paranoia-level/2',\
|
|
1519
|
+
tag:'OWASP_CRS',\
|
|
1520
|
+
tag:'capec/1000/210/272',\
|
|
1521
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1522
|
+
severity:'CRITICAL',\
|
|
1523
|
+
chain"
|
|
1524
|
+
SecRule &REQUEST_HEADERS:Content-Type "@eq 0" \
|
|
1525
|
+
"t:none,\
|
|
1526
|
+
setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'"
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
#
|
|
1530
|
+
# PL2: This is a stricter sibling of 920450.
|
|
1531
|
+
#
|
|
1532
|
+
SecRule REQUEST_HEADERS_NAMES "@rx ^.*$" \
|
|
1533
|
+
"id:920451,\
|
|
1534
|
+
phase:1,\
|
|
1535
|
+
block,\
|
|
1536
|
+
capture,\
|
|
1537
|
+
t:none,t:lowercase,\
|
|
1538
|
+
msg:'HTTP header is restricted by policy (%{MATCHED_VAR})',\
|
|
1539
|
+
logdata:'Restricted header detected: %{MATCHED_VAR}',\
|
|
1540
|
+
tag:'application-multi',\
|
|
1541
|
+
tag:'language-multi',\
|
|
1542
|
+
tag:'platform-multi',\
|
|
1543
|
+
tag:'attack-protocol',\
|
|
1544
|
+
tag:'paranoia-level/2',\
|
|
1545
|
+
tag:'OWASP_CRS',\
|
|
1546
|
+
tag:'capec/1000/210/272',\
|
|
1547
|
+
tag:'PCI/12.1',\
|
|
1548
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1549
|
+
severity:'CRITICAL',\
|
|
1550
|
+
setvar:'tx.header_name_920451_%{tx.0}=/%{tx.0}/',\
|
|
1551
|
+
chain"
|
|
1552
|
+
SecRule TX:/^header_name_920451_/ "@within %{tx.restricted_headers_extended}" \
|
|
1553
|
+
"setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'"
|
|
1554
|
+
|
|
1555
|
+
|
|
1556
|
+
#
|
|
1557
|
+
# Check URL encodings
|
|
1558
|
+
#
|
|
1559
|
+
# See comment on rule 920220.
|
|
1560
|
+
#
|
|
1561
|
+
SecRule REQUEST_HEADERS:Content-Type "@rx ^(?i)application/x-www-form-urlencoded" \
|
|
1562
|
+
"id:920240,\
|
|
1563
|
+
phase:2,\
|
|
1564
|
+
block,\
|
|
1565
|
+
t:none,\
|
|
1566
|
+
msg:'URL Encoding Abuse Attack Attempt',\
|
|
1567
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1568
|
+
tag:'application-multi',\
|
|
1569
|
+
tag:'language-multi',\
|
|
1570
|
+
tag:'platform-multi',\
|
|
1571
|
+
tag:'attack-protocol',\
|
|
1572
|
+
tag:'paranoia-level/2',\
|
|
1573
|
+
tag:'OWASP_CRS',\
|
|
1574
|
+
tag:'capec/1000/255/153/267/72',\
|
|
1575
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1576
|
+
severity:'WARNING',\
|
|
1577
|
+
chain"
|
|
1578
|
+
SecRule REQUEST_BODY "@rx \x25" \
|
|
1579
|
+
"chain"
|
|
1580
|
+
SecRule REQUEST_BODY "@validateUrlEncoding" \
|
|
1581
|
+
"setvar:'tx.inbound_anomaly_score_pl2=+%{tx.warning_anomaly_score}'"
|
|
1582
|
+
|
|
1583
|
+
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:920015,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.9.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|
|
1584
|
+
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:920016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.9.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|
|
1585
|
+
#
|
|
1586
|
+
# -= Paranoia Level 3 =- (apply only when tx.detection_paranoia_level is sufficiently high: 3 or higher)
|
|
1587
|
+
#
|
|
1588
|
+
|
|
1589
|
+
#
|
|
1590
|
+
# PL 3: This is a stricter sibling of 920270. Ascii range: Printable characters in the low range
|
|
1591
|
+
#
|
|
1592
|
+
# This rule is also triggered by the following exploit(s):
|
|
1593
|
+
# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ]
|
|
1594
|
+
#
|
|
1595
|
+
SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteRange 32-36,38-126" \
|
|
1596
|
+
"id:920272,\
|
|
1597
|
+
phase:2,\
|
|
1598
|
+
block,\
|
|
1599
|
+
t:none,t:urlDecodeUni,\
|
|
1600
|
+
msg:'Invalid character in request (outside of printable chars below ascii 127)',\
|
|
1601
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
1602
|
+
tag:'application-multi',\
|
|
1603
|
+
tag:'language-multi',\
|
|
1604
|
+
tag:'platform-multi',\
|
|
1605
|
+
tag:'attack-protocol',\
|
|
1606
|
+
tag:'paranoia-level/3',\
|
|
1607
|
+
tag:'OWASP_CRS',\
|
|
1608
|
+
tag:'capec/1000/210/272',\
|
|
1609
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1610
|
+
severity:'CRITICAL',\
|
|
1611
|
+
setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'"
|
|
1612
|
+
|
|
1613
|
+
#
|
|
1614
|
+
# Missing Accept Header
|
|
1615
|
+
#
|
|
1616
|
+
# This rule has been moved to PL3
|
|
1617
|
+
#
|
|
1618
|
+
# -=[ Rule Logic ]=-
|
|
1619
|
+
# This rule generates a notice if the Accept header is missing.
|
|
1620
|
+
# RFC 7231 does not enforce the use of the Accept header.
|
|
1621
|
+
# It is just typical browser behavior to send and it can indicate a malicious client.
|
|
1622
|
+
#
|
|
1623
|
+
# Notice: The rule tries to avoid known false positives by ignoring
|
|
1624
|
+
# OPTIONS requests, CONNECT requests, and requests coming from known
|
|
1625
|
+
# offending User-Agents via two chained rules.
|
|
1626
|
+
# As ModSecurity only reports the match of the last matching rule,
|
|
1627
|
+
# the alert is misleading.
|
|
1628
|
+
#
|
|
1629
|
+
SecRule &REQUEST_HEADERS:Accept "@eq 0" \
|
|
1630
|
+
"id:920300,\
|
|
1631
|
+
phase:1,\
|
|
1632
|
+
pass,\
|
|
1633
|
+
t:none,\
|
|
1634
|
+
msg:'Request Missing an Accept Header',\
|
|
1635
|
+
tag:'application-multi',\
|
|
1636
|
+
tag:'language-multi',\
|
|
1637
|
+
tag:'platform-multi',\
|
|
1638
|
+
tag:'attack-protocol',\
|
|
1639
|
+
tag:'paranoia-level/3',\
|
|
1640
|
+
tag:'OWASP_CRS',\
|
|
1641
|
+
tag:'capec/1000/210/272',\
|
|
1642
|
+
tag:'PCI/6.5.10',\
|
|
1643
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1644
|
+
severity:'NOTICE',\
|
|
1645
|
+
chain"
|
|
1646
|
+
SecRule REQUEST_METHOD "!@rx ^(?:OPTIONS|CONNECT)$" \
|
|
1647
|
+
"chain"
|
|
1648
|
+
SecRule REQUEST_HEADERS:User-Agent "!@pm AppleWebKit Android" \
|
|
1649
|
+
"t:none,\
|
|
1650
|
+
setvar:'tx.inbound_anomaly_score_pl3=+%{tx.notice_anomaly_score}'"
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
#
|
|
1654
|
+
# PL3: The little known x-up-devcap-post-charset request header can be used to submit
|
|
1655
|
+
# a request with a different encoding as an alternative to the charset parameter in
|
|
1656
|
+
# the Content-Type header. This can be used to circumvent charset restrictions on
|
|
1657
|
+
# the Content-Type header in ASP.NET.
|
|
1658
|
+
# Note that this only works in combination with a User-Agent prefix.
|
|
1659
|
+
#
|
|
1660
|
+
# This rule is based on a blog post by Soroush Dalili at
|
|
1661
|
+
# https://soroush.me/blog/2019/05/x-up-devcap-post-charset-header-in-aspnet-to-bypass-wafs-again/
|
|
1662
|
+
#
|
|
1663
|
+
SecRule &REQUEST_HEADERS:x-up-devcap-post-charset "@ge 1" \
|
|
1664
|
+
"id:920490,\
|
|
1665
|
+
phase:1,\
|
|
1666
|
+
block,\
|
|
1667
|
+
t:none,\
|
|
1668
|
+
msg:'Request header x-up-devcap-post-charset detected in combination with prefix \'UP\' to User-Agent',\
|
|
1669
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
1670
|
+
tag:'language-aspnet',\
|
|
1671
|
+
tag:'platform-windows',\
|
|
1672
|
+
tag:'attack-protocol',\
|
|
1673
|
+
tag:'paranoia-level/3',\
|
|
1674
|
+
tag:'OWASP_CRS',\
|
|
1675
|
+
tag:'capec/1000/210/272',\
|
|
1676
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1677
|
+
severity:'CRITICAL',\
|
|
1678
|
+
chain"
|
|
1679
|
+
SecRule REQUEST_HEADERS:User-Agent "@rx ^(?i)up" \
|
|
1680
|
+
"t:none,\
|
|
1681
|
+
setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'"
|
|
1682
|
+
|
|
1683
|
+
|
|
1684
|
+
#
|
|
1685
|
+
# Cache-Control Request Header allow list
|
|
1686
|
+
#
|
|
1687
|
+
# -=[ Rule Logic ]=-
|
|
1688
|
+
# This rule aims to strictly allow list the Cache-Control request header
|
|
1689
|
+
# values and to blocks all violations. This should be useful to intercept
|
|
1690
|
+
# "bad bot" and tools that impersonate a real browser but with wrong request
|
|
1691
|
+
# header setup.
|
|
1692
|
+
#
|
|
1693
|
+
# The regular expression used on this rule tries to match multiple directives
|
|
1694
|
+
# in a single value, for example: "max-stale=1, max-age=2". This leads us to
|
|
1695
|
+
# use a regular expression that accepts a trailing comma to keep compatibility
|
|
1696
|
+
# with all regex engines and not PCRE only. For example: "max-stale=1, max-age=2, "
|
|
1697
|
+
#
|
|
1698
|
+
# Moreover, this regular expression allows duplicate directives sequence like:
|
|
1699
|
+
# "max-stale, max-stale=1, no-cache, no-cache".
|
|
1700
|
+
#
|
|
1701
|
+
# Standard Cache-Control directives that can be used by the client:
|
|
1702
|
+
# - max-age=<seconds>
|
|
1703
|
+
# - max-stale[=<seconds>]
|
|
1704
|
+
# - min-fresh=<seconds>
|
|
1705
|
+
# - no-cache
|
|
1706
|
+
# - no-store
|
|
1707
|
+
# - no-transform
|
|
1708
|
+
# - only-if-cached
|
|
1709
|
+
#
|
|
1710
|
+
# References:
|
|
1711
|
+
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
|
1712
|
+
# - https://regex101.com/r/CZ0Hxu/22
|
|
1713
|
+
#
|
|
1714
|
+
SecRule &REQUEST_HEADERS:Cache-Control "@gt 0" \
|
|
1715
|
+
"id:920510,\
|
|
1716
|
+
phase:1,\
|
|
1717
|
+
block,\
|
|
1718
|
+
t:none,\
|
|
1719
|
+
msg:'Invalid Cache-Control request header',\
|
|
1720
|
+
logdata:'Invalid Cache-Control value in request found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
|
|
1721
|
+
tag:'application-multi',\
|
|
1722
|
+
tag:'language-multi',\
|
|
1723
|
+
tag:'platform-multi',\
|
|
1724
|
+
tag:'attack-protocol',\
|
|
1725
|
+
tag:'header-allowlist',\
|
|
1726
|
+
tag:'paranoia-level/3',\
|
|
1727
|
+
tag:'OWASP_CRS',\
|
|
1728
|
+
tag:'capec/1000/210/272',\
|
|
1729
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1730
|
+
severity:'CRITICAL',\
|
|
1731
|
+
chain"
|
|
1732
|
+
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}$" \
|
|
1733
|
+
"setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'"
|
|
1734
|
+
|
|
1735
|
+
#
|
|
1736
|
+
# This rule checks for valid Accept-Encoding headers
|
|
1737
|
+
#
|
|
1738
|
+
# This rule has a less strict sibling: 920520
|
|
1739
|
+
#
|
|
1740
|
+
# Regular expression generated from regex-assembly/920521.ra.
|
|
1741
|
+
# To update the regular expression run the following shell script
|
|
1742
|
+
# (consult https://coreruleset.org/docs/development/regex_assembly/ for details):
|
|
1743
|
+
# crs-toolchain regex update 920521
|
|
1744
|
+
#
|
|
1745
|
+
SecRule REQUEST_HEADERS:Accept-Encoding "!@rx br|compress|deflate|(?:pack200-)?gzip|identity|\*|^$|aes128gcm|exi|zstd|x-(?:compress|gzip)" \
|
|
1746
|
+
"id:920521,\
|
|
1747
|
+
phase:1,\
|
|
1748
|
+
block,\
|
|
1749
|
+
t:none,t:lowercase,\
|
|
1750
|
+
msg:'Illegal Accept-Encoding header',\
|
|
1751
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1752
|
+
tag:'application-multi',\
|
|
1753
|
+
tag:'language-multi',\
|
|
1754
|
+
tag:'platform-multi',\
|
|
1755
|
+
tag:'attack-protocol',\
|
|
1756
|
+
tag:'paranoia-level/3',\
|
|
1757
|
+
tag:'OWASP_CRS',\
|
|
1758
|
+
tag:'capec/1000/255/153',\
|
|
1759
|
+
tag:'PCI/12.1',\
|
|
1760
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1761
|
+
severity:'CRITICAL',\
|
|
1762
|
+
setvar:'tx.inbound_anomaly_score_pl3=+%{tx.critical_anomaly_score}'"
|
|
1763
|
+
|
|
1764
|
+
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:920017,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.9.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|
|
1765
|
+
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 4" "id:920018,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.9.0',skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|
|
1766
|
+
#
|
|
1767
|
+
# -= Paranoia Level 4 =- (apply only when tx.detection_paranoia_level is sufficiently high: 4 or higher)
|
|
1768
|
+
#
|
|
1769
|
+
|
|
1770
|
+
#
|
|
1771
|
+
# This is a stricter sibling of rule 920200
|
|
1772
|
+
#
|
|
1773
|
+
|
|
1774
|
+
SecRule REQUEST_BASENAME "@endsWith .pdf" \
|
|
1775
|
+
"id:920202,\
|
|
1776
|
+
phase:1,\
|
|
1777
|
+
block,\
|
|
1778
|
+
t:none,t:urlDecodeUni,\
|
|
1779
|
+
msg:'Range: Too many fields for pdf request (6 or more)',\
|
|
1780
|
+
logdata:'%{MATCHED_VAR}',\
|
|
1781
|
+
tag:'application-multi',\
|
|
1782
|
+
tag:'language-multi',\
|
|
1783
|
+
tag:'platform-multi',\
|
|
1784
|
+
tag:'attack-protocol',\
|
|
1785
|
+
tag:'paranoia-level/4',\
|
|
1786
|
+
tag:'OWASP_CRS',\
|
|
1787
|
+
tag:'capec/1000/210/272',\
|
|
1788
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1789
|
+
severity:'WARNING',\
|
|
1790
|
+
chain"
|
|
1791
|
+
SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?-(?:\d+)?\s*,?\s*){6}" \
|
|
1792
|
+
"setvar:'tx.inbound_anomaly_score_pl4=+%{tx.warning_anomaly_score}'"
|
|
1793
|
+
|
|
1794
|
+
|
|
1795
|
+
#
|
|
1796
|
+
# This is a stricter sibling of 920270.
|
|
1797
|
+
#
|
|
1798
|
+
# This rule is also triggered by the following exploit(s):
|
|
1799
|
+
# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ]
|
|
1800
|
+
#
|
|
1801
|
+
SecRule ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteRange 38,44-46,48-58,61,65-90,95,97-122" \
|
|
1802
|
+
"id:920273,\
|
|
1803
|
+
phase:2,\
|
|
1804
|
+
block,\
|
|
1805
|
+
t:none,t:urlDecodeUni,\
|
|
1806
|
+
msg:'Invalid character in request (outside of very strict set)',\
|
|
1807
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
1808
|
+
tag:'application-multi',\
|
|
1809
|
+
tag:'language-multi',\
|
|
1810
|
+
tag:'platform-multi',\
|
|
1811
|
+
tag:'attack-protocol',\
|
|
1812
|
+
tag:'paranoia-level/4',\
|
|
1813
|
+
tag:'OWASP_CRS',\
|
|
1814
|
+
tag:'capec/1000/210/272',\
|
|
1815
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1816
|
+
severity:'CRITICAL',\
|
|
1817
|
+
setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'"
|
|
1818
|
+
|
|
1819
|
+
#
|
|
1820
|
+
# This is a stricter sibling of 920270.
|
|
1821
|
+
#
|
|
1822
|
+
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" \
|
|
1823
|
+
"id:920274,\
|
|
1824
|
+
phase:1,\
|
|
1825
|
+
block,\
|
|
1826
|
+
t:none,t:urlDecodeUni,\
|
|
1827
|
+
msg:'Invalid character in request headers (outside of very strict set)',\
|
|
1828
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
1829
|
+
tag:'application-multi',\
|
|
1830
|
+
tag:'language-multi',\
|
|
1831
|
+
tag:'platform-multi',\
|
|
1832
|
+
tag:'attack-protocol',\
|
|
1833
|
+
tag:'paranoia-level/4',\
|
|
1834
|
+
tag:'OWASP_CRS',\
|
|
1835
|
+
tag:'capec/1000/210/272',\
|
|
1836
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1837
|
+
severity:'CRITICAL',\
|
|
1838
|
+
setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'"
|
|
1839
|
+
|
|
1840
|
+
#
|
|
1841
|
+
# This is a stricter sibling of 920270.
|
|
1842
|
+
# The headers of this rule are Structured Header booleans, for which only `?0`,
|
|
1843
|
+
# and `?1` are inconspicuous.
|
|
1844
|
+
# Structured Header boolean: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-header-structure-19#section-3.3.6
|
|
1845
|
+
# Sec-Fetch-User: https://www.w3.org/TR/fetch-metadata/#http-headerdef-sec-fetch-user
|
|
1846
|
+
# Sec-CH-UA-Mobile: https://wicg.github.io/ua-client-hints/#sec-ch-ua-mobile
|
|
1847
|
+
#
|
|
1848
|
+
SecRule REQUEST_HEADERS:Sec-Fetch-User|REQUEST_HEADERS:Sec-CH-UA-Mobile "!@rx ^(?:\?[01])?$" \
|
|
1849
|
+
"id:920275,\
|
|
1850
|
+
phase:1,\
|
|
1851
|
+
block,\
|
|
1852
|
+
t:none,t:urlDecodeUni,\
|
|
1853
|
+
msg:'Invalid character in request headers (outside of very strict set)',\
|
|
1854
|
+
logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\
|
|
1855
|
+
tag:'application-multi',\
|
|
1856
|
+
tag:'language-multi',\
|
|
1857
|
+
tag:'platform-multi',\
|
|
1858
|
+
tag:'attack-protocol',\
|
|
1859
|
+
tag:'paranoia-level/4',\
|
|
1860
|
+
tag:'OWASP_CRS',\
|
|
1861
|
+
tag:'capec/1000/210/272',\
|
|
1862
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1863
|
+
severity:'CRITICAL',\
|
|
1864
|
+
setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'"
|
|
1865
|
+
|
|
1866
|
+
# -=[ Abnormal Character Escapes ]=-
|
|
1867
|
+
#
|
|
1868
|
+
# [ Rule Logic ]
|
|
1869
|
+
# Consider the following payload: arg=cat+/e\tc/pa\ssw\d
|
|
1870
|
+
# Here, \s and \d were only used to obfuscate the string passwd and a lot of
|
|
1871
|
+
# parsers will silently ignore the non-necessary escapes. The case with \t is
|
|
1872
|
+
# a bit different though, as \t is a natural escape for the TAB character,
|
|
1873
|
+
# so we will avoid this (and \n, \r, etc.).
|
|
1874
|
+
#
|
|
1875
|
+
# This rule aims to detect non-necessary, abnormal escapes. You could say it is
|
|
1876
|
+
# a nice way to forbid the backslash character where it is not needed.
|
|
1877
|
+
#
|
|
1878
|
+
# This is a new rule at paranoia level 4. We expect quite a few false positives
|
|
1879
|
+
# for this rule and we will later evaluate if the rule makes any sense at all.
|
|
1880
|
+
# The rule is redundant with 920273 and 920274 in PL4. But if the rule proofs
|
|
1881
|
+
# to be useful and false positives remain at a reasonable level, then it might
|
|
1882
|
+
# be shifted to PL3 in a future release, where it would be the only rule
|
|
1883
|
+
# covering the backslash escape.
|
|
1884
|
+
#
|
|
1885
|
+
# We forbid backslashes followed by a list of basic ascii characters - unless
|
|
1886
|
+
# the backslash is preceded by another backslash.
|
|
1887
|
+
#
|
|
1888
|
+
# This rule is also triggered by the following exploit(s):
|
|
1889
|
+
# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ]
|
|
1890
|
+
#
|
|
1891
|
+
SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@rx (?:^|[^\x5c])\x5c[cdeghijklmpqwxyz123456789]" \
|
|
1892
|
+
"id:920460,\
|
|
1893
|
+
phase:2,\
|
|
1894
|
+
block,\
|
|
1895
|
+
capture,\
|
|
1896
|
+
t:none,t:htmlEntityDecode,t:lowercase,\
|
|
1897
|
+
msg:'Abnormal character escapes in request',\
|
|
1898
|
+
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
|
|
1899
|
+
tag:'application-multi',\
|
|
1900
|
+
tag:'language-multi',\
|
|
1901
|
+
tag:'platform-multi',\
|
|
1902
|
+
tag:'attack-protocol',\
|
|
1903
|
+
tag:'paranoia-level/4',\
|
|
1904
|
+
tag:'OWASP_CRS',\
|
|
1905
|
+
tag:'capec/1000/153/267',\
|
|
1906
|
+
ver:'OWASP_CRS/4.9.0',\
|
|
1907
|
+
severity:'CRITICAL',\
|
|
1908
|
+
setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\
|
|
1909
|
+
setvar:'tx.inbound_anomaly_score_pl4=+%{tx.critical_anomaly_score}'"
|
|
1910
|
+
|
|
1911
|
+
|
|
1912
|
+
#
|
|
1913
|
+
# -= Paranoia Levels Finished =-
|
|
1914
|
+
#
|
|
1915
|
+
SecMarker "END-REQUEST-920-PROTOCOL-ENFORCEMENT"
|