--- snort-2.6.1.1.old/etc/snort.conf 2006-11-22 10:53:50.000000000 -0300 +++ snort-2.6.1.1/etc/snort.conf 2006-12-04 12:49:45.000000000 -0300 @@ -378,7 +378,11 @@ preprocessor frag3_engine: policy first # more sessions are purged from the cache when # the session limit or memcap is reached. # Defaults to 5. -# +# detect_covered_channels [number] - Number of bytes to use as threshold to +# detect covered channels, 0 to disable this check +# covered_channels_ports [list] - use the space separated list of ports in [list], +# "all" will turn on detection for all ports, "default" will turn +# on reassembly for ports 21, 25, 80 and 443 # # # Stream4 uses Generator ID 111 and uses the following SIDS @@ -399,6 +403,7 @@ preprocessor frag3_engine: policy first # 12 Stealth scan: NMAP fingerprint scan stateful detect # 13 Stealth scan: SYN-FIN scan # 14 TCP forward overlap +# 26 Covered channel detect preprocessor stream4: disable_evasion_alerts --- snort-2.6.1.1.old/src/generators.h 2006-10-12 17:28:13.000000000 -0300 +++ snort-2.6.1.1/src/generators.h 2006-12-04 12:38:00.000000000 -0300 @@ -100,6 +100,7 @@ #define STREAM4_TCP_NO_ACK 23 #define STREAM4_EVASIVE_FIN 24 #define STREAM4_SYN_ON_ESTABLISHED 25 +#define STREAM4_COVERED_CHANNEL 26 #define GENERATOR_SPP_ARPSPOOF 112 #define ARPSPOOF_UNICAST_ARP_REQUEST 1 @@ -396,6 +397,7 @@ #define STREAM4_TCP_NO_ACK_STR "(spp_stream4) Packet in Established TCP stream missing ACK" #define STREAM4_EVASIVE_FIN_STR "(spp_stream4) possible EVASIVE FIN detection" #define STREAM4_SYN_ON_ESTABLISHED_STR "(spp_stream4) SYN on established session detection, resetting reassembly queue" +#define STREAM4_COVERED_CHANNEL_STR "(spp_stream4) possible COVERED CHANNEL detection" /* FRAG3 strings */ #define FRAG3_IPOPTIONS_STR "(spp_frag3) Inconsistent IP Options on Fragmented Packets" --- snort-2.6.1.1.old/src/preprocessors/stream.h 2006-10-04 18:35:08.000000000 -0300 +++ snort-2.6.1.1/src/preprocessors/stream.h 2006-12-04 12:38:00.000000000 -0300 @@ -73,6 +73,8 @@ typedef struct _Stream u_int8_t alert_count; /* count alerts seen in a stream */ u_int8_t outoforder; /* flag indicating stream is no longer in order */ + + char covered; /* Covered channel status */ } Stream; typedef struct _SessionHashKey @@ -153,6 +155,7 @@ typedef struct _Stream4Data u_int8_t assemble_ports[65536]; u_int8_t emergency_ports[65536]; /* alternate port set for self-preservation mode */ + u_int8_t covered_channels_ports[65536]; u_int32_t sp_threshold; u_int32_t sp_period; @@ -189,6 +192,8 @@ typedef struct _Stream4Data int32_t flush_behavior; u_int32_t flush_seed; + u_int32_t detect_covered_channels; + #ifdef STREAM4_UDP // UDP Stuff u_int32_t max_udp_sessions; --- snort-2.6.1.1.old/src/preprocessors/spp_stream4.c 2006-11-22 11:45:22.000000000 -0300 +++ snort-2.6.1.1/src/preprocessors/spp_stream4.c 2006-12-04 12:52:17.000000000 -0300 @@ -186,6 +186,8 @@ #define STATS_MACHINE_READABLE 2 #define STATS_BINARY 3 +#define COVERED_CHANNELD_THRESHOLD 10240 /* Default covered channels detection bytes threshold */ + #define STATS_MAGIC 0xDEAD029A /* magic for the binary stats file */ #define REVERSE 0 @@ -378,6 +380,7 @@ PreprocStats stream4NewSessPerfStats; PreprocStats stream4LUSessPerfStats; PreprocStats stream4StatePerfStats; PreprocStats stream4StateAsyncPerfStats; +PreprocStats stream4CoveredChannelsPerfStats; PreprocStats stream4ActionPerfStats; PreprocStats stream4ActionAsyncPerfStats; PreprocStats stream4PrunePerfStats; @@ -976,6 +979,9 @@ void Stream4VerifyConfig() void DisplayStream4Config(void) { +char buf[STD_BUF+1]; +int i, j; + LogMessage("Stream4 config:\n"); LogMessage(" Stateful inspection: %s\n", s4data.stateful_inspection_flag ? "ACTIVE": "INACTIVE"); @@ -1007,6 +1013,27 @@ void DisplayStream4Config(void) LogMessage(" MinTTL: %d\n", s4data.min_ttl); LogMessage(" TTL Limit: %d\n", s4data.ttl_limit); LogMessage(" Async Link: %d\n", s4data.asynchronous_link); + LogMessage(" Covered channels threashold: %lu bytes\n", s4data.detect_covered_channels); + + memset(buf, 0, STD_BUF+1); + snprintf(buf, STD_BUF, " Ports: "); + + for(i=0, j=0;i<65536;i++) + { + if(s4data.covered_channels_ports[i]) + { + sfsnprintfappend(buf, STD_BUF, "%d ", i); + j++; + } + + if(j > 20) + { + LogMessage("%s...\n", buf); + return; + } + } + + LogMessage("%s\n", buf); LogMessage(" State Protection: %d\n", s4data.state_protection); LogMessage(" Self preservation threshold: %d\n", s4data.sp_threshold); LogMessage(" Self preservation period: %d\n", s4data.sp_period); @@ -1065,6 +1092,7 @@ void ParseStream4Args(char *args) s4data.path_mtu = 1460; s4data.ttl_limit = STREAM4_TTL_LIMIT; s4data.asynchronous_link = 0; + s4data.detect_covered_channels = 0; s4data.flush_data_diff_size = 500; s4data.zero_flushed_packets = 0; s4data.flush_on_alert = 0; @@ -1079,6 +1107,12 @@ void ParseStream4Args(char *args) s4data.flush_base = STREAM4_FLUSH_BASE; s4data.flush_seed = getpid() + time(NULL); + /* Covered Channels target ports */ + s4data.covered_channels_ports[21] = 1; + s4data.covered_channels_ports[25] = 1; + s4data.covered_channels_ports[80] = 1; + s4data.covered_channels_ports[443] = 1; + #ifdef STREAM4_UDP /* Ports on which to do UDP sessions. * Derived from rules that have "flow" keyword @@ -1113,6 +1147,65 @@ void ParseStream4Args(char *args) { s4data.asynchronous_link = 1; } + else if(!strcasecmp(stoks[0], "detect_covered_channels")) + { + if(isdigit((int)stoks[1][0])) + { + s4data.detect_covered_channels = atol(stoks[1]); + } + else + { + LogMessage("WARNING %s(%d) => Bad threshold in config file, " + "defaulting to %d bytes\n", file_name, file_line, + COVERED_CHANNELD_THRESHOLD); + + s4data.detect_covered_channels = COVERED_CHANNELD_THRESHOLD; + } + } + else if(!strcasecmp(stoks[0], "covered_channels_ports")) + { + char **ports; + char *port; + int j = 0; + u_int32_t portnum; + + for(j = 0;j<65535;j++) + { + s4data.covered_channels_ports[j] = 0; + } + + j = 1; + + while(j < s_toks) + { + port = stoks[j]; + + if(isdigit((int)port[0])) + { + portnum = atoi(port); + + if(portnum > 65535) + { + FatalError("%s(%d) => Bad port list to " + "reassembler\n", file_name, file_line); + } + + s4data.covered_channels_ports[portnum] = 1; + } + else if(!strncasecmp(port, "all", 3)) + { + memset(&s4data.covered_channels_ports, 1, 65536); + } + else if(!strncasecmp(port, "default", 7)) + { + s4data.covered_channels_ports[21] = 1; + s4data.covered_channels_ports[80] = 1; + s4data.covered_channels_ports[443] = 1; + } + + j++; + } + } else if(!strcasecmp(stoks[0], "keepstats")) { s4data.track_stats_flag = STATS_HUMAN_READABLE; @@ -3328,6 +3421,31 @@ int UpdateState2(Session *ssn, Packet *p StreamSegmentAdd(talker, p->dsize); + /* Logic test: + * detect_covered_channels option is set in the config + * Packet direction is from client + * Server to client flow exists + * Port server is a possible target of covered channel (with asymetric behaviour) + * Alert was not send yet for this connection + * Bytes sended and received for this connnection + */ + if(s4data.detect_covered_channels && + direction == FROM_CLIENT && + &ssn->server && + s4data.covered_channels_ports[(ssn->server).port] && + (ssn->client).covered == 0 && + (ssn->client).bytes_sent > s4data.detect_covered_channels && + (ssn->server).bytes_sent > s4data.detect_covered_channels) { + SnortEventqAdd(GENERATOR_SPP_STREAM4, /* GID */ + STREAM4_COVERED_CHANNEL, /* SID */ + 1, /* Rev */ + 0, /* classification */ + 3, /* priority (low) */ + STREAM4_COVERED_CHANNEL_STR, /* msg string */ + 0); + (ssn->client).covered = 1; + } + if(talker->state == ESTABLISHED) { listener->win_size = ntohs(p->tcph->th_win);