]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1550 in SNORT/snort3 from ~BRASTULT/snort3:mime_decomp to master
authorTom Peters (thopeter) <thopeter@cisco.com>
Wed, 27 Mar 2019 17:21:20 +0000 (13:21 -0400)
committerTom Peters (thopeter) <thopeter@cisco.com>
Wed, 27 Mar 2019 17:21:20 +0000 (13:21 -0400)
Squashed commit of the following:

commit 8c90afe003ccdf8367cfdc75bb10b9bac6d0d396
Author: Brandon Stultz <brastult@cisco.com>
Date:   Mon Mar 4 19:59:41 2019 -0500

    mime: add file decompression

20 files changed:
src/mime/file_mime_config.cc
src/mime/file_mime_config.h
src/mime/file_mime_context_data.cc
src/mime/file_mime_context_data.h
src/mime/file_mime_decode.cc
src/mime/file_mime_decode.h
src/mime/file_mime_process.cc
src/mime/file_mime_process.h
src/service_inspectors/imap/imap.cc
src/service_inspectors/imap/imap.h
src/service_inspectors/imap/imap_module.cc
src/service_inspectors/imap/imap_module.h
src/service_inspectors/pop/pop.cc
src/service_inspectors/pop/pop.h
src/service_inspectors/pop/pop_module.cc
src/service_inspectors/pop/pop_module.h
src/service_inspectors/smtp/smtp.cc
src/service_inspectors/smtp/smtp.h
src/service_inspectors/smtp/smtp_module.cc
src/service_inspectors/smtp/smtp_module.h

index 44156db8181dbb657b4db86b884b425b1c6807af..153c96647cffecff0f5fbf6b34a1ede5791674dc 100644 (file)
@@ -81,6 +81,36 @@ int DecodeConfig::get_uu_depth()
     return uu_depth;
 }
 
+void DecodeConfig::set_decompress_pdf(bool enabled)
+{
+    decompress_pdf = enabled;
+}
+
+bool DecodeConfig::is_decompress_pdf()
+{
+    return decompress_pdf;
+}
+
+void DecodeConfig::set_decompress_swf(bool enabled)
+{
+    decompress_swf = enabled;
+}
+
+bool DecodeConfig::is_decompress_swf()
+{
+    return decompress_swf;
+}
+
+void DecodeConfig::set_decompress_zip(bool enabled)
+{
+    decompress_zip = enabled;
+}
+
+bool DecodeConfig::is_decompress_zip()
+{
+    return decompress_zip;
+}
+
 int64_t DecodeConfig::get_file_depth()
 {
     return file_depth;
index 3811063ac75985d749a0a534a65cff3c10d52ee8..677f5e05e057d8fa53e5b05bf2b9795749604e0d 100644 (file)
@@ -53,6 +53,15 @@ public:
     void set_uu_depth(int);
     int get_uu_depth();
 
+    void set_decompress_pdf(bool);
+    bool is_decompress_pdf();
+
+    void set_decompress_swf(bool);
+    bool is_decompress_swf();
+
+    void set_decompress_zip(bool);
+    bool is_decompress_zip();
+
     int64_t get_file_depth();
     bool is_decoding_enabled();
     void sync_all_depths();
@@ -65,6 +74,9 @@ private:
     int qp_depth = DEFAULT_DEPTH;
     int bitenc_depth = DEFAULT_DEPTH;
     int uu_depth = DEFAULT_DEPTH;
+    bool decompress_pdf = false;
+    bool decompress_swf = false;
+    bool decompress_zip = false;
     int64_t file_depth = MIN_DEPTH;
     bool decode_enabled = true;
 };
index cbf7edd825f5be4f8b52681d480dd50844e2a5cf..4e88734cf4965cafdff0d13c46d4d4ec03e02d40 100644 (file)
@@ -34,11 +34,15 @@ unsigned MimeDecodeContextData::mime_ips_id = 0;
 MimeDecodeContextData::MimeDecodeContextData()
 {
     decode_buf = (uint8_t*)snort_alloc(MAX_DEPTH);
+    decompress_buf = (uint8_t*)snort_alloc(MAX_DEPTH);
 }
+
 MimeDecodeContextData::~MimeDecodeContextData()
 {
     snort_free(decode_buf);
+    snort_free(decompress_buf);
     decode_buf = nullptr;
+    decompress_buf = nullptr;
 }
 
 void MimeDecodeContextData::init()
