Bastionado, seguridad en sistemas: Introducción a la creación de preprocesadores Snort (IV) pre { background:#eeeeee; border:1px solid #A6B0BF; font-size:120%; line-height:100%; overflow:auto; padding:10px; color:#000000 } pre:hover { border:1px solid #efefef; } code { font-size:120%; text-align:left; margin:0;padding:0; color: #000000;} .clear { clear:both; overflow:hidden; }

Bienvenido al blog

Bienvenidos al blog de seguridad en sistemas

miércoles, 24 de agosto de 2011

Introducción a la creación de preprocesadores Snort (IV)

Por fin llega el último post de creación de preprocesadores dinámicos en Snort ¿y que mejor forma que coincidiendo con que se ha vuelto a editar el manual de Snort en HTML (http://manual.snort.org/)?

La entrada de hoy es posiblemente la más práctica pero también más largas de las anteriores, ya que crearemos un ejemplo sencillo de un preprocesador dinámico donde se indicará, tanto en la fase de preprocesador como en la de motor de reglas, que si detecta tráfico de una cierta IP que hemos indicado, tanto de origen como destino, se genere una alerta de Snort.

Evidentemente esto ya lo hace Snort con una regla tonta, pero es un ejemplo sencillo que explica bastante bien como funciona Snort, luego ya se puede desarrollar el preprocesador que necesitéis donde el entorno actual de Snort no os permita crearlo mediante reglas. Por ejemplo de esto y que se ha visto ya en el blog fue el preprocesador de geolocalización que permitía generar alertas dependiendo del origen y destino de la alerta.

Para este procesador usaremos el del ejemplo pero editando el fichero blog.c desde cero. Podeis usar el que tenemos y vereis que la estructura es muy parecida simplemente se han cambiado un par de cosas adaptandolo al ejemplo. Recordar el diagrama de la entrada anterior, es importantísimo para esta entrada.

Empecemos revisando el fichero sf_preproc_info.h, el cual tiene que tener una estructura como la siguiente:



#ifndef SF_BLOG_INFO_H_
#define SF_BLOG_INFO_H_

#define MAJOR_VERSION   1
#define MINOR_VERSION   0
#define BUILD_VERSION   1
#define PREPROC_NAME    "Blog"

#define DYNAMIC_PREPROC_SETUP   BlogSetup
extern void BlogSetup();

#endif /* SF_BLOG_INFO_H_ */

Como vemos lo más importante es que hemos declarado el preprocesador dinámico Blog, cuya versión es la 1.0 y hemos indicado que la función de arranque del preprocesador es BlogSetup el cual se encuentra definido en "blog.c".

A partir de ahora nos centraremos en la implementación del preprocesador Blog que se encuentra en el fichero "blog.c". El código está compuesto por cinco bloques virtuales:

1º) Librerías (si ya se, bibliotecas) y declaración del preprocesador.
2º) Configuración de arranque del preprocesador.
3º) Acciones a realizar en el módulo de preoprocesado.
4º) Acciones a realizar cuando es llamado en el motor de reglas.
5º) Acciones a realizar cuando es rearrancado.


Vamos a desarrollar poco a poco el preprocesador empezando por los 5 módulos documentados:

1º) Librerías y declaración del preprocesador:

Empecemos con la primera parte del preprocesador, las librerias:

//Estandar C
#include <stdlib.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>

//Preprocesadores Snort
//Configuración
#include "config.h"
//Para la devolución del valor al hacer match en una regla
#include "sf_snort_plugin_api.h"
#include "preprocids.h"
//Paquete de red que lee el Snort
#include "sf_snort_packet.h"
#include "sf_dynamic_preprocessor.h"
//Politica de los preprocesadores
#include "sfPolicy.h"
#include "sfPolicyUserData.h"

//Soporte inet_ntoa - ÑAPA / PARCHE GUARRO DE SNORT!!!
#undef inet_ntoa
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//Trabajar con sfip_t
#include "sf_ip.h"
#include "sf_ip.c"

A continuación declaramos el ID del preprocesador. Éste es el valor que se usa cuando queramos limitar o eliminar ciertas alertas del preprocesador empleando por ejemplo el tag "suppress". Cada procesador dinámico tiene un identificador único para él, incluido el propio motor de reglas cuyo id es el 1. Para nuestro ejemplo pondremos el número "300" (como la peli):

