owasp-modsecurity / ModSecurity

ModSecurity is an open source, cross platform web application firewall (WAF) engine for Apache, IIS and Nginx. It has a robust event-based programming language which provides protection from a range of attacks against web applications and allows for HTTP traffic monitoring, logging and real-time analysis.
https://www.modsecurity.org
Apache License 2.0
7.7k stars 1.54k forks source link

modsecurity high memory usage 60-70% #785

Closed ton31337 closed 9 years ago

ton31337 commented 9 years ago

Hello,

is it possible to avoid caching all the rules including body content in memory? Because after 2-3 days we have 60-70% memory usage.. Extracting memory dumps there are as expected, rules and body cached inside the memory.

Any idea how to bypass this caching? Or maybe is any way to reduce to minimal this behavior?

Donatas.

zimmerle commented 9 years ago

Hi @ton31337,

Are you running custom rules? OWASP CRS? or others?

Just to confirm, your ModSecurity is using low amount of memory when you start it, but slow increase the usage amount until reach (after 2 ~ 3 days) a high amount of memory used, is that correct?

ton31337 commented 9 years ago

Hi @zimmerle,

we are using OWASP CRS together with Commercial rules. Yes, after few days it consumes almost the whole memory. Need to restart nginx to free the memory.

Maybe it would be possible to tell mmap() / malloc() to do not cache it or just to call madvise() with MADV_DONTNEED flag?

Donatas.

ton31337 commented 9 years ago

@zimmerle Can you explain this snippet?

static void *
modsec_pcre_malloc(size_t size)
{
    return apr_palloc(pool, size);
}

static void
modsec_pcre_free(void *ptr)
{
}

Why modsec_pcre_free() does nothing? Maybe here is a leak? I can try to trace of course to check, but just saw this interesting part :)

zimmerle commented 9 years ago

Hi @ton31337,

It seems to be a memory leak in fact, but not sure if it is attached to this exactly part of the code. The apr works with memory pools which should be destroy after used (e.g. connection end, or so..), thus, this piece of memory should be free by apr, while the pool is destroyed.

Can you tell me if your SecResponseBodyAccess (https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#SecResponseBodyAccess) is enabled? If so, can you disable it to test?

ton31337 commented 9 years ago

@zimmerle SecResponseBodyAccess is disabled in my case. That's really odd. O tried with / without this option, result is the same in both cases..

zimmerle commented 9 years ago

What about SecRequestBodyAccess ? is it enabled or disabled?

ton31337 commented 9 years ago

This is disabled as well.

zimmerle commented 9 years ago

This ModSecurity was a custom build or it is an distro package? Do you know if --enable-pcre-study was used during the compilation? (Ref: #610).

Btw, what version are you using (nginx and modsec) ?

ton31337 commented 9 years ago

No, we don't compile ModSecurity with this option (--enable-pcre-study). Nginx's version is 1.7.2 and ModSecurity is downloaded from trunk. (2.8.0)

zimmerle commented 9 years ago

Can you try this branch: https://github.com/SpiderLabs/ModSecurity/tree/nginx_refactoring ?

Not sure if it will fix this specific problem but worth a try. It is currently under developer, it is a refactoring of our nginx version.

ton31337 commented 9 years ago

@zimmerle I tried this as well :) Actually this branch is I'm testing on :)

zimmerle commented 9 years ago

cool! :) Please let me know if it is working or not.

ton31337 commented 9 years ago

@zimmerle result is the same:

root     29110  0.0 12.4 901276 503344 ?       Ss   09:34   0:00 nginx: master process /usr/local/openresty/nginx/sbin/nginx -c /usr/local/openresty/nginx/conf/nginx.conf
nginx  29111  0.0 13.1 936408 532812 ?       Sl   09:34   0:00  \_ nginx: worker process
nginx  29116  0.0 12.5 910028 506684 ?       Sl   09:34   0:00  \_ nginx: cache manager process

This output is after nginx restart. It eats 15% of memory in advance. In this case it's about 700MB.

ton31337 commented 9 years ago
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 57.73    0.000351           1       674           munmap
 10.20    0.000062           0       674           mmap

strace looks good, no memory leak looking into mmap()/unmap() syscalls.

ton31337 commented 9 years ago

