SSH protocol now assesses the packet length at an earlier stage within binpac. Stops SSH analyzer constantly raising binpac exceptions. Seems to be because a packet continues to go through binpac when empty and only calls the next packet when asked for more data and not on operations.

This commit is contained in:
Andrew Woodford 2017-12-21 16:34:26 +00:00
parent 1c25df6f26
commit f07fdc255f
2 changed files with 25 additions and 12 deletions

View file

@ -173,6 +173,18 @@ refine flow SSH_Flow += {
connection()->bro_analyzer()->ProtocolConfirmation(); connection()->bro_analyzer()->ProtocolConfirmation();
return true; return true;
%} %}
function get_kex_length(v: int, packet_length: uint32): int
%{
switch (v) {
case SSH1:
return packet_length + 4 + 8 -(packet_length%8);
case SSH2:
return packet_length + 4;
default:
return 1; //currently causes the rest of the packet to dump
}
%}
}; };
refine typeattr SSH_Version += &let { refine typeattr SSH_Version += &let {

View file

@ -22,21 +22,23 @@ type SSH_Version(is_orig: bool) = record {
update_version : bool = $context.connection.update_version(version, is_orig); update_version : bool = $context.connection.update_version(version, is_orig);
}; };
type SSH_Key_Exchange(is_orig: bool) = case $context.connection.get_version() of { type SSH_Key_Exchange(is_orig: bool) = record {
SSH1 -> ssh1_msg : SSH1_Key_Exchange(is_orig); packet_length: uint32;
SSH2 -> ssh2_msg : SSH2_Key_Exchange(is_orig); key_ex: case $context.connection.get_version() of {
}; SSH1 -> ssh1_msg : SSH1_Key_Exchange(is_orig, packet_length);
SSH2 -> ssh2_msg : SSH2_Key_Exchange(is_orig, packet_length);
};
} &length = $context.flow.get_kex_length($context.connection.get_version(), packet_length);
# SSH1 constructs # SSH1 constructs
################# #################
type SSH1_Key_Exchange(is_orig: bool) = record { type SSH1_Key_Exchange(is_orig: bool, packet_length: uint32) = record {
packet_length : uint32;
pad_fill : bytestring &length = 8 - (packet_length % 8); pad_fill : bytestring &length = 8 - (packet_length % 8);
msg_type : uint8; msg_type : uint8;
message : SSH1_Message(is_orig, msg_type, packet_length - 5); message : SSH1_Message(is_orig, msg_type, packet_length - 5);
crc : uint32; crc : uint32;
} &length = packet_length + 4 + 8 - (packet_length % 8); } &length = packet_length + 8 - (packet_length % 8);
type SSH1_Message(is_orig: bool, msg_type: uint8, length: uint32) = case msg_type of { type SSH1_Message(is_orig: bool, msg_type: uint8, length: uint32) = case msg_type of {
SSH_SMSG_PUBLIC_KEY -> public_key : SSH1_PUBLIC_KEY(length); SSH_SMSG_PUBLIC_KEY -> public_key : SSH1_PUBLIC_KEY(length);
@ -73,8 +75,7 @@ type ssh1_mp_int = record {
## SSH2 ## SSH2
type SSH2_Header(is_orig: bool) = record { type SSH2_Header(is_orig: bool, packet_length: uint32) = record {
packet_length : uint32;
padding_length : uint8; padding_length : uint8;
msg_type : uint8; msg_type : uint8;
} &let { } &let {
@ -82,11 +83,11 @@ type SSH2_Header(is_orig: bool) = record {
detach : bool = $context.connection.update_state(ENCRYPTED, is_orig) &if(msg_type == MSG_NEWKEYS); detach : bool = $context.connection.update_state(ENCRYPTED, is_orig) &if(msg_type == MSG_NEWKEYS);
}; };
type SSH2_Key_Exchange(is_orig: bool) = record { type SSH2_Key_Exchange(is_orig: bool, packet_length: uint32) = record {
header : SSH2_Header(is_orig); header : SSH2_Header(is_orig, packet_length);
payload : SSH2_Message(is_orig, header.msg_type, header.payload_length); payload : SSH2_Message(is_orig, header.msg_type, header.payload_length);
pad : bytestring &length=header.padding_length; pad : bytestring &length=header.padding_length;
} &length=header.packet_length + 4; } &length=packet_length;
type SSH2_Message(is_orig: bool, msg_type: uint8, length: uint32) = case $context.connection.get_state(is_orig) of { type SSH2_Message(is_orig: bool, msg_type: uint8, length: uint32) = case $context.connection.get_state(is_orig) of {
KEX_INIT -> kex : SSH2_KEXINIT(length, is_orig); KEX_INIT -> kex : SSH2_KEXINIT(length, is_orig);