//GID del preprocesador
#define GENERATOR_ID 300

En el siguiente paso se declaran los ID y textos que se mostraran en caso de que se quiera generar una alerta en la fase de preprocesado. En nuestro caso crearemos la regla 1 del preprocesador 300 con el texto de alerta "He detectado tráfico de la IP indicada", tal como se muestra a continuación:

//Alertas en la fase de preprocesado
#define ALERT_BLOG 1
#define ALERT_BLOG_STR "He detectado tráfico TCP de la IP indicada"

En este punto también declararemos las estructuras que sean necesarias para el preprocesador. En nuestro caso será un puntero a char donde almacenaremos la IP leida en el fichero de configuración:
//Donde almacenaremos la IP indicada en la configuración del Snort:
char *IPPROC;

Para finalizar inicializaremos las variables de Snort necesarias como es el propio preprocesador, las políticas (usar las del ejemplo) y declararemos las funciones que vamos a usar en todo el preprocesador:

//Politicas
tSfPolicyUserContextId ex_config = NULL;

//Si no es un reinicio
#ifdef SNORT_RELOAD
    tSfPolicyUserContextId ex_swap_config = NULL;
#endif

//Estructura de nuestro preprocesador (sería el this en OO)
extern DynamicPreprocessorData _dpd;

//Funciones empleadas en el preprocesador
//Inicialización del preprocesador
static void BlogInit(char *);
//Acciones a realizar en la fase de preprocesado
static void BlogProcess(void *, void *);
//Acciones a realizar cuando cargamos el motor de reglas (lectura de reglas)
static int BlogRuleInit(char *, char *, void **);
//Acciones a realizar al tratar un paquete que hace match con una regla
static int BlogRuleEval(void *, const uint8_t **, void *);
//Esta parte es la que hemos dicho que no tocaríamos del reload, corresponde al quinto punto
#ifdef SNORT_RELOAD
static void BlogReload(char *);
static int BlogReloadSwapPolicyFree(tSfPolicyUserContextId, tSfPolicyId, void *);
static void * BlogReloadSwap(void);
static void BlogReloadSwapFree(void *);
#endif


2º) Configuración de arranque del preprocesador:

Si nos fijamos pusimos una función en el fichero "sf_preproc_info" de nombre "BlogSetup". Esa función es la primera función que llama Snort cuando arranca, éste dependiendo de si es un inicio o un recarga de Snort registra el preprocesador con "registerPreroc".

Para registrar un preprocesador necesitamos principalmente dos argumentos:
  • El primero corresponde con el nombre declarado en la variable "PREPROC_NAME" del fichero "sf_preproc_info" que es el empleado en el fichero de configuración de Snort. En nuestro ejemplo "Blog".
  • El segundo argumento indica el nombre de la función de inicio principal del preprocesador encargada de registrar todas las acciones que ejecutará éste. En nuestro ejemplo "BlogInit".
Veamos la implementación a continuación:

//Registro del preprocesador y inicialización de este
void BlogSetup(void)
{
    #ifndef SNORT_RELOAD
    //Registramos el preprocesador Blog y llamamos a la funcion BlogInit
    _dpd.registerPreproc("Blog", BlogInit);
    #else
    _dpd.registerPreproc("Blog", BlogInit, BlogReload,
        BlogReloadSwap, BlogReloadSwapFree);
    #endif
}

La siguiente función, BlogInit es la encargada real de inicializar el preprocesador, donde se registrará las funciones a usar en la fase de preprocesado mediante "addPreproc" y en la fase del motor de reglas mediante "preprocOptRegister". Para el ejemplo solo usaremos una de cada pero se pueden emplear más de una.

La función BlogInit soporta un único argumento que es un puntero a char, el cual contiene un puntero al texto existente en el fichero de configuración de Snort, y por tanto, contendrá las variables de configuración de nuestro preprocesador. En nuestro ejemplo será donde tendremos IP que queremos que genere alerta en caso de detectarse tráfico hacia o desde esa IP:

