]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb/ntlmssp: add stricter len/offset validation 7272/head
authorVictor Julien <vjulien@oisf.net>
Mon, 11 Apr 2022 10:33:43 +0000 (12:33 +0200)
committerJason Ish <jason.ish@oisf.net>
Tue, 19 Apr 2022 21:59:14 +0000 (15:59 -0600)
(cherry picked from commit 053a9d2e685abe7639e23b1c7fad5ae7d68630e3)

rust/src/smb/ntlmssp_records.rs

index 02a3eab709450314f8c9dec1d065da2e4157393b..dfa660b500ba38a78c3ddb24eff607fe7db64c31 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017 Open Information Security Foundation
+/* Copyright (C) 2017-2022 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -56,54 +56,66 @@ pub struct NTLMSSPAuthRecord<'a> {
     pub version: Option<NTLMSSPVersion>,
 }
 
-named!(pub parse_ntlm_auth_record<NTLMSSPAuthRecord>,
-    do_parse!(
-            _lm_blob_len: le_u16
-         >> _lm_blob_maxlen: le_u16
-         >> _lm_blob_offset: le_u32
-
-         >> _ntlmresp_blob_len: le_u16
-         >> _ntlmresp_blob_maxlen: le_u16
-         >> _ntlmresp_blob_offset: le_u32
-
-         >> domain_blob_len: le_u16
-         >> _domain_blob_maxlen: le_u16
-         >> domain_blob_offset: le_u32
-
-         >> user_blob_len: le_u16
-         >> _user_blob_maxlen: le_u16
-         >> _user_blob_offset: le_u32
-
-         >> host_blob_len: le_u16
-         >> _host_blob_maxlen: le_u16
-         >> _host_blob_offset: le_u32
-
-         >> _ssnkey_blob_len: le_u16
-         >> _ssnkey_blob_maxlen: le_u16
-         >> _ssnkey_blob_offset: le_u32
-
-         >> nego_flags: bits!(tuple!(take_bits!(u8, 6),take_bits!(u8,1),take_bits!(u32,25)))
-         >> version: cond!(nego_flags.1==1, parse_ntlm_auth_version)
-
-         // subtrack 12 as idenfier (8) and type (4) are cut before we are called
-         // subtract 60 for the len/offset/maxlen fields above
-         >> cond!(nego_flags.1==1 && domain_blob_offset > 72, take!(domain_blob_offset - (12 + 60)))
-
-         // or 52 if we have no version
-         >> cond!(nego_flags.1==0 && domain_blob_offset > 64, take!(domain_blob_offset - (12 + 52)))
-
-         >> domain_blob: take!(domain_blob_len)
-         >> user_blob: take!(user_blob_len)
-         >> host_blob: take!(host_blob_len)
-
-         >> ( NTLMSSPAuthRecord {
-                domain: domain_blob,
-                user: user_blob,
-                host: host_blob,
-
-                version: version,
-            })
-));
+pub fn parse_ntlm_auth_record(i: &[u8]) -> nom::IResult<&[u8], NTLMSSPAuthRecord> {
+    let record_len = i.len() + 12; // idenfier (8) and type (4) are cut before we are called
+
+    let (i, _lm_blob_len) = verify!(i, le_u16, |v| (v as usize) < record_len)?;
+    let (i, _lm_blob_maxlen) = le_u16(i)?;
+    let (i, _lm_blob_offset) = verify!(i, le_u32, |v| (v as usize) < record_len)?;
+
+    let (i, _ntlmresp_blob_len) = verify!(i, le_u16, |v| (v as usize) < record_len)?;
+    let (i, _ntlmresp_blob_maxlen) = le_u16(i)?;
+    let (i, _ntlmresp_blob_offset) = verify!(i, le_u32, |v| (v as usize) < record_len)?;
+
+    let (i, domain_blob_len) = verify!(i, le_u16, |v| (v as usize) < record_len)?;
+    let (i, _domain_blob_maxlen) = le_u16(i)?;
+    let (i, domain_blob_offset) = verify!(i, le_u32, |v| (v as usize) < record_len)?;
+
+    let (i, user_blob_len) = verify!(i, le_u16, |v| (v as usize) < record_len)?;
+    let (i, _user_blob_maxlen) = le_u16(i)?;
+    let (i, _user_blob_offset) = verify!(i, le_u32, |v| (v as usize) < record_len)?;
+
+    let (i, host_blob_len) = verify!(i, le_u16, |v| (v as usize) < record_len)?;
+    let (i, _host_blob_maxlen) = le_u16(i)?;
+    let (i, _host_blob_offset) = verify!(i, le_u32, |v| (v as usize) < record_len)?;
+
+    let (i, _ssnkey_blob_len) = verify!(i, le_u16, |v| (v as usize) < record_len)?;
+    let (i, _ssnkey_blob_maxlen) = le_u16(i)?;
+    let (i, _ssnkey_blob_offset) = verify!(i, le_u32, |v| (v as usize) < record_len)?;
+
+    let (i, nego_flags) = bits!(i, tuple!(take_bits!(u8, 6),take_bits!(u8,1),take_bits!(u32,25)))?;
+
+    let (i, version) = cond!(i, nego_flags.1==1, parse_ntlm_auth_version)?;
+
+    // subtrack 12 as idenfier (8) and type (4) are cut before we are called
+    // subtract 60 for the len/offset/maxlen fields above
+    let i = if nego_flags.1 == 1 && domain_blob_offset > 72 {
+        take!(i, domain_blob_offset - (12 + 16))?.0
+    } else {
+        i
+    };
+    //let (i, _) = cond!(i, nego_flags.1==1 && domain_blob_offset > 72, |b| take!(domain_blob_offset - (12 + 60)))?;
+    // or 52 if we have no version
+    let i = if nego_flags.1 == 0 && domain_blob_offset > 64 {
+        take!(i, domain_blob_offset - (12 + 52))?.0
+    } else {
+        i
+    };
+    //let (i, _) = cond!(i, nego_flags.1==0 && domain_blob_offset > 64, |b| take!(domain_blob_offset - (12 + 52)))?;
+
+    let (i, domain_blob) = take!(i, domain_blob_len)?;
+    let (i, user_blob) = take!(i, user_blob_len)?;
+    let (i, host_blob) = take!(i, host_blob_len)?;
+
+    let record = NTLMSSPAuthRecord {
+        domain: domain_blob,
+        user: user_blob,
+        host: host_blob,
+
+        version,
+    };
+    Ok((i, record))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct NTLMSSPRecord<'a> {