@@ -51,3 +55,10 @@ uint8_t* MimeDecodeContextData::get_decode_buf()
     return data->decode_buf;
 }
 
+uint8_t* MimeDecodeContextData::get_decompress_buf()
+{
+    MimeDecodeContextData* data = IpsContextData::get<MimeDecodeContextData>(mime_ips_id);
+
+    return data->decompress_buf;
+}
+
index dc0e1858205b3831896cfc546dd087246a7b275c..7afde22b0eaf8d90d8a145bd830e4c14f31d7cba 100644 (file)
@@ -31,9 +31,11 @@ public:
     static unsigned mime_ips_id;
 
     uint8_t* decode_buf = nullptr;
+    uint8_t* decompress_buf = nullptr;
 
     static void init();
     static uint8_t* get_decode_buf();
+    static uint8_t* get_decompress_buf();
 };
 
 #endif
index 1082d4611912f485b1f4e2faf8fd0b8108fb12f8..4e5558bc6d79748621f94c65e41c6d6ef99cb9b8 100644 (file)
@@ -138,13 +138,74 @@ DecodeType MimeDecode::get_decode_type()
     return decode_type;
 }
 
+DecodeResult MimeDecode::decompress_data(const uint8_t* buf_in, uint32_t size_in,
+                                         const uint8_t*& buf_out, uint32_t& size_out)
+{
+    DecodeResult result = DECODE_SUCCESS;
+
+    if ( fd_state == nullptr )
+    {
+        buf_out = buf_in;
+        size_out = size_in;
+        return result;
+    }
+
+    uint8_t* decompress_buf = MimeDecodeContextData::get_decompress_buf();
+    fd_state->Next_In = buf_in;
+    fd_state->Avail_In = size_in;
+    fd_state->Next_Out = decompress_buf;
+    fd_state->Avail_Out = MAX_DEPTH;
+
+    const fd_status_t status = File_Decomp(fd_state);
+
+    switch ( status )
+    {
+    case File_Decomp_DecompError:
+        result = DECODE_FAIL;
+        // fallthrough
+    case File_Decomp_NoSig:
+    case File_Decomp_Error:
+        buf_out = buf_in;
+        size_out = size_in;
+        break;
+    default:
+        buf_out = decompress_buf;
+        size_out = fd_state->Next_Out - decompress_buf;
+        break;
+    }
+
+    return result;
+}
+
 MimeDecode::MimeDecode(snort::DecodeConfig* conf)
 {
     config = conf;
+
+    bool decompress_pdf = config->is_decompress_pdf();
+    bool decompress_swf = config->is_decompress_swf();
+    bool decompress_zip = config->is_decompress_zip();
+
+    if ( !decompress_pdf && !decompress_swf && !decompress_zip )
+        return;
+
+    fd_state = File_Decomp_New();
+    fd_state->Modes =
+        (decompress_pdf ? FILE_PDF_DEFL_BIT : 0) |
+        (decompress_swf ? (FILE_SWF_ZLIB_BIT | FILE_SWF_LZMA_BIT) : 0) |
+        (decompress_zip ? FILE_ZIP_DEFL_BIT : 0);
+    fd_state->Alert_Callback = nullptr;
+    fd_state->Alert_Context = nullptr;
+    fd_state->Compr_Depth = 0;
+    fd_state->Decompr_Depth = 0;
+
+    (void)File_Decomp_Init(fd_state);
 }
 
 MimeDecode::~MimeDecode()
 {
+    if (fd_state)
+        File_Decomp_StopFree(fd_state);
+
     if (decoder)
         delete decoder;
 }
index b95f09bb2166feef700aa7e50a15696ff10cb444..356801c3454f8b82d6db0960f7a7add00b8ced00 100644 (file)
@@ -22,6 +22,7 @@
 
 // Email attachment decoder, supports Base64, QP, UU, and Bit7/8
 
+#include "decompress/file_decomp.h"
 #include "framework/counts.h"
 #include "main/snort_types.h"
 #include "mime/decode_base.h"
@@ -75,12 +76,16 @@ public:
 
     DecodeType get_decode_type();
 
+    DecodeResult decompress_data(const uint8_t* buf_in, uint32_t size_in,
+                                 const uint8_t*& buf_out, uint32_t& size_out);
+
     static void init();
 
 private:
     DecodeType decode_type = DECODE_NONE;
     snort::DecodeConfig* config;
     DataDecode* decoder = nullptr;
