Customizando Snort
Como mencioné en la primer parte del review de OSSIM, Snort es el mejor y más completo IDS que existe, pero también es bastante complejo. Lograr que la herramienta reporte lo que deseamos requiere de tiempo de análisis monitoreando alertas, buscando y entendiendo lo que reporta y desactivando lo que no necesitamos.
Configurarlo no es cosa de un día, sino una tarea que haremos mientras lo utilicemos. Uno no puede conocer todas las alertas de antemano (son miles), sino que las va conociendo a medida que reportan algo. Lo bueno es que con una buena configuración inicial, los toques que tendremos que hacer en el día a día son mínimos o nulos.
El siguiente artículo resume el trabajo que realicé a lo largo de casi un mes de lidiar con Snort y espero que les ahorre tiempo al momento en que decidan instalar la herramienta. Si bien la mejor forma de aprender es peleando con el sistema, espero que los consejos que doy en esta especie de "guía de configuración" les evite perder tiempo por no haber tenido en cuenta ciertas cosas, como por ejemplo, una buena configuración de snort.conf.


Información previa a la configuración

Antes de comenzar a configurar snort es necesario que conozcan bien cuáles son sus redes locales, cuáles son las direcciones IP de sus servidores, y en cuáles redes confiamos para que accedan a nuestros servidores.
Si en la red, la salida a internet es a través de uno o varios Proxy, tengan a mano las direcciones IP de estos también, ya van a ver por qué.
También es necesario conocer bien las políticas de la empresa. Por ejemplo, utilizar MSN en algunas empresas está permitido y en otras no. Si está permitido, muchas alertas de snort pueden resultar molestas y hay que desactivarlas.
Tengan a mano el manual oficial de snort: Snort User Manual. Es muy completo y lo van a necesitar para entender cómo funcionan las reglas y los preprocesadores. Creo que la parte más jugosa del manual es la de los preprocesadores porque no son tan simples de entender como las reglas.


Mantener Snort actualizado


Para estar al día con los problemas que van surgiendo necesitamos mantener actualizadas las reglas de nuestro snort. Si recuerdan, snort utiliza un conjunto de reglas y de preprocesadores para analizar el tráfico de red. Las reglas se van actualizando a medida que se descubren ataques, o se crean políticas para evitar ciertos dominios. Por ello, necesitamos actualizar las reglas para estar al día.

Para automatizar la descarga de reglas utilizaremos Oinkmaster. Oinkmaster es un script escrito en perl que nos permite descargar las nuevas reglas de forma automática y realizar algunas acciones sobre ellas, como deshabilitarlas, obviarlas, o incluso modificarlas. Esto es extremadamente útil porque durante la customización de las reglas, puede que modifiquemos reglas, o que las eliminemos y no queremos que al realizar la actualización nos pisen nuestras reglas adaptadas con las nuevas descargadas!
Por suerte el paquete oinkmaster está incluido en debian y derivados, así que simplemente debemos instalarlo:
# apt-get install oinkmaster
Debido a que ahora Snort cobra por las reglas que crean, debemos utilizar el conjunto de reglas realizadas por la comunidad. Si bien estas reglas comunitarias son gratuitas, la gente de Sourcefire (empresa detrás de Snort) requiere que el usuario se registre en su página para obtenerlas. Una vez registrados entramos a la sección "rules" y generamos un Oinkcode. El Oinkcode permite armar la URL desde la cual descargamos las reglas. El formato de la URL es:
http://www.snort.org/pub-bin/oinkmaster.cgi/<oinkcode here>/<filename>
donde filename es el nombre del archivo armado a partir de la versión de snort que tengamos, por ejemplo snortrules-snapshot-2851.tar.gz
Una vez armada la URL, editamos el archivo /etc/oinkmaster.conf colocando nuestra URL de descarga:
url = http://www.snort.org/pub-bin/oinkmaster.cgi/<oinkcode here>/<filename>
Por defecto cuando instalamos oinkmaster no se agrega la entrada correspondiente en cron, así que si queremos que se ejecute diariamente, creamos un script bash en /etc/cron.daily/ que ejecute la actualización del oinkmaster:
#!/bin/bash

# check for snort updates with oinkmaster
oinkmaster -o /etc/snort/rules/ -b /data/snortback 2>&1 | logger -t oinkmaster

