coreruleset / dos-protection-plugin-modsecurity

Anti-automation rules plugin to detect denial of service attacks
Apache License 2.0
4 stars 1 forks source link

The DOS block is triggered at significantly lower levels than the configured values #12

Open iliuta opened 1 month ago

iliuta commented 1 month ago

Hi,

I successfully used the 912 DOS protection rules with CRS 3.3.5. It was not without some pain but anyway, I managed to get it working. My 3.3.5 working configuration was this one:

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

Now I migrated to CRS 4.4.0, because of my Nginx Ingress Controller 4.11.0 upgrade.

The DOS rules were migrated to plugins, that's OK.

But I had to add these lines to my global configuration:

                SecAction "id:900130,\
                    phase:1,\
                    pass,\
                    t:none,\
                    nolog,\
                    tag:'OWASP_CRS',\
                    ver:'OWASP_CRS/4.4.0',\
                    setvar:tx.enable_default_collections=1"

On my understanding, the default collections are no longer activated in the newest version of crs-setup.conf and the DOS plugin needs them.

Also I added SecCollectionTimeout 600, also no longer present in crs-setup.conf.

My actual DOS plugin setup is the following:

             SecAction \
                 "id:9514010,\
                 phase:1,\
                 pass,\
                 t:none,\
                 nolog,\
                 ver:'dos-protection-plugin/1.0.0',\
                 setvar:'tx.dos_burst_time_slice=60',\
                 setvar:'tx.dos_counter_threshold=400',\
                 setvar:'tx.dos_block_timeout=300'"

You notice that the tx.dos_counter_threshold is way higher than 150 (my initial value).

Despite of that, valid requests are blocked way earlier than the 400 requests in 60s (which seems to me insanely high).

I had cases of dos block activating at 200 requests in a much bigger interval than 60s (it may be 2, 3 or even 5 minutes or more) ...

So, any solution, please? Thank you.

theseion commented 1 month ago

Hi @iliuta, thanks for reporting.

Are you positive that you can rely on the client IP addresses? NAT or reverse proxy would map many clients to the same IP.

iliuta commented 1 month ago

@theseion I don't think this is important at this point. My question is: why the block is triggered this low?

But yes, I can rely with a fair degree of trust to the client IP addresses, since the calls come mainly from a mobile app so the IP is different for each terminal. Also, the X-Forwarded headers are correctly set up and the "originating" IP is well interpreted by the system.

I also compared the 3.3.5 version with this one and I don't see a major change.

theseion commented 1 month ago

I honestly couldn't tell you why the plugin is behaving this way. None of the core developers actually uses the plugin, so it's not tested well.

I see you're using nginx, so it's possible that there's something in libmodsecurity3 or the nginx connector that's at fault. TBH, I don't have the time at the moment to look into this, unless you can provide a specific way to reproduce the issue.

What we can check pretty easily, is which version you are using. expirevar was implemented in ModSecurity v3.0.11. You need at least that version for the plugin to work.

iliuta commented 1 month ago

It definitely supports expirevar. I know that because it was I who submitted the PR for ModSecurity 3.0.11 :)

Prior to that I was using a hacked version of 912 dos protection rules without expirevar keyword.

Also, now, if I'm downgrading to CRS 3.3.5 (which use expirevar as well), it works as it used to.

But, as far as I understand, it looks like those rules are not supported anymore so I should look for a replacement solution. Which one? I don't know yet. For the moment I'm staying with CRS 3.3.5.

theseion commented 1 month ago

It definitely supports expirevar. I know that because it was I who submitted the PR for ModSecurity 3.0.11 :)

😅 Sorry, hadn't realised that.

It helps to know that the DoS rules from 3.3.5 work for you. I can work with that. It might be a moment before I get around to investigating this issue though.

theseion commented 1 month ago

I quickly diffed the rules from 3.3.5 against the plugin rules and they are identical, with the exception of IDs and other minor changes. In theory, you should be able to simply copy the rules into a new "912-*" file without modification and it should work exactly like the rules from 3.3.5 (assuming you also place the configuration rules where they belong). That would at least exclude the plugin setup mechanism from causing issues.

iliuta commented 1 month ago

Yes, I diffed too, before posting the issue and I haven't found breaking differences, except the rule ids. When I'll have some time, I'll try to embed the plugin code into 3.3.5 CRS rules to see how it behaves.

But anyway, regarding our discussion and what I saw on the internet, I don't see a bright future for this plugin. I'll look for a different solution, like the AWS WAF, but it's hard to use it, because it needs changes in the infrastructure (drop Nginx and use AWS load balancer controller => use of several ALBs instead of a single NLB => increasing costs, harder to manage, etc).

theseion commented 1 month ago

But anyway, regarding our discussion and what I saw on the internet, I don't see a bright future for this plugin.

You mean, because it doesn't work out of the box? That's simply because we haven't tested and released it yet. I wanted to have a sound mechanism for initialising it before we released it.

To be fair, the plugin is only a poor man's DoS protection. It doesn't hold up to serious attacks, especially not distributed ones. We generally advise to look for proper DoS protection instead. It can be useful nonetheless, but it's important to understand the limitations.

iliuta commented 1 month ago

I perfectly know this is a poor man's DoS protection mechanism. And it's weak. It's enough that the attacker changes the user agent at each request to avoid it. Not only it will avoid it but the memory will explode at some point for keeping the collections alive for 600s :) But it used to work somehow. I figured out that since there are no modifications, It should work the same. Maybe there is some initialization procedure I missed?

theseion commented 1 month ago

I don't think you made a mistake. My gut says there might be something fishy w.r.t. to rule ordering or initialisation.