+    fd_session_t* fd_state = nullptr;
 };
 
 } // namespace snort
index 65e730591dfa1959200c434c1fcf8dd6c28e4b54..fbfb6646d6a61d220e366db9f605bcdd11f641fd 100644 (file)
@@ -562,7 +562,7 @@ const uint8_t* MimeSession::process_mime_data_paf(
 
     if ((decode_state) != nullptr)
     {
-        DecodeConfig* conf= decode_conf;
+        DecodeConfig* conf = decode_conf;
         const uint8_t* buffer = nullptr;
         uint32_t buf_size = 0;
 
@@ -570,8 +570,19 @@ const uint8_t* MimeSession::process_mime_data_paf(
 
         if (conf)
         {
-            int detection_size = decode_state->get_detection_depth();
-            set_file_data(buffer, (uint16_t)detection_size);
+            const uint8_t* decomp_buffer = nullptr;
+            uint32_t detection_size, decomp_buf_size = 0;
+
+            detection_size = (uint32_t)decode_state->get_detection_depth();
+
+            DecodeResult result = decode_state->decompress_data(
+                buffer, detection_size, decomp_buffer, decomp_buf_size
+            );
+
+            if ( result != DECODE_SUCCESS )
+                decompress_alert();
+
+            set_file_data(decomp_buffer, decomp_buf_size);
         }
 
         /*Process file type/file signature*/
index 609268f5cf06a79efcd1e30cd886651d4e4d1d5d..5097b62121499e84c8bedb3167930e4368518bb7 100644 (file)
@@ -88,6 +88,7 @@ private:
     virtual int handle_header_line(const uint8_t*, const uint8_t*, int) { return 0; }
     virtual int normalize_data(const uint8_t*, const uint8_t*) { return 0; }
     virtual void decode_alert() { }
+    virtual void decompress_alert() { }
     virtual void reset_state(Flow*) { }
     virtual bool is_end_of_data(Flow*) { return false; }
 
index 2e75a90aa5819e406986552a07c6d5fd8b4e8bd3..756fe6736c4d08d3952f4bfa798ec180c0817001 100644 (file)
@@ -680,6 +680,11 @@ void ImapMime::decode_alert()
     }
 }
 
+void ImapMime::decompress_alert()
+{
+    DetectionEngine::queue_event(GID_IMAP, IMAP_FILE_DECOMP_FAILED);
+}
+
 void ImapMime::reset_state(Flow* ssn)
 {
     IMAP_ResetState(ssn);
index 0aa5ebd854e4c0f01d2cd4d96ed2ea3208b34c81..51c645d9abe26009b80af0fe26dfd73a9068a698 100644 (file)
@@ -149,6 +149,7 @@ class ImapMime : public snort::MimeSession
     using snort::MimeSession::MimeSession;
 private:
     void decode_alert() override;
+    void decompress_alert() override;
     void reset_state(snort::Flow* ssn) override;
     bool is_end_of_data(snort::Flow* ssn) override;
 };
index a7a78a9c488a2e2f022eb1aaa38a63ce4be5a3fe..a3031a1109bf815131c7ebb9b9e10d8274098c2c 100644 (file)
@@ -39,6 +39,15 @@ static const Parameter s_params[] =
     { "bitenc_decode_depth", Parameter::PT_INT, "-1:65535", "1460",
       "non-Encoded MIME attachment extraction depth (-1 no limit)" },
 
+    { "decompress_pdf", Parameter::PT_BOOL, nullptr, "false",
+      "decompress pdf files in MIME attachments" },
+
+    { "decompress_swf", Parameter::PT_BOOL, nullptr, "false",
+      "decompress swf files in MIME attachments" },
+
+    { "decompress_zip", Parameter::PT_BOOL, nullptr, "false",
+      "decompress zip files in MIME attachments" },
+
     { "qp_decode_depth", Parameter::PT_INT, "-1:65535", "1460",
       "quoted Printable decoding depth (-1 no limit)" },
 
@@ -55,6 +64,7 @@ static const RuleMap imap_rules[] =
     { IMAP_B64_DECODING_FAILED, "base64 decoding failed" },
     { IMAP_QP_DECODING_FAILED, "quoted-printable decoding failed" },
     { IMAP_UU_DECODING_FAILED, "Unix-to-Unix decoding failed" },
+    { IMAP_FILE_DECOMP_FAILED, "file decompression failed" },
 
     { 0, nullptr }
 };