/* Inicialización del preprocesador */
static void BlogInit(char *args)
{
    //Variable para argumentos
    char *arg;
    char *config;

    //Politicas de uso
    tSfPolicyId policy_id = _dpd.getParserPolicy();
    if (ex_config == NULL)
    {
        ex_config = sfPolicyConfigCreate();
        if (ex_config == NULL)
            _dpd.fatalMsg("\tFallo en la inicialización del preprocesador, no puede reservar la estructura.\n");
    }

    //Obtenemos las opciones del preprocesador indicadas en el fichero snort.conf
    arg = strtok(args, " \t\n\r,");
    if(arg && !strcasecmp("miip", arg))
    {
      arg = strtok(NULL, " \t\n\r,");
      //Copiamos la IP que queremos que genere alerta
      IPPROC = (char *)calloc(1, sizeof(arg));
      strncpy(IPPROC, arg, strlen(arg));
      _dpd.logMsg("    La IP que generará alerta es %s\n",IPPROC);
    }
    else
    {
      _dpd.fatalMsg("    Blog: Opcion invalida %s\n");
    }
   
    //Seteamos políticas, a muerto un gatito
    config = arg;
    sfPolicyUserPolicySet(ex_config, policy_id);
    sfPolicyUserDataSetCurrent(ex_config, config);


    //Mensaje del preprocesador de salida indicando que vamos a registrar ya las acciones
    _dpd.logMsg("Blog config:\n");
    _dpd.logMsg("    Joaquin Moreno, el Moxi Sexy - 2011\n");

    //Declaración de funciones a procesar en la fase de preprocesador
    //Funcion, Prioridad, ID de la función - es única entre todos los preprocesadores, protocolos tratados
    _dpd.addPreproc(BlogProcess, PRIORITY_TRANSPORT, 10000, PROTO_BIT__TCP | PROTO_BIT__UDP | PROTO_BIT__ICMP);

    //Declaracion de reglas y evaluación de las mismas en el motor de reglas
    //Nombretag, Función de inicialización, Función de Evaluación de la regla, NULL, NULL, ...
    _dpd.preprocOptRegister("miip", BlogRuleInit, BlogRuleEval, NULL, NULL, NULL, NULL, NULL);

    //Mensaje que se mostrará cuando cargue el preprocesador
    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Preprocessor: Blog OK. Hola mama salgo en Interné :P\n"););
}

Como vemos, para registrar la función que se ejecutara en la fase de preprocesador usamos la función "addPreproc" cuyas opciones son las siguientes:
  • BlogProcess: nombre de la función que se ejecutara en la fase de preprocesador por cada paquete de red leido.
  • PRIORITY_TRANSPORT: prioridad del preprocesador.
  • 10000: corresponde con el identificador único de registro de la función. Mucho cuidado porque es GLOBAL para todo Snort... es decir, si tengo un preprocesador 300 donde registro la función número 1000 y creo un preprocesador 301 donde registro la función número 1000 ¡fallará!.
  • PROTO_BIT__TCP | PROTO_BIT__UDP | PROTO_BIT__ICMP: para que protocolos debe saltar esta función, en nuestro caso para TCP o UDP o ICMP.
A su vez para registrar la función que se ejecutará en la fase del motor de reglas usamos "preprocOptRegister" cuyas opciones son las siguientes:
  • "miip": es el tag identificativo de la regla. Un tag se construye en la regla como "tag:valor;", por ejemplo en content:"Hola"; el tag es "content". Por tanto si queremos usar nuestro preprocesador en el motor de reglas añadiríamos a la regla: miip:"127.0.0.1"; (siendo 127.0.0.1 una ip de ejemplo).
  • BlogRuleInit: es la función que se ejecuta por cada regla que lee Snort durante su arranque que contiene el tag indicado en la primera opción. Es decir, cuando arrancamos Snort leemos los ficheros de reglas, pues por cada regla que contenga el tag "miip" se ejecutará esta función. El objetivo de ésta es leer los parametros que hay indicados en la regla y configurarlos para ser procesados posteriormente por cada paquete que llegue al motor de reglas mediante la función "BlogRuleEval". 
  • BlogRuleEval: es la función que se ejecutara por cada paquete de red que llega al motor de reglas y ha cumplido la parte de la izquierda de la regla (esta parte es donde se indica el protocolo, puertos y ips destino / origen). Es la encargada de indicar si el tag se cumple o no. Una regla se activa si todos los tags son ciertos. 
  • "El resto": las restantes 5 opciones ponerlas a Null, no son requeridas para un ejemplo básico.

3º) Acciones a realizar en el módulo de preoprocesado:

