]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1554 in SNORT/snort3 from ~BBANTWAL/snort3:ftp_telnet_fix to...
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Thu, 11 Apr 2019 14:34:42 +0000 (10:34 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Thu, 11 Apr 2019 14:34:42 +0000 (10:34 -0400)
Squashed commit of the following:

commit f58bec4438aa335dd6141a62b1409c5d3eda171f
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Mon Mar 18 23:51:50 2019 -0400

    ftptelnet: use the normalized telnet buffer to alert telnet on ftp command channel, flush on ftp encrypted data boundaries, check for telnet at the start of the ftp packet

src/service_inspectors/ftp_telnet/ftp_splitter.cc
src/service_inspectors/ftp_telnet/pp_ftp.cc
src/service_inspectors/ftp_telnet/pp_telnet.cc
src/service_inspectors/ftp_telnet/pp_telnet.h
src/service_inspectors/ftp_telnet/telnet.cc

index a39dc19da89c1a4b72f998e63a2a91f644e027d9..10a9dbc8a1b94a82940ee062a3cd8a2bbca94fc4 100644 (file)
@@ -22,6 +22,8 @@
 #endif
 
 #include "ftp_splitter.h"
+#include "protocols/ssl.h"
+#include "protocols/packet.h"
 
 #include <cstring>
 
@@ -32,9 +34,14 @@ FtpSplitter::FtpSplitter(bool c2s) : StreamSplitter(c2s) { }
 // flush at last line feed in data
 // preproc will deal with any pipelined commands
 StreamSplitter::Status FtpSplitter::scan(
-    Packet*, const uint8_t* data, uint32_t len,
+    Packet* p, const uint8_t* data, uint32_t len,
     uint32_t, uint32_t* fp)
 {
+    if(IsSSL(data, len, p->packet_flags))
+    {
+        *fp = len;
+        return FLUSH;
+    }
 #ifdef HAVE_MEMRCHR
     uint8_t* lf =  (uint8_t*)memrchr(data, '\n', len);
 #else
index 5f2e0a1c71271f595dc8b7b51d27889f135ff098..e34ac0c8657bc505cd60f272d101c3abdbdead9b 100644 (file)
@@ -60,8 +60,6 @@ using namespace snort;
 #define MAXHOSTNAMELEN 256
 #endif
 
-static THREAD_LOCAL DataBuffer DecodeBuffer;
-
 /*
  * Used to keep track of pipelined commands and the last one
  * that resulted in a
@@ -920,39 +918,45 @@ static int check_ftp_param_validity(Packet* p,
  */
 int initialize_ftp(FTP_SESSION* session, Packet* p, int iMode)
 {
-    int iRet;
     const unsigned char* read_ptr = p->data;
     FTP_CLIENT_REQ* req;
-    char ignoreTelnetErase = FTPP_APPLY_TNC_ERASE_CMDS;
-
-    /* Normalize this packet ala telnet */
-    if (((iMode == FTPP_SI_CLIENT_MODE) &&
-        session->client_conf->ignore_telnet_erase_cmds) ||
-        ((iMode == FTPP_SI_SERVER_MODE) &&
-        session->server_conf->ignore_telnet_erase_cmds) )
-        ignoreTelnetErase = FTPP_IGNORE_TNC_ERASE_CMDS;
-
-    iRet = normalize_telnet(nullptr, p, iMode, ignoreTelnetErase);
 
-    if (iRet != FTPP_SUCCESS && iRet != FTPP_NORMALIZED)
+    if ( session->encr_state == NO_STATE )
     {
-        if (iRet == FTPP_ALERT)
-            DetectionEngine::queue_event(GID_FTP, FTP_EVASIVE_TELNET_CMD);
+        int iRet;
+        char ignoreTelnetErase = FTPP_APPLY_TNC_ERASE_CMDS;
+        /* Normalize this packet ala telnet */
+        if (((iMode == FTPP_SI_CLIENT_MODE) &&
+            session->client_conf->ignore_telnet_erase_cmds) ||
+            ((iMode == FTPP_SI_SERVER_MODE) &&
+            session->server_conf->ignore_telnet_erase_cmds) )
+            ignoreTelnetErase = FTPP_IGNORE_TNC_ERASE_CMDS;
 
-        return iRet;
-    }
+        DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
 
-    if ( DecodeBuffer.len )
-    {
-        /* Normalized data will always be in decode buffer */
-        if ( (iMode == FTPP_SI_CLIENT_MODE) ||
-            (iMode == FTPP_SI_SERVER_MODE) )
+        iRet = normalize_telnet(nullptr, p, buf, iMode, ignoreTelnetErase, true);
+
+        if (iRet != FTPP_SUCCESS && iRet != FTPP_NORMALIZED)
         {
-            DetectionEngine::queue_event(GID_FTP, FTP_TELNET_CMD);
-            return FTPP_ALERT; /* Nothing else to do since we alerted */
+            if (iRet == FTPP_ALERT)
+                DetectionEngine::queue_event(GID_FTP, FTP_EVASIVE_TELNET_CMD);
+
+            return iRet;
         }
 
-        read_ptr = DecodeBuffer.data;
+
+        if ( buf.len )
+        {
+            /* Normalized data will always be in decode buffer */
+            if ( (iMode == FTPP_SI_CLIENT_MODE) ||
+                (iMode == FTPP_SI_SERVER_MODE) )
+            {
+                DetectionEngine::queue_event(GID_FTP, FTP_TELNET_CMD);
+                return FTPP_ALERT; /* Nothing else to do since we alerted */
+            }
+
+            read_ptr = buf.data;
+        }
     }
 
     if (iMode == FTPP_SI_CLIENT_MODE)
@@ -1305,8 +1309,9 @@ int check_ftp(FTP_SESSION* ftpssn, Packet* p, int iMode)
 
     const unsigned char* end = p->data + p->dsize;
 
-    if ( DecodeBuffer.len )
-        end = DecodeBuffer.data + DecodeBuffer.len;
+    DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
+    if ( buf.len )
+        end = buf.data + buf.len;
 
     if (iMode == FTPP_SI_CLIENT_MODE)
     {
index b7bcf7090b6f83937c584851901666fdc1b9c7cb..bea408517cf1c98cedc423168dff9cfcd9d65105 100644 (file)
@@ -93,8 +93,8 @@ const uint8_t* get_telnet_buffer(Packet* p, unsigned& len)
  *
  */
 int normalize_telnet(
-    TELNET_SESSION* tnssn, Packet* p,
-    int iMode, char ignoreEraseCmds)
+    TELNET_SESSION* tnssn, Packet* p, DataBuffer& buf,
+    int iMode, char ignoreEraseCmds, bool on_ftp_channel)
 {
     int ret = FTPP_NORMALIZED;
     const unsigned char* read_ptr, * sb_start = nullptr;
@@ -103,8 +103,8 @@ int normalize_telnet(
     int normalization_required = 0;
     int consec_8bit_chars = 0;
 
-    DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
     const unsigned char* start = buf.data;
+    buf.len = 0;
 
     /* Telnet commands are handled in here.
     * They can be 2 bytes long -- ie, IAC NOP, IAC AYT, etc.
@@ -131,6 +131,10 @@ int normalize_telnet(
         }
         else
         {
+            if ( on_ftp_channel )
+            {
+                return FTPP_SUCCESS;
+            }
             /* Okay, it wasn't an IAC also its a midstream pickup */
             if (*read_ptr > 0x7F && Stream::is_midstream(p->flow))
             {
@@ -214,6 +218,7 @@ int normalize_telnet(
                     if (write_ptr  > start)
                     {
                         write_ptr--;
+                        buf.len--;
                     }
                 }
                 break;
@@ -227,6 +232,7 @@ int normalize_telnet(
                     {
                         /* Go to previous char */
                         write_ptr--;
+                        buf.len--;
 
                         if ((*write_ptr == CR) &&
                             ((*(write_ptr+1) == NUL) || (*(write_ptr+1) == LF)) )
@@ -236,6 +242,7 @@ int normalize_telnet(
                              * beginning of this line
                              */
                             write_ptr+=2;
+                            buf.len+=2;
                             break;
                         }
                     }
@@ -286,6 +293,7 @@ int normalize_telnet(
                 * in the data stream since it was escaped */
                 read_ptr++; /* skip past the first IAC */
                 *write_ptr++ = *read_ptr++;
+                buf.len++;
                 break;
             case TNC_WILL:
             case TNC_WONT:
@@ -415,11 +423,13 @@ int normalize_telnet(
                 if (write_ptr > start)
                 {
                     write_ptr--;
+                    buf.len--;
                 }
                 read_ptr++;
                 break;
             default:
                 *write_ptr++ = *read_ptr++;
+                buf.len++;
                 break;
             }
 
index d402e47538fa770291baccada89dc108eb190528..0389a8275763d264be0020bcd83da7b471ac7653 100644 (file)
@@ -60,8 +60,9 @@
 #define FTPP_APPLY_TNC_ERASE_CMDS 0
 #define FTPP_IGNORE_TNC_ERASE_CMDS 1
 
+struct DataBuffer;
 /* list of function prototypes for this preprocessor */
-extern int normalize_telnet(TELNET_SESSION*, snort::Packet*, int iMode, char ignoreEraseCmd);
+extern int normalize_telnet(TELNET_SESSION*, snort::Packet*, DataBuffer&, int iMode, char ignoreEraseCmd, bool on_ftp_channel);
 
 void reset_telnet_buffer(snort::Packet*);
 const uint8_t* get_telnet_buffer(snort::Packet*, unsigned&);
index 7c9eb8e3e43836eee1d63fad4149123faf011d11..027d2c7393c2f45db8119bcc9db94fcfae49a505 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "telnet.h"
 
+#include "detection/detection_engine.h"
 #include "log/messages.h"
 #include "profiler/profiler.h"
 #include "protocols/packet.h"
@@ -79,8 +80,9 @@ static int SnortTelnet(TELNET_PROTO_CONF* telnet_config, TELNET_SESSION* Telnets
 
     if ( telnet_config->normalize )
     {
-        int ret = normalize_telnet(Telnetsession, p, iInspectMode,
-            FTPP_APPLY_TNC_ERASE_CMDS);
+        DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
+        int ret = normalize_telnet(Telnetsession, p, buf, iInspectMode,
+            FTPP_APPLY_TNC_ERASE_CMDS, false);
 
         if ( ret == FTPP_SUCCESS || ret == FTPP_NORMALIZED )
         {