@@ -97,6 +107,15 @@ bool ImapModule::set(const char*, Value& v, SnortConfig*)
     else if ( v.is("bitenc_decode_depth") )
         config->decode_conf.set_bitenc_depth(mime_value);
 
+    else if ( v.is("decompress_pdf") )
+        config->decode_conf.set_decompress_pdf(v.get_bool());
+
+    else if ( v.is("decompress_swf") )
+        config->decode_conf.set_decompress_swf(v.get_bool());
+
+    else if ( v.is("decompress_zip") )
+        config->decode_conf.set_decompress_zip(v.get_bool());
+
     else if ( v.is("qp_decode_depth") )
         config->decode_conf.set_qp_depth(mime_value);
 
index 3f45b27254b01ac6a053c3611de868f93e47feb2..dfcd87a2a9cac3c4e474d43185d4198b499c050f 100644 (file)
@@ -33,6 +33,7 @@
 #define IMAP_B64_DECODING_FAILED    4
 #define IMAP_QP_DECODING_FAILED     5
 #define IMAP_UU_DECODING_FAILED     7
+#define IMAP_FILE_DECOMP_FAILED     8
 
 #define IMAP_NAME "imap"
 #define IMAP_HELP "imap inspection"
index a9222c4be05ea750feca04e21a5249e215f66110..17f76164d87b81240d22786abfb325f2c1b5f5a0 100644 (file)
@@ -619,6 +619,11 @@ void PopMime::decode_alert()
     }
 }
 
+void PopMime::decompress_alert()
+{
+    DetectionEngine::queue_event(GID_POP, POP_FILE_DECOMP_FAILED);
+}
+
 void PopMime::reset_state(Flow* ssn)
 {
     POP_ResetState(ssn);
index 4e4bc2e03583735911014f10fb6a8d596850d00d..d69655a26f39a4985cdec7be9c5d52ac729ba4d5 100644 (file)
@@ -104,6 +104,7 @@ class PopMime : public snort::MimeSession
     using snort::MimeSession::MimeSession;
 private:
     void decode_alert() override;
+    void decompress_alert() override;
     void reset_state(snort::Flow* ssn) override;
     bool is_end_of_data(snort::Flow* ssn) override;
 };
index 50728e1f71fad43c1c7bb4ef5834e039cedd4b75..0f74dc439a6fc2b0ae9e280befda6ebc1f4870b1 100644 (file)
@@ -39,6 +39,15 @@ static const Parameter s_params[] =
     { "bitenc_decode_depth", Parameter::PT_INT, "-1:65535", "1460",
       "Non-Encoded MIME attachment extraction depth (-1 no limit)" },
 
+    { "decompress_pdf", Parameter::PT_BOOL, nullptr, "false",
+      "decompress pdf files in MIME attachments" },
+
+    { "decompress_swf", Parameter::PT_BOOL, nullptr, "false",
+      "decompress swf files in MIME attachments" },
+
+    { "decompress_zip", Parameter::PT_BOOL, nullptr, "false",
+      "decompress zip files in MIME attachments" },
+
     { "qp_decode_depth", Parameter::PT_INT, "-1:65535", "1460",
       "Quoted Printable decoding depth (-1 no limit)" },
 
@@ -55,6 +64,7 @@ static const RuleMap pop_rules[] =
     { POP_B64_DECODING_FAILED, "base64 decoding failed" },
     { POP_QP_DECODING_FAILED, "quoted-printable decoding failed" },
     { POP_UU_DECODING_FAILED, "Unix-to-Unix decoding failed" },
+    { POP_FILE_DECOMP_FAILED, "file decompression failed" },
     { 0, nullptr }
 };
 
@@ -96,6 +106,15 @@ bool PopModule::set(const char*, Value& v, SnortConfig*)
     else if ( v.is("bitenc_decode_depth") )
         config->decode_conf.set_bitenc_depth(mime_value);
 
+    else if ( v.is("decompress_pdf") )
+        config->decode_conf.set_decompress_pdf(v.get_bool());
+
+    else if ( v.is("decompress_swf") )
+        config->decode_conf.set_decompress_swf(v.get_bool());
+
+    else if ( v.is("decompress_zip") )
+        config->decode_conf.set_decompress_zip(v.get_bool());
+
     else if ( v.is("qp_decode_depth") )
         config->decode_conf.set_qp_depth(mime_value);
 
