]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smtp/mime: Restrict file name lengths
authorJeff Lucovsky <jeff@lucovsky.org>
Tue, 4 Feb 2020 15:13:49 +0000 (10:13 -0500)
committerJeff Lucovsky <jeff@lucovsky.org>
Sun, 22 Mar 2020 15:40:59 +0000 (11:40 -0400)
This commit places restrictions on the length of the file name specified
in attachments (`name=` or `filename=`) to `NAME_MAX`. Names exceeding
these limits will be truncated and processing will continue with the
truncated name.

(cherry picked from commit d0d20bd8746ad8933a515fa4facf9e3e10f22ecc)

src/suricata-common.h
src/util-decode-mime.c

index b55509c52eb942022f1f271faad501a6abca2379..ed71a88b8a90e111f860d05029ff70e49fab1778 100644 (file)
@@ -497,5 +497,9 @@ extern int g_ut_covered;
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
 #endif /* __SURICATA_COMMON_H__ */
 
index 7dbc814d3785cbdde4b8c47111a51c0f0814f5bc..24dee93debe2663ce02b360163623d94de3f903c 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2012 BAE Systems
+ * Copyright (C) 2020 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -1830,30 +1831,62 @@ static int FindMimeHeader(const uint8_t *buf, uint32_t blen,
  * \param search_start The start of the search (ie. boundary=\")
  * \param search_end The end of the search (ie. \")
  * \param tlen The output length of the token (if found)
+ * \param max_len The maximum offset in which to search
  *
  * \return A pointer to the token if found, otherwise NULL if not found
  */
-static uint8_t * FindMimeHeaderToken(MimeDecField *field, const char *search_start,
-        const char *search_end, uint32_t *tlen)
+static uint8_t * FindMimeHeaderTokenRestrict(MimeDecField *field, const char *search_start,
+        const char *search_end, uint32_t *tlen, uint32_t max_len, bool *toolong)
 {
     uint8_t *fptr, *tptr = NULL, *tok = NULL;
 
+    if (toolong)
+        *toolong = false;
+
     SCLogDebug("Looking for token: %s", search_start);
 
     /* Check for token definition */
-    fptr = FindBuffer(field->value, field->value_len, (const uint8_t *)search_start, strlen(search_start));
+    size_t ss_len = strlen(search_start);
+    fptr = FindBuffer(field->value, field->value_len, (const uint8_t *)search_start, ss_len);
     if (fptr != NULL) {
-        fptr += strlen(search_start); /* Start at end of start string */
-        tok = GetToken(fptr, field->value_len - (fptr - field->value), search_end,
-                &tptr, tlen);
-        if (tok != NULL) {
-            SCLogDebug("Found mime token");
+        fptr += ss_len; /* Start at end of start string */
+        uint32_t offset = fptr - field->value;
+        if (offset > field->value_len) {
+            return tok;
+        }
+        tok = GetToken(fptr, field->value_len - offset, search_end, &tptr, tlen);
+        if (tok == NULL) {
+            return tok;
+        }
+        SCLogDebug("Found mime token");
+
+        /* Compare the actual token length against the maximum */
+        if (toolong && max_len && *tlen > max_len) {
+            SCLogDebug("Token length %d exceeds length restriction %d; truncating", *tlen, max_len);
+            *toolong = true;
+            *tlen = max_len;
         }
     }
 
     return tok;
 }
 
+/**
+ * \brief Finds a mime header token within the specified field
+ *
+ * \param field The current field
+ * \param search_start The start of the search (ie. boundary=\")
+ * \param search_end The end of the search (ie. \")
+ * \param tlen The output length of the token (if found)
+ *
+ * \return A pointer to the token if found, otherwise NULL if not found
+ */
+static uint8_t * FindMimeHeaderToken(MimeDecField *field, const char *search_start,
+        const char *search_end, uint32_t *tlen)
+{
+    return FindMimeHeaderTokenRestrict(field, search_start, search_end, tlen, 0);
+}
+
 /**
  * \brief Processes the current line for mime headers and also does post-processing
  * when all headers found
@@ -1899,7 +1932,7 @@ static int ProcessMimeHeaders(const uint8_t *buf, uint32_t len,
         /* Check for file attachment in content disposition */
         field = MimeDecFindField(entity, CTNT_DISP_STR);
         if (field != NULL) {
-            bptr = FindMimeHeaderToken(field, "filename=", TOK_END_STR, &blen);
+            bptr = FindMimeHeaderTokenRestrict(field, "filename=", TOK_END_STR, &blen, NAME_MAX);
             if (bptr != NULL) {
                 SCLogDebug("File attachment found in disposition");
                 entity->ctnt_flags |= CTNT_IS_ATTACHMENT;
@@ -1941,7 +1974,7 @@ static int ProcessMimeHeaders(const uint8_t *buf, uint32_t len,
 
             /* Look for file name (if not already found) */
             if (!(entity->ctnt_flags & CTNT_IS_ATTACHMENT)) {
-                bptr = FindMimeHeaderToken(field, "name=", TOK_END_STR, &blen);
+                bptr = FindMimeHeaderTokenRestrict(field, "name=", TOK_END_STR, &blen, NAME_MAX);
                 if (bptr != NULL) {
                     SCLogDebug("File attachment found");
                     entity->ctnt_flags |= CTNT_IS_ATTACHMENT;