From: Philippe Antoine Date: Tue, 19 Oct 2021 10:38:49 +0000 (+0200) Subject: range: checks that end is after start for HTTP2 X-Git-Tag: suricata-7.0.0-beta1~1288 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bd065cb3c4daea720608db55b19e7f06f71c284;p=thirdparty%2Fsuricata.git range: checks that end is after start for HTTP2 As was done only for HTTP1 in previous commit The verification part stays separated from the parsing part, as we want to keep on logging invalid ranges values. --- diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs index 99a8d16a1c..3cbbf1d2b3 100644 --- a/rust/src/http2/http2.rs +++ b/rust/src/http2/http2.rs @@ -221,7 +221,7 @@ impl HTTP2Transaction { STREAM_TOCLIENT, "content-range", ) { - match range::http2_parse_content_range(&value) { + match range::http2_parse_check_content_range(&value) { Ok((_, v)) => { range::http2_range_open(self, &v, flow, sfcm, flags, decompressed); if over && self.file_range != std::ptr::null_mut() { diff --git a/rust/src/http2/range.rs b/rust/src/http2/range.rs index 5533820905..08f3b5bec5 100644 --- a/rust/src/http2/range.rs +++ b/rust/src/http2/range.rs @@ -23,6 +23,8 @@ use crate::filecontainer::FileContainer; use crate::http2::http2::HTTP2Transaction; use nom::character::complete::digit1; +use nom::error::ErrorKind; +use nom::Err; use nom::IResult; use std::os::raw::c_uchar; use std::str::FromStr; @@ -68,7 +70,7 @@ pub fn http2_parse_content_range_def<'a>(input: &'a [u8]) -> IResult<&'a [u8], H )); } -pub fn http2_parse_content_range<'a>(input: &'a [u8]) -> IResult<&'a [u8], HTTPContentRange> { +fn http2_parse_content_range<'a>(input: &'a [u8]) -> IResult<&'a [u8], HTTPContentRange> { let (i2, _) = take_while!(input, |c| c == b' ')?; let (i2, _) = take_till!(i2, |c| c == b' ')?; let (i2, _) = take_while!(i2, |c| c == b' ')?; @@ -78,6 +80,14 @@ pub fn http2_parse_content_range<'a>(input: &'a [u8]) -> IResult<&'a [u8], HTTPC ); } +pub fn http2_parse_check_content_range<'a>(input: &'a [u8]) -> IResult<&'a [u8], HTTPContentRange> { + let (rem, v) = http2_parse_content_range(input)?; + if v.start > v.end { + return Err(Err::Error((rem, ErrorKind::Verify))); + } + return Ok((rem, v)); +} + #[no_mangle] pub unsafe extern "C" fn rs_http_parse_content_range( cr: &mut HTTPContentRange, buffer: *const u8, buffer_len: u32, @@ -127,6 +137,13 @@ pub fn http2_range_open( tx: &mut HTTP2Transaction, v: &HTTPContentRange, flow: *const Flow, cfg: &'static SuricataFileContext, flags: u16, data: &[u8], ) { + if v.end <= 0 || v.size <= 0 { + // skipped for incomplete range information + return; + } else if v.end == v.size - 1 && v.start == 0 { + // whole file in one range + return; + } if let Ok((key, index)) = http2_range_key_get(tx) { let name = &key[index..]; tx.file_range = unsafe {