From: Victor Julien Date: Tue, 19 Apr 2022 06:13:48 +0000 (+0200) Subject: smb2: validate negotiate read/write max sizes X-Git-Tag: suricata-5.0.9~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=acf32d5693d65caf7c73ecc15daaaf0150070558;p=thirdparty%2Fsuricata.git smb2: validate negotiate read/write max sizes Raise event if they exceed the configured limit. (cherry picked from commit fc9b65d8d3188c57016635aef8d7cdfe4552324e) --- diff --git a/rust/src/smb/events.rs b/rust/src/smb/events.rs index 604804f285..f33e6932f7 100644 --- a/rust/src/smb/events.rs +++ b/rust/src/smb/events.rs @@ -30,16 +30,20 @@ pub enum SMBEvent { FileOverlap = 7, RequestToClient = 8, ResponseToServer = 9, + /// Negotiated max sizes exceed our limit + NegotiateMaxReadSizeTooLarge = 10, + NegotiateMaxWriteSizeTooLarge = 11, + /// READ request asking for more than `max_read_size` - ReadRequestTooLarge = 10, + ReadRequestTooLarge = 12, /// READ response bigger than `max_read_size` - ReadResponseTooLarge = 11, - ReadResponseQueueSizeExceeded = 12, - ReadResponseQueueCntExceeded = 13, + ReadResponseTooLarge = 13, + ReadResponseQueueSizeExceeded = 14, + ReadResponseQueueCntExceeded = 15, /// WRITE request for more than `max_write_size` - WriteRequestTooLarge = 14, - WriteQueueSizeExceeded = 15, - WriteQueueCntExceeded = 16, + WriteRequestTooLarge = 16, + WriteQueueSizeExceeded = 17, + WriteQueueCntExceeded = 18, } impl SMBEvent { @@ -55,13 +59,15 @@ impl SMBEvent { 7 => Some(SMBEvent::FileOverlap), 8 => Some(SMBEvent::RequestToClient), 9 => Some(SMBEvent::ResponseToServer), - 10 => Some(SMBEvent::ReadRequestTooLarge), - 11 => Some(SMBEvent::ReadResponseTooLarge), - 12 => Some(SMBEvent::ReadResponseQueueSizeExceeded), - 13 => Some(SMBEvent::ReadResponseQueueCntExceeded), - 14 => Some(SMBEvent::WriteRequestTooLarge), - 15 => Some(SMBEvent::WriteQueueSizeExceeded), - 16 => Some(SMBEvent::WriteQueueCntExceeded), + 10 => Some(SMBEvent::NegotiateMaxReadSizeTooLarge), + 11 => Some(SMBEvent::NegotiateMaxWriteSizeTooLarge), + 12 => Some(SMBEvent::ReadRequestTooLarge), + 13 => Some(SMBEvent::ReadResponseTooLarge), + 14 => Some(SMBEvent::ReadResponseQueueSizeExceeded), + 15 => Some(SMBEvent::ReadResponseQueueCntExceeded), + 16 => Some(SMBEvent::WriteRequestTooLarge), + 17 => Some(SMBEvent::WriteQueueSizeExceeded), + 18 => Some(SMBEvent::WriteQueueCntExceeded), _ => None, } } @@ -80,6 +86,8 @@ pub fn smb_str_to_event(instr: &str) -> i32 { "file_overlap" => SMBEvent::FileOverlap as i32, "request_to_client" => SMBEvent::RequestToClient as i32, "response_to_server" => SMBEvent::ResponseToServer as i32, + "negotiate_max_read_size_too_large" => SMBEvent::NegotiateMaxReadSizeTooLarge as i32, + "negotiate_max_write_size_too_large" => SMBEvent::NegotiateMaxWriteSizeTooLarge as i32, "read_request_too_large" => SMBEvent::ReadRequestTooLarge as i32, "read_response_too_large" => SMBEvent::ReadResponseTooLarge as i32, "read_queue_size_too_large" => SMBEvent::ReadResponseQueueSizeExceeded as i32, diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index 3bb2155742..f34ca68260 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -2231,6 +2231,8 @@ pub extern "C" fn rs_smb_state_get_event_info_by_id(event_id: std::os::raw::c_in SMBEvent::FileOverlap => { "file_overlap\0" }, SMBEvent::RequestToClient => { "request_to_client\0" }, SMBEvent::ResponseToServer => { "response_to_server\0" }, + SMBEvent::NegotiateMaxReadSizeTooLarge => { "negotiate_max_read_size_too_large\0" }, + SMBEvent::NegotiateMaxWriteSizeTooLarge => { "negotiate_max_write_size_too_large\0" }, SMBEvent::ReadRequestTooLarge => { "read_request_too_large\0" }, SMBEvent::ReadResponseTooLarge => { "read_response_too_large\0" }, SMBEvent::ReadResponseQueueSizeExceeded => { "read_queue_size_too_large\0" }, diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index 08e65ddeb9..a050f7cfeb 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -837,6 +837,15 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) Ok((_, rd)) => { SCLogDebug!("SERVER dialect => {}", &smb2_dialect_string(rd.dialect)); + let smb_cfg_max_read_size = unsafe { SMB_CFG_MAX_READ_SIZE }; + if smb_cfg_max_read_size != 0 && rd.max_read_size > smb_cfg_max_read_size { + state.set_event(SMBEvent::NegotiateMaxReadSizeTooLarge); + } + let smb_cfg_max_write_size = unsafe { SMB_CFG_MAX_WRITE_SIZE }; + if smb_cfg_max_write_size != 0 && rd.max_write_size > smb_cfg_max_write_size { + state.set_event(SMBEvent::NegotiateMaxWriteSizeTooLarge); + } + state.dialect = rd.dialect; state.max_read_size = rd.max_read_size; state.max_write_size = rd.max_write_size;