Skip to content

Segmentation fault during collection cleanup on possibly corrupted dbm data #3082

Closed
@twouters

Description

@twouters

Describe the bug

Apache segfaults during processing of requests when the persistent collection is being processed to remove stale records.

Logs and dumps

Note: IP addresses have been obfuscated

(gdb) bt full
#0  0x00007236e618c456 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
No symbol table info available.
#1  0x00007236e65bb2f8 in memcpy (__len=4294967295, __src=0x7236bc01deae, __dest=<optimized out>)
    at /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34
No locals.
#2  apr_pstrmemdup (a=<optimized out>, s=s@entry=0x7236bc01deae "\017\061\070\061.123.123.12", 
    n=4294967295) at strings/apr_strings.c:107
        res = <optimized out>
#3  0x00007236e5fb4664 in collection_unpack (msr=msr@entry=0x7236bc020eb0, blob=0x7236bc01de76 "7", 
    blob_size=228, log_vars=log_vars@entry=0) at persist_dbm.c:71
        var = 0x7236bc0b2e60
        col = 0x7236bc0b2a38
        blob_offset = 56
#4  0x00007236e5fb5c96 in collections_remove_stale (msr=msr@entry=0x7236bc020eb0, 
    col_name=0x7236bc009020 "ip") at persist_dbm.c:781
        col = 0x0
        var = 0x0
        dbm_filename = 0x7236bc02d578 "/var/cache/httpd/www-ip"
        key = {dptr = 0x7236bc030ea0 "127.12.12.123", dsize = 14}
        value = {dptr = 0x7236bc01de76 "7", dsize = 228}
        dbm = <optimized out>
        rc = <optimized out>
        keys_arr = 0x7236bc02d700
        keys = 0x7236bc031ae8
        now = <optimized out>
        i = 314
        userinfo = 0x7236bc02d570 "www"
[snip]

To Reproduce

Not sure, I guess: have corrupt persistent collection data files (I made backups, if you're interested) and perform some specific requests to trigger a segfault (don't known exactly when it triggers).

Expected behavior

Webserver doesn't crash

Server (please complete the following information):

  • ModSecurity version: 2.9.7
  • WebServer: Apache 2.4.57
  • OS (and distro): Debian bullseye/bookworm

Additional context

var->value = apr_pstrmemdup(msr->mp, (const char *)blob + blob_offset, var->value_len - 1);

collection_unpack() checks if blob_offset + var->value_len expands beyond blob_size, but then runs apr_pstrmemdup() with a size of var->value_len - 1. If var->value_len = 0 the size value will wrap around to 4294967295.

The following patch might help:

--- a/apache2/persist_dbm.c
+++ b/apache2/persist_dbm.c
@@ -67,7 +67,7 @@
         var->value_len = (blob[blob_offset] << 8) + blob[blob_offset + 1];
         blob_offset += 2;
 
-        if (blob_offset + var->value_len > blob_size) return NULL;
+        if (blob_offset + (var->value_len - 1) > blob_size) return NULL;
         var->value = apr_pstrmemdup(msr->mp, (const char *)blob + blob_offset, var->value_len - 1);
         blob_offset += var->value_len;
         var->value_len--;

Metadata

Metadata

Assignees

No one assigned

    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