Package: snort
Severity: critical
Version: 2.3.3-2
Justification: remote compromise

Well, I have just read both an X-force and a CERT alert related to Snort,
it seems that it is possible to make a preprocessor (bo) crash and run code
remotely through a single UDP traffic.

I'm still investigating the issue to see if it affects the sarge, etch and
sid versions (we are not using the bo preprocessor from 2.4, which seems to
be the one vulnerable). 

For more information:
http://xforce.iss.net/xforce/alerts/id/207
http://www.us-cert.gov/cas/techalerts/TA05-291A.html
http://www.snort.org/docs/change_logs/2.4.3/Changelog.txt
http://www.snort.org/pub-bin/snortnews.cgi

It seems CERT's VU#175500 is the only reference available, as no CVE name has
been asigned. It also seems that X-force reported this October 13th and
disclosed it October 18th. It doesn't look like CERT coordinated much, did
they?

Attached is the patch from the 2.4.3 that seems to be relevant to the issue,
it's a rather long patch and does not apply cleanly to 2.3.2-3 at least.

For those people running Snort Debian packages it is advised they disable the
Snort 'bo' preprocessor (it's enabled in the stock Debian configuration)
until this issue has been reviewed and, maybe, fixed.

Regards

Javier
diff -Nru snort-2.4.2/etc/gen-msg.map snort-2.4.3/etc/gen-msg.map
--- snort-2.4.2/etc/gen-msg.map 2005-09-14 21:09:09.000000000 +0200
+++ snort-2.4.3/etc/gen-msg.map 2005-10-16 20:55:28.000000000 +0200
@@ -1,4 +1,4 @@
-# $Id: gen-msg.map,v 1.16.2.2.2.3 2005/09/14 19:09:09 amullican Exp $
+# $Id: gen-msg.map,v 1.16.2.2.2.4 2005/10/16 18:55:28 ssturges Exp $
 # GENERATORS -> msg map
 # Format: generatorid || alertid || MSG
 
@@ -22,6 +22,7 @@
 105 || 1 || spp_bo: Back Orifice Traffic Detected
 105 || 2 || spp_bo: Back Orifice Client Traffic Detected
 105 || 3 || spp_bo: Back Orifice Server Traffic Detected
+105 || 4 || spp_bo: Back Orifice Snort Buffer Attack
 106 || 1 || spp_rpc_decode: Fragmented RPC Records
 106 || 2 || spp_rpc_decode: Multiple Records in one packet
 106 || 3 || spp_rpc_decode: Large RPC Record Fragment
diff -Nru snort-2.4.2/etc/snort.conf snort-2.4.3/etc/snort.conf
--- snort-2.4.2/etc/snort.conf  2005-09-28 04:42:26.000000000 +0200
+++ snort-2.4.3/etc/snort.conf  2005-10-17 15:50:55.000000000 +0200
@@ -1,8 +1,8 @@
 #--------------------------------------------------
-#   http://www.snort.org     Snort 2.4.0 config file
+#   http://www.snort.org     Snort 2.4.3 config file
 #     Contact: [EMAIL PROTECTED]
 #--------------------------------------------------
-# $Id: snort.conf,v 1.144.2.9.2.15 2005/09/16 21:06:34 roesch Exp $
+# $Id: snort.conf,v 1.144.2.9.2.17 2005/10/16 22:21:08 mnorton Exp $
 #
 ###################################################
 # This file contains a sample snort configuration. 
@@ -425,13 +425,24 @@
 
 # bo: Back Orifice detector
 # -------------------------
-# Detects Back Orifice traffic on the network.  Takes no arguments in 2.0.
+# Detects Back Orifice traffic on the network.
+#
+# arguments:  
+#   syntax:
+#     preprocessor bo: noalert { client | server | general | snort_attack } \
+#                      drop    { client | server | general | snort_attack }
+#   example:
+#     preprocessor bo: noalert { general server } drop { snort_attack }
+
 # 
 # The Back Orifice detector uses Generator ID 105 and uses the 
 # following SIDS for that GID:
 #  SID     Event description
 # -----   -------------------
 #   1       Back Orifice traffic detected
+#   2       Back Orifice Client Traffic Detected
+#   3       Back Orifice Server Traffic Detected
+#   4       Back Orifice Snort Buffer Attack
 
 preprocessor bo
 
diff -Nru snort-2.4.2/src/generators.h snort-2.4.3/src/generators.h
--- snort-2.4.2/src/generators.h        2005-09-14 21:09:10.000000000 +0200
+++ snort-2.4.3/src/generators.h        2005-10-16 20:55:29.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: generators.h,v 1.36.4.4 2005/09/14 19:09:10 amullican Exp $ */
+/* $Id: generators.h,v 1.36.4.5 2005/10/16 18:55:29 ssturges Exp $ */
 /*
 ** Copyright (C) 1998-2002 Martin Roesch <[EMAIL PROTECTED]>
 **
@@ -55,6 +55,7 @@
 #define     BO_TRAFFIC_DETECT           1
 #define     BO_CLIENT_TRAFFIC_DETECT    2
 #define     BO_SERVER_TRAFFIC_DETECT    3
+#define     BO_SNORT_BUFFER_ATTACK      4
 
 #define GENERATOR_SPP_RPC_DECODE    106
 #define     RPC_FRAG_TRAFFIC                1
@@ -272,6 +273,7 @@
 #define BO_TRAFFIC_DETECT_STR "(spo_bo) Back Orifice Traffic detected"
 #define BO_CLIENT_TRAFFIC_DETECT_STR "(spo_bo) Back Orifice Client Traffic 
detected"
 #define BO_SERVER_TRAFFIC_DETECT_STR "(spo_bo) Back Orifice Server Traffic 
detected"
+#define BO_SNORT_BUFFER_ATTACK_STR "(spo_bo) Back Orifice Snort buffer attack"
 
 #define FNORD_NOPSLED_IA32_STR "(spp_fnord) Possible Mutated IA32 NOP Sled 
detected"
 #define FNORD_NOPSLED_HPPA_STR "(spp_fnord) Possible Mutated HPPA NOP Sled 
detected"
diff -Nru snort-2.4.2/src/preprocessors/spp_bo.c 
snort-2.4.3/src/preprocessors/spp_bo.c
--- snort-2.4.2/src/preprocessors/spp_bo.c      2005-03-16 22:52:18.000000000 
+0100
+++ snort-2.4.3/src/preprocessors/spp_bo.c      2005-10-16 20:55:29.000000000 
+0200
@@ -16,7 +16,7 @@
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
-/* $Id: spp_bo.c,v 1.18.6.1 2005/03/16 21:52:18 jhewlett Exp $ */
+/* $Id: spp_bo.c,v 1.18.6.2 2005/10/16 18:55:29 ssturges Exp $ */
 /* Snort Preprocessor Plugin Source File Bo */
 
 /* spp_bo 
@@ -100,6 +100,14 @@
  *   BoRandValues_DefaultKey[6] = LocalBoRand() % 256;  --> 173 (0xad)
  *   BoRandValues_DefaultKey[7] = LocalBoRand() % 256;  -->  29 (0x1d)
  * 
+ * Notes:
+ * 
+ *   10/13/2005 marc norton - This has a lot of changes  to the runtime 
+ *   decoding and testing.  The '% 256' op was removed, 
+ *   the xor op is bit wise so modulo is not needed, 
+ *   the char casting truncates to one byte,
+ *   and len testing has been modified as was the xor decode copy and 
+ *   final PONG test.
  */
 
 #include <sys/types.h>
@@ -117,6 +125,8 @@
 #include "mstring.h"
 #include "util.h"
 #include "event_queue.h"
+/* In case we need to drop this packet */
+#include "inline.h"
 
 #include "snort.h"
 
@@ -129,15 +139,31 @@
 #define BO_FROM_CLIENT            1
 #define BO_FROM_SERVER            2
 
+#define BO_BUF_SIZE         8
+#define BO_BUF_ATTACK_SIZE  1024
+
+/* Configuration defines */
+#define START_LIST      "{"
+#define END_LIST        "}"
+#define CONF_SEPARATORS         " \t\n\r"
+#define BO_ALERT_GENERAL        0x0001
+#define BO_ALERT_CLIENT         0x0002
+#define BO_ALERT_SERVER         0x0004
+#define BO_ALERT_SNORT_ATTACK   0x0008
+
+
 /* list of function prototypes for this preprocessor */
-void BoInit(u_char *);;
+void BoInit(u_char *);
 void BoProcess(Packet *);
 void BoFind(Packet *, void *);
 
 /* list of private functions */
 static int  BoGetDirection(Packet *p, char *pkt_data);
 static void PrecalcPrefix();
-static int  BoRand();
+static char BoRand();
+static void ProcessArgs(u_char *args);
+static int  ProcessOptionList(void);
+static void PrintConfig(void);
 
 #define MODNAME "spp_bo"
 
@@ -149,6 +175,10 @@
 int brute_force_enable = 1;
 int default_key;
 
+static u_int16_t noalert_flags = 0;
+static u_int16_t drop_flags = 0;
+
+
 u_int16_t lookup1[65536][3];
 u_int16_t lookup2[65536];
 
@@ -185,15 +215,176 @@
  */
 void BoInit(u_char *args)
 {
-    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: Bo Initialized\n"););
+    static int bIsInitialized = 0;
+
+    /* BoInit is re-entrant */
+    if ( !bIsInitialized )
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: Bo 
Initialized\n"););
+
+        /* we no longer need to take args */
+        PrecalcPrefix();
 
-    /* we no longer need to take args */
-    PrecalcPrefix();
+        /* Set the preprocessor function into the function list */
+        AddFuncToPreprocList(BoFind);
+
+        bIsInitialized = 1;
+    }
+
+    /* Process argument list */
+    ProcessArgs(args);
+}
+
+
+/*
+ * Function: ProcessArgs(u_char *)
+ *
+ * Purpose: Parse additional config items.
+ *
+ * Arguments: args => ptr to argument string
+ *   syntax:
+ *     preprocessor bo: noalert { client | server | general | snort_attack } \
+ *                      drop    { client | server | general | snort_attack }
+ *
+ *   example:
+ *     preprocessor bo: noalert { general server } drop { snort_attack }
+ *
+ * Returns: void function
+ *
+ */
+static void ProcessArgs(u_char *args)
+{
+    char *arg;
+   
+    if ( args == NULL )
+        return;
+
+    arg = strtok(args, CONF_SEPARATORS);
+    
+    while ( arg != NULL )
+    {
+        if ( !strcasecmp("noalert", arg) )
+        {
+            noalert_flags = ProcessOptionList();
+        }
+        else if ( !strcasecmp("drop", arg) )
+        {
+            drop_flags = ProcessOptionList();
+        }
+        else
+        {
+            FatalError("%s(%d) => Unknown bo option %s.\n", 
+                        file_name, file_line, arg);
+        }
+
+        arg = strtok(NULL, CONF_SEPARATORS);
+    }
+
+    PrintConfig();
+
+    return;
+}
+
+
+/*
+ * Function: ProcessOptionList(u_char *)
+ *
+ * Purpose: Parse config list, either "noalert" or "drop".
+ *
+ * Arguments: none, use string from strtok in ProcessArgs
+ *
+ * Returns: AND'ed list of flags based on option list
+ *
+ */
+static int ProcessOptionList(void)
+{
+    char *arg;
+    int   retFlags = 0;
+
+    arg = strtok(NULL, CONF_SEPARATORS);
+
+    if ( arg == NULL || strcmp(START_LIST, arg) )
+    {
+        FatalError("%s(%d) => Invalid bo option.\n", 
+                        file_name, file_line);        
+        return 0;
+    }
+    
+    while ( (arg = strtok(NULL, CONF_SEPARATORS)) )
+    {
+        if ( !strcmp(END_LIST, arg) )
+        {
+            break;
+        }
+
+        if ( !strcasecmp("general", arg) )
+        {
+            retFlags |= BO_ALERT_GENERAL;
+        }
+        else if ( !strcasecmp("client", arg) )
+        {
+            retFlags |= BO_ALERT_CLIENT;
+        }
+        else if ( !strcasecmp("server", arg) )
+        {
+            retFlags |= BO_ALERT_SERVER;
+        }
+        else if ( !strcasecmp("snort_attack", arg) )
+        {
+            retFlags |= BO_ALERT_SNORT_ATTACK;
+        }
+        else
+        {
+            FatalError("%s(%d) => Invalid bo option argument %s.\n", 
+                        file_name, file_line, arg);        
+        }
+    }
 
-    /* Set the preprocessor function into the function list */
-    AddFuncToPreprocList(BoFind);
+    return retFlags;
 }
 
