]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb: resistance against padding evasions
authorPhilippe Antoine <contact@catenacyber.fr>
Tue, 14 Apr 2020 12:24:22 +0000 (14:24 +0200)
committerJason Ish <jason.ish@oisf.net>
Wed, 7 Oct 2020 15:40:38 +0000 (09:40 -0600)
Scenario is use of dummy padding in write AndX request
or other similar commands using a data offset.

Parsing skips now these dummy bytes, and generates one event

rust/src/smb/smb1_records.rs

index 20a4a22e69aa77cb2a0e5ca4a9339acd2de6d64f..2112304c5c1e95259ef4f2fda006902b4f614f9c 100644 (file)
@@ -80,11 +80,12 @@ named!(pub parse_smb1_write_andx_request_record<Smb1WriteRequestRecord>,
         >>  _remaining: le_u16
         >>  data_len_high: le_u16
         >>  data_len_low: le_u16
-        >>  _data_offset: le_u16
+        >>  data_offset: le_u16
         >>  high_offset: cond!(wct==14,le_u32)
         >>  bcc: le_u16
-        //>>  padding: cond!(data_offset > 32, take!(data_offset - 32))
+        //spec [MS-CIFS].pdf says always take one byte padding
         >>  _padding: cond!(bcc > data_len_low, take!(bcc - data_len_low)) // TODO figure out how this works with data_len_high
+        >>  _padding_evasion: cond!(data_offset > 36+2*(wct as u16), take!(data_offset - (36+2*(wct as u16))))
         >>  file_data: rest
         >> (Smb1WriteRequestRecord {
                 offset: if high_offset != None { ((high_offset.unwrap() as u64) << 32)|(offset as u64) } else { 0 },
@@ -370,7 +371,7 @@ named!(pub parse_smb_trans_response_error_record<SmbRecordTransResponse>,
 
 named!(pub parse_smb_trans_response_regular_record<SmbRecordTransResponse>,
     do_parse!(
-          _wct: le_u8
+          wct: le_u8
        >> _total_param_cnt: le_u16
        >> _total_data_count: le_u16
        >> take!(2) // reserved
@@ -378,12 +379,13 @@ named!(pub parse_smb_trans_response_regular_record<SmbRecordTransResponse>,
        >> _param_offset: le_u16
        >> _param_displacement: le_u16
        >> data_cnt: le_u16
-       >> _data_offset: le_u16
+       >> data_offset: le_u16
        >> _data_displacement: le_u16
        >> _setup_cnt: le_u8
        >> take!(1) // reserved
        >> bcc: le_u16
        >> take!(1) // padding
+       >> _padding_evasion: cond!(data_offset > 36+2*(wct as u16), take!(data_offset - (36+2*(wct as u16))))
        >> data: take!(data_cnt)
        >> (SmbRecordTransResponse {
                 data_cnt,
@@ -491,17 +493,18 @@ pub struct SmbResponseReadAndXRecord<'a> {
 
 named!(pub parse_smb_read_andx_response_record<SmbResponseReadAndXRecord>,
     do_parse!(
-            _wct: le_u8
+            wct: le_u8
         >>  _andx_command: le_u8
         >>  take!(1)    // reserved
         >>  _andx_offset: le_u16
         >>  take!(6)
         >>  data_len_low: le_u16
-        >>  _data_offset: le_u16
+        >>  data_offset: le_u16
         >>  data_len_high: le_u32
         >>  take!(6)    // reserved
         >>  bcc: le_u16
         >>  _padding: cond!(bcc > data_len_low, take!(bcc - data_len_low)) // TODO figure out how this works with data_len_high
+        >>  _padding_evasion: cond!(data_offset > 36+2*(wct as u16), take!(data_offset - (36+2*(wct as u16))))
         >>  file_data: rest
 
         >> (SmbResponseReadAndXRecord {
@@ -671,6 +674,7 @@ named!(pub parse_smb_trans2_request_record<SmbRequestTrans2Record>,
         >>  subcmd: le_u16
         >>  _bcc: le_u16
         >>  _padding: take!(3)
+        //TODO test and use _param_offset and _data_offset
         >>  setup_blob: take!(param_cnt)
         >>  data_blob: take!(data_cnt)