Tal como se indico en el punto 2, la función BlogProcess que ha sido registrada mediante "addPreproc" será la que se ejecutara por cada paquete de red leido en la fase de preprocesado. Está función soporta dos opciones aunque únicamente nos interesa la primera. "void *pkt". la cual es un puntero a una estructura SFSnortPacket donde se encuentra normalizado el paquete leido:

void BlogProcess(void *pkt, void *context)
{
    //Paquete leído
    SFSnortPacket *p = (SFSnortPacket *)pkt;

    //Política de prioridades
    sfPolicyUserPolicySet(ex_config, _dpd.getRuntimePolicy());

    //Se debe comprobar que realmente el paquete es un paquete IP
    if(p->ip4h == NULL)
    {
        //No es un paquete IP
        if(p->ip4_header == NULL)
        {
                return;
        }
        else
        {
             //Arpa never die!, estructura in_addr
           //Si la IP origen o destino es la indicada en el fichero de configuración de snort generamos un alerta
  if((strcmp(IPPROC, inet_ntoa((p->ip4_header->destination))) == 0) || (strcmp(IPPROC, inet_ntoa((p->ip4_header->source))) == 0) )
           {
               _dpd.logMsg("Acertado: %s\n", ALERT_BLOG_STR);
               _dpd.alertAdd(GENERATOR_ID, ALERT_BLOG, 1, 0, 1, ALERT_BLOG_STR, 0);
               return;
            }
        } //fin Else de la condición (
p->ip4_header == NULL)
    } //Incio Else de la condición p->ip4h == NULL
    else
    {
        //Snort Never Die!, estructura snort
        //Si la IP origen o destino es la indicada en el fichero de configuración de snort generamos un alerta
  if((strcmp(IPPROC, sfip_to_str(&((p->ip4h->ip_dst)))) == 0) || (strcmp(IPPROC, sfip_to_str(&((p->ip4h->ip_src)))) == 0) )
        {
            //Generamos alerta de preprocesador (ID_GEN, ID_RULE, VER_RULE, REV_RULE, Priority, MSG, X)
            _dpd.alertAdd(GENERATOR_ID, ALERT_BLOG, 1, 0, 1, ALERT_BLOG_STR, 0);
         }
      return;
    }
}

Lo que hace la función anterior es buscar si la IP origen o destino del paquete es la misma que hemos indicado en el fichero snort.conf, entonces ejecutamos la función "alertAdd" encargada de generar un alerta a nivel de preprocesador. La explicación de los argumentos de la función son los siguientes:
  • GENERATOR_ID: es la variable que contiene el ID del preprocesador (300).
  • ALERT_BLOG: id de la regla en preprocesado (1).  
  • 1: versión de la alerta.
  • 0: revisión de la alerta.
  • 1: prioridad, dejar tal cual.
  • ALERT_BLOG_STR: cadena de texto que mostrará Snort como alerta. 
  • 0: nada, no nos interesa.
4º) Acciones a realizar cuando es llamado en el motor de reglas:

Primero se trabaja con la función de inicialización de las reglas de nuestro preprocesador, la cual se ejecuta cuando las reglas son leidas durante el arranque de Snort. El nombre de esta función es BlogRuleInit, la cual fue registrada mediante "preprocOptRegister". BlogRuleInit soporta los siguientes argumentos:
  • name: nombre de la regla. No se suele usar.
  • params: argumento de la opcion de la regla, lo que ha escrito a la derecha del tag en la regla, es decir si hemos puesto "miip:127.0.0.1;" entonces args contendría "127.0.0.1".
  • data: variable donde guardamos los datos que nos interesa de la regla, para pasarselo posteriormente a la función que se ejecutará en el motor de reglas por cada paquete leido.
La implementación se mostrará a continuación:

static int BlogRuleInit(char *name, char *args, void **data)
{
    //Guardaremos la IP como un simple char, aunque normalmente se usan estructuras complejas
    char *miip = NULL;

    if(args == NULL)
    {
      //Mensaje de fallo
      _dpd.fatalMsg("Ande vas pallo malvado!!!\n");
    }
    else
    {
      miip = (char *)calloc(1, sizeof(args));
      strncpy(miip, args, strlen(args));
      _dpd.logMsg("La IP leida es %s\n", miip);
    }

    //Almaceno la IP indicada en la regla
    *data = (void *)miip;

  return 1;
}

El código de la función anterior es sencillo, leemos el String "args" que contiene la configuración del preprocesador, por ejemplo: "miip 127.0.0.1" y es almacenada en el doble puntero data.

