IDS en la red: SNORT

SNORT ([Roe99]) es un sniffer capaz de actuar como sistema de detección de intrusos en redes de tráfico moderado; su facilidad de configuración, su adaptabilidad, sus requerimientos mínimos (funciona en diferentes Unices, incluyendo un simple PC con Linux, Solaris o cualquier BSD gratuito), y sobre todo su precio (se trata de un software completamente gratuito que podemos descargar desde su página oficial en INet, http://www.snort.org/) lo convierten en una óptima elección en multitud de entornos, frente a otros sistemas como NFR (Network Flight Recorder) o ISS RealSecure que, aunque quizás sean más potentes, son también mucho más pesados e infinitamente más caros.

Para instalar un sistema de detección de intrusos basado en SNORT en primer lugar necesitamos evidentemente este programa, que podemos descargar desde su página web. Además, para compilarlo correctamente es necesario disponer de las librerías libpcap, un interfaz para tratamiento de paquetes de red desde espacio de usuario, y es recomendable también (aunque no obligatorio) instalar Libnet, librería para la construcción y el manejo de paquetes de red. Con este software correctamente instalado en nuestro sistema, la compilación de SNORT es trivial.

Si volvemos a la clasificación de IDSes que hemos presentado al principio de este capítulo, podemos clasificar a SNORT como un sistema basado en red (se monitoriza todo un dominio de colisión) y que funciona mediante detección de usos indebidos. Estos usos indebidos - o cuanto menos sospechosos - se reflejan en una base de datos formada por patrones de ataques; dicha base de datos se puede descargar también desde la propia página web de SNORT, donde además se pueden generar bases de patrones `a medida' de diferentes entornos (por ejemplo, ataques contra servidores web, intentos de negaciones de servicio, exploits...). El archivo que utilicemos en nuestro entorno será la base para el correcto funcionamiento de nuestro sistema de detección de intrusos.

Una vez hemos compilado e instalado correctamente el programa llega el momento de ponerlo en funcionamiento; y es aquí donde se produce - al menos inicialmente - uno de los errores más graves en la detección de intrusos. Por lógica, uno tiende a pensar que el sensor proporcionará mejores resultados cuantos más patrones de ataques contenga en su base de datos; nada más lejos de la realidad. En primer lugar, es muy probable que no todos los ataques que SNORT es capaz de detectar sean susceptibles de producirse en el segmento de red monitorizado; si situamos el sensor en una zona desmilitarizada donde únicamente ofrecemos servicio de web, >qué interés tiene tratar de detectar ataques contra DNS? Lo lógico es que las políticas implementadas en nuestro cortafuegos ni siquiera dejen pasar tráfico hacia puertos que no sean los de los servidores web pero, incluso en caso de que el potencial ataque se produjera entre máquinas del propio segmento, hemos de evaluar con mucho cuidado si realmente vale la pena sobrecargar la base de datos con patrones que permitan detectar estos ataques. Evidentemente, cuanta más azúcar más dulce, pero si el sensor ha de analizar todo el tráfico, quizás mientras trata de decidir si un paquete entre dos máquinas protegidas se adapta a un patrón estamos dejando pasar tramas provenientes del exterior que realmente representan ataques: hemos de tener presente que el sniffer no detendrá el tráfico que no sea capaz de analizar para hacerlo más tarde, sino que simplemente lo dejará pasar. Así, debemos introducir en la base de patrones de ataques los justos para detectar actividades sospechosas contra nuestra red.

En segundo lugar, pero no menos importante, es necesario estudiar los patrones de tráfico que circulan por el segmento donde el sensor escucha para detectar falsos positivos y, o bien reconfigurar la base de datos, o bien eliminar los patrones que generan esas falsas alarmas. Aunque suene algo crudo, si un patrón nos genera un número considerable de falsos positivos, debemos plantearnos su eliminación: simplemente no podremos decidir si se trata de verdaderas o de falsas alarmas. Esto es especialmente crítico si lanzamos respuestas automáticas contra las direcciones `atacantes' (por ejemplo, detener todo su tráfico en nuestro firewall): volviendo al ejemplo de la zona desmilitarizada con servidores web, podemos llegar al extremo de detener a simples visitantes de nuestras páginas simplemente porque han generado falsos positivos; aunque en un entorno de alta seguridad quizás vale la pena detener muchas acciones no dañinas con tal de bloquear también algunos ataques (aunque constituiría una negación de servicio en toda regla contra los usuarios que hacen uso legítimo de nuestros sistemas), en un entorno normal de producción esto es impensable. Seguramente será más provechoso detectar y detener estos ataques por otros mecanismos ajenos al sensor.

En resumen, hemos de adaptar a nuestro entorno de trabajo, de una forma muy fina, la base de datos de patrones de posibles ataques. Quizás valga la pena perder tiempo el tiempo que sea necesario en esta parte de la implantación, ya que eso nos ahorrará después muchos análisis de falsas alarmas y, por qué negarlo, algún que otro susto; una vez tengamos todo configurado, podemos utilizar el siguiente script para lanzar SNORT de forma automática al arrancar el sistema (Solaris):
anita:~# cat /etc/init.d/snort
#!/sbin/sh
# 
# Instalacion:
#       # cp <script> /etc/init.d/snort
#       # chmod 744 /etc/init.d/snort
#       # chown root:sys /etc/init.d/snort
#       # ln /etc/init.d/snort /etc/rc2.d/S99snort
#

# Directorio de log
DIRLOG=/var/log/snort
# Fichero de reglas
RULES=/usr/local/security/snort.conf
# Ejecutable
SNORT=/usr/local/security/snort
# Interfaz
IF=hme0

case "$1" in
'start')
        if [ ! -d "$DIRLOG" ]; then
                mkdir -p "$DIRLOG"
        fi
        if [ ! -r "$RULES" ]; then
                echo "No puedo leer el fichero de patrones..."
                exit -1
        fi
        if [ ! -x "$SNORT" ]; then
                echo "No encuentro el ejecutable..."
                exit -1
        fi
        $SNORT -l $DIRLOG -c $RULES -i $IF -N -D
        ;;
