owasp-modsecurity / owasp-modsecurity/ModSecurity

SecRequestBodyAccess Off is still loading request body in memory

Open
#3,022 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

3.x
Dominant language
C++
Stars
9.8k
Forks
1.8k
Avg merge
2h 46m
Merged PRs (30d)
1

Description

Hello!
I'm trying to setup ModSecurity but I'm dealing with issues when uploading large files.

At first I had issues uploading files so I set SecRequestBodyAccess to Off, which is working fine for files up to ~800MB but with larger files (1.3GB), nginx is still crashing.

Logs and dumps

Output of:

  1. Error logs
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
[alert] 18607#18607: worker process 18608 exited on signal 6 (core dumped)
  1. Backtrace of core dump
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007f7bd79ac535 in __GI_abort () at abort.c:79
#2  0x00007f7bd70dc983 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007f7bd70e28c6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007f7bd70e2901 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007f7bd70e2b89 in __cxa_rethrow () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007f7bd7834d84 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<std::istreambuf_iterator<char, std::char_traits<char> > > (this=this@entry=0x7ffc4a54a280, __beg=..., __end=...) at /usr/include/c++/8/ext/new_allocator.h:116
#7  0x00007f7bd7840489 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct_aux<std::istreambuf_iterator<char, std::char_traits<char> > > (__end=..., __beg=..., this=0x7ffc4a54a280) at /usr/include/c++/8/bits/basic_string.h:252
#8  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<std::istreambuf_iterator<char, std::char_traits<char> > > (
    __end=..., __beg=..., this=0x7ffc4a54a280) at /usr/include/c++/8/bits/basic_string.h:255
#9  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::istreambuf_iterator<char, std::char_traits<char> >, void> (__a=..., __end=..., __beg=..., this=0x7ffc4a54a280) at /usr/include/c++/8/bits/basic_string.h:617
#10 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace_dispatch<std::istreambuf_iterator<char, std::char_traits<char> > > (__k2=..., __k1=..., __i2=..., __i1=0 '\000', this=0x7ffc4a54a1e0) at /usr/include/c++/8/bits/basic_string.tcc:384
#11 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::replace<std::istreambuf_iterator<char, std::char_traits<char> >, void> (
    __k2=..., __k1=..., __i2=..., __i1=..., this=0x7ffc4a54a1e0) at /usr/include/c++/8/bits/basic_string.h:2091
#12 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign<std::istreambuf_iterator<char, std::char_traits<char> >, void> (
    __last=..., __first=..., this=0x7ffc4a54a1e0) at /usr/include/c++/8/bits/basic_string.h:1471
#13 modsecurity::Transaction::requestBodyFromFile (this=0x5642022075d0, path=<optimized out>) at transaction.cc:1032
#14 0x00007f7bd7fdbe5c in ngx_http_modsecurity_pre_access_handler (r=0x564202279dc0)
    at /usr/local/src/ModSecurity-nginx/src/ngx_http_modsecurity_pre_access.c:170
#15 0x00005641fe7d512f in ngx_http_core_generic_phase ()
#16 0x00005641fe7d0bdd in ngx_http_core_run_phases ()
#17 0x00007f7bd7fdbd66 in ngx_http_modsecurity_request_read (r=<optimized out>) at /usr/local/src/ModSecurity-nginx/src/ngx_http_modsecurity_pre_access.c:38
#18 0x00005641fe80ac33 in ?? ()
#19 0x00005641fe80d980 in ?? ()
#20 0x00005641fe7d9d1c in ?? ()
#21 0x00005641fe7b8810 in ngx_event_process_posted ()
#22 0x00005641fe7bff71 in ?? ()
#23 0x00005641fe7be84b in ngx_spawn_process ()
#24 0x00005641fe7c0374 in ?? ()
#25 0x00005641fe7c0bd7 in ngx_master_process_cycle ()
#26 0x00005641fe797588 in main ()

Expected behavior

I expected body not to be loaded in memory as SecRequestBodyAccess is set to Off and SecRequestBodyLimitAction is set to ProcessPartial.

Server :

  • ModSecurity version (and connector): ModSecurity v3.0.10 with nginx-connector v1.0.3
  • WebServer: nginx-1.22.0
  • OS (and distro): Debian 10 (buster)

Rule Set:
OWASP coreruleset v3.3.5

Additional context

This issue is similar to https://github.com/SpiderLabs/ModSecurity/issues/1517

Would this patch be acceptable ? I have tested it with large files and nginx does not crash with it. Thanks.

diff --git a/src/transaction.cc b/src/transaction.cc
index 0c98b49c..fffeb70f 100644
--- a/src/transaction.cc
+++ b/src/transaction.cc
@@ -1023,13 +1023,13 @@ int Transaction::requestBodyFromFile(const char *path) {
     request_body.seekg(0, std::ios::end);
     try {
         str.reserve(request_body.tellg());
+        request_body.seekg(0, std::ios::beg);
+        str.assign((std::istreambuf_iterator<char>(request_body)),
+                   std::istreambuf_iterator<char>());
     } catch (...) {
         ms_dbg(3, "Failed to allocate memory to load request body.");
         return false;
     }
-    request_body.seekg(0, std::ios::beg);
-    str.assign((std::istreambuf_iterator<char>(request_body)),
-            std::istreambuf_iterator<char>());
 
     const char *buf = str.c_str();
     int len = request_body.tellg();

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/transaction.cc at Transaction::requestBodyFromFile, then inspect the nginx connector path through ngx_http_modsecurity_pre_access_handler and ngx_http_modsecurity_request_read. Reproduce with a request larger than available memory and verify that SecRequestBodyAccess Off no longer causes the body to be loaded in memory or crashes nginx.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, nginx
Domain
backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.