Re: My variable seems to never expire...

Mikaël Pirio <[email protected]>
Newsgroups gmane.comp.apache.mod-security.user
Message-ID <CAG1WCxiYGx+kTMBbJnHWgkf=bf8dtZEevz+LcSmUwq8fUeQ=-w@mail.gmail.com>
@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";
      ...
  }
...

_______________________________________________
mod-security-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mod-security-users
Commercial ModSecurity Rules and Support from Trustwave's SpiderLabs:
http://www.modsecurity.org/projects/commercial/rules/
http://www.modsecurity.org/projects/commercial/support/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.