]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ssh: fixing incomplete kex parsing
authorPhilippe Antoine <contact@catenacyber.fr>
Mon, 13 Jul 2020 12:29:27 +0000 (14:29 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 21 Jul 2020 14:50:26 +0000 (16:50 +0200)
We use the record length from the ssh record header,
and not the size of the parsed data, as is done in other places.

rust/src/ssh/ssh.rs

index 71e01f60d5541d52aa1494d080ffca305b0a6dfd..cf0229360ed9658971898f7fc932dff859f8df44 100644 (file)
@@ -62,7 +62,6 @@ pub enum SSHConnectionState {
 
 const SSH_MAX_BANNER_LEN: usize = 256;
 const SSH_RECORD_HEADER_LEN: usize = 6;
-const SSH_RECORD_PADDING_LEN: usize = 4;
 const SSH_MAX_REASSEMBLED_RECORD_LEN: usize = 65535;
 
 pub struct SshHeader {
@@ -158,24 +157,28 @@ impl SSHState {
         if hdr.record_left > 0 {
             //should we check for overflow ?
             let ilen = input.len() as u32;
-            if hdr.record_left >= ilen {
+            if hdr.record_left > ilen {
                 hdr.record_left -= ilen;
                 return AppLayerResult::ok();
             } else {
+                let start = hdr.record_left as usize;
                 match hdr.record_left_msg {
                     // parse reassembled tcp segments
                     parser::MessageCode::SshMsgKexinit if hassh_is_enabled() => {
-                        if let Ok((rem, key_exchange)) = parser::ssh_parse_key_exchange(&input) {
-                            key_exchange.generate_hassh(&mut hdr.hassh_string, &mut hdr.hassh, &resp);
-                            input = &rem[SSH_RECORD_PADDING_LEN..];
+                        if let Ok((_rem, key_exchange)) =
+                            parser::ssh_parse_key_exchange(&input[..start])
+                        {
+                            key_exchange.generate_hassh(
+                                &mut hdr.hassh_string,
+                                &mut hdr.hassh,
+                                &resp,
+                            );
                         }
                         hdr.record_left_msg = parser::MessageCode::SshMsgUndefined(0);
                     }
-                    _ => {
-                        let start = hdr.record_left as usize;
-                        input = &input[start..];
-                    }
+                    _ => {}
                 }
+                input = &input[start..];
                 hdr.record_left = 0;
             }
         }
@@ -186,7 +189,9 @@ impl SSHState {
                     SCLogDebug!("SSH valid record {}", head);
                     match head.msg_code {
                         parser::MessageCode::SshMsgKexinit if hassh_is_enabled() => {
-                               if let Ok((_, key_exchange)) = parser::ssh_parse_key_exchange(&input[SSH_RECORD_HEADER_LEN..]) {
+                            //let endkex = SSH_RECORD_HEADER_LEN + head.pkt_len - 2;
+                            let endkex = input.len() - rem.len();
+                            if let Ok((_, key_exchange)) = parser::ssh_parse_key_exchange(&input[SSH_RECORD_HEADER_LEN..endkex]) {
                                 key_exchange.generate_hassh(&mut hdr.hassh_string, &mut hdr.hassh, &resp);
                             }
                         }
@@ -222,6 +227,7 @@ impl SSHState {
                                 }
                                 parser::MessageCode::SshMsgKexinit if hassh_is_enabled() => {
                                     // check if buffer is bigger than maximum reassembled packet size
+                                    hdr.record_left = head.pkt_len - 2;
                                     if hdr.record_left < SSH_MAX_REASSEMBLED_RECORD_LEN as u32 {
                                         // saving type of incomplete kex message
                                         hdr.record_left_msg = parser::MessageCode::SshMsgKexinit;