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;
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();
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;
};
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()
return data->decode_buf;
}
+uint8_t* MimeDecodeContextData::get_decompress_buf()
+{
+ MimeDecodeContextData* data = IpsContextData::get<MimeDecodeContextData>(mime_ips_id);
+
+ return data->decompress_buf;
+}
+
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
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;
}
// 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"
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
if ((decode_state) != nullptr)
{
- DecodeConfig* conf= decode_conf;
+ DecodeConfig* conf = decode_conf;
const uint8_t* buffer = nullptr;
uint32_t buf_size = 0;
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*/
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; }
}
}
+void ImapMime::decompress_alert()
+{
+ DetectionEngine::queue_event(GID_IMAP, IMAP_FILE_DECOMP_FAILED);
+}
+
void ImapMime::reset_state(Flow* ssn)
{
IMAP_ResetState(ssn);
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;
};
{ "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)" },
{ 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 }
};
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);
#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"
}
}
+void PopMime::decompress_alert()
+{
+ DetectionEngine::queue_event(GID_POP, POP_FILE_DECOMP_FAILED);
+}
+
void PopMime::reset_state(Flow* ssn)
{
POP_ResetState(ssn);
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;
};
{ "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)" },
{ 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 }
};
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);
#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"
}
}
+void SmtpMime::decompress_alert()
+{
+ DetectionEngine::queue_event(GID_SMTP, SMTP_FILE_DECOMP_FAILED);
+}
+
void SmtpMime::reset_state(Flow* ssn)
{
SMTP_ResetState(ssn);
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;
};
{ "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" },
{ 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 }
};
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();
#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"