File: REQUEST-912-DOS-PROTECTION.conf

package info (click to toggle)
modsecurity-crs 3.0.2-1~bpo9+1
  • links: PTS
  • area: main
  • in suites: stretch-backports
  • size: 1,064 kB
  • sloc: ansic: 727; perl: 428; python: 218; ruby: 69; makefile: 15
file content (296 lines) | stat: -rw-r--r-- 9,271 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# ------------------------------------------------------------------------
# OWASP ModSecurity Core Rule Set ver.3.0.2
# Copyright (c) 2006-2016 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.
# ------------------------------------------------------------------------

#
# Anti-Automation rules to detect Denial of Service attacks.
#
# Description of mechanics:
# When a request hits a non-static resource (TX:STATIC_EXTENSIONS), then a counter for the IP
# address is being raised (IP:DOS_COUNTER). If the counter (IP:DOS_COUNTER) hits a limit
# (TX:DOS_COUNTER_THRESHOLD), then a burst is identified (IP:DOS_BURST_COUNTER) and the
# counter (IP:DOS_COUNTER) is reset. The burst counter expires within a timeout period
# (TX:DOS_BURST_TIME_SLICE).
# If the burst counter (IP:DOS_BURST_COUNTER) is greater equal 2, then the blocking flag
# is being set (IP:DOS_BLOCK). The blocking flag (IP:DOS_BLOCK) expires within a timeout
# period (TX:DOS_BLOCK_TIMEOUT). All this counting happens in phase 5.
# There is a stricter sibling to this rule (912170) in paranoia level 2, where the
# burst counter check (IP:DOS_BURST_COUNTER) hits at greater equal 1.
#
# The blocking is done in phase 1: When the blocking flag is encountered (IP:DOS_BLOCK),
# then the request is dropped without sending a response. If this happens, then a
# counter is # raised (IP:DOS_BLOCK_COUNTER).
# When an IP address is blocked for the first time, then the blocking is reported in a
# message and a flag (IP:DOS_BLOCK_FLAG) is set. This flag expires in 60 seconds.
# When an IP address is blocked and the flag (IP:DOS_BLOCK_FLAG) is set, then the
# blocking is not being reported (to prevent a flood of alerts). When the flag
# (IP:DOS_BLOCK_FLAG) has expired and a new request is being blocked, then the
# counter (IP:DOS_BLOCK_COUNTER) is being reset to 0 and the block is being treated
# as the first block (-> alert).
# In order to be able to display the counter (IP:DOS_BLOCK_COUNTER) and resetting
# it at the same time, we copy the counter (IP:DOS_BLOCK_COUNTER) into a different
# variable (TX:DOS_BLOCK_COUNTER), which is then displayed in turn.
#
# Variables:
# IP:DOS_BLOCK              Flag if an IP address should be blocked
# IP:DOS_BLOCK_COUNTER      Counter of blocked requests
# IP:DOS_BLOCK_FLAG         Flag keeping track of alert. Flag expires after 60 seconds.
# IP:DOS_BURST_COUNTER      Burst counter
# IP:DOS_COUNTER            Request counter (static resources are ignored)
# TX:DOS_BLOCK_COUNTER      Copy of IP:DOS_BLOCK_COUNTER (needed for display reasons)
# TX:DOS_BLOCK_TIMEOUT      Period in seconds a blocked IP will be blocked
# TX:DOS_COUNTER_THRESHOLD  Limit of requests, where a burst is identified
# TX:DOS_BURST_TIME_SLICE   Period in seconds when we will forget a burst
# TX:STATIC_EXTENSIONS      Paths which can be ignored with regards to DoS
#
# As a precondition for these rules, please set the following three variables:
#  - TX:DOS_BLOCK_TIMEOUT
#  - TX:DOS_COUNTER_THRESHOLD
#  - TX:DOS_BURST_TIME_SLICE
#
# And make sure that TX:STATIC_EXTENSIONS is also set.
#

#
# -= Paranoia Level 0 (empty) =- (apply unconditionally)
#

