From: Michael Altizer (mialtize) Date: Thu, 11 Apr 2019 14:34:42 +0000 (-0400) Subject: Merge pull request #1554 in SNORT/snort3 from ~BBANTWAL/snort3:ftp_telnet_fix to... X-Git-Tag: 3.0.0-253~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=99356e01f9ce79b0f0556508e16c8c09c82fa2af;p=thirdparty%2Fsnort3.git Merge pull request #1554 in SNORT/snort3 from ~BBANTWAL/snort3:ftp_telnet_fix to master Squashed commit of the following: commit f58bec4438aa335dd6141a62b1409c5d3eda171f Author: Bhagya Tholpady 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 --- diff --git a/src/service_inspectors/ftp_telnet/ftp_splitter.cc b/src/service_inspectors/ftp_telnet/ftp_splitter.cc index a39dc19da..10a9dbc8a 100644 --- a/src/service_inspectors/ftp_telnet/ftp_splitter.cc +++ b/src/service_inspectors/ftp_telnet/ftp_splitter.cc @@ -22,6 +22,8 @@ #endif #include "ftp_splitter.h" +#include "protocols/ssl.h" +#include "protocols/packet.h" #include @@ -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 diff --git a/src/service_inspectors/ftp_telnet/pp_ftp.cc b/src/service_inspectors/ftp_telnet/pp_ftp.cc index 5f2e0a1c7..e34ac0c86 100644 --- a/src/service_inspectors/ftp_telnet/pp_ftp.cc +++ b/src/service_inspectors/ftp_telnet/pp_ftp.cc @@ -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) { diff --git a/src/service_inspectors/ftp_telnet/pp_telnet.cc b/src/service_inspectors/ftp_telnet/pp_telnet.cc index b7bcf7090..bea408517 100644 --- a/src/service_inspectors/ftp_telnet/pp_telnet.cc +++ b/src/service_inspectors/ftp_telnet/pp_telnet.cc @@ -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; } diff --git a/src/service_inspectors/ftp_telnet/pp_telnet.h b/src/service_inspectors/ftp_telnet/pp_telnet.h index d402e4753..0389a8275 100644 --- a/src/service_inspectors/ftp_telnet/pp_telnet.h +++ b/src/service_inspectors/ftp_telnet/pp_telnet.h @@ -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&); diff --git a/src/service_inspectors/ftp_telnet/telnet.cc b/src/service_inspectors/ftp_telnet/telnet.cc index 7c9eb8e3e..027d2c739 100644 --- a/src/service_inspectors/ftp_telnet/telnet.cc +++ b/src/service_inspectors/ftp_telnet/telnet.cc @@ -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 ) {