severity 381726 normal thanks Demarc reported a security vulnerability to Snort through Bugtraq, this "security" issue is actually a problem with the HTTP inspector module in Snort which prevents it from detecting an attack against *Apache* web servers (not others) because it doesn't take into account that a carriage return might be included in the request and accepted (even if its not RFC). More info in the attached text file.
FWI the 2.4.5 changelog of Snort says: 2006-06-05 - Snort 2.4.5 Released * Fixed potential evasion in URI content buffers * Fixed potential evasion in Stream4 So, actually, to evasion bugs were fixed in this engine. I have backported both fixes to the 2.3.3-8 packages and have uploaded a new snort package. However, I don't think that the 'grave' severity of this bug stands and I'm downgrading it. Notice that: a) it is an evasion issue, not a security vulnerability. That is, it only affects the ability of Snort to detect attacks (but much in the same way that an *outdated* ruleset [1] could be considered a security issue) b) it only affects attacks to Apache web servers For reference, attached is the 2.4.4 vs. 2.4.5 patch (stripping other info) which fixes the bug, it is easily backported to the 2.3.3 (there is only one rejection, easy to solve). [2] Regards Javier [1] Like the one we are providing due to the license change in Snort, post 2.3, with the appearance of the VRT rules [2] Even if asked to (in #320920) I'm not sure it is reasonable to do an upgrade to 2.6.0 and provide a Snort package with *no* ruleset (which means that the Snort service could not be started by default). Since people now have to download it manually from snort.org as it is not provided in the GPL package.
diff -Nru snort-2.4.4/doc/README.http_inspect snort-2.4.5/doc/README.http_inspect --- snort-2.4.4/doc/README.http_inspect 2005-05-19 17:05:07.000000000 +0200 +++ snort-2.4.5/doc/README.http_inspect 2006-06-02 21:41:41.000000000 +0200 @@ -249,7 +249,7 @@ since some web sites refer to files using directory traversals. * apache_whitespace [yes/no] * -This option deals with non-RFC standard of tab for a space delimiter. Apache +This option deals with non-RFC standard of tab or carriage return for a space delimiter. Apache uses this, so if the emulated web server is Apache you need to enable this option. Alerts on this option may be interesting, but may also be false positive prone. diff -Nru snort-2.4.4/src/generators.h snort-2.4.5/src/generators.h --- snort-2.4.4/src/generators.h 2005-10-16 20:55:29.000000000 +0200 +++ snort-2.4.5/src/generators.h 2006-05-24 18:14:33.000000000 +0200 @@ -98,6 +98,7 @@ #define STREAM4_ZERO_TIMESTAMP 21 #define STREAM4_OVERLAP_LIMIT 22 #define STREAM4_TCP_NO_ACK 23 +#define STREAM4_EVASIVE_FIN 24 #define GENERATOR_SPP_ARPSPOOF 112 #define ARPSPOOF_UNICAST_ARP_REQUEST 1 @@ -335,6 +336,7 @@ #define STREAM4_ZERO_TIMESTAMP_STR "(spp_stream4) TCP Option Timestamp value of 0" #define STREAM4_OVERLAP_LIMIT_STR "(spp_stream4) TCP stream too many overlapping packets" #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" /* FRAG3 strings */ #define FRAG3_IPOPTIONS_STR "(spp_frag3) Inconsistent IP Options on Fragmented Packets" diff -Nru snort-2.4.4/src/preprocessors/HttpInspect/client/hi_client.c snort-2.4.5/src/preprocessors/HttpInspect/client/hi_client.c --- snort-2.4.4/src/preprocessors/HttpInspect/client/hi_client.c 2005-03-16 22:52:18.000000000 +0100 +++ snort-2.4.5/src/preprocessors/HttpInspect/client/hi_client.c 2006-06-02 21:41:41.000000000 +0200 @@ -85,6 +85,8 @@ */ static LOOKUP_FCN lookup_table[256]; static int hex_lookup[256]; +static int NextNonWhiteSpace(HI_SESSION *Session, u_char *start, + u_char *end, u_char **ptr, URI_PTR *uri_ptr); /* ** NAME @@ -455,7 +457,7 @@ return URI_END; } - return NO_URI; + return NextNonWhiteSpace(Session, start, end, ptr, uri_ptr); } /* @@ -677,7 +679,7 @@ (*ptr)++; continue; } - else if((**ptr == '\t')) + else if((**ptr == '\t') || (**ptr == '\r')) { if(ServerConf->apache_whitespace.on) { diff -Nru snort-2.4.4/src/preprocessors/spp_stream4.c snort-2.4.5/src/preprocessors/spp_stream4.c --- snort-2.4.4/src/preprocessors/spp_stream4.c 2006-01-09 21:38:30.000000000 +0100 +++ snort-2.4.5/src/preprocessors/spp_stream4.c 2006-05-24 18:14:33.000000000 +0200 @@ -412,7 +412,7 @@ void PreprocCleanExitFunction(int); static INLINE int isBetween(u_int32_t low, u_int32_t high, u_int32_t cur); static INLINE int NotForStream4(Packet *p); -static INLINE int SetFinSent(Packet *p, Session *ssn, int direction); +static INLINE int SetFinSent(Session *ssn, int direction, u_int32_t pkt_seq, Packet *p); static INLINE int WithinSessionLimits(Packet *p, Stream *stream); /* helpers for dealing with session byte_counters */ @@ -1777,32 +1777,115 @@ return; } +/** + * Check a FIN is valid within the window + * + * @param s stream to set the next_seq on + * @param direction direction of the packet + * @param pkt_seq sequence number for the packet + * @param p packet to grab the session from + * + * @return 0 if everything went ok + */ +static INLINE int CheckFin(Stream *s, int direction, u_int32_t pkt_seq, Packet *p) +{ + DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "CheckFin() called for %s\n", + direction ? "FROM_CLIENT":"FROM_SERVER");); + + /* If not tracking state ignore it */ + if( !s4data.stateful_inspection_flag ) + return 0; + + /* + * We want to make sure the FIN has the next valid sequence that + * this side should be sending + * If the pkt_seq < next_seq it's essentially a duplicate + * sequence, and is probably going to be discarded, it certainly + * should be. Also, the base sequence includes the SYN sequence count. + * If the packet seq is after the next seq than we should queue the + * packet for later, in case an out of order packet arrives. We + * should also honor the FIN-ACK requirements. + * + * Ignoring a FIN implies we won't shutdown this session due to it. + * + * This is a standard TCP/IP stack 'in the window' check, but it's + * not always the way stacks handle FIN's: + * + * if(SEQ_LT(pkt_seq,s->base_seq+s->bytes_tracked) || + * SEQ_GEQ(pkt_seq,(s->last_ack+s->win_size))) + * + */ + if(SEQ_LT(pkt_seq,s->base_seq+s->bytes_tracked) || + SEQ_GEQ(pkt_seq,(s->last_ack+s->win_size))) + { + DEBUG_WRAP(DebugMessage(DEBUG_STREAM, + "Bad FIN packet, bad sequence!\n" + "pkt seq: 0x%X last_ack: 0x%X win: 0x%X\n", + pkt_seq, s->last_ack, s->win_size);); + + /* we should probably alert here */ + if(s4data.evasion_alerts) + { + SnortEventqAdd(GENERATOR_SPP_STREAM4, /* GID */ + STREAM4_EVASIVE_FIN, /* SID */ + 1, /* Rev */ + 0, /* classification */ + 3, /* priority (low) */ + STREAM4_EVASIVE_FIN_STR, /* msg string */ + 0); + } + return 1; + } + return 0; +} + + /** * Set that this side of the session has sent a fin. * * This overloads the next_seq variable to also be used to tell how * far forward we can acknowledge data. * - * @param p packet to grab the session from * @param s stream to set the next_seq on + * @param direction direction of the packet + * @param pkt_seq sequence number for the packet + * @param p packet to grab the session from * * @return 0 if everything went ok */ -static INLINE int SetFinSent(Packet *p, Session *ssn, int direction) +static INLINE int SetFinSent(Session *ssn, int direction, u_int32_t pkt_seq, Packet *p) { Stream *stream; DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "SetFinSet() called for %s\n", direction ? "FROM_CLIENT":"FROM_SERVER");); + /* If not tracking state ignore it */ + if( !s4data.stateful_inspection_flag ) + return 0; + if(direction == FROM_SERVER) - { + { stream = &ssn->server; + DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"--RST From Server!\n");); + } + else + { + stream = &ssn->client; + DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"--RST From Client!\n");); + } + + if (CheckFin(stream, direction, pkt_seq, p)) + { + return 0; + } + + if(direction == FROM_SERVER) + { ssn->session_flags |= SSNFLAG_SERVER_FIN; } else { - stream = &ssn->client; ssn->session_flags |= SSNFLAG_CLIENT_FIN; } @@ -2596,14 +2679,6 @@ direction = GetDirection(ssn, p); - if(p->tcph->th_flags & TH_FIN) - { - DEBUG_WRAP(DebugMessage(DEBUG_STREAM, - "Marking that a fin was was sent %s\n", - (direction ? "FROM_CLIENT" : "FROM_SERVER"));); - SetFinSent(p, ssn, direction); - } - if(direction == FROM_SERVER) { ssn->session_flags |= SSNFLAG_SEEN_SERVER; @@ -2638,6 +2713,15 @@ " %s state: %s\n", l, state_names[listener->state]);); } + if(p->tcph->th_flags & TH_FIN) + { + DEBUG_WRAP(DebugMessage(DEBUG_STREAM, + "Marking that a fin was was sent %s\n", + (direction ? "FROM_CLIENT" : "FROM_SERVER"));); + + SetFinSent(ssn, direction, pkt_seq, p); + } + StreamSegmentAdd(talker, p->dsize); if(talker->state == ESTABLISHED) @@ -2754,10 +2838,13 @@ if((p->tcph->th_flags & TH_FIN) == TH_FIN) { - talker->state = FIN_WAIT_1; - DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - " %s Transition: FIN_WAIT_1\n", t);); - QueueState(CLOSE_WAIT, listener, TH_ACK, pkt_seq, CHK_SEQ); + if (!CheckFin(talker, direction, pkt_seq, p)) + { + talker->state = FIN_WAIT_1; + DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, + " %s Transition: FIN_WAIT_1\n", t);); + QueueState(CLOSE_WAIT, listener, TH_ACK, pkt_seq, CHK_SEQ); + } } break; diff -Nru snort-2.4.4/src/preprocessors/xlink2state.c snort-2.4.5/src/preprocessors/xlink2state.c --- snort-2.4.4/src/preprocessors/xlink2state.c 2005-08-23 17:52:20.000000000 +0200 +++ snort-2.4.5/src/preprocessors/xlink2state.c 2006-06-02 21:00:10.000000000 +0200 @@ -38,7 +38,7 @@ /* Pointer to current session data */ XLINK2STATE *_xlink; -static u_int _xlink2state_ports[65535]; +static u_int _xlink2state_ports[65536]; static u_int _xlink2state_disabled = 0; static u_int _xlink2state_drop = 0; static Packet *_xlink2state_pkt = NULL; @@ -67,9 +67,6 @@ /* Set up commands we will watch for */ SearchInit(1); - /* Set up commands we will watch for */ - SearchInit(1); - SearchAdd(0, "X-LINK2STATE", 0); SearchPrepPatterns(0);
Possible Evasion in http_inspect Jennifer Steffens (Sourcefire) @ May 31, 2006 18:32:28 Sourcefire is aware of a possible Snort evasion that exists in the http_inspect preprocessor. This evasion case only applies to protected Apache web servers. We have prepared fixes for both the 2.4 and 2.6 branches and will have fully tested releases, including binaries, available for both on Monday, June 5th. Evasion Details: The Apache web server supports special characters in HTTP requests that do not affect the processing of the particular request. The current target-based profiles for Apache in the http_inspect preprocessor do not properly handle these requests, resulting in the possibility that an attacker can bypass detection of rules that use the "uricontent" keyword by embedding special characters in a HTTP request. Background Information: It is important to note that this is an evasion and not a vulnerability. This means that while it is possible for an attacker to bypass detection, Snort sensors and the networks they protect are not at a heightened risk of other attacks. Timeline: Sourcefire has prepared fixes and is currently finalizing a complete round of testing to ensure that the fixes not only solve the issue at hand but do not create new bugs as well. The following releases, including binaries for Linux and Windows deployments, will be available on Monday, June 5th: * Snort v2.4.5 * Snort v2.6.0 final Questions: Any questions regarding these releases can be sent to [EMAIL PROTECTED]
signature.asc
Description: Digital signature