]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
http2: event on mismatch between authority and host 9770/head 9771/head
authorPhilippe Antoine <pantoine@oisf.net>
Mon, 6 Nov 2023 15:38:27 +0000 (16:38 +0100)
committerPhilippe Antoine <pantoine@oisf.net>
Fri, 10 Nov 2023 09:10:07 +0000 (10:10 +0100)
Ticket: #6425
(cherry picked from commit 46a46e5b1f4909446e6f727f41b2eaeb3cb34bbd)

rules/http2-events.rules
rust/src/http2/http2.rs

index 97961da38fc620eba7c3d761adc0b9aaeab3b202..b2d6afc473aa2cb62d4539f6b4f02528315d1b33 100644 (file)
@@ -15,3 +15,4 @@ 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 authority host mismatch"; flow:established,to_server; app-layer-event:http2.authority_host_mismatch; classtype:protocol-command-decode; sid:2290013; rev:1;)
index ee285ad1eebb69f09433111e046a5356c358e955..e5edcda48ef36e604e5b03d444daeeef46d0c17e 100644 (file)
@@ -175,14 +175,32 @@ impl HTTP2Transaction {
         }
     }
 
-    #[cfg(not(feature = "decompression"))]
-    fn handle_headers(&mut self, _blocks: &Vec<parser::HTTP2FrameHeaderBlock>, _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<parser::HTTP2FrameHeaderBlock>, 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;