index 37e462b951cbd71e608acc18a41ed50983599c4e..4daac862f53cf7760be95b6d0555ae56b11a0193 100644 (file)
@@ -33,6 +33,7 @@
 #define POP_B64_DECODING_FAILED    4
 #define POP_QP_DECODING_FAILED     5
 #define POP_UU_DECODING_FAILED     7
+#define POP_FILE_DECOMP_FAILED     8
 
 #define POP_NAME "pop"
 #define POP_HELP "pop inspection"
index 1aaef0436252296bc9aa42e001c552e8a3595a64..943d49fc2fd0395f0051e13ce643be7da9ecff48 100644 (file)
@@ -1368,6 +1368,11 @@ void SmtpMime::decode_alert()
     }
 }
 
+void SmtpMime::decompress_alert()
+{
+    DetectionEngine::queue_event(GID_SMTP, SMTP_FILE_DECOMP_FAILED);
+}
+
 void SmtpMime::reset_state(Flow* ssn)
 {
     SMTP_ResetState(ssn);
index 6a75a3cc5b1594d58b5d411c789dc61e5047f78c..031b65fc85d1d5cf5bc5f00cceb0cec112a44aac 100644 (file)
@@ -148,6 +148,7 @@ private:
         int max_header_len) override;
     int normalize_data(const uint8_t* ptr, const uint8_t* data_end) override;
     void decode_alert() override;
+    void decompress_alert() override;
     void reset_state(snort::Flow* ssn) override;
     bool is_end_of_data(snort::Flow* ssn) override;
 };
index 27e655abebb7eb4c849ce6f1feefd91949579c5a..444de65fbd5ae090ed8a98e368456595ddb3073e 100644 (file)
@@ -82,6 +82,15 @@ static const Parameter s_params[] =
     { "data_cmds", Parameter::PT_STRING, nullptr, nullptr,
       "commands that initiate sending of data with an end of data delimiter" },
 
+    { "decompress_pdf", Parameter::PT_BOOL, nullptr, "false",
+      "decompress pdf files in MIME attachments" },
+
+    { "decompress_swf", Parameter::PT_BOOL, nullptr, "false",
+      "decompress swf files in MIME attachments" },
+
+    { "decompress_zip", Parameter::PT_BOOL, nullptr, "false",
+      "decompress zip files in MIME attachments" },
+
     { "email_hdrs_log_depth", Parameter::PT_INT, "0:20480", "1464",
       "depth for logging email headers" },
 
@@ -155,6 +164,7 @@ static const RuleMap smtp_rules[] =
     { SMTP_UU_DECODING_FAILED, "Unix-to-Unix decoding failed" },
     { SMTP_AUTH_ABORT_AUTH, "Cyrus SASL authentication attack" },
     { SMTP_AUTH_COMMAND_OVERFLOW, "attempted authentication command buffer overflow" },
+    { SMTP_FILE_DECOMP_FAILED, "file decompression failed" },
 
     { 0, nullptr }
 };
@@ -247,6 +257,15 @@ bool SmtpModule::set(const char*, Value& v, SnortConfig*)
     else if ( v.is("data_cmds"))
         add_commands(v, PCMD_DATA);
 
+    else if ( v.is("decompress_pdf") )
+        config->decode_conf.set_decompress_pdf(v.get_bool());
+
+    else if ( v.is("decompress_swf") )
+        config->decode_conf.set_decompress_swf(v.get_bool());
+
+    else if ( v.is("decompress_zip") )
+        config->decode_conf.set_decompress_zip(v.get_bool());
+
     else if ( v.is("email_hdrs_log_depth") )
         config->log_config.email_hdrs_log_depth = v.get_uint16();
 
index 3c7dd08eb46b3e47454dfbe597177a29c3635628..303e911d958da82d78983a54420e0ac13643eb6a 100644 (file)
@@ -44,6 +44,7 @@
 #define SMTP_UU_DECODING_FAILED     13
 #define SMTP_AUTH_ABORT_AUTH        14
 #define SMTP_AUTH_COMMAND_OVERFLOW  15
+#define SMTP_FILE_DECOMP_FAILED     16
 
 #define SMTP_NAME "smtp"
 #define SMTP_HELP "smtp inspection"