# replace rules to reflect a proxy in the lan - comment out if you don't have a proxy y your lan
# /usr/sbin/snort_proxy-fixer 2>&1 | logger -t snort_proxy-fixer
La última línea ejecuta un script que explicaré luego, pero básicamente reemplaza reglas para reflejar que existe un proxy en la red.
Como les mencionaba anteriormente, Oinkmaster nos permite mantener deshabilitadas reglas, o bien deshabilitarlas si las actualiza. Para hacer que la actualización no vuelva a habilitar las reglas que deshabilitamos, podemos agregar en oinkmaster.conf los SIDs de las reglas deshabilitadas. Por ejemplo, si queremos mantener deshabilitada la regla cuyo SID es 1411 (regla public SNMP), agregamos el sid en la línea:
disablesid 1411
Cabe aclarar en este punto que Oinkmaster sólo procesa las reglas que descarga, y si se han modificado con respecto a las que ya tenemos. Es decir, si seteamos para que Oinkmaster deshabilite la regla cuyo SID es 1411, sólo lo hará si el nuevo archivo que contiene dicha regla va a pisar al que ya teníamos. Por lo tanto, si no existen modificaciones en el archivo, Oinkmaster no lo procesa. Les aclaro esto porque Oinkmaster no sirve para deshabilitar reglas, a menos que las reglas se tengan que actualizar.
En resumen, si quieren deshabilitar reglas, haganlo sobre las reglas actuales, y agreguen el SID en disablesid para que Oinkmaster no las habilite cuando las actualiza.

Les resultará útil leer la documentación de Oinkmaster: Oinkmaster README.

Por si alguno no lo leyó, hace un tiempo publiqué una optimización para Oinkmaster que permite agragar rangos de sid en los parámetros disablesid, enablesid y localsid, algo que ahorra tiempo cuando queremos, por ejemplo, desactivar varias reglas dentro de un dado rango. Pueden ver la modificación y la forma de agregarla en el artículo Nueva característica para Oinkmaster.


snort.conf

Lo primero que deben hacer al configurar snort, es prestar mucha atención (si, mucha) al archivo de configuración. En el default de snort, el archivo suele ser /etc/snort/snort.conf, pero si tenemos más de una interfaz de red, conviene crear uno por cada interfaz. Por ejemplo OSSIM mantiene tanto snoft.conf como snort.eth0.conf.
Algo a tener en cuenta en las distribuciones basadas en debian es que el script que inicia snort (/etc/init.d/snort) toma como parámetros las variables configuradas en /etc/snort/snort.debian.conf. En ese archivo se debe especificar cuáles son las redes locales en la variable DEBIAN_SNORT_HOME_NET. Esta variable se utiliza como la variable HOME_NET en snort, la cual indica a las reglas cuáles son las redes locales. Realmente me llamó mucho la atención (y me costó un rato de trabajo) el hecho de configurar las redes locales en snort.debian.conf, cuando esto se suele hacer en el archivo snort.conf. El script de inicio de snort no "presta atención" a la HOME_NET configurada en snort.conf porque directamente pasa por parámetro lo obtenido del archivo snort.debian.conf. Me parece horrible tener dos archivos que definen las mismas variables, porque lleva a confusión. Claro que podemos cambiar esto si editamos el script /etc/init.d/snort.

Existe el caso peculiar de la red 169.254.0.0/16 (o direcciones link-local), la cual está designada para autoconfiguración de las máquinas cuando no existe un servidor dhcp. Si la máquina no tiene IP fija y no encuentra servidor DHCP, se auto-asigna una IP de ese rango (configuración default en los Windows). A estas IPs se las podría considerar como local porque es imposible que llegue un paquete externo con alguna de ellas, dado que los routers no los reenvían. Me ocurrió de tener una altísima cantidad de alertas por una máquina que no se asignó IP y enviaba pedidos al proxy con una link-local. Teniendo esta red en la HOME_NET elimina el problema.

Configurar cuáles son las redes locales es muuuuy importante, porque luego dependiendo de éstas, snort dispara alertas o no. Es decir, no es lo mismo recibir una conexión CIFS (protocolo de compartición de archivos de Microsoft) desde una red local que desde una red externa, la primera es considerada tráfico normal, mientras que la segunda se puede considerar un ataque y se dispara una alerta. Si revisan un poco las alertas de snort, verán que la mayoría de las reglas tienen el formato "$HOME_NET port_orig -> $EXTERNAL_NET port_dest" o bien "$EXTERNAL_NET port_orig -> $HOME_NET port_dest", es decir, se dispara alertas en caso de tráfico interno externo y externo interno.
En el default $EXTERNAL_NET está definido como todo lo que no es $HOME_NET, lo cual encaja con la idea y sirve para la mayoría de los casos. Si en el monitoreo que desear realizar esto cambia, presten atención también a esta variable.


Variables