Allocated/Freed memory is the same..

# grep mmap testing-memory-leak | awk -F ','  'BEGIN { sum = 0 } {sum+=$2} END { print sum }'
112738304
# grep unmap testing-memory-leak | awk -F ',' '{print $2}' | awk -F ')' 'BEGIN { sum = 0 } {sum+=$1} END { print sum }'
112738304
ton31337 commented 9 years ago

Hi @zimmerle,

problem is that we are using ModSecurity with different waf rules for different website. For example:

/usr/local/openresty/nginx/conf/website1_waf/*.conf
/usr/local/openresty/nginx/conf/website2_waf/*.conf
/usr/local/openresty/nginx/conf/website3_waf/*.conf

Inside website*_waf are lot of flles.

Adding additional such one eats additional ~12% of memory. Why it maps everything into the memory? Maybe it's possible to read these rules from the disk instead of memory?

By the way, it doesn't matter if ModSecurityEnabled off or on. It keeps everything mapped into the memory.. If commenting ModSecurityEnabled and ModSecurityConfig directives, usage drops.

7fc5675ce000-7fc585b7f000 rwxp 00000000 00:00 0 (1 website enabled with WAF)
Size:             497348 kB
Rss:              497200 kB
Pss:              124300 kB
Shared_Clean:          0 kB
Shared_Dirty:     497200 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            4 kB
Anonymous:        497200 kB
AnonHugePages:     16384 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
VmFlags: rd wr ex mr mw me ac sd

7f1beda3d000-7f1c295aa000 rwxp 00000000 00:00 0 (2 websites enabled with WAF)
Size:             978356 kB
Rss:              978048 kB
Pss:              244512 kB
Shared_Clean:          0 kB
Shared_Dirty:     978048 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            4 kB
Anonymous:        978048 kB
AnonHugePages:     16384 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
VmFlags: rd wr ex mr mw me ac sd

From this output it seems memory isn't mapped from a file.. So, why it allocates so much memory when ModSecurity is enabled, depending on how much rules are added.

Donatas.

zimmerle commented 9 years ago

Hi @ton31337,

This problem of ModSecurity using resources even if it is disabled is being discussed at #644.

Currently there is no such option to load the rules on demand. Once you start the web server all the rules are loaded. In particular @pmFromFile uses a lot of memory. Not sure if it is the case, as the memory used while loading the rules are allocated on the startup. It won't increase after the service is running.

One test that you can do is to complete disable all the rules, and check if after a while it still increasing the memory usage, even without rules. This may help to identify if the problem is associate with a particular rule or with the nginx-module.

ton31337 commented 9 years ago

Hi @zimmerle ,

seems that no memory is increasing after disabling Request/ResponseBody filtering. But it's crazy still why ModSecurity loads all the rules into the memory.. It will be good to have an option to load all rules in advance or just on demand, or even do not load into the memory at all.

Maybe you can give me an advice, what the function is responsible for loading into the memory the rules? I will take a look myself on this.

D.

Menahem1 commented 7 years ago

Hello,

Somebody know, what's the method for find precisely what ModSecurity is consuming in memory with Nginx ?

Thanks

zimmerle commented 7 years ago

Hi @men18,

I recommend you to switch to libModSecurity and nginx connector: https://github.com/SpiderLabs/ModSecurity-nginx

Menahem1 commented 7 years ago

Hello @zimmerle

Thanks for your answer !

It's precisely what i use (with CRS rule in v3.0), but my problem is about increasing memory in Nginx. For now i can't be sure that the increasing memory (or memory leak) is on ModSecurity or other part of Nginx, how to be sure ?

My conf : nginx version: nginx/1.11.9 built by gcc 4.9.2 (Debian 4.9.2-10) built with OpenSSL 1.0.1t 3 May 2016 TLS SNI support enabled configure arguments: --add-module=../ModSecurity-nginx --with-debug --with-cc-opt='-O0 -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --with-pcre-jit --with-http_ssl_module --with-http_realip_module

Usage of Memory

capture d ecran 2017-02-07 a 14 02 55
zimmerle commented 7 years ago

Do you mind to open another issue to keep track of this memory problem? Initially #785 refers to ModSecurity version 2.x

Menahem1 commented 7 years ago

Ok, Done #1318