ssh: fix record_left for oversized KEXINIT records

When an incomplete SSH_MSG_KEXINIT record has a body of at least
SSH_MAX_REASSEMBLED_RECORD_LEN bytes and hassh is enabled, record_left
was overwritten with the full body length even though the function
returns ok() and thus consumes the body bytes already present in the
input. The next call then over-skipped by that many bytes into the
following record, desynchronising the parser for that direction so
hassh was never computed and ssh.hassh keywords could not match.

This patch keeps the record_left computed from the bytes actually consumed in
the oversized path, and only use the full body length in the path that
returns incomplete, where the body bytes are delivered again.

Ticket #8837

(cherry picked from commit f13021e022)
pull/16211/head
Giuseppe Longo 2 months ago committed by Philippe Antoine
parent c254d424bc
commit 92859e3ae7

@ -289,15 +289,21 @@ impl SSHState {
}
parser::MessageCode::Kexinit 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 {
let body_len = head.pkt_len - 2;
if body_len < SSH_MAX_REASSEMBLED_RECORD_LEN as u32 {
// returning incomplete means the body bytes in rem are
// not consumed and will be delivered again, so the whole
// body has to be skipped on the next call
hdr.record_left = body_len;
// saving type of incomplete kex message
hdr.record_left_msg = parser::MessageCode::Kexinit;
return AppLayerResult::incomplete(
(il - rem.len()) as u32,
head.pkt_len - 2,
body_len,
);
} else {
// returning ok consumes the body bytes in rem, so keep
// record_left = body_len - remlen computed above
SCLogDebug!("SSH buffer is bigger than maximum reassembled packet size");
self.set_event(SSHEvent::LongKexRecord);
}

Loading…
Cancel
Save