El siguiente función será llamada por el motor de reglas si por cada paquete que llegue a éste la parte de la izquierda de una regla se cumpla y en la parte de la derecha éste el tag que hemos usado para registrar la regla. En este caso el tag es "miip". Esta función la hemos llamado "BlogRuleEval" la cual fue registrada empleando "preprocOptRegister". Esta función soporta los siguientes argumentos:
  • pkt: contiene el paquete que estamos analizando en la regla.
  • cursor: ni caso.
  • data: contiene los valores que guardamos en el tercer argumento de la función "BlogRuleInit", es decir, los valores de la regla.
Veamos la implementación:

static int BlogRuleEval(void *pkt, const uint8_t **cursor, void *data)
{
    SFSnortPacket *p = (SFSnortPacket *)pkt;
    char * miip = (char *) data;
    if(p->ip4h == NULL)
    {
        if(p->ip4_header == NULL)
        {
                return RULE_NOMATCH;
        }
        else
        {
                //Soporte Arpa
  if((strcmp(miip, inet_ntoa((p->ip4_header->destination))) == 0) || (strcmp(miip, inet_ntoa((p->ip4_header->source))) == 0) )
                {
                      _dpd.logMsg("Acertado!");
                     return RULE_MATCH;
                 }
        }
    }
    else
    {
           //Soporte Snort
  if((strcmp(miip, sfip_to_str(&((p->ip4h->ip_dst)))) == 0))) || (strcmp(miip, sfip_to_str(&((p->ip4h->ip_src)))) == 0) )
           {
                _dpd.logMsg("Acertado!");
                 return RULE_MATCH;
            }
    }
    //Salimos si no cumple
    return RULE_NOMATCH; 
}

Como vemos es muy parecida a la regla de evaluación en la fase de preprocesado, pero en este caso la configuración está guardada en la variable "data". Así mismo para indicar que este tag se cumple se devuelve la constante "RULE_MATCH" o en caso contrario se devuelve "RULE_NOMATCH". Para que una regla se cumpla todos los tags que está tenga declarado debe cumplirse.


5º) Acciones a realizar cuando es rearrancado:

En ésta parte dejaremos tal cual está la del ejemplo puesto que su explicación requeriría más de una entrada solo para este punto. Digamos que nuestro preprocesador no funcionará si hacemos un reload, por tanto será necesario parar y rearrancar Snort. Si vemos ejemplos veremos que es prácticamente implementar lo mismo que hemos visto pero teniendo en cuenta un par de cosas. Veamos la implementación:

#ifdef SNORT_RELOAD
static void BlogReload(char *args)
{
    char *config = NULL;
    tSfPolicyId policy_id = _dpd.getParserPolicy();

    _dpd.logMsg("blog dynamic preprocessor configuration\n");

    if (ex_swap_config == NULL)
    {
        ex_swap_config = sfPolicyConfigCreate();
        if (ex_swap_config == NULL)
            _dpd.fatalMsg("Could not allocate configuration struct.\n");
    }

    sfPolicyUserPolicySet(ex_swap_config, policy_id);
    sfPolicyUserDataSetCurrent(ex_swap_config, config);

    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Preprocessor: blog is initialized\n"););
}

static int BlogReloadSwapPolicyFree(tSfPolicyUserContextId config, tSfPolicyId policyId, void *data)
{
    char *policy_config = (char *)data;

    sfPolicyUserDataClear(config, policyId);
    free(policy_config);
    return 0;
}

static void * BlogReloadSwap(void)
{
    tSfPolicyUserContextId old_config = ex_config;

    if (ex_swap_config == NULL)
        return NULL;

    ex_config = ex_swap_config;
    ex_swap_config = NULL;

    return (void *)old_config;
}

static void BlogReloadSwapFree(void *data)
{
    tSfPolicyUserContextId config = (tSfPolicyUserContextId)data;

    if (data == NULL)
        return;

    sfPolicyUserDataIterate(config, BlogReloadSwapPolicyFree);
    sfPolicyConfigDelete(config);
}
#endif

Una vez escrito nuestro preprocesador lo compilamos y lo instalamos:

# make
# make install

Vamos a declarar el preprocesador indicando que notifique en la fase de preprocesado si detecta tráfico de la IP 8.8.8.8. Para ello editamos el fichero de configuración de Snort (/etc/snort/snort.conf) y añadimos como último preprocesador (el orden de posicionamiento del preprocesador SI que importa) la siguiente línea:

