From 9e61bfd0108f5e47c6cd124ca35fdf47a228d400 Mon Sep 17 00:00:00 2001 From: xb-anssi <149695709+xb-anssi@users.noreply.github.com> Date: Fri, 3 Nov 2023 13:21:16 +0100 Subject: [PATCH] Let signature framework match HTTP body end The HTTP analyzer never tells the signature framework when the body of a request or a response ends, so any signature regex ending in a '$' used in an 'http-request-body' or in an 'http-reply-body' condition will never match. This made it impossible to write a signature which could distinguish an HTTP body consisting only of something from an HTTP body prefixed by that same something. - Fix: The fix notifies the signature framework on EndOfData() that there will be no further data to match for this body by giving it an empty buffer of length 0 with the eol parameter set to true and all others set to false. This lets it reach the '$' state in its DFA, and doesn't affect other documented HTTP match behaviours. - Limitation: Since the signature framework doesn't appear to keep previously consumed data on hand, any match of an http-*-body condition whose patterns ends with a '$' will lead to an empty data parameter being passed to the signature_match() event because the body data is no longer available when EndOfData() happens. Due to segmentation there is anyway no guarantee the data parameter would have held the entire match even without the '$', since the data parameter only receives the last chunk of data which completed the match condition, as can be seen on prefix matches in the btest cases where the matching data spans multiple segments (the event gives 'B' and not 'AB'), so this is only an extreme case of partial data being given to that event. --- src/analyzer/protocol/http/HTTP.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/analyzer/protocol/http/HTTP.cc b/src/analyzer/protocol/http/HTTP.cc index 863c65ad02..4a0fd83201 100644 --- a/src/analyzer/protocol/http/HTTP.cc +++ b/src/analyzer/protocol/http/HTTP.cc @@ -69,6 +69,12 @@ void HTTP_Entity::EndOfData() { encoding = IDENTITY; } + zeek::detail::Rule::PatternType rule = + http_message->IsOrig() ? zeek::detail::Rule::HTTP_REQUEST_BODY : zeek::detail::Rule::HTTP_REPLY_BODY; + + http_message->MyHTTP_Analyzer()->Conn()->Match(rule, reinterpret_cast(""), 0, + http_message->IsOrig(), false, true, false); + if ( body_length ) http_message->MyHTTP_Analyzer()->ForwardEndOfData(http_message->IsOrig());