Habiendo aclarado el tema de los archivos de configuración, veamos un poco las variables que podemos tocar:
- DEBIAN_SNORT_HOME_NET (/etc/snort/snort.debian.conf): es la variable más importante, donde definiremos cuáles son las redes locales.
- HOME_NET (/etc/snort/snort.eth0.conf): al igual que DEBIAN_SNORT_HOME_NET, setea las redes locales, pero como les expliqué, en el paquete de debian el script de inicio obvia esta variable y utiliza en su lugar la otra.
- EXTERNAL_NET (/etc/snort/snort.conf): suele definirse como todo lo que no es la home net. A menos que necesiten explicitar algo distinto, dejen esta configuración como está, es decir "EXTERNAL_NET !HOME_NET".
- DNS_SERVERS, SMTP_SERVERS, HTTP_SERVERS, SQL_SERVERS, FTP_SERVERS, SNMP_SERVERS (/etc/snort/snort.conf): define cuáles son los servidores DNS, SMTP, HTTP, SQL, FTP y SNMP respectivamente. Siempre que quieran definir un grupo de IPs o ports, utilicen corchetes []. Por ejemplo, si decimos que los servidores HTTP son 192.168.1.81 y 192.168.1.82, la notación será HTTP_SERVERS [192.168.1.81, 192.168.1.82]. También pueden definir redes enteras con notación CIDR en estas variables.
- HTTP_PORTS, ORACLE_PORTS, FTP_PORTS (/etc/snort/snort.conf): define los ports en los que escuchan nuestros servidores HTTP, ORACLE y FTP. Algunas reglas toman estos parámetros como indicativo que tráfico de estos protocolos a otros ports son ataques.


Preprocesadores

Teniendo declaradas las variables, pasemos a configurar los preprocesadores.
Como les mencionaba en el artículo donde describí snort, éste provee reglas y preprocesadores. Los preprocesadores permiten modificar o analizar los paquetes de forma más completa que usando reglas.

En mi caso particular necesité modificar la configuración de 3 preprocesadores: ssh, http_inspect, sfportscan y Frag3. Las modificaciones son simples, aunque toma tiempo leer los manuales de los preprocesadores para entender lo que reportan y cómo configurarlos.
Veamos entonces una breve descripción y las modificaciones que realicé en cada preprocesador:

- ssh: busca anomalías en las comunicaciones SSH y las reporta. Tiene varias opciones que permiten detectar distintos tipos de ataques overflow conocidos, y detectar payloads que no cumplen con las especificaciones del protocolo (por ejemplo tamaños, dirección del tráfico, etc).

El problema con este preprocesador es que reporta continuamente el error "ssh: Protocol mismatch", el cual es una alerta disparada en los casos que detecta que la versión SSH del cliente es distinta a la del servidor (SSH v1 o v2). Ejecutando la misma versión en cliente y servidor, esta opción del preprocesador (enable_protomismatch) me seguía alertando, y buscando encontré que hay un bug. Por esto decidí deshabilitarla.
Desactivar la opción es tan simple como borrarla de la configuración. Es decir, ahora el preprocesador debería quedar algo como:
preprocessor ssh: server_ports { 22 } \
max_client_bytes 19600 \
max_encrypted_packets 20 \
enable_respoverflow enable_ssh1crc32 \
enable_srvoverflow enable_protomismatch
donde como ven, no está "enable_protomismatch.
Pueden ver el manual del preprocesador SSH en el README.

- sfPortscan: detecta escaneo de ports buscando cierta cantidad de respuestas negativas en un dado intervalo de tiempo. Si un cliente es "legal" conocerá al port que debe conectarse, mientras que si está haciendo un escaneo, seguramente recibirá muchas respuestas negativas al encontrarse con ports cerrados. Esto es lo que sfportscan reconoce y alerta.

La configuración que realicé sobre este preprocesador es básicamente definir qué "escaneadores" ignorar. Tenía el problema que detectaba a mis servidores DNS, SMTP y Proxy como escaneadores, cuando en realidad no lo son. La razón de la detección puede ser el hecho que tanto el proxy como los servidores DNS y SMTP reciben muchos paquetes TCP con el bit RST encendido, aunque debería investigar un poco más el por qué sucede esto. El bit RST se envía cuando uno de los extremos decide terminar la conexión debido a algún fallo, y es algo que se utiliza cuando un port no está abierto, por ello portscan lo toma como respuesta negativa (alias, port scan) y lo reporta.
Sea como sea, me registraba muchas alertas falsas, así que decidí ignorar estos host. Esto lo podemos hacer agregando la opción "ignore_scanners" y registrando los host separados por coma. Por ejemplo, suponiendo que el Proxy es 192.168.1.80, el DNS 192.168.1.53 y STMP 192.168.1.22, el preprocesador debería quedar algo como:
preprocessor sfportscan: proto  { all } \
memcap { 10000000 } \
sense_level { low } \
ignore_scanners { 192.168.1.80, 192.168.1.53, 192.168.1.22 }


sfPortscan tiene muchas más opciones y probablemente les interesen varias, así que aconsejo leer el README.

- HttpInspect: decodifica el protocolo HTTP para aplicaciones del usuario. Dado un buffer de datos, HttpInspect decodifica el buffer, encuentra los campos HTTP y los normaliza. Este preprocesador permite alertar ante ciertos campos sospechosos en el protocolo HTTP.

El problema que encontré con HttpInspect es que alerta sobre codificaciones sospechosas donde los "afectados" eran servers de la extranet. Los alertas más recurrentes eran "Double decoding attack", "IIS Unicode Codepoint Encoding", "Bare Byte Unicode Encoding", y "Oversize Request URI Directory". La mayoría de los alertas son falsos positivos y se deben al funcionamiento de cada página. Debido a que me interesan sólo ataques sobre mis servers Web, y dada la cantidad de falsos positivos, es necesario modificar la configuración.

HttpInspect permite definir configuraciones diferentes para diferentes servers. Además ofrece configuraciones default llamadas "perfiles" ya personalizadas para cada tipo de server (Apache, IIS, etc). Estas configuraciones personalizadas traen activadas diferentes opciones que tienen en cuenta las características del server. Por ejemplo, hay alertas que tienen sentido si el servidor es Apache y no IIS.

Supongamos entonces que en mi red tengo un servidor Apache 192.168.1.81 y un servidor IIS 192.168.1.82. Por un lado eliminamos los alerts para todo servidor que no esté en nuestra red:
preprocessor http_inspect: global \
iis_unicode_map unicode.map 1252

preprocessor http_inspect_server: server default \
profile all ports { 80 8080 8180 } \
no_alerts
Como pueden observar, en la primer configuración seteo el mapeo unicode a 1252, esto ya viene así por defecto y conviene dejarlo. La parte interesante es donde definimos el comportamiento del preprocesador para cualquier servidor (server default). Seteamos que los posibles ports HTTP son 80, 8080 y 8180, y agregamos la opción "no_alerts" para que no envíe alertas.

Ahora que ya tenemos la configuración default, especificaremos las opciones para los servers de nuestra intranet:
preprocessor http_inspect_server: server { 192.168.1.81 } \
profile iis ports { 80 }

preprocessor http_inspect_server: server { 192.168.1.82 } \
profile iis ports { 80 }
El resultado es que el preprocesador alertará sólo si ve tráfico sospechoso sobre los servers 192.168.1.81 y 192.168.1.82.
Al igual que sfPortscan, HttpInspect provee muchas opciones, logrando alto nivel de customización. Pueden leer sobre el resto en el README.

- Frag3: observa la fragmentación de los paquetes IPs y reporta en casos de encontrar anomalías. Debido a que cada SO interpreta a su manera las secciones ambiguas de los RFC del protocolo IP, existen distintas implementaciones sobre cómo es posible fragmentar un paquete.
Gracias a esto, puede que la fragmentación de paquetes permita bypassear firewalls o IDS. Un paquete que es inválido para un sistema, tal vez es ensamblable por otro, convirtiéndolo en un paquete válido.
Uno de los ataques conocidos es fragmentar los paquetes de forma que un fragmento pise los datos que entregó un fragmento anterior, de forma de cambiar el port orígen o destino.

El problema que encontré con este preprocesador es el recurrente alert "Fragmentation overlap". Al parecer frag3 no funciona correctamente con VPNs basadas en IPSec (tal vez con otras VPNs también). No indagué más profundamente el por qué de los overlap en IPSec, pero da muchos falsos positivos.
La solución que encontré es limitar el preprocesador para que analice los paquetes cuyas IP destino no pertenecen a la VPN. Esto se puede hacer utilizando la opción "bind_to". Con esta opción asignamos las redes/IPs que queremos analizar.

Suponiendo que las IPs de mi red, no pertenecientes a la VPN son del rango 192.168.1.0/24, la configuración quedaría de la siguiente forma:
preprocessor frag3_engine: policy first detect_anomalies overlap_limit 10 \
bind_to 192.168.1.0/24
Para más información sobre Frag3, leer el README.


Desactivar/modificar reglas

OK, terminamos de configurar los preprocesadores, es hora de desactivar reglas!
Cada regla tiene su propósito y fue designada por alguna razón, pero la realidad es que muchas no tienen sentido en todas las redes. Snort les puede llenar un disco en pocas horas si no está configurado correctamente y se obvian alertas que no son necesarias.

Existen distintas formas de desactivar alertas en Snort, las cuales están explicadas en el excelente documento escrito por el creador de Oinkmaster How to stop Snort alerts from being generated / how to (not) ignore traffic.
A mi parecer, la mejor opción es comentar las reglas que no nos sirven y agregarlas en la opcion disablesid del oinkmaster.conf para que no las vuelva a activar en alguna actualización.

Las reglas que desactivé están destinadas a aplicar políticas sobre el tráfico que los usuarios tienen permitido. Como en la empresa que trabajo está permitido el acceso a webmails y el chat, éstas reglas son inútiles dado que reportan continuamente algo que ya asumimos:
- sids 2000571, 2000572, 2003121, 2003122, 2000035-2000039, 2008238-2008242, 2001424-2001426 : ubicadas en /etc/snort/rules/emerging-policy.rules, estas reglas están destinadas a reportar acceso a webmails (AOL, Hotmail, Yahoo), y google docs.
- sids 2002332-2002335, 2001241-2001243, 2001682, 2002192, 2008289, 2009375-2009376, 2001253-2001264, 2002659, 2007066-2007069: ubicadas en /etc/snort/rules/emerging-policy.rules, estas reglas reportan la presencia de programas de chat (MSN, GTalk, Yahoo IM).

Por otra parte tuve que modificar algunas reglas por generar reportes erróneos. El caso es que las reglas destinadas a detectar anomalías en el protocolo SIP (protocolo de voz), no matchean correctamente los campos que deben y generan miles de falsos positivos.
Como pueden ver en el manual de snort, las reglas tienen el formato "acción protocol IPsrc port -> IPdst port (opciones)". Existen distintas acciones posibles, siendo la más común "alert". Si bien no encontré una referencia que me diga qué sucede cuando el protocolo usado es "ip", al parecer este no funciona como los que desarrollaron las reglas SIP creían.
Las reglas que reportan errores en SIP tienen el siguiente formato: alert ip any any -> any 5060 (opciones). La idea creo que era matchear tanto paquetes tcp como udp, porque el protocolo SIP puede trabajar sobre ambos. La versión de Snort que yo tengo [2.8.5.2 (Build 121)], no interpreta las eglas de esta forma.
Por lo explicado anteriormente, y como no quería eliminar estas reglas, lo que hice fue deshabilitarlas en su archivo original (/etc/snort/rules/community-sip.rules), agregar los sids en disablesid de Oinkmaster (100000158-100000163, 100000223), y crear nuevas reglas en el archivo /etc/snort/rules/local.rules. Este último archivo está destinado a eso, para generar reglas propias, y Oinkmaster no lo pisa al realizar actualizaciones.
En local.rules agregué las mismas reglas, pero ahora dividiéndolas en tcp y udp. Por ejemplo, para la regla con sid 100000158, cree una versión tcp con el mismo sid y una versión udp con el mismo sid pero comenzando en 9.
alert tcp any any -> any 5060 (msg:"COMMUNITY SIP INVITE message flooding"; content:"INVITE"; depth:6; threshold: type both, track by_src, count 100, seconds 60; classtype:attempted-dos; sid:100000158; rev:2;)
alert udp any any -> any 5060 (msg:"COMMUNITY SIP INVITE message flooding"; content:"INVITE"; depth:6; threshold: type both, track by_src, count 100, seconds 60; classtype:attempted-dos; sid:900000158; rev:2;)
Lo mismo hice con el resto de las reglas.

Siguiendo con las modificaciones, también tuve que adaptar una regla que reportan anomalías DNS. La regla en cuestión genera el alerta "COMMUNITY SIP DNS No such name treshold - Abnormaly high count of No such name responses" y se encuentra en /etc/snort/rules/community-sip.rules.
La regla dispara la alerta cuando alguno de nuestros servidores DNS ($DNS_SERVERS) retorna varias respuestas del tipo "Not Found" a un dado host en un determinado intervalo de tiempo. En general esto puede significar que algún atacante está haciendo fuerza bruta para determinar qué nombres DNS existen en la red, pero hay excepciones.
Como en la empresa utilizamos el servicio de spamhaus para determinar si una dirección DNS se encuentra en una lista negra (algo que nos permite descubrir Spammers y así rechazar e-mails de Spam), este tipo de alertas surge a menudo. Por diseño las DNSBL (DNS Black List) funcionan retornando "Not Found" si una dirección DNS no se encuentra en la lista negra, y dado que se reciben muchos mails por minuto, se arrojan muchos "Not Found" por minuto, ocasionando que la regla de snort genere muchos alerts.
Además el Proxy que actúa de servidor DNS y de cliente de nuestro servidor de DNS, puede también ocasionar muchos "Not Found", por lo que necesitamos evitar las consultas de estos equipos.
Para evitar esto, al igual que antes, podemos comentar la regla cuyo sid es 100000161 y agregar una nueva en local.rules que tenga en cuenta estos casos.
alert udp $DNS_SERVERS 53 -> ![$DNS_SERVERS,$SMTP_SERVERS,$MONITOR] any (msg:"COMMUNITY SIP DNS No such name treshold - Abnormaly high count of No such name responses"; content:"|83|"; offset:3; depth:1; threshold: type both, track by_dst, count 100, seconds 60; content:!"spamhaus.org"; classtype:attempted-dos; sid:100000161; rev:2;)
Existe una regla casi igual a la anterior, que también debemos modificar. Esta regla se encuentra en /etc/snort/rules/emerging-policy.rules y, al igual que la anterior, alerta cuando ve muchos "Not Found" enviados por algún servidor DNS. La diferencia con la regla anterior es que en este caso, el servidor orígen puede ser cualquiera, y los hosts destinos no deben ser ni nuestros servidores DNS ni los SMTP.
El problema con esta regla es que recibía muchos alertas desde la misma máquina monitor (OSSIM). Esto se debe a que la máquina monitor intenta resolver todas las IPs que ve pasar, y como muchas IPs no tienen resolución inversa, recibe muchos "Not Found".
En este caso, haremos igual que antes, comentamos la regla con sid 2103195 y creamos una nueva en local.rules que sea como la siguiente:
alert udp any 53 -> ![$DNS_SERVERS,$SMTP_SERVERS,$MONITOR] any (msg:"ET POLICY Unusual number of DNS No Such Name Responses"; content:"|83|"; offset:3; depth:1; threshold: type both , track by_dst, count 50, seconds 300; classtype:bad-unknown; reference:url,doc.emergingthreats.net/2003195; reference:url,www.emergingthreats.net/cgi-bin/cvsweb.cgi/sigs/POLICY/POLICY_DNS_Responses; sid:2103195; rev:5;)
donde $MONITOR es la IP de la máquina monitor.


Reglas con Proxy

La mayoría de las reglas no tienen en cuenta que puede existir un proxy en la red y que todos los accesos Web a internet se realizan a través de este. El formato de las reglas suele ser:
alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (opciones)
y en las opciones se especifican los parámetros a matchear en un paquete para descubrir anomalías como accesos a megaupload, uso de Base64 para transmitir credenciales, etc.
Si bien las reglas funcionan correctamente y podemos ver el alert, no podemos ver quién fue el origen. Es decir, como tenemos un Proxy, el pedido de un usuario en la red será al proxy (HOME_NET -> HOME_NET), y la alerta no se dispara. La alerta recién se dispara cuando el Proxy sale a buscar la página a internet (HOME_NET -> EXTERNAL_NET), pero en este caso el orígen del pedido es el Proxy. Como resultado tenemos que todos los alerts parecen causados por el proxy y no tenemos forma de ver quién fue el que hizo el pedido al proxy... es decir, un alert que no nos sirve de nada.

Entre las opciones se me ocurrió sacar al proxy de HOME_NET, quedando entonces en EXTERNAL_NET, por lo que los pedidos de los clientes al proxy quedarían registrados. El problema es que como nuestro proxy forma parte del dominio, utiliza recursos de varios otros servidores (DNS, CIFS, LDAP, etc), y hay muchas reglas que si detectan que un host de la EXTERNAL_NET accede a servicios de la HOME_NET como LDAP, disparan alertas. Es decir, arreglo un problema, pero comienzo a tener un tremendo problema de falsos positivos.

La solución que implementé es reescribir todas estas reglas y que queden con el formato:
alert tcp $HOME_NET any -> $PROXY_SERVERS $PROXY_PORTS (opciones)

Como existen muchas reglas de este estilo, cree un script en bash que automatice el proceso, y lo agregué al script de actualización de reglas de snort que cité en "Mantener Snort actualizado" (ver la última línea snort_proxy-fixer). Este script deberían colocarlo en /usr/sbin para que funcione el script de actualización. La función es simple, revisa todos los archivos con reglas y utiliza sed para reemplazar "tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS" por "tcp $HOME_NET any -> $PROXY_SERVERS $PROXY_PORTS":

#!/bin/bash

######################################################
# Created by: d3m4s1@d0v1v0
# Covered by GPLv2.0
######################################################

SNORT_RULES_PATH="/etc/snort/rules/"

RULES_FILE=$( ls $SNORT_RULES_PATH )

echo "************************************************"
echo "*** snort rules proxy fixer by d3m4s1@d0v1v0 ***"
echo "************************************************"
echo
echo "replacing rules <\$HOME_NET any -> \$EXTERNAL_NET \$HTTP_PORTS> with <\$HOME_NET any -> \$PROXY_SERVERS \$PROXY_PORTS>"
echo "please define the variables \$PROXY_SERVERS and \$PROXY_PORTS in snort.conf. Usual PROXY_PORTS are 8080 (ISA) and 3121 (Squid)"
echo

for FILE in $RULES_FILE
do
FILE=$SNORT_RULES_PATH$FILE
TMP_FILE=$FILE".tmp"
if [ -f $FILE ]
then
sed s/"tcp \$HOME_NET any -> \$EXTERNAL_NET \$HTTP_PORTS"/"tcp \$HOME_NET any -> \$PROXY_SERVERS \$PROXY_PORTS"/ $FILE > $TMP_FILE
cp $TMP_FILE $FILE
rm $TMP_FILE
if [ $? != 0 ]
then
echo "ERROR fixing file!:"$?
else
echo -n .
fi
fi
done

echo "[done]"

Habría que pensar qué otro formato se le puede dar para el caso de tener hosts que no salen por el proxy, pero en mi caso funciona perfecto.


Problema sin solución simple

Encontré un problema con el preprocesador sfPortscan. Si, solucioné el problema inicial con los servers más utilizados (DNS, Proxy, SMTP), pero sigo obteniendo muchos falsos positivos. Tal vez sea la configuración Windows que envía muchos RST cuando no correspondería hacerlo.
Estaré trabajando sobre este problema y si encuentro alguna solución les comento =)


Conclusiones

Snort es un IDS excelente y muy completo, pero algo complejo y que necesitamos utilizarlo un tiempo para entender el funcionamiento y adaptarlo a nuestras necesidades. Como siempre digo, no hay mejor forma de aprender a utilizar snort que leyendo el Snort User Manual. Leerlo toma un tiempo, pero ahorra tiempo de enojo y de buscar qué es lo que pasa cuando algo no anda.

Por suerte una vez customizado tendremos una fuente confiable de lo que sucede en la red, la cual podemos consultar en el momento que deseemos, o incluso configurar para que nos envíe las alertas por mail.
Si bien no hablé sobre activar acciones al ocurrir ciertos alertas, esto es factible y una característica muy interesante que espero estar aprendiendo próximamente. Por ahora utilizo Snort como sistema de reporte de problemas a través de la interfaz Web de OSSIM.

No se desesperen por la cantidad de falsos positivos que ven al principio. Luego del uso diario aprenden a distinguir falsos positivos y a "adaptar" las reglas que los generan para que no siga sucediendo. Por suerte las reglas están escritas en texto plano y son fáciles de entender una vez que leen el manual, o los diversos tutoriales que existen sobre escritura de reglas.
Una vez que aprenden a crear reglas, les resultará muy útil para generar alertas especiales sobre cosas que suceden en la red. La posibilidad de adaptación de Snort a una red es enorme, solo lleva un tiempo.

Como dije al principio, espero que esta Guía los ayude a entender un poco más Snort y no repetir errores que yo cometí, o investigar sobre cosas que ya investigué.

23 comentarios:

MagnoBalt dijo...

Muchas Gracias d3m4s1@d0v1v0 muy buen articulo completisimo

d3m4s1@d0v1v0 dijo...

Me alegra que te resultara interesante.

Manuel dijo...

Hola, muy bueno el articulo! No se si me puedes ayudar si sabes como cortar la conexion? O trabajar snort como inline? Es decir tomar ademas de detectar poder prevenir!

Anónimo dijo...

necesito ayuda con ossim

d3m4s1@d0v1v0 dijo...

Necesitaría que especifiques un poco qué problema estás teniendo con OSSIM.

koke dijo...

tengo un problema.
no puedo arrancar snort.
voy al directorio
/etc/init.d/snort y aplico start
pero me arroja un error y no arranca
necesito q cuando la ip 193.168.x.x ingrese a la pagina facebook snort me da una alerta
ademas quiisera saber en que parte de la interfaz web de ossim muestra este reporte
ojala puedas ayudarme

koke dijo...

tengo un problema.
no puedo arrancar snort.
voy al directorio
/etc/init.d/snort y aplico start
pero me arroja un error y no arranca
necesito q cuando la ip 193.168.x.x ingrese a la pagina facebook snort me da una alerta
ademas quiisera saber en que parte de la interfaz web de ossim muestra este reporte
ojala puedas ayudarme
mi correo es jorge.avila.vidal@gmail.com

d3m4s1@d0v1v0 dijo...

Hola koke,
si estás utilizando OSSIM fijate que debes tener un script en /etc/init.d denominado snort_eth0 o similar. Tenes que utilizar el correspondiente a la placa que utilices para monitoreo. De esta forma, debes ejecutar, por ejemplo, /etc/init.d/snort_eth0 start
Si te arroja algún error, compartilo en el comentario y veo si te puedo ayudar.
En OSSIM las detecciones de Snort aparecen en la sección Analysis -> SIEM. También se utiliza Snort en las correlaciones, generando alarmas en Incidents -> Alarms.
Suerte!

koke dijo...

que tengo que poner en el script /etc/init.d/snort_eth0??? porq no aparece

koke dijo...

ya lo encontre pero no se levanta el servicio.. me aparece fail

koke dijo...

me manda el siguiente error en una de las regras:
/etc/snort/rules/facebook.rules(1)Illegal direcction specifier: $HTTP_PORTS
la regla es la siguiente:
ALERT tcp $EXTERNAL_NET any $HTTP_PORTS ->$HOME_NET any (msg:"web prohbida"; content:"http://www.facebook.com"; nocase; flow:to_client, established;)
la mayor parte del codigo lo copie de internet

d3m4s1@d0v1v0 dijo...

La regla está mal armada, fijate que tenes un parámetro de más en el source:
$EXTERNAL_NET any $HTTP_PORTS
Ahí sobra un parámetro, el formato es:
ALERT tcp <IP fuente> <Port fuente> -> <IP destino> <Port destino>
Por lo que veo, estas capturando la respuesta del servidor de facebook a tu red. Borrá el any que está luego de $EXTERNAL_NET para que quede así:
ALERT tcp $EXTERNAL_NET $HTTP_PORTS ->$HOME_NET any (msg:"web prohbida"; content:"http://www.facebook.com"; nocase; flow:to_client, established;)
Con eso la regla no debería arrojar más error.

koke dijo...

gracias por la ayuda anterior ahora no me aparece ese error pero me aparece un nuevo error es el siguiente
FATAL ERROR: /etc/snort/rules/facebook.rules(1) Each rule must contain a rule sid
ojala puedas ayudarme ahora..
te lo agradecere un monton

d3m4s1@d0v1v0 dijo...

Estás teniendo errores muy básicos de creación de reglas de snort. El mensaje es bastante claro al respecto, tenés que poner un SID a la regla. Toma alguna regla como ejemplo y verás que es necesario especificar el campo sid, que es el identificador que utiliza snort para la regla. El mismo debe ser único y no debe colisionar con alguno existente.
Te recomiendo que leas el manual de Snort: http://www.snort.org/assets/140/snort_manual_2_8_6.pdf
Saludos.

Anónimo dijo...

Tengo una pregunta: implemente Snort con mysql y ACIDBASE, ya esta funcional, el detalle es que tengo servidores proxy para salida a internet y no me esta permitiendo captar el trafico de la red, me dicen que pruebe agregando al snort.conf otros puertos aparte del 80 que viene por default.
Alguien me podrìa ayudar, y tambien si alguien hasta ahorita el snort con gusto se los paso.
En una red si proxy funciona bien.

d3m4s1@d0v1v0 dijo...

Si tenes proxy, los pedidos web de cada máquina salen con IP destino la IP del proxy y con puerto destino el puerto del Proxy, luego el proxy envía con su IP como origen los pedidos hacia Internet.
Deberías estar viendo aunque sea ese tráfico saliente del proxy, eso tampoco lo ves? si no lo ves es porque los datos no están pasando por el host donde tenes snort, o bien porque hay alguna configuración mal en snort. Ejecutá snort en modo sniffer para ver si el tráfico que deseas ver está realmente pasando por el host donde tenes instalado snort.
Te aconsejo que corras el script que dejé en este artículo si queres ver cuáles son las IPs origen de los pedidos Web, sino siempre verás la IP del proxy en las alertas.

Anónimo dijo...

d3m4s1 gracias por tu comentario, si ya cheque lo que me comentas,.... si pasa trafico por la red, si pasa, el problema que tengo es para la salida a los otros segmentos que tengo en mi red,.... si tienes las disponibilidad no se si me podrias dar tu email y te muestro la topologia y como configure snort a ver si me puedes ayudar en donde estar mi error

d3m4s1@d0v1v0 dijo...

Si hay otros segmentos de red cuyo tráfico no es visible para el snort que instalaste, vas a tener que instalar snorts en cada segmento.
Espero que no te ofendas, pero de la consultoría privada es de lo que vivo, así que si queres podemos arreglar un precio para lo que necesitás hacer. Me encanta compartir conocimientos en el blog, porque creo que el conocimiento debe estar disponible para todo el mundo de forma gratuita, pero lo que estás necesitando es un trabajo específico.
Saludos!

Anónimo dijo...

Muy bueno, d3m4s1@d0v1v0!

ESSTAMPIDA dijo...

Bravo!!!!!!

Jose L S Rocha dijo...

Que buenos articulos d3m4s1@d0v1v0, gracias por este y los demás, me han sido de mucha utilidad para mi trabajo de tesis de la licenciatura. Quiero ponerte como referencia para darte los creditos correspondientes, pero no veo tu nombre por ningún lado. ¿Qué pruebas me recomiendas (principalmente de ataques) para comprobar la funcionalidad de OSSIM?

d3m4s1@d0v1v0 dijo...

Hola Jose. Me alegra mucho que te hayan servido los artículos, es muy bueno saber que de alguna forma logro ayudar a través de los mismos. Sería interesante leer tu tesis una vez la termines =)
Mi nombre es Victor H. Batista.
Para probar la funcionalidad de OSSIM podes hacer pruebas con nmap (escaneo de ports, o usando los scripts), de exploits con Metasploit o Nessus (u OpenVAS). También podes hacer cambios de MACs en las máquinas (activa arpwatch), modificar archivos de sistema (eso activa OSSEC).
Mirando la funcionalidad de cada una de las herramientas podes ir viendo qué ataque la activará.
Saludos!

Jose L S Rocha dijo...

Primero que nada gracias por tu nombre. En otro comentario de otro post comente que lo estoy implementando para una red inalambrica (relativamente grande)donde todos los AP llegan a una controladora y de ahi a un Switch (donde esta el port-mirrorring) con dhcp, por tal motivo no utilizare arpwatch, porque tengo entendido que compara mac con ip, ni OSSEC. Se me olvido comentarte que ya habia hecho pruebas con nmap para el escaneo, pero no me arrojo resultados.
Hare las pruebas con las demás herramientas que me sugeriste. Nuevamente gracias por los post y sobre todo por contestar.

Publicar un comentario