]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4417: ssh: added abort session in streamsplitter
authorShijin Bose (shibose) <shibose@cisco.com>
Thu, 12 Sep 2024 13:51:34 +0000 (13:51 +0000)
committerShanmugam S (shanms) <shanms@cisco.com>
Thu, 12 Sep 2024 13:51:34 +0000 (13:51 +0000)
Merge in SNORT/snort3 from ~SHIBOSE/snort3:ssh_fallback to master

Squashed commit of the following:

commit c5a27bacf94fff0db24793b62ffa22ee6587ff42
Author: shibose <shibose@cisco.com>
Date:   Thu Aug 8 05:37:06 2024 +0000

    ssh: added abort session in streamsplitter

src/service_inspectors/ssh/ssh.cc
src/service_inspectors/ssh/ssh.h
src/service_inspectors/ssh/ssh_config.h
src/service_inspectors/ssh/ssh_module.cc
src/service_inspectors/ssh/ssh_splitter.cc

index ae6a04db73cfe5f98b1db3f0630e950d079f3859..81789dfc87594aa4dc038a4cd0b1dad6d71aecec 100644 (file)
@@ -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.
index 168b96326362abdffdf6dc8e1d8633620f6b37af..aa44bb8ebe92766f3ae37276755aba6bf60009e9 100644 (file)
@@ -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
index ad88233ff6ba221202205f695d2d9814c70ccc15..e8f0054f88fbfdfb393b53d018e74f55642a970c 100644 (file)
@@ -37,6 +37,7 @@ struct SshStats
     PegCount total_bytes;
     PegCount concurrent_sessions;
     PegCount max_concurrent_sessions;
+    PegCount aborted_sessions;
 };
 
 #endif
index ab26c260b09ba38cbfae2a5452c9347c1c4628b9..6cca983c2aba570670815338ecb706f9e1abc5e0 100644 (file)
@@ -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 }
 };
 
index 15bc30d993398ea04767e382ba62fb315da975c9..f05e49c2c732ce966658808a0a79df1ebaa87b75 100644 (file)
@@ -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);