+/*
+ * Function: PrintConfig(u_char *)
+ *
+ * Purpose: Print configuration
+ *
+ * Arguments: none
+ *
+ * Returns: none
+ *
+ */
+static void PrintConfig(void)
+{
+    if ( noalert_flags != 0 || drop_flags != 0 )
+        LogMessage("Back Orifice Config:\n");
+    
+    if ( noalert_flags != 0 )
+    {
+        LogMessage("    Disable alerts:");
+        if ( noalert_flags & BO_ALERT_CLIENT )
+            LogMessage(" client");
+        if ( noalert_flags & BO_ALERT_SERVER )
+            LogMessage(" server");
+        if ( noalert_flags & BO_ALERT_GENERAL )
+            LogMessage(" general");
+        if ( noalert_flags & BO_ALERT_SNORT_ATTACK )
+            LogMessage(" snort_attack");
+        LogMessage("\n");
+    }
+    if ( drop_flags != 0 )
+    {
+        LogMessage("    Drop packets (inline only) on alerts:");
+        if ( drop_flags & BO_ALERT_CLIENT )
+            LogMessage(" client");
+        if ( drop_flags & BO_ALERT_SERVER )
+            LogMessage(" server");
+        if ( drop_flags & BO_ALERT_GENERAL )
+            LogMessage(" general");
+        if ( drop_flags & BO_ALERT_SNORT_ATTACK )
+            LogMessage(" snort_attack");
+        LogMessage("\n");
+    }
+}
 
 /*
  * Function: BoRand()
@@ -204,9 +395,10 @@
  *
  * Returns: key to XOR with current char to be "encrypted"
  */
