Description
Describe the bug
I created a configuration, based on this article, to rate limit a specific url. I'm using apache + modsecurity. This configuration works fine, but I noticed that if I have any SecRuleRemoveById directive in any of my *.conf files, the rate limit doesn't work anymore.
Logs and dumps and To Reproduce
It's works:
SecRuleEngine On
SecStatusEngine On
<Location /influxdb>
SecAction initcol:ip=%{X-Forwarded-For},pass,nolog,id:11
SecAction "phase:5,deprecatevar:ip.somepathcounter=1/1,pass,nolog,id:12"
SecRule IP:SOMEPATHCOUNTER "@gt 60" "phase:2,pause:300,deny,status:429,setenv:RATELIMITED,skip:1,nolog,id:13"
SecAction "phase:2,pass,setvar:ip.somepathcounter=+1,expirevar:ip.somepathcounter=600,nolog,id:14"
Header always set Retry-After "10" env=RATELIMITED
ProxyPass "http://influxdb:8086"
ProxyPassReverse "http://influxdb:8086"
</Location>
ErrorDocument 429 "Rate Limit Exceeded"
The output of my test script is:
58 - Status code: 200 - {"version":"1.8.0"}
59 - Status code: 200 - {"version":"1.8.0"}
60 - Status code: 200 - {"version":"1.8.0"}
61 - Status code: 200 - {"version":"1.8.0"}
62 - Status code: 429 - Rate Limit Exceeded
63 - Status code: 200 - {"version":"1.8.0"}
64 - Status code: 429 - Rate Limit Exceeded
65 - Status code: 429 - Rate Limit Exceeded
66 - Status code: 429 - Rate Limit Exceeded
It doesn't work:
SecRuleEngine On
SecStatusEngine On
<Location /influxdb>
SecAction initcol:ip=%{X-Forwarded-For},pass,nolog,id:11
SecAction "phase:5,deprecatevar:ip.somepathcounter=1/1,pass,nolog,id:12"
SecRule IP:SOMEPATHCOUNTER "@gt 60" "phase:2,pause:300,deny,status:429,setenv:RATELIMITED,skip:1,nolog,id:13"
SecAction "phase:2,pass,setvar:ip.somepathcounter=+1,expirevar:ip.somepathcounter=600,nolog,id:14"
Header always set Retry-After "10" env=RATELIMITED
ProxyPass "http://influxdb:8086"
ProxyPassReverse "http://influxdb:8086"
</Location>
ErrorDocument 429 "Rate Limit Exceeded"
Include /etc/apache2/conf-available/modsecurity_rules.conf
Content of modsecurity_rules.conf:
SecRuleRemoveById 932130
SecRuleRemoveById 932100
SecRuleRemoveById 932105
SecRuleRemoveById 932140
SecRuleRemoveById 942220
SecRuleRemoveById 920180
SecRuleRemoveById 980130
SecRuleRemoveById 920420
If I comment ALL of these SecRuleRemoveById, the rate limit works.
If I uncomment ANY of these SecRuleRemoveById, the rate limit doesn't work. In this scenario, the output of my test script is:
58 - Status code: 200 - {"version":"1.8.0"}
59 - Status code: 200 - {"version":"1.8.0"}
60 - Status code: 200 - {"version":"1.8.0"}
61 - Status code: 200 - {"version":"1.8.0"}
62 - Status code: 200 - {"version":"1.8.0"}
63 - Status code: 200 - {"version":"1.8.0"}
64 - Status code: 200 - {"version":"1.8.0"}
65 - Status code: 200 - {"version":"1.8.0"}
66 - Status code: 200 - {"version":"1.8.0"}
Expected behavior
- SecRuleRemoveById directive shouldn't affect the rate limit script.
Server (please complete the following information):
- ModSecurity version (and connector): [v2.9.3 with modSecurity-CRS: 3.2.0-1]
- WebServer: [apache v2.4.43]
- OS (and distro): [Linux Ubuntu Focal (20.04), running in Docker]
Rule Set (please complete the following information):
- modSecurity-CRS: 3.2.0-1
Additional context
I develop a script in python to test the rate limit:
import requests
URL = "https://localhost/influxdb/ping"
PARAMS = {'verbose':'true'}
for x in range(10000):
r = requests.get(url = URL, params = PARAMS, verify=False)
print(str(x) + ' - Status code: ' + str(r.status_code) + ' - ' + r.text)
print('Finish')