Skip to content

Segmentation fault in ModSecurity 2.9 for Apache #3300

Open
@vizovitin

Description

@vizovitin

Describe the bug

Segmentation fault in ModSecurity 2.9.7 for Apache on very specific POST requests.

Logs and dumps

I cannot provide full core dump or request parameters due to potential inclusion of information from a production server. However, here's the stack trace:

(gdb) where
#0  0x00007f33133b507f in modsecurity_request_body_end_raw (msr=0x7f33030f7ba8, error_msg=0x7ffc207520e8)
    at apache2/msc_reqbody.c:572
#1  0x00007f33133aa748 in modsecurity_request_body_end_urlencoded (error_msg=0x7ffc207520e8, msr=0x7f33030f7ba8)
    at apache2/msc_reqbody.c:622
#2  modsecurity_request_body_end (error_msg=0x7ffc207520e8, msr=0x7f33030f7ba8)
    at apache2/msc_reqbody.c:730
#3  read_request_body (error_msg=0x7ffc207520e8, msr=<optimized out>)
    at apache2/apache2_io.c:350
#4  hook_request_late (r=0x7f33114960a0)
    at apache2/mod_security2.c:1026
#5  0x0000564a3d81b9a8 in ap_run_fixups ()
#6  0x0000564a3d82e553 in ap_process_request_internal ()
#7  0x0000564a3d84f8e5 in ap_process_async_request ()
#8  0x0000564a3d84fb33 in ap_process_request ()
#9  0x0000564a3d84fe77 in ?? ()
#10 0x0000564a3d83be88 in ap_run_process_connection ()
#11 0x00007f3313eed128 in ?? () from /usr/lib/apache2/modules/mod_mpm_prefork.so
#12 0x00007f3313eed4a1 in ?? () from /usr/lib/apache2/modules/mod_mpm_prefork.so
#13 0x00007f3313eedda7 in ?? () from /usr/lib/apache2/modules/mod_mpm_prefork.so
#14 0x0000564a3d8070e8 in ap_run_mpm ()
#15 0x0000564a3d806609 in main ()
(gdb) bt full
#0  0x00007f33133b507f in modsecurity_request_body_end_raw (msr=0x7f33030f7ba8, error_msg=0x7ffc207520e8)
    at apache2/msc_reqbody.c:572
        chunks = <optimized out>
        one_chunk = <optimized out>
        d = 0x564a3f7dc390 "\340s}\027\003\003\b@alswitch\",\"from\":\"meta\",\"options\":{\"H\":\"DISABLE\",\"S\":\"ENABLE\"},\"default\":\"H\",\"children\":[\"vibe_partial_units\"],\"hide_nodes\":[\"vibe_partial_units\"],\"value\":\"H\"},{\"label\":\"Select items for parti"...
        i = <optimized out>
        sofar = 0
#1  0x00007f33133aa748 in modsecurity_request_body_end_urlencoded (error_msg=0x7ffc207520e8, msr=0x7f33030f7ba8)
    at apache2/msc_reqbody.c:622
        invalid_count = 0
        invalid_count = <optimized out>
#2  modsecurity_request_body_end (error_msg=0x7ffc207520e8, msr=0x7f33030f7ba8)
    at apache2/msc_reqbody.c:730
        my_error_msg = 0x0
        metadata = <optimized out>
...
(gdb) print msr->msc_reqbody_length
$5 = 128070
(gdb) print msr->msc_reqbody_buffer
$4 = 0x564a3f7dc390 "\340s}\027\003\003\b@alswitch\",\"from\":\"meta\",\"options\":{\"H\":\"DISABLE\",\"S\":\"ENABLE\"},\"default\":\"H\",\"children\":[\"vibe_partial_units\"],\"hide_nodes\":[\"vibe_partial_units\"],\"value\":\"H\"},{\"label\":\"Select items for parti"...
(gdb) print i
$1 = <optimized out>
(gdb) print msr->msc_reqbody_chunks
$2 = (apr_array_header_t *) 0x0
(gdb) print sofar
$6 = 0
 543 static apr_status_t modsecurity_request_body_end_raw(modsec_rec *msr, char **error_msg) {
 ...
 567     /* Copy the data we keep in chunks into the new buffer. */
 568
 569     sofar = 0;
 570     d = msr->msc_reqbody_buffer;
 571     chunks = (msc_data_chunk **)msr->msc_reqbody_chunks->elts;
 572     for(i = 0; i < msr->msc_reqbody_chunks->nelts; i++) {
 573         if (sofar + chunks[i]->length <= msr->msc_reqbody_length) {
 574             memcpy(d, chunks[i]->data, chunks[i]->length);
 575             d += chunks[i]->length;
 576             sofar += chunks[i]->length;
 577         } else {
 578             *error_msg = apr_psprintf(msr->mp, "Internal error, request body buffer overflow.");
 579             return -1;
 580         }
 581     }

To Reproduce

N/A

Reproduced only on production server with very specific steps in a very customized WordPress.
ModSecurity for Apache, blocking, with Comodo (free) ruleset, in Fast mode, with 210710 and 222212 security rule IDs switched off.

Actual behavior

Request fails with 502 Bad Gateway served by nginx (reverse proxy before Apache). In the backend the following is logged:

==> /var/www/vhosts/system/example.net/logs/proxy_error_log <==
2024/11/13 08:59:28 [error] 3413043#0: *178721 upstream prematurely closed connection while reading response header from upstream, client: 123.45.123.45, server: example.net, request: "POST /wp-json/wplms/v2/saveDraft/?post HTTP/2.0", upstream: "https://127.0.0.1:7081/wp-json/wplms/v2/saveDraft/?post", host: "example.net", referrer: "https://example.net/"

==> /var/log/apache2/error.log <==
[Wed Nov 13 08:59:29.122617 2024] [core:notice] [pid 1141769] AH00051: child pid 3437845 exit signal Segmentation fault (11), possible coredump in /etc/apache2

Expected behavior

Apache children should not crash due to ModSecurity.

Server (please complete the following information):

  • ModSecurity version (and connector): 2.9.7
  • WebServer: apache2 2.4.52-1ubuntu4.12 (OS vendor packages)
  • OS (and distro): Ubuntu 22.04 x86_64 (likely ANY Linux)

Rule Set (please complete the following information):

  • Running any public or commercial rule set? Comodo (free)
  • What is the version number? 1.241

Additional context

Unfortunately, I cannot test the issue on 2.9.8 (as it is production server I don't own).

The following patch alleviates the issue, although it is most certainly "incorrect":

--- apache2/msc_reqbody.c.orig  2024-11-13 14:52:48.728063792 +0000
+++ apache2/msc_reqbody.c       2024-11-13 14:56:58.774675155 +0000
@@ -547,6 +547,11 @@

     *error_msg = NULL;

+    if (msr->msc_reqbody_chunks == NULL) {
+       *error_msg = apr_psprintf(msr->mp, "Internal error, request body chunks are NULL.");
+       return -1;
+    }
+
     /* Allocate a buffer large enough to hold the request body. */

     if (msr->msc_reqbody_length + 1 == 0) {

Metadata

Metadata

Assignees

Labels

2.xRelated to ModSecurity version 2.x

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions