Vamos a tratar ahora de definir unas pautas para crear un sistema distribuido de detección de intrusos, capaz de generar respuestas automáticas, alarmas, o simplemente logs a distintos niveles de nuestra arquitectura de red, formando lo que se suele denominar un modelo de seguridad de círculos concéntricos ([ISV95]). Para ello, imaginemos un pirata externo a nuestra organización que intenta atacar una determinada máquina, y pensemos en el primer punto en el que podemos detectar dicho ataque y actuar sobre él: ahí es donde deberemos implantar el primer sensor, ya que se trata de la primera barrera que estamos interponiendo entre el atacante y su objetivo; ese primer punto no es otro que nuestro router de salida a Internet, el marcado como `1' en la figura 18.1 (pido perdón por mi estilo `artístico'). No podemos entrar aquí a tratar detalles sobre las capacidades de detección de intrusos de productos como los routers Cisco y su IOS, o de otros elementos fácilmente integrables con esta electrónica de red, como NetRanger (también de Cisco), ya que se trata de sistemas que poco tienen que ver con Unix, y que en muchos casos no controlamos nosotros directamente sino una tercera organización (por ejemplo, Telefónica), a pesar de que tengan incluso una dirección IP perteneciente a nuestra red. En las páginas web de los distintos fabricantes se puede encontrar información muy útil sobre sus productos orientados a la detección y respuesta ante ataques.
IDS en el cortafuegos
Volviendo a la figura 18.1, el segundo punto que separará al atacante de su objetivo (es decir, nos protegerá de él) será nuestro cortafuegos corporativo. Este elemento, sobre el que probablemente ya tendremos pleno control, estará formado por uno o varios sistemas Unix con un software de filtrado de paquetes ejecutándose sobre ellos, y es aquí donde vamos a implantar el primer esquema de detección de intrusos y respuesta automática ante ataques (esta respuesta será habitualmente el bloqueo de la dirección atacante en el propio firewall).
Para decidir qué tipos de ataques debemos detectar y bloquear en nuestro cortafuegos debemos pararnos a pensar con qué información trabaja habitualmente este sistema; cualquier firewall lo hará al menos con los cinco elementos que definen una conexión bajo la pila TCP/IP: dirección origen, dirección destino, puerto origen, puerto destino y protocolo. De estos cinco, quizás los dos menos importantes (de cara a detectar ataques) son quizás el protocolo utilizado y el puerto origen de la conexión; por tanto, son los otros tres elementos los que nos ayudarán en la constitución de nuestro IDS y los que nos facilitarán el poder lanzar una respuesta automática contra el atacante.
Conociendo las direcciones origen y destino y el puerto destino de una conexión ya podemos detectar cierto tipo de ataques; quizás el ejemplo más habitual son los escaneos de puertos, tanto horizontales como verticales, que se lanzan contra nuestros sistemas. La técnica de detección de estos ataques se define perfectamente en [Nor99]: está basada por el momento en comprobar X eventos de interés dentro de una ventana de tiempo Y. Así, podemos analizar en nuestro cortafuegos cuándo una misma dirección origen accede a un determinado puerto de varios destinos en menos de un cierto tiempo umbral (escaneo horizontal) o cuando accede a diferentes puertos bien conocidos de un mismo sistema también en menos de ese tiempo umbral (escaneo vertical). >Por qué el hecho de fijarnos sólo en puertos bien conocidos en este último caso? Muy sencillo: muchas aplicaciones abren muchos puertos destino, generalmente altos (por encima del 1024), en una única sesión de funcionamiento, por lo que esa sesión sería identificada por el cortafuegos como un escaneo vertical cuando realmente no lo es (y si además en nuestro esquema de respuesta automática decidimo bloquear la IP `atacante', causaríamos una grave negación de servicio contra usuarios legítimos de nuestros sistemas).
Una técnica alternativa que con frecuencia suele ser utilizada con bastante efectividad para detectar escaneos verticales consiste en vigilar del acceso a determinados puertos de los sistemas protegidos por el firewall, acceso que con toda probabilidad representará un intento de violación de nuestras políticas de seguridad. No nos engañemos: si alguien trata de acceder desde fuera del segmento protegido a puertos como echo (7/TCP,UDP), systat (11/TCP), netstat (15/TCP), tcpmux (1/tcp) o el desfasado uucp (540/TCP), lo más probable es que se trate de una persona que no lleva muy buena intención con respecto a nuestras máquinas. Seguramente estará lanzando un escaneo vertical contra nosotros, aunque a veces también se puede tratar de un simple curioso que trata de comprobar nuestro grado de seguridad para lanzar un ataque posterior: evidentemente, si alguien tiene abierto un puerto de los citados anteriormente, denota una escasa preocupacion por su seguridad, por lo que casi con toda certeza se puede intuir que tendrá agujeros importantes en alguna de sus máquinas.
Otro tipo de ataques que también son fácilmente detectables vigilando el acceso a determinados puertos de nuestros sistemas protegidos son aquellos que detectan la presencia - o la comprobación de la presencia - de diferentes troyanos como NetBus o BackOrifice: si en el firewall se detecta tráfico dirigido a puertos como 12345, 12346 o 20034 (TCP) o como 31337 (UDP), sin duda se trata de un atacante que está tratando de aprovechar estos troyanos; en muchos casos - la mayoría - se tratará de escaneos horizontales en busca de máquinas contaminadas a lo largo de toda o gran parte de nuestra clase C.
Tabla 18.1: Algunos puertos a monitorizar en un firewall|| || Servicio || Puerto || Protocolo || Ataque || || ttymux || 1 || TCP || Escaneo horizontal || || echo || 7 || TCP/UDP || Escaneo horizontal || || systat || 7 || TCP || Escaneo horizontal || || daytime || 13 || TCP/UDP || Escaneo horizontal || || netstat || 15 || TCP || Escaneo horizontal || || finger || 79 || TCP || Escaneo horizontal/vertical || || who || 513 || UDP || Escaneo horizontal || || uucp || 540 || TCP || Escaneo horizontal/vertical || || NetBus || 12345 || TCP || Troyano || || NetBus || 12346 || TCP || Troyano || || NetBus || 20034 || TCP || Troyano || || BackOrifice || 31337 || UDP || Troyano || || Hack´a´Tack || 31789 || UDP || Troyano || || Hack´a´Tack || 31790 || UDP || Troyano || ||
En la tabla 18.1 se muestran algunos de los puertos a los que conviene estar atentos a la hora de diseñar una política de detección de intrusos en nuestro cortafuegos; por supuesto, existen muchos más que pueden ser considerados `sospechosos', pero en cualquier caso siempre conviene ser muy precavido con su monitorización ya que algunos de ellos pueden ser usados por usuarios lícitos a los que causaríamos una grave negación de servicio si, por ejemplo, les bloqueáramos el acceso a nuestra red a causa de un falso positivo.
Todos sabemos que el cortafuegos es algo vital para proteger a nuestros sistemas, pero lamentablemente es un elemento muy limitado a la hora de detectar ataques. Por ejemplo, imaginemos la siguiente situación: un atacante decide comprobar si nuestro servidor web corporativo tiene algún tipo de vulnerabilidad que le pueda ayudar en un ataque contra la máquina; algo muy común hoy en día, ya que quizás uno de los mayores daños que puede sufrir la imagen de una empresa - especialmente si está relacionada con las nuevas tecnologías - es una modificación de su página web principal. Es muy probable que ese pirata lanzara en primer lugar un escaneo de puertos vertical contra el servidor, para comprobar si aparte del servicio HTTP se está ofreciendo algún otro; si todo es correcto, el puerto de web será el único abierto en el cortafuegos corporativo, cortafuegos que además detectará el ataque contra la máquina y bloqueará, al menos temporalmente, cualquier acceso de la dirección atacante. Un punto a nuestro favor, pero el pirata no tiene más que colgar el módem y volver a llamar a su proveedor para conseguir otra IP, con lo cual obtiene de nuevo acceso a nuestro servicio HTTP y además ya sabe que el único puerto abierto en la máquina es ese.
Ahora ese atacante no necesita ningún tipo de escaneo de puertos adicional; puede seguir varios caminos para atacarnos, pero sin duda el más lógico y fácil es tratar de localizar vulnerabilidades en el servidor web de nuestra organización. Para ello puede lanzar un escaneador de vulnerabilidades en servidores web19.1contra la máquina, escaneador que no generará ninguna alerta en el cortafuegos; al fin y al cabo, lo único que hacen estos programas es lanzar peticiones al puerto 80 de nuestro servidor web, algo que el firewall no contempla como sospechoso: para él, no hay diferencia entre un analizador de CGIs y peticiones normales a nuestras páginas.
Parece por tanto evidente que nuestra primera barrera de detección de intrusos es realmente útil, pero también insuficiente frente a determinados ataques; entonces entra en juego el segundo nivel de nuestro sistema de detección de intrusos, el ubicado en el segmento de red - en el dominio de colisión - en el que se encuentra el host que estamos tratando de proteger.
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-, 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.
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.