Re: [mod-security-users] My variable seems to never expire...
Brought to you by:
victorhora,
zimmerletw
|
From: Mikaël P. <mik...@bo...> - 2020-09-18 13:36:01
|
@christian yes, the initial workaround about `expirevar` is from @theseion ( https://github.com/SpiderLabs/ModSecurity/issues/1803#issuecomment-474884652). In my conf, I've added a rule (see rule: 5, the second part) to init my session.api_req_counter__expire_timestamp variable once. If my recipe can help somebody, here the modsec and nginx (to add X-Limit-* headers) configuration: ModSec conf : # # Rate-limiting rules identified by PHPSESSIONID on /api requests # # Variables: # SESSION:API_REQ_COUNTER counter of API requests # TX:API_REQ_COUNTER_MAX max number of API requests which can pass in %{tx.api_req_counter_timeout} seconds # TX:API_REQ_COUNTER_TIMEOUT period in seconds a blocked PHP session id will be blocked on API requests # # As a precondition for these rules, please set the following 2 variables: # - TX:API_REQ_COUNTER_MAX # - TX:API_REQ_COUNTER_TIMEOUT # # Define TX:API_REQ_COUNTER_MAX and TX_REQ_COUNTER_TIMEOUT SecAction \ "id:1,\ phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.api_req_counter_timeout=60,\ setvar:tx.api_req_counter_max=100" # # Define SESSION # SecRule REQUEST_COOKIES:PHPSESSID "!^$" \ "id:2,\ phase:1,\ pass,\ nolog,\ setsid:%{REQUEST_COOKIES.PHPSESSID}" ################################################### # TEMPORARY WORKAROUND FOR not working `expirevar` ################################################### # Expire variables SecRule &SESSION:API_REQ_COUNTER__EXPIRE_TIMESTAMP "@eq 1" \ "id:3,\ phase:1,\ pass,\ t:none,\ nolog,\ chain" SecRule SESSION:API_REQ_COUNTER__EXPIRE_TIMESTAMP "@lt %{TIME_EPOCH}" \ "setvar:'!session.api_req_counter',\ setvar:'!session.api_req_counter__expire_timestamp'" ################################################### ################################################### # # If it's an API request: # 1. Identify API requests # 2. update counter # 3. if session:api_req_counter__expire_timestamp is not define, define it # SecRule REQUEST_URI "@beginsWith /api/" \ "id:4,\ phase:1,\ pass,\ nolog,\ setvar:'tx.is_api_req=1',\ setvar:'session.api_req_counter=+1',\ expirevar:'session.api_req_counter=%{tx.api_req_counter_timeout}',\ chain" SecRule &SESSION:API_REQ_COUNTER__EXPIRE_TIMESTAMP "@eq 0" \ "setvar:'session.api_req_counter__expire_timestamp=%{TIME_EPOCH}',\ setvar:'session.api_req_counter__expire_timestamp=+%{tx.api_req_counter_timeout}'" # # If max counter is reached AND it's an API request, deny it # SecRule SESSION:API_REQ_COUNTER "@gt %{tx.api_req_counter_max}" \ "id:5,\ deny,\ status:429,\ log,\ msg:'RATELIMITED',\ chain" SecRule TX:IS_API_REQ "@eq 1" SecRule TX:IS_API_REQ "@eq 1" \ "id:6,\ phase:1,\ pass,\ nolog,\ setenv:'ratelimit_limit=%{tx.api_req_counter_max}',\ setenv:'ratelimit_counter=%{session.api_req_counter}',\ setenv:'ratelimit_reset=%{session.api_req_counter__expire_timestamp}'" Nginx Conf (i use the module lua https://openresty.org/en/lua-nginx-module.html) : ... location /api/ { set_by_lua $ratelimit_limit 'return os.getenv("ratelimit_limit")'; set_by_lua $ratelimit_remaining 'return os.getenv("ratelimit_limit") - os.getenv("ratelimit_counter")'; set_by_lua $ratelimit_reset 'return os.getenv("ratelimit_reset")'; add_header X-RateLimit-Limit "$ratelimit_limit"; add_header X-RateLimit-Remaining "$ratelimit_remaining"; add_header X-RateLimit-Reset "$ratelimit_reset"; ... } ... |