]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: limit base64_decode `bytes` to 64KiB
authorPhilippe Antoine <pantoine@oisf.net>
Tue, 17 Dec 2024 14:06:25 +0000 (15:06 +0100)
committerVictor Julien <vjulien@oisf.net>
Tue, 18 Mar 2025 09:49:25 +0000 (10:49 +0100)
Ticket: 7613

Avoids potential large per-thread memory allocation. A buffer with the
size of the largest decode_base64 buffer size setting would be allocated
per thread. As this was a u32, it could mean a per-thread 4GiB memory
allocation.

64KiB was already the built-in default for cases where bytes size wasn't
specified.

doc/userguide/rules/base64-keywords.rst
src/detect-base64-decode.c
src/detect.h

index 9e4f942e46d8b81e9ee026e7cb051450acc721a2..ee19c8a03a8e82a9f9ad9bb75a54468fd764099a 100644 (file)
@@ -17,6 +17,7 @@ Syntax::
     base64_decode:bytes <value>, offset <value>, relative;
 
 The ``bytes`` option specifies how many bytes Suricata should decode and make available for base64_data.
+This number is limited to 64KiB.
 The decoding will stop at the end of the buffer.
 
 The ``offset`` option specifies how many bytes Suricata should skip before decoding.
index 4a2219a3ceaae48f459d6a847d7622c5e2eaaa7f..35d79c90047b1543d4d6c99ed014cd3fd66ec945 100644 (file)
@@ -28,7 +28,7 @@
 #define BASE64_DECODE_MAX 65535
 
 typedef struct DetectBase64Decode_ {
-    uint32_t bytes;
+    uint16_t bytes;
     uint32_t offset;
     uint8_t relative;
 } DetectBase64Decode;
@@ -110,8 +110,8 @@ int DetectBase64DecodeDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s
     return det_ctx->base64_decoded_len > 0;
 }
 
-static int DetectBase64DecodeParse(const char *str, uint32_t *bytes,
-    uint32_t *offset, uint8_t *relative)
+static int DetectBase64DecodeParse(
+        const char *str, uint16_t *bytes, uint32_t *offset, uint8_t *relative)
 {
     const char *bytes_str = NULL;
     const char *offset_str = NULL;
@@ -131,7 +131,7 @@ static int DetectBase64DecodeParse(const char *str, uint32_t *bytes,
 
     if (pcre_rc >= 3) {
         if (pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&bytes_str, &pcre2_len) == 0) {
-            if (StringParseUint32(bytes, 10, 0, bytes_str) <= 0) {
+            if (StringParseUint16(bytes, 10, 0, bytes_str) <= 0) {
                 SCLogError("Bad value for bytes: \"%s\"", bytes_str);
                 goto error;
             }
@@ -185,7 +185,7 @@ error:
 static int DetectBase64DecodeSetup(DetectEngineCtx *de_ctx, Signature *s,
     const char *str)
 {
-    uint32_t bytes = 0;
+    uint16_t bytes = 0;
     uint32_t offset = 0;
     uint8_t relative = 0;
     DetectBase64Decode *data = NULL;
@@ -233,9 +233,6 @@ static int DetectBase64DecodeSetup(DetectEngineCtx *de_ctx, Signature *s,
         data->bytes = BASE64_DECODE_MAX;
     }
     if (data->bytes > de_ctx->base64_decode_max_len) {
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-        data->bytes = BASE64_DECODE_MAX;
-#endif
         de_ctx->base64_decode_max_len = data->bytes;
     }
 
@@ -267,7 +264,7 @@ static int g_http_header_buffer_id = 0;
 static int DetectBase64TestDecodeParse(void)
 {
     int retval = 0;
-    uint32_t bytes = 0;
+    uint16_t bytes = 0;
     uint32_t offset = 0;
     uint8_t relative = 0;
 
index cea44e7a1b68e486f8a55873473169a43d0af06a..90507ff031881df3e2af0b37aaff7ce8cc922428 100644 (file)
@@ -943,7 +943,7 @@ typedef struct DetectEngineCtx_ {
     struct SigGroupHead_ *decoder_event_sgh;
 
     /* Maximum size of the buffer for decoded base64 data. */
-    uint32_t base64_decode_max_len;
+    uint16_t base64_decode_max_len;
 
     /** Store rule file and line so that parsers can use them in errors. */
     int rule_line;