#
# Skip if variables defining DoS protection are not set
#
SecRule &TX:dos_burst_time_slice "@eq 0" \
	"id:912100,\
	phase:1,\
	t:none,\
	nolog,\
	pass,\
	chain,\
	skipAfter:END_DOS_PROTECTION_CHECKS"
	SecRule &TX:dos_counter_threshold "@eq 0" "chain"
	SecRule &TX:dos_block_timeout "@eq 0"

SecRule &TX:dos_burst_time_slice "@eq 0" \
	"id:912110,\
	phase:5,\
	t:none,\
	nolog,\
	pass,\
	chain,\
	skipAfter:END_DOS_PROTECTION_CHECKS"
	SecRule &TX:dos_counter_threshold "@eq 0" "chain"
	SecRule &TX:dos_block_timeout "@eq 0"


SecRule TX:PARANOIA_LEVEL "@lt 1" "phase:1,id:912011,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
SecRule TX:PARANOIA_LEVEL "@lt 1" "phase:2,id:912012,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
#
# -= Paranoia Level 1 (default) =- (apply only when tx.paranoia_level is sufficiently high: 1 or higher)
#

#
# -=[ Anti-Automation / DoS Protection : Block ]=-
#

#
# Block and track # of requests and log
#
SecRule IP:DOS_BLOCK "@eq 1" \
	"chain,\
	phase:1,\
	id:912120,\
	drop,\
	tag:'application-multi',\
	tag:'language-multi',\
	tag:'platform-multi',\
	tag:'attack-dos',\
	msg:'Denial of Service (DoS) attack identified from %{tx.real_ip} (%{tx.dos_block_counter} hits since last alert)'"
	SecRule &IP:DOS_BLOCK_FLAG "@eq 0" \
		"setvar:ip.dos_block_counter=+1,\
		setvar:ip.dos_block_flag=1,\
		expirevar:ip.dos_block_flag=60,\
		setvar:tx.dos_block_counter=%{ip.dos_block_counter},\
		setvar:ip.dos_block_counter=0"


#
# Block and track # of requests but don't log
#
SecRule IP:DOS_BLOCK "@eq 1" \
	"phase:1,\
	id:912130,\
	t:none,\
	drop,\
	nolog,\
	tag:'application-multi',\
	tag:'language-multi',\
	tag:'platform-multi',\
	tag:'attack-dos',\
	setvar:ip.dos_block_counter=+1"


#
# -=[ Anti-Automation / DoS Protection: Count requests ]=-
#

#
# Skip if we have blocked the request
#
SecRule IP:DOS_BLOCK "@eq 1" \
	"phase:5,\
	id:912140,\
	t:none,\
	nolog,\
	tag:'application-multi',\
	tag:'language-multi',\
	tag:'platform-multi',\
	tag:'attack-dos',\
	pass,\
	skipAfter:END_DOS_PROTECTION_CHECKS"


#
# DOS Counter: Count the number of requests to non-static resources
#
SecRule REQUEST_BASENAME ".*?(\.[a-z0-9]{1,10})?$" \
	"phase:5,\
	id:912150,\
	t:none,\
	t:lowercase,\
	nolog,\
	pass,\
	tag:'application-multi',\
	tag:'language-multi',\
	tag:'platform-multi',\
	tag:'attack-dos',\
	capture,\
   	setvar:tx.extension=/%{TX.1}/,\
	chain"
	SecRule TX:EXTENSION "!@within %{tx.static_extensions}" \
		"setvar:ip.dos_counter=+1"


