From: Tom Peters (thopeter) Date: Wed, 6 Mar 2019 15:29:36 +0000 (-0500) Subject: Merge pull request #1530 in SNORT/snort3 from ~BRASTULT/snort3:file_decomp_zip to... X-Git-Tag: 3.0.0-251~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c24b8a36125eabd40507399523a60e3c00a9338a;p=thirdparty%2Fsnort3.git Merge pull request #1530 in SNORT/snort3 from ~BRASTULT/snort3:file_decomp_zip to master Squashed commit of the following: commit 57dc105bf414ec66d623de5cbadc31af7c0fdc4b Author: Brandon Stultz Date: Wed Feb 27 19:28:08 2019 -0500 decompress: add zip file decompression --- diff --git a/src/decompress/CMakeLists.txt b/src/decompress/CMakeLists.txt index 27b44e5f0..21ba69be9 100644 --- a/src/decompress/CMakeLists.txt +++ b/src/decompress/CMakeLists.txt @@ -10,6 +10,8 @@ add_library (decompress OBJECT file_decomp_pdf.h file_decomp_swf.cc file_decomp_swf.h + file_decomp_zip.cc + file_decomp_zip.h ) install (FILES ${DECOMPRESS_INCLUDES} diff --git a/src/decompress/file_decomp.cc b/src/decompress/file_decomp.cc index b076f21ee..3749b6e7e 100644 --- a/src/decompress/file_decomp.cc +++ b/src/decompress/file_decomp.cc @@ -31,6 +31,7 @@ #include "file_decomp_pdf.h" #include "file_decomp_swf.h" +#include "file_decomp_zip.h" #ifdef UNIT_TEST #include "catch/snort_catch.h" @@ -44,6 +45,7 @@ static const char SWF_ZLIB_Sig[3] = { 'C', 'W', 'S' }; static const char SWF_LZMA_Sig[3] = { 'Z', 'W', 'S' }; #endif static const char SWF_Uncomp_Sig[3] = { 'F', 'W', 'S' }; +static const char ZIP_Sig[4] = { 'P', 'K', 0x03, 0x04 }; /* Please assure that the following value correlates with the set of sig's */ #define MAX_SIG_LENGTH (5) @@ -64,6 +66,9 @@ static struct sig_map_s #ifdef HAVE_LZMA { SWF_LZMA_Sig, sizeof(SWF_LZMA_Sig), false, FILE_TYPE_SWF, FILE_COMPRESSION_TYPE_LZMA }, #endif + + { ZIP_Sig, sizeof(ZIP_Sig), false, FILE_TYPE_ZIP, FILE_COMPRESSION_TYPE_NONE }, + { nullptr, 0, false, FILE_TYPE_NONE, FILE_COMPRESSION_TYPE_NONE } }; @@ -195,6 +200,9 @@ static fd_status_t Initialize_Decompression(fd_session_t* SessionPtr) Ret_Code = File_Decomp_Init_PDF(SessionPtr); break; } + case ( FILE_TYPE_ZIP ): + Ret_Code = File_Decomp_Init_ZIP(SessionPtr); + break; default: return( File_Decomp_Error ); } @@ -221,6 +229,11 @@ static fd_status_t Process_Decompression(fd_session_t* SessionPtr) Ret_Code = File_Decomp_PDF(SessionPtr); break; } + case ( FILE_TYPE_ZIP ): + { + Ret_Code = File_Decomp_ZIP(SessionPtr); + break; + } default: return( File_Decomp_Error ); } @@ -262,6 +275,10 @@ fd_status_t File_Decomp_Init(fd_session_t* SessionPtr) ((SessionPtr->Modes & FILE_SWF_LZMA_BIT) != 0) ) Signature_Map[Sig].Enabled = true; #endif + + if ( (Signature_Map[Sig].File_Type == FILE_TYPE_ZIP ) && + ((SessionPtr->Modes & FILE_ZIP_DEFL_BIT) != 0) ) + Signature_Map[Sig].Enabled = true; } return( File_Decomp_OK ); @@ -337,6 +354,8 @@ fd_status_t File_Decomp_End(fd_session_t* SessionPtr) { return( File_Decomp_End_PDF(SessionPtr) ); } + case ( FILE_TYPE_ZIP ): + return( File_Decomp_End_ZIP(SessionPtr) ); } return( File_Decomp_Error ); @@ -382,6 +401,10 @@ void File_Decomp_Free(fd_session_t* SessionPtr) assert(SessionPtr->PDF); snort_free(SessionPtr->PDF); break; + case FILE_TYPE_ZIP: + assert(SessionPtr->ZIP); + snort_free(SessionPtr->ZIP); + break; } delete SessionPtr; diff --git a/src/decompress/file_decomp.h b/src/decompress/file_decomp.h index c55a5d56c..4c36c960f 100644 --- a/src/decompress/file_decomp.h +++ b/src/decompress/file_decomp.h @@ -60,9 +60,11 @@ enum file_compression_type_t #define FILE_SWF_LZMA_BIT (0x00000001) #define FILE_SWF_ZLIB_BIT (0x00000002) #define FILE_PDF_DEFL_BIT (0x00000004) +#define FILE_ZIP_DEFL_BIT (0x00000008) #define FILE_PDF_ANY (FILE_PDF_DEFL_BIT) #define FILE_SWF_ANY (FILE_SWF_LZMA_BIT | FILE_SWF_ZLIB_BIT) +#define FILE_ZIP_ANY (FILE_ZIP_DEFL_BIT) /* Error codes either passed to caller via the session->Error_Alert of the File_Decomp_Alert() call-back function. */ @@ -73,7 +75,9 @@ enum FileDecompError FILE_DECOMP_ERR_PDF_DEFL_FAILURE, FILE_DECOMP_ERR_PDF_UNSUP_COMP_TYPE, FILE_DECOMP_ERR_PDF_CASC_COMP, - FILE_DECOMP_ERR_PDF_PARSE_FAILURE + FILE_DECOMP_ERR_PDF_PARSE_FAILURE, + FILE_DECOMP_ERR_ZIP_PARSE_FAILURE, + FILE_DECOMP_ERR_ZIP_DEFL_FAILURE }; /* Private Types */ @@ -82,6 +86,7 @@ enum file_type_t FILE_TYPE_NONE, FILE_TYPE_SWF, FILE_TYPE_PDF, + FILE_TYPE_ZIP, FILE_TYPE_MAX }; @@ -102,6 +107,7 @@ struct fd_session_t { struct fd_PDF_t* PDF; struct fd_SWF_t* SWF; + struct fd_ZIP_t* ZIP; }; const uint8_t* Next_In; // next input byte @@ -257,12 +263,12 @@ inline bool Move_N(fd_session_t* SessionPtr, uint16_t N) if ( (SessionPtr->Next_Out != nullptr) && (SessionPtr->Avail_Out >= N) && (SessionPtr->Next_In != nullptr) && (SessionPtr->Avail_In >= N) ) { - strncpy( (char*)SessionPtr->Next_Out, (const char*)SessionPtr->Next_In, N); + memcpy( (char*)SessionPtr->Next_Out, (const char*)SessionPtr->Next_In, N); SessionPtr->Next_Out += N; SessionPtr->Next_In += N; SessionPtr->Avail_In -= N; SessionPtr->Avail_Out -= N; - SessionPtr->Avail_Out -= N; + SessionPtr->Total_In += N; SessionPtr->Total_Out += N; return( true ); } diff --git a/src/decompress/file_decomp_zip.cc b/src/decompress/file_decomp_zip.cc new file mode 100644 index 000000000..48a66723f --- /dev/null +++ b/src/decompress/file_decomp_zip.cc @@ -0,0 +1,404 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- + +// file_decomp_zip.cc author Brandon Stultz + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "file_decomp_zip.h" +#include "utils/util.h" + +using namespace snort; + +// initialize zlib decompression +static fd_status_t Inflate_Init(fd_session_t* SessionPtr) +{ + z_stream* z_s = &(SessionPtr->ZIP->Stream); + + memset((char*)z_s, 0, sizeof(z_stream)); + + z_s->zalloc = (alloc_func)nullptr; + z_s->zfree = (free_func)nullptr; + + SYNC_IN(z_s) + + int z_ret = inflateInit2(z_s, -MAX_WBITS); + + if ( z_ret != Z_OK ) + return File_Decomp_Error; + + return File_Decomp_OK; +} + +// end zlib decompression +static fd_status_t Inflate_End(fd_session_t* SessionPtr) +{ + z_stream* z_s = &(SessionPtr->ZIP->Stream); + + inflateEnd(z_s); + + return File_Decomp_OK; +} + +// perform zlib decompression +static fd_status_t Inflate(fd_session_t* SessionPtr) +{ + const uint8_t *zlib_start, *zlib_end; + + z_stream* z_s = &(SessionPtr->ZIP->Stream); + + zlib_start = SessionPtr->Next_In; + + SYNC_IN(z_s) + + int z_ret = inflate(z_s, Z_SYNC_FLUSH); + + SYNC_OUT(z_s) + + zlib_end = SessionPtr->Next_In; + + // keep track of decompression progress + SessionPtr->ZIP->progress += zlib_end - zlib_start; + + if ( z_ret == Z_STREAM_END ) + return File_Decomp_Complete; + + if ( z_ret != Z_OK ) + return File_Decomp_Error; + + if ( SessionPtr->Avail_Out == 0 ) + return File_Decomp_BlockOut; + + return File_Decomp_OK; +} + +// allocate and set initial ZIP state +fd_status_t File_Decomp_Init_ZIP(fd_session_t* SessionPtr) +{ + if ( SessionPtr == nullptr ) + return File_Decomp_Error; + + SessionPtr->ZIP = (fd_ZIP_t*)snort_calloc(sizeof(fd_ZIP_t)); + + // file_decomp.cc already matched the local header + // skip the version and bitflag (4 bytes) + SessionPtr->ZIP->State = ZIP_STATE_SKIP; + SessionPtr->ZIP->Length = 4; + + // land on compression method + SessionPtr->ZIP->Next = ZIP_STATE_METHOD; + SessionPtr->ZIP->Next_Length = 2; + + return File_Decomp_OK; +} + +// end ZIP processing +fd_status_t File_Decomp_End_ZIP(fd_session_t* SessionPtr) +{ + if ( SessionPtr == nullptr ) + return File_Decomp_Error; + + // end zlib decompression if we are processing a stream + if ( SessionPtr->ZIP->State == ZIP_STATE_INFLATE ) + Inflate_End(SessionPtr); + + // File_Decomp_Free() will free SessionPtr->ZIP + return File_Decomp_OK; +} + +// run the ZIP state machine +fd_status_t File_Decomp_ZIP(fd_session_t* SessionPtr) +{ + uint8_t byte; + + if ( SessionPtr == nullptr ) + return File_Decomp_Error; + + fd_ZIP_t* parser = SessionPtr->ZIP; + + // while we have data to read in the stream + while ( SessionPtr->Avail_In > 0 ) + { + if ( SessionPtr->Next_In == nullptr ) + return File_Decomp_Error; + + switch ( parser->State ) + { + // local header + case ZIP_STATE_LH: + // check if we are done with the local_header + if ( parser->Index == parser->Length ) + { + // check if we read a local_header + if ( parser->local_header != ZIP_LOCAL_HEADER ) + return File_Decomp_Complete; + + // read a local_header, reset the index + parser->Index = 0; + + // reset ZIP fields + parser->local_header = 0; + parser->method = 0; + parser->compressed_size = 0; + parser->filename_length = 0; + parser->extra_length = 0; + + // reset decompression progress + parser->progress = 0; + + // skip the version and bitflag (4 bytes) + parser->State = ZIP_STATE_SKIP; + parser->Length = 4; + + // land on compression method + parser->Next = ZIP_STATE_METHOD; + parser->Next_Length = 2; + continue; + } + // read the local header + byte = *SessionPtr->Next_In; + parser->local_header |= byte << parser->Index*8; + break; + // compression method + case ZIP_STATE_METHOD: + // check if we are done with the method + if ( parser->Index == parser->Length ) + { + // read the method, reset the index + parser->Index = 0; + + // skip: + // modtime(2), moddate(2), crc(4) = 8 bytes + parser->State = ZIP_STATE_SKIP; + parser->Length = 8; + + // land on compressed size + parser->Next = ZIP_STATE_COMPSIZE; + parser->Next_Length = 4; + continue; + } + // read the method + byte = *SessionPtr->Next_In; + parser->method |= byte << parser->Index*8; + break; + // compressed size + case ZIP_STATE_COMPSIZE: + // check if we are done with the compressed size + if ( parser->Index == parser->Length ) + { + // read the compressed size, reset the index + parser->Index = 0; + + // skip the uncompressed size (4 bytes) + parser->State = ZIP_STATE_SKIP; + parser->Length = 4; + + // land on filename length + parser->Next = ZIP_STATE_FILENAMELEN; + parser->Next_Length = 2; + continue; + } + // read the compressed size + byte = *SessionPtr->Next_In; + parser->compressed_size |= byte << parser->Index*8; + break; + // filename length + case ZIP_STATE_FILENAMELEN: + // check if we are done with the filename length + if ( parser->Index == parser->Length ) + { + // read the filename length, reset the index + parser->Index = 0; + + // read the extra field length next + parser->State = ZIP_STATE_EXTRALEN; + parser->Length = 2; + continue; + } + // read the filename length + byte = *SessionPtr->Next_In; + parser->filename_length |= byte << parser->Index*8; + break; + // extra length + case ZIP_STATE_EXTRALEN: + // check if we are done with the extra length + if ( parser->Index == parser->Length ) + { + // read the extra length, reset the index + parser->Index = 0; + + // skip the filename and extra fields + parser->State = ZIP_STATE_SKIP; + parser->Length = parser->filename_length + parser->extra_length; + + if ( (SessionPtr->Avail_Out > 0) && (parser->method == 8) ) + { + // we have available output space and + // the compression type is deflate (8), + // land on the compressed stream, init zlib + parser->Next = ZIP_STATE_INFLATE_INIT; + parser->Next_Length = parser->compressed_size; + continue; + } + + // no output space or compression type isn't deflate, skip the stream + parser->Length += parser->compressed_size; + + // land on another local header + parser->Next = ZIP_STATE_LH; + parser->Next_Length = 4; + continue; + } + // read the extra length + byte = *SessionPtr->Next_In; + parser->extra_length |= byte << parser->Index*8; + break; + // initialize zlib inflate + case ZIP_STATE_INFLATE_INIT: + parser->State = ZIP_STATE_INFLATE; + + if ( Inflate_Init(SessionPtr) == File_Decomp_Error ) + return File_Decomp_Error; + + // fallthrough + // perform zlib inflate + case ZIP_STATE_INFLATE: + { + // run inflate + fd_status_t status = Inflate(SessionPtr); + + if ( status == File_Decomp_Error ) + { + // error inflating the stream + // File_Decomp_End_ZIP() will + // close the inflate stream + return File_Decomp_Error; + } + + if ( status == File_Decomp_BlockOut ) + { + // ran out of output space + // progress should be < compressed_size + if ( parser->progress >= parser->compressed_size ) + return File_Decomp_Error; + + // close the inflate stream + Inflate_End(SessionPtr); + + // skip the rest of the stream + parser->State = ZIP_STATE_SKIP; + parser->Length = parser->compressed_size - parser->progress; + + // land on another local header + parser->Next = ZIP_STATE_LH; + parser->Next_Length = 4; + continue; + } + + if ( status == File_Decomp_Complete ) + { + // done decompressing the stream + // close the inflate stream + Inflate_End(SessionPtr); + + // parse next local header + parser->State = ZIP_STATE_LH; + parser->Length = 4; + continue; + } + + // keep the inflate stream open + // circle back for more input + return File_Decomp_OK; + } + // skip state + case ZIP_STATE_SKIP: + // check if we need to skip + if ( parser->Index < parser->Length ) + { + unsigned skip = parser->Length - parser->Index; + + // check if we can skip within this flush + if ( SessionPtr->Avail_In < skip ) + { + // the available input is < skip + parser->Index += SessionPtr->Avail_In; + + unsigned min = SessionPtr->Avail_In < SessionPtr->Avail_Out ? + SessionPtr->Avail_In : SessionPtr->Avail_Out; + + // copy what we can + Move_N(SessionPtr, min); + + // get more input + return File_Decomp_BlockIn; + } + + if ( SessionPtr->Avail_Out < skip ) + { + // the available input is >= skip + // the available output is < skip <= available input + skip -= SessionPtr->Avail_Out; + // copy what we can + Move_N(SessionPtr, SessionPtr->Avail_Out); + // available output is now 0 + // skip the rest + SessionPtr->Next_In += skip; + SessionPtr->Avail_In -= skip; + SessionPtr->Total_In += skip; + // done skipping, index should be 0 + } + else + { + // the available input is >= skip + // the available output is >= skip + // copy skip bytes from input to output + Move_N(SessionPtr, skip); + // done skipping, index should be 0 + } + } + // done skipping, reset the index + parser->Index = 0; + + // switch to the next state + parser->State = parser->Next; + parser->Length = parser->Next_Length; + continue; + } + + // make sure we can write a byte + if ( SessionPtr->Avail_Out > 0 ) + { + // advance and copy the stream + Move_1(SessionPtr); + } + else + { + // advance the stream + SessionPtr->Next_In += 1; + SessionPtr->Avail_In -= 1; + SessionPtr->Total_In += 1; + } + + parser->Index++; + } + + return File_Decomp_BlockIn; +} diff --git a/src/decompress/file_decomp_zip.h b/src/decompress/file_decomp_zip.h new file mode 100644 index 000000000..fe82f9731 --- /dev/null +++ b/src/decompress/file_decomp_zip.h @@ -0,0 +1,99 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- + +// file_decomp_zip.h author Brandon Stultz + +#ifndef FILE_DECOMP_ZIP_H +#define FILE_DECOMP_ZIP_H + +#include "file_decomp.h" + +#include + +static const uint32_t ZIP_LOCAL_HEADER = 0x04034B50; + +enum fd_ZIP_states +{ + ZIP_STATE_LH, // local header (4 bytes) + + // skipped: + // ZIP_STATE_VER, // version (2 bytes) + // ZIP_STATE_BITFLAG, // bitflag (2 bytes) + + ZIP_STATE_METHOD, // compression method (2 bytes) + + // skipped: + // ZIP_STATE_MODTIME, // modification time (2 bytes) + // ZIP_STATE_MODDATE, // modification date (2 bytes) + // ZIP_STATE_CRC, // CRC-32 (4 bytes) + + ZIP_STATE_COMPSIZE, // compressed size (4 bytes) + + // skipped: + // ZIP_STATE_UNCOMPSIZE, // uncompressed size (4 bytes) + + ZIP_STATE_FILENAMELEN, // filename length (2 bytes) + ZIP_STATE_EXTRALEN, // extra field length (2 bytes) + + // skipped: + // ZIP_STATE_FILENAME, // filename field (filenamelen bytes) + // ZIP_STATE_EXTRA, // extra field (extralen bytes) + // ZIP_STATE_STREAM, // compressed stream (compsize bytes) + + ZIP_STATE_INFLATE_INIT, // initialize zlib inflate + ZIP_STATE_INFLATE, // perform zlib inflate + ZIP_STATE_SKIP // skip state +}; + +struct fd_ZIP_t +{ + // zlib stream + z_stream Stream; + + // decompression progress + unsigned progress; + + // ZIP fields + uint32_t local_header; + uint16_t method; + uint32_t compressed_size; + uint16_t filename_length; + uint16_t extra_length; + + // field index + unsigned Index; + + // current parser state + fd_ZIP_states State; + unsigned Length; + + // next parser state + fd_ZIP_states Next; + unsigned Next_Length; +}; + +// allocate and set initial ZIP state +fd_status_t File_Decomp_Init_ZIP(fd_session_t*); + +// end ZIP processing +fd_status_t File_Decomp_End_ZIP(fd_session_t*); + +// run the ZIP state machine +fd_status_t File_Decomp_ZIP(fd_session_t*); + +#endif diff --git a/src/service_inspectors/http_inspect/http_enum.h b/src/service_inspectors/http_inspect/http_enum.h index 1bb26d78b..d4b186833 100644 --- a/src/service_inspectors/http_inspect/http_enum.h +++ b/src/service_inspectors/http_inspect/http_enum.h @@ -215,7 +215,7 @@ enum Infraction INF_PDF_UNSUP_COMP_TYPE, INF_PDF_CASC_COMP, INF_PDF_PARSE_FAILURE, - INF_PDF_SWF_OVERRUN, + INF_FILE_DECOMPR_OVERRUN, INF_BAD_CHAR_IN_HEADER_NAME, INF_HEADER_WRAPPING, INF_CHUNK_BAD_SEP, @@ -330,7 +330,7 @@ enum EventSid EVENT_UNKNOWN_ENCODING, EVENT_STACKED_ENCODINGS, EVENT_RESPONSE_WO_REQUEST, - EVENT_PDF_SWF_OVERRUN, + EVENT_FILE_DECOMPR_OVERRUN, EVENT_BAD_CHAR_IN_HEADER_NAME, // 230 EVENT_BAD_CONTENT_LENGTH, EVENT_HEADER_WRAPPING, diff --git a/src/service_inspectors/http_inspect/http_module.cc b/src/service_inspectors/http_inspect/http_module.cc index c5f310113..4f3c90207 100644 --- a/src/service_inspectors/http_inspect/http_module.cc +++ b/src/service_inspectors/http_inspect/http_module.cc @@ -51,6 +51,9 @@ const Parameter HttpModule::http_params[] = { "decompress_swf", Parameter::PT_BOOL, nullptr, "false", "decompress swf files in response bodies" }, + { "decompress_zip", Parameter::PT_BOOL, nullptr, "false", + "decompress zip files in response bodies" }, + { "normalize_javascript", Parameter::PT_BOOL, nullptr, "false", "normalize javascript in response bodies" }, @@ -160,6 +163,10 @@ bool HttpModule::set(const char*, Value& val, SnortConfig*) { params->decompress_swf = val.get_bool(); } + else if (val.is("decompress_zip")) + { + params->decompress_zip = val.get_bool(); + } else if (val.is("normalize_javascript")) { params->js_norm_param.normalize_javascript = val.get_bool(); diff --git a/src/service_inspectors/http_inspect/http_module.h b/src/service_inspectors/http_inspect/http_module.h index 5ddcbaa31..cfec45b23 100644 --- a/src/service_inspectors/http_inspect/http_module.h +++ b/src/service_inspectors/http_inspect/http_module.h @@ -41,6 +41,7 @@ public: bool normalize_utf = true; bool decompress_pdf = false; bool decompress_swf = false; + bool decompress_zip = false; struct JsNormParam { diff --git a/src/service_inspectors/http_inspect/http_msg_body.cc b/src/service_inspectors/http_inspect/http_msg_body.cc index 24e372d80..7f5429ccf 100644 --- a/src/service_inspectors/http_inspect/http_msg_body.cc +++ b/src/service_inspectors/http_inspect/http_msg_body.cc @@ -49,8 +49,8 @@ void HttpMsgBody::analyze() if (session_data->detect_depth_remaining[source_id] > 0) { - do_pdf_swf_decompression(decoded_body, decompressed_pdf_swf_body); - do_js_normalization(decompressed_pdf_swf_body, js_norm_body); + do_file_decompression(decoded_body, decompressed_file_body); + do_js_normalization(decompressed_file_body, js_norm_body); const int32_t detect_length = (js_norm_body.length() <= session_data->detect_depth_remaining[source_id]) ? js_norm_body.length() : session_data->detect_depth_remaining[source_id]; @@ -111,7 +111,7 @@ void HttpMsgBody::do_utf_decoding(const Field& input, Field& output) output.set(input); } -void HttpMsgBody::do_pdf_swf_decompression(const Field& input, Field& output) +void HttpMsgBody::do_file_decompression(const Field& input, Field& output) { if ((source_id == SRC_CLIENT) || (session_data->fd_state == nullptr)) { @@ -141,8 +141,8 @@ void HttpMsgBody::do_pdf_swf_decompression(const Field& input, Field& output) session_data->fd_state = nullptr; break; case File_Decomp_BlockOut: - add_infraction(INF_PDF_SWF_OVERRUN); - create_event(EVENT_PDF_SWF_OVERRUN); + add_infraction(INF_FILE_DECOMPR_OVERRUN); + create_event(EVENT_FILE_DECOMPR_OVERRUN); // Fall through default: output.set(session_data->fd_state->Next_Out - buffer, buffer, true); diff --git a/src/service_inspectors/http_inspect/http_msg_body.h b/src/service_inspectors/http_inspect/http_msg_body.h index 320010e29..d49beb3ec 100644 --- a/src/service_inspectors/http_inspect/http_msg_body.h +++ b/src/service_inspectors/http_inspect/http_msg_body.h @@ -53,13 +53,13 @@ protected: private: void do_file_processing(Field& file_data); void do_utf_decoding(const Field& input, Field& output); - void do_pdf_swf_decompression(const Field& input, Field& output); + void do_file_decompression(const Field& input, Field& output); void do_js_normalization(const Field& input, Field& output); Field detect_data; Field classic_client_body; // URI normalization applied Field decoded_body; - Field decompressed_pdf_swf_body; + Field decompressed_file_body; Field js_norm_body; const bool detection_section; }; diff --git a/src/service_inspectors/http_inspect/http_msg_header.cc b/src/service_inspectors/http_inspect/http_msg_header.cc index 142466351..8c1e75b7f 100644 --- a/src/service_inspectors/http_inspect/http_msg_header.cc +++ b/src/service_inspectors/http_inspect/http_msg_header.cc @@ -303,7 +303,7 @@ void HttpMsgHeader::prepare_body() setup_file_processing(); setup_encoding_decompression(); setup_utf_decoding(); - setup_pdf_swf_decompression(); + setup_file_decompression(); update_depth(); if (source_id == SRC_CLIENT) { @@ -481,15 +481,17 @@ void HttpMsgHeader::setup_utf_decoding() session_data->utf_state->set_decode_utf_state_charset(charset_code); } -void HttpMsgHeader::setup_pdf_swf_decompression() +void HttpMsgHeader::setup_file_decompression() { - if (source_id == SRC_CLIENT || (!params->decompress_pdf && !params->decompress_swf)) + if (source_id == SRC_CLIENT || + (!params->decompress_pdf && !params->decompress_swf && !params->decompress_zip)) return; session_data->fd_state = File_Decomp_New(); session_data->fd_state->Modes = (params->decompress_pdf ? FILE_PDF_DEFL_BIT : 0) | - (params->decompress_swf ? (FILE_SWF_ZLIB_BIT | FILE_SWF_LZMA_BIT) : 0); + (params->decompress_swf ? (FILE_SWF_ZLIB_BIT | FILE_SWF_LZMA_BIT) : 0) | + (params->decompress_zip ? FILE_ZIP_DEFL_BIT : 0); session_data->fd_state->Alert_Callback = HttpMsgBody::fd_event_callback; session_data->fd_state->Alert_Context = &session_data->fd_alert_context; session_data->fd_state->Compr_Depth = 0; diff --git a/src/service_inspectors/http_inspect/http_msg_header.h b/src/service_inspectors/http_inspect/http_msg_header.h index 3ba0f1c32..2c00c1ab4 100644 --- a/src/service_inspectors/http_inspect/http_msg_header.h +++ b/src/service_inspectors/http_inspect/http_msg_header.h @@ -49,7 +49,7 @@ private: void setup_file_processing(); void setup_encoding_decompression(); void setup_utf_decoding(); - void setup_pdf_swf_decompression(); + void setup_file_decompression(); // Dummy configurations to support MIME processing MailLogConfig mime_conf; diff --git a/src/service_inspectors/http_inspect/http_tables.cc b/src/service_inspectors/http_inspect/http_tables.cc index 54c2c91df..fb5f9ea30 100644 --- a/src/service_inspectors/http_inspect/http_tables.cc +++ b/src/service_inspectors/http_inspect/http_tables.cc @@ -355,7 +355,7 @@ const snort::RuleMap HttpModule::http_events[] = { EVENT_UNKNOWN_ENCODING, "unknown Content-Encoding used" }, { EVENT_STACKED_ENCODINGS, "multiple Content-Encodings applied" }, { EVENT_RESPONSE_WO_REQUEST, "server response before client request" }, - { EVENT_PDF_SWF_OVERRUN, "PDF/SWF decompression of server response too big" }, + { EVENT_FILE_DECOMPR_OVERRUN, "PDF/SWF/ZIP decompression of server response too big" }, { EVENT_BAD_CHAR_IN_HEADER_NAME, "nonprinting character in HTTP message header name" }, { EVENT_BAD_CONTENT_LENGTH, "bad Content-Length value in HTTP header" }, { EVENT_HEADER_WRAPPING, "HTTP header line wrapped" },