http2: limits the number of active transactions per flow

Ticket: 4530

So, that we do not get DOS by quadratic complexity, while
looking for a new stream id over the ever growing list
of active streams
pull/6911/head
Philippe Antoine 3 years ago committed by Victor Julien
parent b39554b11f
commit 5475212f21

@ -17,3 +17,4 @@ alert http2 any any -> any any (msg:"SURICATA HTTP2 invalid HTTP1 settings durin
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;)

@ -58,8 +58,9 @@ const HTTP2_FRAME_GOAWAY_LEN: usize = 4;
const HTTP2_FRAME_RSTSTREAM_LEN: usize = 4;
const HTTP2_FRAME_PRIORITY_LEN: usize = 5;
const HTTP2_FRAME_WINDOWUPDATE_LEN: usize = 4;
//TODO make this configurable
//TODO make these configurable
pub const HTTP2_MAX_TABLESIZE: u32 = 0x10000; // 65536
pub const HTTP2_MAX_STREAMS: usize = 0x1000; // 4096
#[repr(u8)]
#[derive(Copy, Clone, PartialOrd, PartialEq, Debug)]
@ -110,6 +111,8 @@ pub enum HTTP2TransactionState {
HTTP2StateClosed = 7,
//not a RFC-defined state, used for stream 0 frames appyling to the global connection
HTTP2StateGlobal = 8,
//not a RFC-defined state, dropping this old tx because we have too many
HTTP2StateTodrop = 9,
}
#[derive(Debug)]
@ -367,6 +370,7 @@ pub enum HTTP2Event {
FailedDecompression,
InvalidRange,
HeaderIntegerOverflow,
TooManyStreams,
}
pub struct HTTP2DynTable {
@ -571,6 +575,18 @@ impl HTTP2State {
tx.tx_id = self.tx_id;
tx.stream_id = sid;
tx.state = HTTP2TransactionState::HTTP2StateOpen;
// do not use SETTINGS_MAX_CONCURRENT_STREAMS as it can grow too much
if self.transactions.len() > HTTP2_MAX_STREAMS {
// set at least one another transaction to the drop state
for tx_old in &mut self.transactions {
if tx_old.state != HTTP2TransactionState::HTTP2StateTodrop {
// use a distinct state, even if we do not log it
tx_old.set_event(HTTP2Event::TooManyStreams);
tx_old.state = HTTP2TransactionState::HTTP2StateTodrop;
break;
}
}
}
self.transactions.push(tx);
return self.transactions.last_mut().unwrap();
}

Loading…
Cancel
Save