#
# Check DOS Counter
# If the request count is greater than or equal to user settings,
# we raise the burst counter. This happens via two separate rules:
# - 912160: raise from 0 to 1
# - 912161: raise from 1 to 2
#
# This approach with two rules avoids raising the burst counter
# from 0 to 2 via two concurrent requests. We do not raise the
# burst counter beyond 2.
#
#
SecRule IP:DOS_COUNTER "@ge %{tx.dos_counter_threshold}" \
	"phase:5,\
	id:912160,\
	t:none,\
	nolog,\
	pass,\
	tag:'application-multi',\
	tag:'language-multi',\
	tag:'platform-multi',\
	tag:'attack-dos',\
	chain"
	SecRule &IP:DOS_BURST_COUNTER "@eq 0" \
		"setvar:ip.dos_burst_counter=1,\
		expirevar:ip.dos_burst_counter=%{tx.dos_burst_time_slice},\
		setvar:!ip.dos_counter"


SecRule IP:DOS_COUNTER "@ge %{tx.dos_counter_threshold}" \
	"phase:5,\
	id:912161,\
	t:none,\
	nolog,\
	pass,\
	tag:'application-multi',\
	tag:'language-multi',\
	tag:'platform-multi',\
	tag:'attack-dos',\
	chain"
	SecRule &IP:DOS_BURST_COUNTER "@ge 1" \
		"setvar:ip.dos_burst_counter=2,\
		expirevar:ip.dos_burst_counter=%{tx.dos_burst_time_slice},\
		setvar:!ip.dos_counter"


#
# Check DOS Burst Counter and set Block
# Check the burst counter - if greater than or equal to 2, then we set the IP
# block variable for a given expiry and issue an alert.
#
SecRule IP:DOS_BURST_COUNTER "@ge 2" \
	"phase:5,\
	id:912170,\
	t:none,\
	log,\
	pass,\
	tag:'application-multi',\
	tag:'language-multi',\
	tag:'platform-multi',\
	tag:'attack-dos',\
	msg:'Potential Denial of Service (DoS) Attack from %{tx.real_ip} - # of Request Bursts: %{ip.dos_burst_counter}',\
	setvar:ip.dos_block=1,\
	expirevar:ip.dos_block=%{tx.dos_block_timeout}"



SecRule TX:PARANOIA_LEVEL "@lt 2" "phase:1,id:912013,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
SecRule TX:PARANOIA_LEVEL "@lt 2" "phase:2,id:912014,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
SecRule TX:PARANOIA_LEVEL "@lt 2" "phase:5,id:912019,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
#
# -= Paranoia Level 2 =- (apply only when tx.paranoia_level is sufficiently high: 2 or higher)
#

#
# Check DOS Burst Counter and set Block
# Check the burst counter - if greater than or equal to 1, then we set the IP
# block variable for a given expiry and issue an alert.
#
# This is a stricter sibling of rule 912170.
#
SecRule IP:DOS_BURST_COUNTER "@ge 1" \
	"phase:5,\
	id:912171,\
	t:none,\
	log,\
	pass,\
	tag:'application-multi',\
	tag:'language-multi',\
	tag:'platform-multi',\
	tag:'attack-dos',\
	tag:'paranoia-level/2',\
	msg:'Potential Denial of Service (DoS) Attack from %{tx.real_ip} - # of Request Bursts: %{ip.dos_burst_counter}',\
	setvar:ip.dos_block=1,\
	expirevar:ip.dos_block=%{tx.dos_block_timeout}"



SecRule TX:PARANOIA_LEVEL "@lt 3" "phase:1,id:912015,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
SecRule TX:PARANOIA_LEVEL "@lt 3" "phase:2,id:912016,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
#
# -= Paranoia Level 3 =- (apply only when tx.paranoia_level is sufficiently high: 3 or higher)
#



SecRule TX:PARANOIA_LEVEL "@lt 4" "phase:1,id:912017,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
SecRule TX:PARANOIA_LEVEL "@lt 4" "phase:2,id:912018,nolog,pass,skipAfter:END-REQUEST-912-DOS-PROTECTION"
#
# -= Paranoia Level 4 =- (apply only when tx.paranoia_level is sufficiently high: 4 or higher)
#



#
# -= Paranoia Levels Finished =-
#
SecMarker "END-REQUEST-912-DOS-PROTECTION"

SecMarker END_DOS_PROTECTION_CHECKS