'stop')
        if [ ! -r "/var/run/snort_$IF.pid" ]; then
                echo "No puedo obtener el PID..."
                exit -1
        fi
        kill -TERM `cat /var/run/snort_$IF.pid`
        ;;
*)
        echo "Usage: $0 { start | stop }"
        exit 1
esac
exit 0
anita:~#
Con el sensor y sus patrones correctamente configurados ya estamos listos para poner en funcionamiento nuestro sistema de detección de intrusos. Seguramente hasta ahora no hemos tenido muchos problemas con el IDS; no obstante, a partir de ahora las cosas se empiezan a complicar un poco, ya que comienza la segunda parte, la del tratamiento de la información que nuestro sensor nos va a proporcionar. Y es que desde este momento el sistema de detección va a empezar a funcionar y a generar logs con notificaciones de posibles ataques, o cuanto menos de actividades sospechosas; es hora de decidir cosas como dónde situar al sensor, qué hacer ante la generación de un evento en el mismo, cómo procesar la información recibida, o simplemente cuándo rotar los logs generados.

El último de los problemas planteados realmente tiene fácil solución; >cuándo rotar los logs que SNORT genera? La respuesta es muy sencilla: depende. Depende de la cantidad de informes generados en nuestro sensor, depende de la frecuencia con la que debamos realizar informes de los ataque sufridos, depende de la implementación elegida para ejecutar respuestas automáticas ante un ataque (si las ejecutamos), etc. En definitiva, la rotación correcta de unos logs es algo que se debe estudiar y planificar para cada entorno concreto, no se puede dar un periodo estricto que se aplique siempre porque sería sin duda erróneo. No obstante, una idea que nos puede ayudar en la toma de esta decisión es la siguiente: rotaremos los logs cuando los hayamos procesado y extraído de ellos la información que nos pueda interesar para proteger nuestro entorno.

SNORT genera logs en el directorio /var/log/snort/ si no le indicamos lo contrario (podemos hacerlo con la opción `-l' del programa). En ese directorio encontraremos un fichero denominado alert con las actividades que se vayan registrando, y, si no hubiéramos especificado la opción `-N' al arrancar el programa, una serie de subdirectorios cuyos nombres son las direcciones IP de las máquinas de las que se detecta alguna actividad (es el denominado `packet logging'). Como nosotros lo que buscamos es básicamente la generación de alarmas, independiente del packet logging, no necesitamos generar estos directorios (aunque nada nos impide hacerlo).

El siguiente shellscript planificado convenientemente con crontab (si lo ejecutamos más de una vez durante el día quizás nos interese afinar la variable $FECHA) puede ser utilizado para realizar la rotación del archivo de alarmas generado por SNORT:
anita:~# cat /usr/local/security/rotalog
#!/bin/sh
#
# Directorio de log
DIRLOG=/var/log/snort
# Fecha (DD/MM/YY)
FECHA=`date +%d.%m.%Y`
# Interfaz
IF=hme0

if [ ! -d "$DIRLOG" ]; then
        mkdir -p "$DIRLOG"
