diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index be5f97ddef..74bd51d4b5 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -2753,6 +2753,16 @@ export { } # end export +module MIME; +export { + ## Stop analysis of nested multipart MIME entities if this depth is + ## reached. Setting this value to 0 removes the limit. + const max_depth = 100 &redef; + +} # end export + + + module MOUNT3; export { diff --git a/src/analyzer/protocol/mime/CMakeLists.txt b/src/analyzer/protocol/mime/CMakeLists.txt index 774766d2d8..86cccb9b2e 100644 --- a/src/analyzer/protocol/mime/CMakeLists.txt +++ b/src/analyzer/protocol/mime/CMakeLists.txt @@ -10,4 +10,5 @@ zeek_add_plugin( MIME.cc Plugin.cc BIFS + consts.bif events.bif) diff --git a/src/analyzer/protocol/mime/MIME.cc b/src/analyzer/protocol/mime/MIME.cc index 22ccfb4899..d136e86fee 100644 --- a/src/analyzer/protocol/mime/MIME.cc +++ b/src/analyzer/protocol/mime/MIME.cc @@ -5,6 +5,7 @@ #include "zeek/Base64.h" #include "zeek/NetVar.h" #include "zeek/Reporter.h" +#include "zeek/analyzer/protocol/mime/consts.bif.h" #include "zeek/analyzer/protocol/mime/events.bif.h" #include "zeek/digest.h" #include "zeek/file_analysis/Manager.h" @@ -531,7 +532,10 @@ MIME_Entity::MIME_Entity(MIME_Message* output_message, MIME_Entity* parent_entit parent = parent_entity; message = output_message; if ( parent ) + { content_encoding = parent->ContentTransferEncoding(); + depth = parent->Depth() + 1; + } want_all_headers = (bool)mime_all_headers; } @@ -560,6 +564,7 @@ void MIME_Entity::init() base64_decoder = nullptr; + depth = 0; data_buf_length = 0; data_buf_data = nullptr; data_buf_offset = -1; @@ -1250,6 +1255,21 @@ void MIME_Entity::SubmitAllHeaders() void MIME_Entity::BeginChildEntity() { ASSERT(current_child_entity == nullptr); + + // If the maximum depth for analysis is reached, don't create a new + // child entity. Instead, its header/body will be delivered to the + // current entity. + if ( zeek::BifConst::MIME::max_depth > 0 && Depth() >= zeek::BifConst::MIME::max_depth ) + { + if ( message->GetAnalyzer() ) + { + const char* addl = zeek::util::fmt("%" PRIu64, Depth()); + message->GetAnalyzer()->Weird("exceeded_mime_max_depth", addl); + } + + return; + } + current_child_entity = NewChildEntity(); message->BeginEntity(current_child_entity); } diff --git a/src/analyzer/protocol/mime/MIME.h b/src/analyzer/protocol/mime/MIME.h index 80dbca02b7..fd5008adf3 100644 --- a/src/analyzer/protocol/mime/MIME.h +++ b/src/analyzer/protocol/mime/MIME.h @@ -109,6 +109,7 @@ public: virtual void EndOfData(); MIME_Entity* Parent() const { return parent; } + zeek_uint_t Depth() const { return depth; }; int MIMEContentType() const { return content_type; } const StringValPtr& GetContentType() const { return content_type_str; } const StringValPtr& GetContentSubType() const { return content_subtype_str; } @@ -180,6 +181,7 @@ protected: zeek::detail::Base64Converter* base64_decoder; + zeek_uint_t depth; int data_buf_length; char* data_buf_data; int data_buf_offset; diff --git a/src/analyzer/protocol/mime/consts.bif b/src/analyzer/protocol/mime/consts.bif new file mode 100644 index 0000000000..c8d7317c2e --- /dev/null +++ b/src/analyzer/protocol/mime/consts.bif @@ -0,0 +1 @@ +const MIME::max_depth: count; diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index f7ca106dc0..259f659353 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -175,6 +175,7 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/plugins/Zeek_KRB.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Login.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Login.functions.bif.zeek + build/scripts/base/bif/plugins/Zeek_MIME.consts.bif.zeek build/scripts/base/bif/plugins/Zeek_MIME.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Modbus.events.bif.zeek build/scripts/base/bif/plugins/Zeek_MQTT.types.bif.zeek diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index ce766b6a49..97c3679d08 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -175,6 +175,7 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/plugins/Zeek_KRB.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Login.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Login.functions.bif.zeek + build/scripts/base/bif/plugins/Zeek_MIME.consts.bif.zeek build/scripts/base/bif/plugins/Zeek_MIME.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Modbus.events.bif.zeek build/scripts/base/bif/plugins/Zeek_MQTT.types.bif.zeek diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index 43b14bb70c..67a989ff5c 100644 --- a/testing/btest/Baseline/plugins.hooks/output +++ b/testing/btest/Baseline/plugins.hooks/output @@ -381,6 +381,7 @@ 0.000000 MetaHookPost LoadFile(0, ./Zeek_KRB.types.bif.zeek, <...>/Zeek_KRB.types.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_Login.events.bif.zeek, <...>/Zeek_Login.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_Login.functions.bif.zeek, <...>/Zeek_Login.functions.bif.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, ./Zeek_MIME.consts.bif.zeek, <...>/Zeek_MIME.consts.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_MIME.events.bif.zeek, <...>/Zeek_MIME.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_MQTT.events.bif.zeek, <...>/Zeek_MQTT.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_MQTT.types.bif.zeek, <...>/Zeek_MQTT.types.bif.zeek) -> -1 @@ -666,6 +667,7 @@ 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_KRB.types.bif.zeek, <...>/Zeek_KRB.types.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_Login.events.bif.zeek, <...>/Zeek_Login.events.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_Login.functions.bif.zeek, <...>/Zeek_Login.functions.bif.zeek) -> (-1, ) +0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_MIME.consts.bif.zeek, <...>/Zeek_MIME.consts.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_MIME.events.bif.zeek, <...>/Zeek_MIME.events.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_MQTT.events.bif.zeek, <...>/Zeek_MQTT.events.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_MQTT.types.bif.zeek, <...>/Zeek_MQTT.types.bif.zeek) -> (-1, ) @@ -1295,6 +1297,7 @@ 0.000000 MetaHookPre LoadFile(0, ./Zeek_KRB.types.bif.zeek, <...>/Zeek_KRB.types.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_Login.events.bif.zeek, <...>/Zeek_Login.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_Login.functions.bif.zeek, <...>/Zeek_Login.functions.bif.zeek) +0.000000 MetaHookPre LoadFile(0, ./Zeek_MIME.consts.bif.zeek, <...>/Zeek_MIME.consts.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_MIME.events.bif.zeek, <...>/Zeek_MIME.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_MQTT.events.bif.zeek, <...>/Zeek_MQTT.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_MQTT.types.bif.zeek, <...>/Zeek_MQTT.types.bif.zeek) @@ -1580,6 +1583,7 @@ 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_KRB.types.bif.zeek, <...>/Zeek_KRB.types.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_Login.events.bif.zeek, <...>/Zeek_Login.events.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_Login.functions.bif.zeek, <...>/Zeek_Login.functions.bif.zeek) +0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_MIME.consts.bif.zeek, <...>/Zeek_MIME.consts.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_MIME.events.bif.zeek, <...>/Zeek_MIME.events.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_MQTT.events.bif.zeek, <...>/Zeek_MQTT.events.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_MQTT.types.bif.zeek, <...>/Zeek_MQTT.types.bif.zeek) @@ -2208,6 +2212,7 @@ 0.000000 | HookLoadFile ./Zeek_KRB.types.bif.zeek <...>/Zeek_KRB.types.bif.zeek 0.000000 | HookLoadFile ./Zeek_Login.events.bif.zeek <...>/Zeek_Login.events.bif.zeek 0.000000 | HookLoadFile ./Zeek_Login.functions.bif.zeek <...>/Zeek_Login.functions.bif.zeek +0.000000 | HookLoadFile ./Zeek_MIME.consts.bif.zeek <...>/Zeek_MIME.consts.bif.zeek 0.000000 | HookLoadFile ./Zeek_MIME.events.bif.zeek <...>/Zeek_MIME.events.bif.zeek 0.000000 | HookLoadFile ./Zeek_MQTT.events.bif.zeek <...>/Zeek_MQTT.events.bif.zeek 0.000000 | HookLoadFile ./Zeek_MQTT.types.bif.zeek <...>/Zeek_MQTT.types.bif.zeek @@ -2493,6 +2498,7 @@ 0.000000 | HookLoadFileExtended ./Zeek_KRB.types.bif.zeek <...>/Zeek_KRB.types.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_Login.events.bif.zeek <...>/Zeek_Login.events.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_Login.functions.bif.zeek <...>/Zeek_Login.functions.bif.zeek +0.000000 | HookLoadFileExtended ./Zeek_MIME.consts.bif.zeek <...>/Zeek_MIME.consts.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_MIME.events.bif.zeek <...>/Zeek_MIME.events.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_MQTT.events.bif.zeek <...>/Zeek_MQTT.events.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_MQTT.types.bif.zeek <...>/Zeek_MQTT.types.bif.zeek diff --git a/testing/btest/Baseline/scripts.base.protocols.http.deeply-nested-mime/http.log b/testing/btest/Baseline/scripts.base.protocols.http.deeply-nested-mime/http.log new file mode 100644 index 0000000000..f4096b6a73 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.deeply-nested-mime/http.log @@ -0,0 +1,12 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer version user_agent origin request_body_len response_body_len status_code status_msg info_code info_msg tags username password proxied orig_fuids orig_filenames orig_mime_types resp_fuids resp_filenames resp_mime_types +#types time string addr port addr port count string string string string string string string count count count string count string set[enum] string string set[string] vector[string] vector[string] vector[string] vector[string] vector[string] vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 48724 127.0.0.1 8080 1 POST localhost:8080 / - 1.0 python-requests/2.25.1 - 0 497 501 Unsupported method ('POST') - - (empty) - - - Fx3nQj3PL606RGh4A5,Fdjahd1XxlaUKC7vn8,Fe52j84XySnHI9mUz3,FxA6cG3PA85BxWwwue,FXB5842rxVtgRiI2Vb,Fw9fsX12UMGC0mGdXa,Fl4MFh2QO56Q341Pta,FYZdwQ25lK4xMv9Qob,FTr1zV3F6Fwdhnw5Ik,F6LDXlarWo5lMUQOi,F7m83Od9JOgipOzrc,FVzPLi3cocOyPUvib5,FH7s3jYnZ1R4gqO1g,FrlqlF3HqNAWohppk1,FobeqY2mIbUTMYzkva - text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain,text/plain FWhx6m3AbtxIJtthb - text/html +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 48724 127.0.0.1 8080 2 - - - - - - - 39686 0 - - - - (empty) - - - - - - - - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.http.deeply-nested-mime/weird.log b/testing/btest/Baseline/scripts.base.protocols.http.deeply-nested-mime/weird.log new file mode 100644 index 0000000000..0c85ed52de --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.deeply-nested-mime/weird.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path weird +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source +#types time string addr port addr port string string bool string string +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 48724 127.0.0.1 8080 exceeded_mime_max_depth 100 F zeek HTTP +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/http/deeply-nested-mime.pcap b/testing/btest/Traces/http/deeply-nested-mime.pcap new file mode 100644 index 0000000000..021acd6991 Binary files /dev/null and b/testing/btest/Traces/http/deeply-nested-mime.pcap differ diff --git a/testing/btest/scripts/base/protocols/http/deeply-nested-mime.zeek b/testing/btest/scripts/base/protocols/http/deeply-nested-mime.zeek new file mode 100644 index 0000000000..0def245e5b --- /dev/null +++ b/testing/btest/scripts/base/protocols/http/deeply-nested-mime.zeek @@ -0,0 +1,7 @@ +# @TEST-DOC: HTTP POST request with 100 nestesd message/rfc822 entities, causing an analysis depth of 200 or so, Zeek stops at 100 and produces a weird. +# +# @TEST-EXEC: zeek -b -r $TRACES/http/deeply-nested-mime.pcap %INPUT +# @TEST-EXEC: btest-diff http.log +# @TEST-EXEC: btest-diff weird.log + +@load base/protocols/http