From: Adrian Mamolea Date: Tue, 19 Jul 2022 18:34:22 +0000 (-0400) Subject: http2_inspect: add support for GOAWAY frames X-Git-Tag: 3.1.38.0~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a194bb87fefe2e9138031bebdff388c55695e631;p=thirdparty%2Fsnort3.git http2_inspect: add support for GOAWAY frames --- diff --git a/doc/reference/builtin_stubs.txt b/doc/reference/builtin_stubs.txt index 4b6fda14b..52eec8bcf 100644 --- a/doc/reference/builtin_stubs.txt +++ b/doc/reference/builtin_stubs.txt @@ -1501,6 +1501,10 @@ direction of the flow. The opposite direction may be OK. Invalid HTTP/2 PRIORITY frame. Stream ID is 0 or length is not 5. +121:41 + +Invalid HTTP/2 GOAWAY frame. R bit is set or stream ID is not 0 or length is less than 8. + 122:1 Basic one host to one host TCP portscan where multiple TCP ports are scanned on diff --git a/src/service_inspectors/http2_inspect/CMakeLists.txt b/src/service_inspectors/http2_inspect/CMakeLists.txt index 5327ca0e0..bb05cf9d5 100644 --- a/src/service_inspectors/http2_inspect/CMakeLists.txt +++ b/src/service_inspectors/http2_inspect/CMakeLists.txt @@ -11,6 +11,8 @@ set (FILE_LIST http2_flow_data.h http2_frame.cc http2_frame.h + http2_goaway_frame.cc + http2_goaway_frame.h http2_headers_frame.cc http2_headers_frame.h http2_headers_frame_header.cc @@ -38,6 +40,7 @@ set (FILE_LIST http2_module.cc http2_module.h http2_ping_frame.h + http2_priority_frame.h http2_push_promise_frame.cc http2_push_promise_frame.h http2_request_line.cc diff --git a/src/service_inspectors/http2_inspect/dev_notes.txt b/src/service_inspectors/http2_inspect/dev_notes.txt index 1b3af79d2..6362509e0 100644 --- a/src/service_inspectors/http2_inspect/dev_notes.txt +++ b/src/service_inspectors/http2_inspect/dev_notes.txt @@ -22,6 +22,7 @@ HTTP/2 frames are stored in frame objects for processing. 9. Http2RstStreamFrame : Http2Frame 10. Http2WindowUpdateFrame: Http2Frame 11. Http2PriorityFrame: Http2Frame +12. Http2GoAwayFrame: Http2Frame Http2Frame virtual methods: 1. bool valid_sequence(Http2Enums::StreamState state) - Returns if the current frame has been sent diff --git a/src/service_inspectors/http2_inspect/http2_enum.h b/src/service_inspectors/http2_inspect/http2_enum.h index ec2df0cc3..edaa4bd8e 100644 --- a/src/service_inspectors/http2_inspect/http2_enum.h +++ b/src/service_inspectors/http2_inspect/http2_enum.h @@ -96,6 +96,7 @@ enum EventSid EVENT_NON_DATA_FRAME_TOO_LONG = 38, EVENT_LOSS_OF_SYNC = 39, EVENT_INVALID_PRIORITY_FRAME = 40, + EVENT_INVALID_GOAWAY_FRAME = 41, EVENT__MAX_VALUE }; @@ -155,6 +156,9 @@ enum Infraction INF_NON_DATA_FRAME_TOO_LONG = 49, INF_BAD_PRIORITY_FRAME_STREAM_ID = 50, INF_BAD_PRIORITY_FRAME_LENGTH = 51, + INF_BAD_GOAWAY_FRAME_STREAM_ID = 52, + INF_BAD_GOAWAY_FRAME_LENGTH = 53, + INF_BAD_GOAWAY_FRAME_R_BIT = 54, INF__MAX_VALUE }; diff --git a/src/service_inspectors/http2_inspect/http2_flow_data.h b/src/service_inspectors/http2_inspect/http2_flow_data.h index 4e1442047..63b84b679 100644 --- a/src/service_inspectors/http2_inspect/http2_flow_data.h +++ b/src/service_inspectors/http2_inspect/http2_flow_data.h @@ -67,6 +67,7 @@ public: friend class Http2Frame; friend class Http2DataFrame; friend class Http2DataCutter; + friend class Http2GoAwayFrame; friend class Http2HeadersFrame; friend class Http2HeadersFrameHeader; friend class Http2HeadersFrameTrailer; diff --git a/src/service_inspectors/http2_inspect/http2_frame.cc b/src/service_inspectors/http2_inspect/http2_frame.cc index 3be6f7be0..3cfae512c 100644 --- a/src/service_inspectors/http2_inspect/http2_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_frame.cc @@ -26,6 +26,7 @@ #include "http2_data_frame.h" #include "http2_enum.h" #include "http2_flow_data.h" +#include "http2_goaway_frame.h" #include "http2_headers_frame_header.h" #include "http2_headers_frame_trailer.h" #include "http2_ping_frame.h" @@ -90,6 +91,10 @@ Http2Frame* Http2Frame::new_frame(const uint8_t* header, const uint32_t header_l frame = new Http2PingFrame(header, header_len, data, data_len, session_data, source_id, stream); break; + case FT_GOAWAY: + frame = new Http2GoAwayFrame(header, header_len, data, data_len, session_data, + source_id, stream); + break; case FT_RST_STREAM: frame = new Http2RstStreamFrame(header, header_len, data, data_len, session_data, source_id, stream); diff --git a/src/service_inspectors/http2_inspect/http2_goaway_frame.cc b/src/service_inspectors/http2_inspect/http2_goaway_frame.cc new file mode 100644 index 000000000..48afe2cb6 --- /dev/null +++ b/src/service_inspectors/http2_inspect/http2_goaway_frame.cc @@ -0,0 +1,52 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2022-2022 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. +//-------------------------------------------------------------------------- +// http2_goaway_frame.cc author Adrian Mamolea + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "http2_goaway_frame.h" + +#include "http2_enum.h" +#include "http2_frame.h" + +using namespace Http2Enums; + +Http2GoAwayFrame::Http2GoAwayFrame(const uint8_t* header_buffer, const uint32_t header_len, + const uint8_t* data_buffer, const uint32_t data_len, Http2FlowData* ssn_data, + HttpCommon::SourceId src_id, Http2Stream* _stream) : + Http2Frame(header_buffer, header_len, data_buffer, data_len, ssn_data, src_id, _stream) +{ + if (get_stream_id() != 0) + { + session_data->events[source_id]->create_event(EVENT_INVALID_GOAWAY_FRAME); + *session_data->infractions[source_id] += INF_BAD_GOAWAY_FRAME_STREAM_ID; + } + if (data.length() < 8) + { + session_data->events[source_id]->create_event(EVENT_INVALID_GOAWAY_FRAME); + *session_data->infractions[source_id] += INF_BAD_GOAWAY_FRAME_LENGTH; + } + else if (data.start()[0] & 0x80) + { + session_data->events[source_id]->create_event(EVENT_INVALID_GOAWAY_FRAME); + *session_data->infractions[source_id] += INF_BAD_GOAWAY_FRAME_R_BIT; + } +} + diff --git a/src/service_inspectors/http2_inspect/http2_goaway_frame.h b/src/service_inspectors/http2_inspect/http2_goaway_frame.h new file mode 100644 index 000000000..dcbc32fae --- /dev/null +++ b/src/service_inspectors/http2_inspect/http2_goaway_frame.h @@ -0,0 +1,40 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2022-2022 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. +//-------------------------------------------------------------------------- +// http2_goaway_frame.h author Adrian Mamolea + +#ifndef HTTP2_GOAWAY_FRAME_H +#define HTTP2_GOAWAY_FRAME_H + +#include "http2_flow_data.h" + +class Http2Frame; + +class Http2GoAwayFrame : public Http2Frame +{ +public: + friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const uint32_t, const uint8_t*, + const uint32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream); + bool is_detection_required() const override { return false; } + +private: + Http2GoAwayFrame(const uint8_t* header_buffer, const uint32_t header_len, + const uint8_t* data_buffer, const uint32_t data_len, Http2FlowData* ssn_data, + HttpCommon::SourceId src_id, Http2Stream* _stream); +}; +#endif + diff --git a/src/service_inspectors/http2_inspect/http2_tables.cc b/src/service_inspectors/http2_inspect/http2_tables.cc index 500f46779..1c91b9b46 100644 --- a/src/service_inspectors/http2_inspect/http2_tables.cc +++ b/src/service_inspectors/http2_inspect/http2_tables.cc @@ -74,6 +74,7 @@ const RuleMap Http2Module::http2_events[] = { EVENT_NON_DATA_FRAME_TOO_LONG, "HTTP/2 non-Data frame longer than 63780 bytes" }, { EVENT_LOSS_OF_SYNC, "not HTTP/2 traffic or unrecoverable HTTP/2 protocol error" }, { EVENT_INVALID_PRIORITY_FRAME, "invalid HTTP/2 PRIORITY frame" }, + { EVENT_INVALID_GOAWAY_FRAME, "invalid HTTP/2 GOAWAY frame" }, { 0, nullptr } };