From: Mike Stepanek (mstepane) Date: Fri, 4 Oct 2019 18:09:44 +0000 (-0400) Subject: Merge pull request #1779 in SNORT/snort3 from ~DERAMADA/snort3:h2i_validate_connectio... X-Git-Tag: 3.0.0-262~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=353b337e83d56079671b892f38c91a9de4837a58;p=thirdparty%2Fsnort3.git Merge pull request #1779 in SNORT/snort3 from ~DERAMADA/snort3:h2i_validate_connection_preface to master Squashed commit of the following: commit 7391aa89fb2f7b2c274ec8966c63fa22b2f86b27 Author: deramada Date: Wed Oct 2 15:29:09 2019 -0400 http2_inspect: validate connection preface --- diff --git a/src/service_inspectors/http2_inspect/http2_enum.h b/src/service_inspectors/http2_inspect/http2_enum.h index 55590f832..cf02cbe17 100644 --- a/src/service_inspectors/http2_inspect/http2_enum.h +++ b/src/service_inspectors/http2_inspect/http2_enum.h @@ -52,6 +52,7 @@ enum EventSid EVENT_STRING_DECODE_FAILURE = 3, EVENT_MISSING_CONTINUATION = 4, EVENT_UNEXPECTED_CONTINUATION = 5, + EVENT_PREFACE_MATCH_FAILURE = 7, EVENT__MAX_VALUE }; diff --git a/src/service_inspectors/http2_inspect/http2_inspect.cc b/src/service_inspectors/http2_inspect/http2_inspect.cc index e8b84060e..e893ff56e 100644 --- a/src/service_inspectors/http2_inspect/http2_inspect.cc +++ b/src/service_inspectors/http2_inspect/http2_inspect.cc @@ -113,6 +113,11 @@ void Http2Inspect::eval(Packet* p) (int) session_data->frame_data_size[source_id] : HttpCommon::STAT_NOT_PRESENT, session_data->frame_data[source_id]).print(HttpTestManager::get_output_file(), "Frame Data"); + if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2)) + { + printf("Finished processing section from test %" PRIi64 "\n", + HttpTestManager::get_test_number()); + } } #endif } diff --git a/src/service_inspectors/http2_inspect/http2_stream_splitter.h b/src/service_inspectors/http2_inspect/http2_stream_splitter.h index 12bcb1377..167353e61 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter.h +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter.h @@ -54,5 +54,10 @@ const snort::StreamBuffer implement_reassemble(Http2FlowData* session_data, unsi unsigned offset, const uint8_t* data, unsigned len, uint32_t flags, HttpCommon::SourceId source_id); +enum ValidationResult { V_GOOD, V_BAD, V_TBD }; + +ValidationResult validate_preface(const uint8_t* data, const uint32_t length, + const uint32_t octets_seen); + #endif diff --git a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc index 91d5efe5d..9c31c68b7 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc @@ -45,14 +45,22 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t if (session_data->preface[source_id]) { // 24-byte preface, not a real frame, no frame header - const uint32_t preface_length = 24; - if (session_data->octets_seen[source_id] + length < preface_length) + // Verify preface is correct, else generate loss of sync event and abort + switch (validate_preface(data, length, session_data->octets_seen[source_id])) { - session_data->octets_seen[source_id] += length; - return status = StreamSplitter::SEARCH; + case V_GOOD: + break; + case V_BAD: + session_data->events[source_id]->create_event(EVENT_PREFACE_MATCH_FAILURE); + // FIXIT-H: Workaround till abort is implemented + if((session_data->octets_seen[source_id] + length) >= 24) + break; + // Falls through + case V_TBD: + session_data->octets_seen[source_id] += length; + return StreamSplitter::SEARCH; } - //FIXIT-M verify preface is correct, else generate loss of sync event and abort *flush_offset = 24 - session_data->octets_seen[source_id]; session_data->header_coming[source_id] = false; session_data->preface[source_id] = false; @@ -324,3 +332,24 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to return frame_buf; } +ValidationResult validate_preface(const uint8_t* data, const uint32_t length, + const uint32_t octets_seen) +{ + const uint32_t preface_length = 24; + + static const uint8_t connection_prefix[] = {'P', 'R', 'I', ' ', '*', ' ', + 'H', 'T', 'T', 'P', '/', '2', '.', '0', '\r', '\n', '\r', '\n', 'S', 'M', + '\r', '\n', '\r', '\n'}; + + assert(octets_seen < preface_length); + + const uint32_t count = (octets_seen + length) < preface_length ? length : (preface_length - octets_seen); + + if (memcmp(data, connection_prefix + octets_seen, count)) + return V_BAD; + + if ((octets_seen + length) < preface_length) + return V_TBD; + + return V_GOOD; +} diff --git a/src/service_inspectors/http2_inspect/http2_tables.cc b/src/service_inspectors/http2_inspect/http2_tables.cc index bf1686e8a..8620f5f6e 100644 --- a/src/service_inspectors/http2_inspect/http2_tables.cc +++ b/src/service_inspectors/http2_inspect/http2_tables.cc @@ -35,6 +35,7 @@ const snort::RuleMap Http2Module::http2_events[] = { EVENT_STRING_DECODE_FAILURE, "error in HPACK string value" }, { EVENT_MISSING_CONTINUATION, "missing continuation frame"}, { EVENT_UNEXPECTED_CONTINUATION, "unexpected continuation frame"}, + { EVENT_PREFACE_MATCH_FAILURE, "HTTP/2 connection preface does not match"}, { 0, nullptr } };