From: Shijin Bose (shibose) Date: Thu, 12 Sep 2024 13:51:34 +0000 (+0000) Subject: Pull request #4417: ssh: added abort session in streamsplitter X-Git-Tag: 3.3.7.0~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8fc4096fcfd2f5d0b4b51945bcaeb5437765d2df;p=thirdparty%2Fsnort3.git Pull request #4417: ssh: added abort session in streamsplitter Merge in SNORT/snort3 from ~SHIBOSE/snort3:ssh_fallback to master Squashed commit of the following: commit c5a27bacf94fff0db24793b62ffa22ee6587ff42 Author: shibose Date: Thu Aug 8 05:37:06 2024 +0000 ssh: added abort session in streamsplitter --- diff --git a/src/service_inspectors/ssh/ssh.cc b/src/service_inspectors/ssh/ssh.cc index ae6a04db7..81789dfc8 100644 --- a/src/service_inspectors/ssh/ssh.cc +++ b/src/service_inspectors/ssh/ssh.cc @@ -54,6 +54,7 @@ static bool process_ssh_version_string(SSH_PROTO_CONF* config, SSHData* sessionp static bool process_ssh1_key_exchange(SSHData *sessionp, Packet *p, uint8_t direction); static bool process_ssh2_kexinit(SSHData *sessionp, Packet *p, uint8_t direction); static bool process_ssh2_key_exchange(SSHData *sessionp, Packet *p, uint8_t direction); +bool is_us_ascii(const char *str, uint16_t size); unsigned SshFlowData::inspector_id = 0; @@ -150,6 +151,8 @@ static void snort_ssh(SSH_PROTO_CONF* config, Packet* p) { SshEvent event(SSH_VALIDATION, SSH_INVALID_VERSION, "", pkt_direction, p); DataBus::publish(pub_id, SshEventIds::STATE_CHANGE, event, p->flow); + if (sessp->version == NON_SSH_TRAFFIC) + sessp->ssh_aborted = true; } } else if (!(sessp->state_flags & search_dir_keyinit)) @@ -237,6 +240,26 @@ static void snort_ssh(SSH_PROTO_CONF* config, Packet* p) } } +bool is_us_ascii(const char *str, uint16_t size) +{ + for (uint16_t i = 0, count = 0; i < size; i++) + { + if ((((unsigned char)*str < 32) or (unsigned char)*str > 127) and + (((unsigned char)*str != 10 ) and ((unsigned char)*str != 13))) + { + if ((count == 0) && (unsigned char)*str == '-') + { + count++; + str++; + continue; + } + return false; + } + str++; + } + return true; +} + static bool process_ssh_version_string( SSH_PROTO_CONF* config, SSHData* sessionp, Packet* p, uint8_t direction) { @@ -260,6 +283,13 @@ static bool process_ssh_version_string( // so we will ignore them. return true; } + + if (!(is_us_ascii((const char*) p->data + 4, p->dsize - 4))) + { + sessionp->version = NON_SSH_TRAFFIC; + return false; + } + const char *proto_ver = (const char *)p->data + sizeof(SSH_BANNER) - 1; const char *proto_ver_end = (const char *)memchr(proto_ver, '-', p->dsize - sizeof(SSH_BANNER)); if (!proto_ver_end) @@ -285,12 +315,17 @@ static bool process_ssh_version_string( sessionp->version = SSH_VERSION_1; } } - else + else if (((proto_ver[0] >= '3') and (proto_ver[0] <= '9')) and proto_ver[1] == '.') { DetectionEngine::queue_event(GID_SSH, SSH_EVENT_VERSION); sessionp->version = SSH_VERSION_UNKNOWN; return false; } + else + { + sessionp->version = NON_SSH_TRAFFIC; + return false; + } /* Saw a valid protocol exchange message. Mark the session * according to the direction. diff --git a/src/service_inspectors/ssh/ssh.h b/src/service_inspectors/ssh/ssh.h index 168b96326..aa44bb8eb 100644 --- a/src/service_inspectors/ssh/ssh.h +++ b/src/service_inspectors/ssh/ssh.h @@ -86,6 +86,7 @@ #define SSH_VERSION_UNKNOWN (0x0) #define SSH_VERSION_1 (0x1) #define SSH_VERSION_2 (0x2) +#define NON_SSH_TRAFFIC (0xF) // Per-session data block containing current state // of the SSH inspector for the session. @@ -95,6 +96,7 @@ struct SSHData uint16_t num_enc_pkts; // encrypted packets seen on this session uint16_t num_client_bytes; // bytes of encrypted data sent by client without a server response uint32_t state_flags; // Bit vector describing the current state of the session + bool ssh_aborted; // Set when the session is not a ssh traffic }; class SshFlowData : public snort::FlowData diff --git a/src/service_inspectors/ssh/ssh_config.h b/src/service_inspectors/ssh/ssh_config.h index ad88233ff..e8f0054f8 100644 --- a/src/service_inspectors/ssh/ssh_config.h +++ b/src/service_inspectors/ssh/ssh_config.h @@ -37,6 +37,7 @@ struct SshStats PegCount total_bytes; PegCount concurrent_sessions; PegCount max_concurrent_sessions; + PegCount aborted_sessions; }; #endif diff --git a/src/service_inspectors/ssh/ssh_module.cc b/src/service_inspectors/ssh/ssh_module.cc index ab26c260b..6cca983c2 100644 --- a/src/service_inspectors/ssh/ssh_module.cc +++ b/src/service_inspectors/ssh/ssh_module.cc @@ -74,6 +74,7 @@ const PegInfo ssh_pegs[] = { CountType::SUM, "total_bytes", "total number of bytes processed" }, { CountType::NOW, "concurrent_sessions", "total concurrent ssh sessions" }, { CountType::MAX, "max_concurrent_sessions", "maximum concurrent ssh sessions" }, + { CountType::SUM, "aborted_sessions", "total session aborted" }, { CountType::END, nullptr, nullptr } }; diff --git a/src/service_inspectors/ssh/ssh_splitter.cc b/src/service_inspectors/ssh/ssh_splitter.cc index 15bc30d99..f05e49c2c 100644 --- a/src/service_inspectors/ssh/ssh_splitter.cc +++ b/src/service_inspectors/ssh/ssh_splitter.cc @@ -23,6 +23,7 @@ #endif #include "ssh_splitter.h" +#include "ssh_module.h" using namespace snort; @@ -91,6 +92,12 @@ StreamSplitter::Status SshSplitter::scan( Flow* flow = p->flow; SSHData* sessp = get_session_data(flow); + if (sessp and sessp->ssh_aborted) + { + sshstats.aborted_sessions++; + return ABORT; + } + if (nullptr == sessp) { sessp = SetNewSSHData(p);