-static int BoRand()
+static char BoRand()
 {
-    return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
+    holdrand = holdrand * 214013L + 2531011L;
+    return (char) (((holdrand  >> 16) & 0x7fff) & 0xFF);
 }
 
 
@@ -233,7 +425,7 @@
         /* convert the plaintext cookie to cyphertext for this key */
         for(cookie_index=0;cookie_index<BACKORIFICE_MAGIC_SIZE;cookie_index++)
         {
-            cookie_cyphertext[cookie_index] 
=(u_int8_t)(*cp_ptr^(BoRand()%256));
+            cookie_cyphertext[cookie_index] =(u_int8_t)(*cp_ptr^(BoRand()));
             cp_ptr++;
         }
 
@@ -285,6 +477,7 @@
  *
  * Returns: void function
  *
+ *
  */
 void BoFind(Packet *p, void *context)
 {
@@ -347,13 +540,13 @@
         if(lookup2[key] == cyphertext_suffix)
         {
             holdrand = key;
-            pkt_data = p->data;
-            end = p->data + BACKORIFICE_MAGIC_SIZE;
+            pkt_data = (char*)p->data;
+            end = (char*)p->data + BACKORIFICE_MAGIC_SIZE;
             magic_data = magic_cookie;
 
             while(pkt_data<end)
             {
-                plaintext = (char) (*pkt_data ^ (BoRand()%256));
+                plaintext = (char) (*pkt_data ^ BoRand());
 
                 if(*magic_data != plaintext)
                 {
@@ -376,20 +569,44 @@
 
             if ( bo_direction == BO_FROM_CLIENT )
             {
-                SnortEventqAdd(GENERATOR_SPP_BO, BO_CLIENT_TRAFFIC_DETECT, 1, 
0, 0,
-                    BO_CLIENT_TRAFFIC_DETECT_STR, 0);
+                if ( !(noalert_flags & BO_ALERT_CLIENT) )
+                {
+                    SnortEventqAdd(GENERATOR_SPP_BO, BO_CLIENT_TRAFFIC_DETECT, 
1, 0, 0,
+                                            BO_CLIENT_TRAFFIC_DETECT_STR, 0);
+                }
+                if ( (drop_flags & BO_ALERT_CLIENT) && InlineMode() )
+                {
+                    p->packet_flags |= PKT_INLINE_DROP;
+                    InlineDrop();
+                }
                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Client packet\n"););
             }
             else if ( bo_direction == BO_FROM_SERVER )
             {
-                SnortEventqAdd(GENERATOR_SPP_BO, BO_SERVER_TRAFFIC_DETECT, 1, 
0, 0,
-                    BO_SERVER_TRAFFIC_DETECT_STR, 0);
+                if ( !(noalert_flags & BO_ALERT_SERVER) )
+                {
+                    SnortEventqAdd(GENERATOR_SPP_BO, BO_SERVER_TRAFFIC_DETECT, 
1, 0, 0,
+                                            BO_SERVER_TRAFFIC_DETECT_STR, 0);
+                }
+                if ( (drop_flags & BO_ALERT_SERVER) && InlineMode() )
+                {
+                    p->packet_flags |= PKT_INLINE_DROP;
+                    InlineDrop();
+                }
                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Server packet\n"););
             }
             else
             {
-                SnortEventqAdd(GENERATOR_SPP_BO, BO_TRAFFIC_DETECT, 1, 0, 0,
-                    BO_TRAFFIC_DETECT_STR, 0);
+                if ( !(noalert_flags & BO_ALERT_GENERAL) )
+                {
+                    SnortEventqAdd(GENERATOR_SPP_BO, BO_TRAFFIC_DETECT, 1, 0, 
0,
+                                            BO_TRAFFIC_DETECT_STR, 0);
+                }
+                if ( (drop_flags & BO_ALERT_GENERAL) && InlineMode() )
+                {
+                    p->packet_flags |= PKT_INLINE_DROP;
+                    InlineDrop();
+                }
             }           
         }
     }
@@ -412,14 +629,15 @@
  *
  * Reference: http://www.magnux.org/~flaviovs/boproto.html
  *    BO header structure:
- *      Mnemonic       Size in bytes
+ *      Mnemonic    Size in bytes
  *      -------------------------
- *      MAGIC      8
- *      LEN        4
- *      ID             4
- *      T              1
- *      DATA       variable
- *      CRC        1
+ *      MAGIC       8
+ *      LEN         4
+ *      ID          4
+ *      T           1
+ *      DATA        variable
+ *      CRC         1
+ *
  */
 static int BoGetDirection(Packet *p, char *pkt_data)
 {
@@ -427,11 +645,9 @@
     u_int32_t id = 0;
     u_int32_t l, i;
     char type;
-    char buf1[1024];
-    char buf2[1024];
-    char *buf_ptr;
+    static char buf1[BO_BUF_SIZE];
     char plaintext;
-
+    
     /* Check for the default port on either side */
     if ( p->dp == BACKORIFICE_DEFAULT_PORT )
     {
@@ -447,7 +663,7 @@
     /* Get length from BO header - 32 bit int */
     for ( i = 0; i < 4; i++ )
     {
-        plaintext = (char) (*pkt_data ^ (BoRand()%256));
+        plaintext = (char) (*pkt_data ^ BoRand());
         l = (u_int32_t) plaintext;
         len += l << (8*i);
         pkt_data++;
@@ -456,22 +672,57 @@
     /* Get ID from BO header - 32 bit int */
     for ( i = 0; i < 4; i++ )
     {
-        plaintext = (char) (*pkt_data ^ (BoRand()%256));
+        plaintext = (char) (*pkt_data ^ BoRand() );
         l = ((u_int32_t) plaintext) & 0x000000FF;
         id += l << (8*i);
         pkt_data++;
     }
     
-    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Length = %lu\n", len););
+    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Data length = %lu\n", len););
+    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "ID = %lu\n", id););
+
+    /* Do more len checking */
+    
+    if ( len >= BO_BUF_ATTACK_SIZE )
+    {
+        if ( !(noalert_flags & BO_ALERT_SNORT_ATTACK) )
+        {
+            SnortEventqAdd(GENERATOR_SPP_BO, BO_SNORT_BUFFER_ATTACK, 1, 0, 0,
+                                            BO_SNORT_BUFFER_ATTACK_STR, 0);
+        }
+        if ( (drop_flags & BO_ALERT_SNORT_ATTACK) && InlineMode() )
+        {
+            p->packet_flags |= PKT_INLINE_DROP;
+            InlineDrop();
+        }
+
+        return BO_FROM_UNKNOWN;
+    }
 
     /* Adjust for BO packet header length */
-    len -= 18;
+    len -= BACKORIFICE_MIN_SIZE;
 
-    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Data length = %lu\n", len););
-    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "ID = %lu\n", id););
+    if( len == 0 )
+    {
+        /* Need some data, or we can't figure out client or server */
+        return BO_FROM_UNKNOWN; 
+    }
+    
+    if( len > 7 )
+    {
+        len = 7; /* we need no more than  7 variable chars */
+    }
 
+    /* length must be 7 OR LESS due to above logic  */
+  
+    if( p->dsize < len )
+    {
+        /* We don't have enough data to inspect */
+        return BO_FROM_UNKNOWN;
+    }
+    
     /* Continue parsing BO header */
-    type = (char) (*pkt_data ^ (BoRand()%256));
+    type = (char) (*pkt_data ^ BoRand());
     pkt_data++;
         
     if ( type & 0x80 )
@@ -488,37 +739,27 @@
 
     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Type = 0x%x\n", type););
 
-    /* Only examine data if this a ping request or response */
+    /* Only examine data if this is a ping request or response */
     if ( type == BO_TYPE_PING )
     {
-        i = 0;
-        buf_ptr = buf1;
-        *buf1 = 0;
-        *buf2 = 0;
-        /* Decrypt data */
-        while ( i < len )
-        {
-            plaintext = (char) (*pkt_data ^ (BoRand()%256));
-            *buf_ptr = plaintext;
-            i++;
-            pkt_data++;
-            buf_ptr++;
-            if ( plaintext == 0 )
-                buf_ptr = buf2;
-        }
-        /* null-terminate string */
-        *buf_ptr = 0;
-
-        DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "buf1 = %s\n", buf1););
-
-        if ( *buf2 != 0 )
-        {
-            DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "buf2 = %s\n", buf2););
-        }
-
-        DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "crc = 0x%x\n", (char) 
(*pkt_data ^ (BoRand()%256))););
-           
-        if ( len > 4 && !strncasecmp((buf1+3), "PONG", 4) )
+        if ( len < 7 )
+        {
+            return BO_FROM_CLIENT;
+        }
+
+        for(i=0;i<len;i++ ) /* start at 0 to advance the BoRand() function 
properly */
+        {
+            buf1[i] = (char) (pkt_data[i] ^ BoRand());
+            if ( buf1[i] == 0 )
+            {
+                return BO_FROM_UNKNOWN; 
+            }
+        }
+
+        if( ( buf1[3] == 'P' || buf1[3] == 'p' ) &&
+            ( buf1[4] == 'O' || buf1[4] == 'o' ) && 
+            ( buf1[5] == 'N' || buf1[5] == 'n' ) && 
+            ( buf1[6] == 'G' || buf1[6] == 'g' ) )
         {
             return BO_FROM_SERVER;
         }
@@ -526,6 +767,7 @@
         {
             return BO_FROM_CLIENT;
         }
-    }
+    } 
+   
     return BO_FROM_UNKNOWN;
 }

Attachment: signature.asc
Description: Digital signature

Reply via email to