]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb: handle records in the wrong direction
authorJason Ish <jason.ish@oisf.net>
Fri, 18 Feb 2022 04:57:30 +0000 (22:57 -0600)
committerVictor Julien <vjulien@oisf.net>
Fri, 4 Mar 2022 15:50:54 +0000 (16:50 +0100)
If an SMB record is seen in the wrong direction, set an event on the PDU
frame and don't process the record in the state.

No error is returned, so the next record will be processed.

rust/src/smb/events.rs
rust/src/smb/smb.rs
rust/src/smb/smb2_records.rs

index f8b3055ede995f22725a8528c4035d243303f0dc..b2a49ca1aabfb32d8733e59cd9e97b1cc3a5162e 100644 (file)
@@ -27,6 +27,10 @@ pub enum SMBEvent {
     DuplicateNegotiate,
     NegotiateMalformedDialects,
     FileOverlap,
+    /// A request was seen in the to client direction.
+    RequestToClient,
+    /// A response was seen in the to server direction,
+    ResponseToServer,
 }
 
 impl SMBTransaction {
index eaf886395c440963145fc81e0b6a410a3651174a..d50bbd905034f1ed9cb44ad1fef9c215d4a29ae4 100644 (file)
@@ -1453,9 +1453,18 @@ impl SMBState {
                                     SCLogDebug!("SMBv1 record");
                                     match parse_smb_record(nbss_hdr.data) {
                                         Ok((_, ref smb_record)) => {
-                                            self.add_smb1_ts_pdu_frame(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64);
+                                            let pdu_frame = self.add_smb1_ts_pdu_frame(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64);
                                             self.add_smb1_ts_hdr_data_frames(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64);
-                                            smb1_request_record(self, smb_record);
+                                            if smb_record.is_request() {
+                                                smb1_request_record(self, smb_record);
+                                            } else {
+                                                // If we recevied a response when expecting a request, set an event
+                                                // on the PDU frame instead of handling the response.
+                                                SCLogDebug!("SMB1 reply seen from client to server");
+                                                if let Some(frame) = pdu_frame {
+                                                    frame.add_event(flow, 0, SMBEvent::ResponseToServer as u8);
+                                                }
+                                            }
                                         },
                                         _ => {
                                             if let Some(frame) = nbss_data_frame {
@@ -1472,10 +1481,19 @@ impl SMBState {
                                         match parse_smb2_request_record(nbss_data) {
                                             Ok((nbss_data_rem, ref smb_record)) => {
                                                 let record_len = (nbss_data.len() - nbss_data_rem.len()) as i64;
-                                                self.add_smb2_ts_pdu_frame(flow, stream_slice, nbss_data, record_len);
+                                                let pdu_frame = self.add_smb2_ts_pdu_frame(flow, stream_slice, nbss_data, record_len);
                                                 self.add_smb2_ts_hdr_data_frames(flow, stream_slice, nbss_data, record_len, smb_record.header_len as i64);
                                                 SCLogDebug!("nbss_data_rem {}", nbss_data_rem.len());
-                                                smb2_request_record(self, smb_record);
+                                                if smb_record.is_request() {
+                                                    smb2_request_record(self, smb_record);
+                                                } else {
+                                                    // If we recevied a response when expecting a request, set an event
+                                                    // on the PDU frame instead of handling the response.
+                                                    SCLogDebug!("SMB2 reply seen from client to server");
+                                                    if let Some(frame) = pdu_frame {
+                                                        frame.add_event(flow, 0, SMBEvent::ResponseToServer as u8);
+                                                    }
+                                                }
                                                 nbss_data = nbss_data_rem;
                                             },
                                             _ => {
@@ -1571,9 +1589,10 @@ impl SMBState {
         (nbss_pdu, nbss_hdr_frame, nbss_data_frame)
     }
 
-    fn add_smb1_tc_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) {
-        let _smb_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len, SMBFrameType::SMB1Pdu as u8);
-        SCLogDebug!("SMB PDU frame {:?}", _smb_pdu);
+    fn add_smb1_tc_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> Option<Frame> {
+        let smb_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len, SMBFrameType::SMB1Pdu as u8);
+        SCLogDebug!("SMB PDU frame {:?}", smb_pdu);
+        smb_pdu
     }
     fn add_smb1_tc_hdr_data_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) {
         let _smb1_hdr = Frame::new_tc(flow, stream_slice, input, SMB1_HEADER_SIZE as i64, SMBFrameType::SMB1Hdr as u8);
@@ -1585,9 +1604,10 @@ impl SMBState {
         }
     }
 
-    fn add_smb2_tc_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) {
-        let _smb_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len, SMBFrameType::SMB2Pdu as u8);
-        SCLogDebug!("SMBv2 PDU frame {:?}", _smb_pdu);
+    fn add_smb2_tc_pdu_frame(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64) -> Option<Frame> {
+        let smb_pdu = Frame::new_tc(flow, stream_slice, input, nbss_len, SMBFrameType::SMB2Pdu as u8);
+        SCLogDebug!("SMBv2 PDU frame {:?}", smb_pdu);
+        smb_pdu
     }
     fn add_smb2_tc_hdr_data_frames(&mut self, flow: *const Flow, stream_slice: &StreamSlice, input: &[u8], nbss_len: i64, hdr_len: i64) {
         let _smb2_hdr = Frame::new_tc(flow, stream_slice, input, hdr_len, SMBFrameType::SMB2Hdr as u8);
@@ -1764,9 +1784,16 @@ impl SMBState {
                                     SCLogDebug!("SMBv1 record");
                                     match parse_smb_record(nbss_hdr.data) {
                                         Ok((_, ref smb_record)) => {
-                                            self.add_smb1_tc_pdu_frame(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64);
+                                            let pdu_frame = self.add_smb1_tc_pdu_frame(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64);
                                             self.add_smb1_tc_hdr_data_frames(flow, stream_slice, nbss_hdr.data, nbss_hdr.length as i64);
-                                            smb1_response_record(self, smb_record);
+                                            if smb_record.is_response() {
+                                                smb1_response_record(self, smb_record);
+                                            } else {
+                                                SCLogDebug!("SMB1 request seen from server to client");
+                                                if let Some(frame) = pdu_frame {
+                                                    frame.add_event(flow, 1, SMBEvent::RequestToClient as u8);
+                                                }
+                                            }
                                         },
                                         _ => {
                                             self.set_event(SMBEvent::MalformedData);
@@ -1780,9 +1807,16 @@ impl SMBState {
                                         match parse_smb2_response_record(nbss_data) {
                                             Ok((nbss_data_rem, ref smb_record)) => {
                                                 let record_len = (nbss_data.len() - nbss_data_rem.len()) as i64;
-                                                self.add_smb2_tc_pdu_frame(flow, stream_slice, nbss_data, record_len);
+                                                let pdu_frame = self.add_smb2_tc_pdu_frame(flow, stream_slice, nbss_data, record_len);
                                                 self.add_smb2_tc_hdr_data_frames(flow, stream_slice, nbss_data, record_len, smb_record.header_len as i64);
-                                                smb2_response_record(self, smb_record);
+                                                if smb_record.is_response() {
+                                                    smb2_response_record(self, smb_record);
+                                                } else {
+                                                    SCLogDebug!("SMB2 request seen from server to client");
+                                                    if let Some(frame) = pdu_frame {
+                                                        frame.add_event(flow, 1, SMBEvent::RequestToClient as u8);
+                                                    }
+                                                }
                                                 nbss_data = nbss_data_rem;
                                             },
                                             _ => {
index 2d8950bcfcb348a132594f555016b96eb415466e..d069ef0486c1b5dd22ec15f422b7211ef8a46d97 100644 (file)
@@ -69,6 +69,14 @@ impl<'a> Smb2Record<'a> {
     pub fn is_async(&self) -> bool {
         self.async_id != 0
     }
+
+    pub fn is_request(&self) -> bool {
+        self.direction == 0
+    }
+
+    pub fn is_response(&self) -> bool {
+        self.direction == 1
+    }
 }
 
 #[derive(Debug)]