fi
cd $DIRLOG
mv alert alert-$FECHA
touch alert
chmod 600 alert
kill -HUP `cat /var/run/snort_$IF.pid`
compress alert-$FECHA
anita:~#
Independientemente de la rotación de logs que llevemos a cabo en cada sensor, suele resultar interesante centralizar todos los logs generados en un sólo sistema (a veces se le denomina maestro o master), aunque sólo sea para realizar estadísticas, seguimientos de máquinas atacantes y atacadas, o simplemente un `top ten' de piratas. Para ello podemos establecer relaciones de confianza entre los sensores y ese maestro para que puedan conectarse entre sí sin necesidad de contraseñas y, de forma automática, transferir los logs almacenados y rotados. Por supuesto, a estas alturas dicha relación no la estableceremos mediante la definición de máquinas confiables en archivos .rhosts o similares, ni con las herramientas r-$\ast $, sino mediante SSH y las claves públicas y privadas de cada máquina. Aparte de una mayor seguridad (no autenticamos a una máquina simplemente por su dirección o nombre, algo fácilmente falseable), siguiendo un mecanismo de este estilo conseguimos que todas las comunicaciones entre sistemas se realicen de forma cifrada, algo que aquí es muy importante: cualquier información relativa a potenciales ataques o respuestas automáticas a los mismos se ha de considerar como confidencial, por lo que sería un grave error echar todo nuestro trabajo a perder simplemente porque alguien sea capaz de esnifar dicho tráfico.

Volviendo a nuestras cuestiones iniciales, también debíamos decidir dónde situar lógicamente al sensor; por ejemplo, una cuestión típica es si debemos emplazarlo detrás o delante del firewall que protege a nuestra red. En principio, si dejamos que el sensor analice el tráfico antes de que sea filtrado en el cortafuegos, estaremos en disposición de detectar todos los ataques reales que se lanzan contra nuestra red, sin ningún tipo de filtrado que pueda detener las actividades de un pirata; no obstante, probablemente lo que más nos interesará no es detectar todos estos intentos de ataque (aunque nunca está de más permanecer informado en este sentido), sino detectar el tráfico sospechoso que atraviesa nuestro firewall y que puede comprometer a nuestros servidores. Por tanto, es recomendable ([Con99]) emplazar el sensor de nuestro sistema de detección de intrusos en la zona protegida; de cualquier forma, los potenciales ataques que no lleguen al mismo quedarán registrados en los logs del cortafuegos, e incluso serán neutralizados en el mismo.

Como el sensor ha de analizar todo el tráfico dirigido a las máquinas protegidas, si nos encontramos en un entorno donde dichas máquinas se conecten mediante un concentrador (hub) o mediante otras arquitecturas en las que cualquiera de ellas vea (o pueda ver) el tráfico de las demás, no hay muchos problemas de decisión sobre dónde situar al sensor: lo haremos en cualquier parte del segmento. Sin embargo, si nuestros sistemas se conectan con un switch la cuestión se complica un poco, ya que en las bocas de este elemento se verá únicamente el tráfico dirigido a las máquinas que estén conectadas a cada una de ellas; en este caso, tenemos varias opciones. Una de ellas puede ser modificar por completo - con todo lo que esto implica - nuestra arquitectura de red para integrar un concentrador por el que pasen los paquetes ya filtrados antes de llegar a las máquinas del switch, tal y como se muestra en la figura 18.2. No obstante, suelen existir alternativas más sencillas y cómodas, como la replicación de puertos que se puede configurar en la mayoría de switches; la idea es muy simple: todo el tráfico dirigido a determinada boca del switch se monitoriza y se duplica en otra boca. Así, no tenemos más que configurar este port mirroring y replicar la boca por la que se dirige el tráfico hacia el segmento de máquinas a monitorizar, enviándolo también a una segunda boca en la que conectaremos nuestro sensor.

Figura 18.2: Situación del sensor


Para acabar con los comentarios sobre dónde y cómo situar al sensor de nuestro sistema detector de intrusos, un último apunte: quizás nos conviene recordar que el interfaz por el que se analiza el tráfico (hablando claro, por el que se esnifan las tramas) no tiene por qué tener dirección IP. Perfectamente podemos tener un interfaz levantado e inicializado pero sin asignarle ninguna dirección. Esto nos puede resultar útil si no nos interesa que en el segmento protegido se detecte una nueva máquina, o simplemente si no queremos que nuestro sensor sea alcanzable de alguna forma por el resto de sistemas de su dominio de colisión. Para nuestra comodidad (por ejemplo, a la hora de centralizar logs de diferentes sensores) podemos usar una máquina con dos interfaces, una escuchando todo el tráfico y la otra configurada de forma normal, que será por la que accedamos al sistema.
© 2002 Antonio Villalón Huerta