diff --git a/rules/http2-events.rules b/rules/http2-events.rules index 97961da38fc6..a32f6ca8fb68 100644 --- a/rules/http2-events.rules +++ b/rules/http2-events.rules @@ -15,3 +15,7 @@ alert http2 any any -> any any (msg:"SURICATA HTTP2 too long frame data"; flow:e alert http2 any any -> any any (msg:"SURICATA HTTP2 stream identifier reuse"; flow:established; app-layer-event:http2.stream_id_reuse; classtype:protocol-command-decode; sid:2290007; rev:1;) alert http2 any any -> any any (msg:"SURICATA HTTP2 invalid HTTP1 settings during upgrade"; flow:established; app-layer-event:http2.invalid_http1_settings; classtype:protocol-command-decode; sid:2290008; rev:1;) alert http2 any any -> any any (msg:"SURICATA HTTP2 failed decompression"; flow:established; app-layer-event:http2.failed_decompression; classtype:protocol-command-decode; sid:2290009; rev:1;) +#alert http2 any any -> any any (msg:"SURICATA HTTP2 invalid range header"; flow:established; app-layer-event:http2.invalid_range; classtype:protocol-command-decode; sid:2290010; rev:1;) +#alert http2 any any -> any any (msg:"SURICATA HTTP2 variable-length integer overflow"; flow:established; app-layer-event:http2.header_integer_overflow; classtype:protocol-command-decode; sid:2290011; rev:1;) +#alert http2 any any -> any any (msg:"SURICATA HTTP2 too many streams"; flow:established; app-layer-event:http2.too_many_streams; classtype:protocol-command-decode; sid:2290012; rev:1;) +alert http2 any any -> any any (msg:"SURICATA HTTP2 authority host mismatch"; flow:established,to_server; app-layer-event:http2.authority_host_mismatch; classtype:protocol-command-decode; sid:2290013; rev:1;) diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs index ee285ad1eebb..e5edcda48ef3 100644 --- a/rust/src/http2/http2.rs +++ b/rust/src/http2/http2.rs @@ -175,14 +175,32 @@ impl HTTP2Transaction { } } - #[cfg(not(feature = "decompression"))] - fn handle_headers(&mut self, _blocks: &Vec, _dir: u8) {} + pub fn set_event(&mut self, event: HTTP2Event) { + let ev = event as u8; + core::sc_app_layer_decoder_events_set_event_raw(&mut self.events, ev); + } - #[cfg(feature = "decompression")] - fn handle_headers(&mut self, blocks: &Vec, dir: u8) { - for i in 0..blocks.len() { - if blocks[i].name == b"content-encoding" { - self.decoder.http2_encoding_fromvec(&blocks[i].value, dir); + fn handle_headers(&mut self, blocks: &[parser::HTTP2FrameHeaderBlock], _dir: u8) { + let mut authority = None; + let mut host = None; + for block in blocks { + if block.name == b"content-encoding" { + #[cfg(feature = "decompression")] + self.decoder.http2_encoding_fromvec(&block.value, _dir); + } else if block.name.eq_ignore_ascii_case(b":authority") { + authority = Some(&block.value); + } else if block.name.eq_ignore_ascii_case(b"host") { + host = Some(&block.value); + } + } + if let Some(a) = authority { + if let Some(h) = host { + if !a.eq_ignore_ascii_case(h) { + // The event is triggered only if both headers + // are in the same frame to avoid excessive + // complexity at runtime. + self.set_event(HTTP2Event::AuthorityHostMismatch); + } } } } @@ -336,6 +354,7 @@ pub enum HTTP2Event { StreamIdReuse, InvalidHTTP1Settings, FailedDecompression, + AuthorityHostMismatch, } impl HTTP2Event { @@ -351,6 +370,7 @@ impl HTTP2Event { 7 => Some(HTTP2Event::StreamIdReuse), 8 => Some(HTTP2Event::InvalidHTTP1Settings), 9 => Some(HTTP2Event::FailedDecompression), + 10 => Some(HTTP2Event::AuthorityHostMismatch), _ => None, } } @@ -1146,6 +1166,7 @@ pub extern "C" fn rs_http2_state_get_event_info( "stream_id_reuse" => HTTP2Event::StreamIdReuse as i32, "invalid_http1_settings" => HTTP2Event::InvalidHTTP1Settings as i32, "failed_decompression" => HTTP2Event::FailedDecompression as i32, + "authority_host_mismatch" => HTTP2Event::AuthorityHostMismatch as i32, _ => -1, // unknown event } } @@ -1175,6 +1196,7 @@ pub extern "C" fn rs_http2_state_get_event_info_by_id( HTTP2Event::StreamIdReuse => "stream_id_reuse\0", HTTP2Event::InvalidHTTP1Settings => "invalid_http1_settings\0", HTTP2Event::FailedDecompression => "failed_decompression\0", + HTTP2Event::AuthorityHostMismatch => "authority_host_mismatch\0", }; unsafe { *event_name = estr.as_ptr() as *const std::os::raw::c_char;