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
|