modSecurity规则学习(八)——防止CC攻击

时间:2021-09-05 17:00:01

modSecurity日志收集:在phase 5阶段处理。

由于CC攻击主要考虑对动态请求的防护,所以要排除静态资源的请求,或者自定义动态请求的后缀或者关键字做接口针对性的防护。

定义需要排除的请求url后缀名称

SecAction \
 "id:900260,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:'tx.static_extensions=/.mvc/ /.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/'"

 

然后是怎么判断是CC攻击?根据访问频率来定义,某个ip在dos_burst_time_slice的时间(单位秒)内dos_counter_threshold次请求算一次攻击嫌疑,如果超过2次,我们就认定是CC攻击的IP,对该IP封禁,解封时间定义为dos_block_timeout。

例如,定义60s内100次动态请求算一次攻击嫌疑,封禁时间为600s。

SecAction \
 "id:900700,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:'tx.dos_burst_time_slice=60',\
  setvar:'tx.dos_counter_threshold=100',\
  setvar:'tx.dos_block_timeout=600'"

 接下来就是关键的拦截策略了。

总体思路如下:

1、如果一个请求访问的是非静态(TX:STATIC_EXTENSIONS)资源,那我们就定义一个变量(IP:DOS_COUNTER)+1,IP为客户端IP

 

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"

  

2、如果IP:DOS_COUNTER大于TX:DOS_COUNTER_THRESHOLD阈值,就创建一个CC嫌疑次数IP:DOS_BURST_COUNTER=1,如果存在则该值设置为2。且IP:DOS_COUNTER置0,CC嫌疑次数IP:DOS_BURST_COUNTER有一个超时时间TX:DOS_BURST_TIME_SLICE。

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" 

3、如果CC嫌疑次数IP:DOS_BURST_COUNTER大于2就认定为CC攻击,定义一个值IP:DOS_BLOCK,该变量超时时间为TX:DOS_BLOCK_TIMEOUT。

定义大于等于两次封IP的规则:如果IP:DOS_BURST_COUNTER大于等于2,设置变量ip.dos_block=1,且设置该变量的超时时间为TX:DOS_BLOCK_TIMEOUT。在phase5发生。

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}"

4、在phase1,如果IP:DOS_BLOCK为1,则阻断该请求,且IP:DOS_BLOCK_COUNTER+=1。如果一个IP第一次被阻断,记录阻断日志并设置一个IP:DOS_BLOCK_FLAG 标志,该标志的超时时间为60s,设置该标志的后面不记录日志,避免刷屏。也就是说如果一直攻击,最多60s记录一次日志。为了显示IP:DOS_BLOCK_COUNTER的同时重置该值,将IP:DOS_BLOCK_COUNTER复制到TX:DOS_BLOCK_COUNTER这个变量。

#
# 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"

  

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"