preprocessor Blog: miip 8.8.8.8

Para crear una regla de ejemplo que generará una alerta si el paquete es TCP, el puerto es 80 y la ip de origen o destino es la 8.8.8.8:
alert tcp any any -> any 80 (msg:"Hola gente!"; miip:8.8.8.8; sid: 1; rev: 1;)

Una vez configurado inicializaremos Snort:

# /usr/local/bin/snort -u snort -g snort -c /etc/snort/snort.conf -i eth0 -l /var/log/snort

Running in IDS mode

        --== Initializing Snort ==--
...
  Loading dynamic preprocessor library /usr/local/lib/snort_dynamicpreprocessor/lib_sfdynamic_preprocessor_blog.so... done
...
Blog config:
    Joaquin Moreno, el Moxi Sexy - 2011
La IP que generará alerta es 8.8.8.8
...
      --== Initialization Complete ==--
...
Preprocessor Object: Blog  Version 1.0  <Build 1>
...
(Snort se queda a la escucha)

Posteriormente para probar el funcionamiento del preprocesador en la fase de preprocesado se he realizado un simple ping donde se muestra dos alertas a nivel de preprocesado, por un lado la ida y por otro la vuelta correspondiente al tráfico ICMP 8 y 0 del ping:

# ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_req=1 ttl=54 time=39.0 ms

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 39.075/39.075/39.075/0.000 ms

Mostrando por la consola de Snort las siguientes dos notificaciones:


Acertado: He detectado tráfico TCP al puerto indicado
Acertado: He detectado tráfico TCP al puerto indicado

Y si accedemos al log de Snort veremos que se han generado dos alertas a nivel de preprocesador, donde se nos indica que ha sido el GID 300, regla 1, revision 1 ([300:1:1]):

[**] [300:1:1] He detectado tráfico TCP al puerto indicado [**]
[Priority: 1]
08/23-21:56:02.628184 10.0.0.1 -> 8.8.8.8
ICMP TTL:64 TOS:0x0 ID:0 IpLen:20 DgmLen:84 DF
Type:8  Code:0  ID:29225   Seq:1  ECHO

[**] [300:1:1] He detectado tráfico TCP al puerto indicado [**]
[Priority: 1]
08/23-21:56:02.668564 8.8.8.8 -> 10.0.0.1
ICMP TTL:54 TOS:0x0 ID:9947 IpLen:20 DgmLen:84
Type:0  Code:0  ID:29225  Seq:1  ECHO REPLY

Para probar la regla he realizado lo siguiente:
# printf "GET / HTTP/1.0\n\n" | nc 8.8.8.8 80 > /dev/null
(PD: Tened en cuenta que con esta acción también se cumple los requisitos del preprocesador, para no liar solo se muestra las alertas desde el motor de reglas)

Al no recibir respuesta desde el puerto 80 solo se detecta el paquete de la ída, teniendo como resultado en la pantalla de Snort la siguientes entrada:

Acertado!

Y como alerta de Snort:

[**] [1:1:1] Hola gente! [**]
[Priority: 0]
08/23-22:01:43.613062 10.0.0.1:49149 -> 8.8.8.8:80
TCP TTL:64 TOS:0x0 ID:23450 IpLen:20 DgmLen:60 DF
******S* Seq: 0x155736A2  Ack: 0x0  Win: 0x16D0  TcpLen: 40
TCP Options (5) => MSS: 1460 SackOK TS: 2701226025 0 NOP WS: 6

Bueno ahora ya sí, con esto hemos termino la introducción a la implementación de preprocesadores dinámicos. Realmene lo importante ahora es tener buenas ideas y cumplir requisitos que son necesarios en nuestra infraestructura, pero que Snort por defecto no nos lo ofrece. En mi caso, y gracias a tener a unos cracks en el curro, tenemos uns preprocesadores que son la bomba, parece que no, pero estos entornos permiten hacer muchísimas cosas y detectar cosas que por defecto un Snort no puede.

Hasta la proxima, que espero no sea dentro de mucho aunque teniendo en cuenta que empiezo el Inglés y que tengo el examen  del 542 de SANS me parece a mí que hasta finales de Septiembre la cosa estará difícil ;)


1 comentario:

  1. Espectacular saga de post que te has currado! Esta info vale pasta xD

    ResponderEliminar