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

jueves, 30 de junio de 2011

Primeros resultados del preprocesador de geolocalización

Hace un par de semanas definimos cuales eran las principales limitaciones que presentan los IDS/IPS actuales y como era necesario aportar algo más de conocimiento para poder detectar amenazas y riesgos en la infraestructura.

Como ejemplo de requisito adicional se desarrolló un preprocesador dinámico de geolocalización para Snort que permitía poder generar alertas en función del origen o destino de la IP de un paquete de red. El concepto era totalmente distinto a lo que se había desarrollado actualmente con la geolocalización, puesto que nuestro objetivo no era, una vez generada una alerta obtener la procedencia o destinatario con fines únicamente estadístico, sino ser capaces de generar la alerta por la procedencia o el destino de un paquete de red.

Una vez comprobado el correcto comportamiento de esta nueva funcionalidad en distintos entornos de preproducción, se procedió a desplegarla en varios IDS de producción para comprobar su funcionamiento, analizando la información obtenida para comprobar si realmente podría ayudar a detectar amenazas y riesgos en la infraestructura. Las reglas de detección que se han empleado para esta primera fase corresponden a nuevas conexiones hacia países de China y Rusia a los servicios SSH y HTTPS ( puerto destino 22, 2222 y 443).

Los resultados fueron buenos, y aunque lógicamente se pueden mejorar y trabajaremos en ello la primera versión supero las estimaciones previstas. Del conjunto de alertas totales que se generaron en los IDS, el 2.4% fueron del preprocesador de geolocalización. De dichas alertas el 49% correspondían a IP’s ya conocidas de Malware puesto que se trataban principalmente de RBN’s y servidores comprometidos conocidos.

De las 51% de las alertas restantes que no correspondían a IPs de Malware conocido se procedió a realizar un muestreo para comprobar aproximadamente cuales de dichas alertas correspondían a falsos positivos y por tanto, conexiones legítimas a dichos países y en cuales no había ningún motivo para que se hubiera efectuado dicha conexión, identificando posible Malware desconocido.

Los resultados fueron que el 30% de ese 51% correspondía a falsos positivos mientras que el 70% correspondían con IP’s para las cuales no existía ningún motivo aparente de que se realizará dicha conexión, y por tanto, es más que probable que el equipo estuviera infectado con Malware. De hecho es en este punto en donde se está trabajando actualmente.

El resumen de los primeros resultados se muestra en la siguiente gráfica donde conocido corresponde a IP’s que ya eran conocidas como fuente de malware, desconocido implica aquellas IP’s para las cuales no se conoce un motivo aparente para que se hubiera establecido una conexión a un puerto cifrado mientras que falso positivo indica conexiones legítimas a China o Rusia que generaron alerta:






Por tanto, pese a tratarse de conexiones en su gran mayoría al puerto 443 (HTTPS) y cifradas, las cuales nunca hubieran generado alerta en los IDS tradicionales, se generó alertas que identificaron Malware no detectado previamente.

PD: entrada publicada también para securityartwork


Continuar...

martes, 21 de junio de 2011

Filtros BFP con Tcpdump

Tcpdump, Windump en Windows, es un analizador de red en modo consola bastante básico que permite ver el tráfico de red empleando la biblioteca libpcap/winpcap.

Esta herramienta permite analizar de forma sencilla y resumida el tráfico de red, ya que es capaz de leer las cabeceras de los protocolos de red mostrando la información tratada de forma que sea sencilla de entender. A su vez permite mostrar el payload en crudo (hexadecimal) y en texto (ASCII) y permitiendo crear filtros BFP (berkley filter packet) para mostrar únicamente los paquetes que nos interese. La estructura de opciones que permite tcpdump es la siguiente:

tcpdump [-i interfaz/-r fichero] [opciones] ['filtro']

Interfaz será el nombre de la interfaz de red donde se desee leer el tráfico, por ejemplo eth0. Mientras que fichero será el fichero "pcap" que contiene el tráfico guardado con anterioridad.


Opciones son las opciones que soporta tcpdump, principalmente las siguientes:
-n: no resuelve las ip's.
-nn: no resuelve las ip's de los host y muestre el valor númerico de los puertos y no su nombre, por ejemplo 21 en vez de ftp.
-vv: más información de las cabeceras, como por ejemplo el Identificador de la cabecera IP.
-S: muestra los valores reales del Seq de los paquetes TCP y no el valor relativo sobre el Syn inicial.
-e: muestra la MAC.
-x: muestra el payload en hexadecimal.
-X: muestra el payload en hexadecimal y en ASCII.
-A: muestra el payload en ASCII.
-sX: muestra X bytes del payload incluido las cabeceras de los protocolos a partir de la capa de red. En las versiones antiguas de tcpdump se muestra un máximo de 68 bytes. Para mostrar todo el payload se usa -s0.
-w fichero: permite guardar el tráfico leido en un fichero Pcap.
-c X: leer los X primeros paquetes del fichero leido con -r fichero.
Filtro corresponde a los filtros BFP que permite mostrar solo aquellos datos que cumplan una serie de condiciones. Estos filtros pueden ser de dos tipos: macros o a bajo nivel.

Los macros son palabras reservadas que permite poder realizar filtros a más alto nivel. Por ejemplo si queremos mostrar solo el tráfico del host 192.168.0.1 se puede usar el macro "host 192.168.0.1" o emplear un filtro a bajo nivel y acceder a la cabecera IP donde se encuentra la IP de origen y destino comparandola con su valor hexadecimal.

Los macros más usados son los siguientes:
host IP: host origen o destino IP.
dst host IP: host destino IP.
src host IP: host origen IP.
port X: puerto origen o destino X.
src port X: puerto origen X.
dst port X: puerto destino X.
net Clase: subred "Clase" donde clase es el valor numérico de la red que no varía. Es decir 192.168.0.0/24 sería "net 192.168".
src net Clase: igual que el anterior pero solo origen.
dst net Clase: igual que el anterior pero solo destino.
icmp: paquetes ICMP
tcp: paquetes TCP.
udp: paquetes UDP.
Se pueden relacionar más de un macro mediante las ordenes "or" o "and". Con "Or" con que se cumpla una de las condición se muestra el paquete mientras que "and" indica que deben cumplirse todas las condicones.

Por ejemplo si se quiere decir que quiero ver todo el tráfico hacia el host 10.0.0.1 o el tráfico ICMP sería:

'icmp or dst host 10.0.0.1'

Otro ejemplo sería que el host sea 10.0.0.1 y que el paquete sea ICMP o UDP:

'host 10.0.0.1 and (icmp or udp)'

Pese a que los macros son muy comodos es posible que nos encontremos en ocasiones con que es necesario acceder a algun campo de las cabeceras para las cuales no se dispone de macros, por lo que es necesario usar filtros a nivel bajo. Para ello se emplea la siguiente sintaxis:

'protocolo[posicion] comparador valor'
  • Donde protocolo es la cabecera del protocolo buscado: IP, ICMP, UDP y TCP.
  • Posición es el byte, empezando a contar en 0, que buscamos dentro de la cabecera.
  • Comparador es la operación a comparar con valor. Soporta igual "=", distinto "!=", mayor ">" y menor "<" (entre otros). 
  • Valor es el valor en decimal o hexadecimal con que se compara el dato de la cabecera. 

Si por ejemplo queremos ver todos los paquetes cuyo TOS (type of service), situado en el segundo byte de la cabecera IP, seá distinto de 0 se emplearía el siguiente filtro:  

'ip[1] != 0'

Para acceder a más de un byte seguido se puede realizar mediante "posicion_ini:cantidad_bytes", por ejemplo para buscar aquellos paquetes cuyo tamaño sea menor de 40 bytes podemos consultar el byte 2 y 3 de la cabecera IP: 

'ip[2:2] > 40'

Otro ejemplo sería un filtro que muestre el checksum de la cabecera IP (bytes 10 y 11) cuyo valor sea igual a 0:

'ip[10:2] = 0'

Como vemos de esta forma podemos acceder a los bytes de las cabeceras de distintos protocolos. ¿Pero que ocurre si quiero acceder a un solo bit o un nibble(medio byte)? Es necesario usar mascaras.

El objetivo de las mascaras es realizar la operación binaria and sobre el byte obteniendo únicamente aquellos valores que nos interese, donde los bits de la mascara valdrán 0 en aquellos bits que no nos interesa y 1 en los que nos interesa. Sobre el resultado de la operación binaria se realiza la comparación que se buscaba inicialmente, veamoslo con un ejemplo:

Queremos leer solo los paquetes con el flag Syn activado (inicio de conexión), el cual es el segundo bit del byte 13 TCP (EEUAPRSF). Por tanto nos interesa obtener el 2 bit únicamente y luego indicar que ese bit tiene que ser distinto de 0. La mascara para poner a 0 todos los bits de un byte menos el segundo es 0x02 (0000 0010), por tanto el filtro será el siguiente:

tcpdump -i eth0 'tcp[13] & 0x02 !=0'

Una alterantiva al filtro anterior sería cualquiera de los siguientes:

tcpdump -i eth0 'tcp[13] & 0x02 = 0x02'
tcpdump -i eth0 'tcp[13] & 0x02 = 2'

En los casos expuestos con anterioridad buscamos aqueños paquetes que tenga el bit Syn activado pero los paquetes pueden tener otros bits activados a parte del Syn, como por ejemplo Syn + Ack. Si queremos solo mostrar los paquetes con únicamente el bit Syn se realizaría de la siguiente forma:

tcpdump -i eth0 'tcp[13] = 2'
tcpdump -i eth0 'tcp[13] = 0x02'

PD: existen macros para el acceso a los flags TCP con tcpflags.

Es importante tener en cuenta que no es lo mismo explorar el nibble alto que bajo. Por ejemplo si se quiere visualizar únicamente los paquetes que contenga el flag ACK, el cual es el primer bit del nibble alto del byte 13 de la cabecera TCP(EEUAPRSF), se realizaría de la siguiente forma:

tcpdump -i eth0 'tcp[13] & 0x10 = 0x10'
tcpdump -i eth0 'tcp[13] & 0x10 = 16'

Puede parecer que sea lo mismo, ¿verdad? Veamos un ejemplo más claro. El nibble alto del byte 12 del protocolo TCP contiene el tamaño de la cabecera TCP en tamañp palabra (4 bytes), es por ello que de normal el nibble vale 5 y por tanto 5 * 4 igual a 20 bytes. Imaginemos que queremos obtener aquellos paquetes cuyo tamaño de cabecera TCP sea superior a 20 bytes:

tcpdump -i eth0 '((tcp[12] & 0xf0)*4) > 20'

Aparentemente sería lo correcto ¿verdad?... no, hay que tener en cuenta que al tratarse del nibble alto donde Tcpdump leé los datos en byte y no en nibble, cuando le indicamos que leá el valor del byte 12 no está leyendo "5" representado como "0101", sino "0101 0000". Por tanto es necesario dividir entre 16 para obtener el "5" y no el "96" que obtuvimos con anterioridad:

tcpdump -i eth0 '(((tcp[12] & 0xf0)/16) *4) > 20'

O lo que es lo mismo:

tcpdump -i eth0 '((tcp[12] & 0xf0)/4) > 20'

Como vemos, con un conocimiento básico de las cabeceras IP, TCP, UDP y ICMP se pueden realizar filtros realmente complejos que nos pueden ayudar durante un incidentes. Espero que os sea de utilidad.

Continuar...

viernes, 3 de junio de 2011

Network Tap en NIDS

Uno de los problemas que surgen a la hora de implantar las sondas para la detección de intrusos a nivel de red (NIDS) es el lugar de conexión de ésta. Normalmente se suele conectar en las interfaces span o puerto espejo del Switch (conmutador) de la red donde queremos detectar las alertas, incluso para aquellas soluciones donde se dispone de un presupuesto reducido se emplean Hub (concentrador).

Pero dichas soluciones presentan un problema de perdidas de paquetes. En caso de un Hub es debido a las colisiones que se genera en el tráfico, donde en una red 10/100 la interfaz del NIDS puede llegar a tratar un máximo de 40 mbits/segundo. En caso de los Switch el problema surge con el coste computacional adicional de tener que procesar y replicar los paquetes de una o varias interfaces sobre la interfaz espejo, así como, no ser capaces de inyectar en una única interfaz el tráfico total que circula por las interfaces replicadas.

Es por ello que en el puerto espejo de un Switch 10/100 un NIDS es capaz de analizar un máximo de 60 a 80 mbits/segundo, mientras que en una red a giga el máximo estará entre 400 y 600 mbits/segundo.

Para solucionar estos problemas en entornos de carga elevada y críticos con full duplex se emplean Copper Test Access Ports o Taps, permitiendo obtener el tráfico que circula por un cable y replicarlo a a la interfaz del NIDS sin que el tráfico se vea afectado. 

¿Como hacer esto? imaginemos que se desea leer el tráfico que va entre dos dispositivos de red al que llamaremos A y B. Esos dispositivos de red se conectan por un cable (Cobre/RJ45 o Fibra). En la interfaz A tendremos la señal de recepción RX la cual se conecta al de transmisión TX de B, y así mismo, la interfaz de B tendrá el RX conectado a la TX de A. El TAP  se sitúa en medio de los dos cables, teniendo dos bocas donde en una se conecta A y en la otra a B como si se tratara de una prolongación del cable. A su vez coge la señal TX de A y de B y las lleva a dos bocas adicionales.  Veámoslo en un diagrama sencillo:


Es importante comprender que no se puede conectar el TX de A y el TX de B en la misma interfaz del NIDS, puesto que la interfaz encargada de leer el tráfico (la sonda del NIDS) solo puede leer por su RX y no leer tráfico por su TX, ya que es de transmisión y no de recepción (gracias Jose Luis :P). 

Existen diagramas sencillos para crearnos nuestro propio Tap 10/100 (pieza indispensable de un análisis forenses), a un precio más que asequible empleando únicamente cuatro anclajes para RJ45 y un cable RJ45. Claro este en entornos críticos a giga los tap no son tan sencillos y son realmente caros, del entorno de 2000 a 5000 euros.

Como se habrán dado cuenta el tráfico capturado por el Tap se encuentra dividio en las dos interfaces (TXA y TXB) donde una dirección del tráfico está en una interfaz y el de otra dirección en la otra. Por tanto es necesario juntar el tráfico de esas dos interfaces para poder leerlo como si lo estuviéramos haciendo directamente sobre el cable. Para ello se emplean Switch que permiten "unir" el tráfico de ambas interfaces en una única interfaz. Se puede pensar que es lo mismo que poner un Switch directamente sin el Tap como se comento al principio, pero no, por que en este caso el Switch solo tiene que replicar el tráfico en una única interfaz, así mismo, dicho proceso no influye en el funcionamiento del Switch de producción.

El problema de está solución es que en la tarjeta span puede recibir la mitad del tráfico máximo que puede circular en ambas interfaces, por ejemplo si el TX de A es a Giga y el TX de B es a Giga, si tengo que inyectar ese tráfico en una tarjeta a Giga en el peor de los casos podría llegar a perder la mitad del tráfico: TXA + TXB en TXSpan.

Para ello existe dos soluciones. La primera y más económica, pero nos obliga a emplear NIDS por software, es por software empleando para ello un servidor con dos interfaces que soporten el mismo tráfico, o más, que las interfaces TXA y TXB del Tap. El servidor deberá usar el sistema operativo linux y emplear bonding, mediante el comando ifenslave que permite agregar el tráfico de ambas interfaces en una. Si por ejemplo tenemos un tráfico a giga necesitaríamos un Tap que sea a Giga, un servidor con al menos 2 interfaces a giga y una tercera de gestión, donde conectaremos cada interfaz del Tap (TXA y TXB) a cada una de las interfaces giga del servidor y una vez conectado activaremos el Bonding. Si por ejemplo las interfaces a giga son Eth0 y Eth1 los comandos a ejecutar serán los siguientes:

# ifconfig bond0 promisc up
# ifconfig eth0 promisc up
# ifconfig eth1 promisc up
# ifenslave bond0 eth0
# ifenslave bond0 eth1


De esta forma podemos invertir en un servidor potente con fuente redundante que se encargue de la agregación por bonding y a su vez, del análisis de tráfico al instalar  alguna herramienta de detección de intrusos a nivel de red por software como puede ser Suricata o Snort, que hará la función de la sonda de detección de intrusos al leer el tráfico de la interfaz bond0.

Tal como hemos comentado, existe una segunda alternativa al bonding, mucho más cara y algo mejor, que es emplear el balanceador de tráfico de Top Layer, la cual se puede emplear con sondas por hardware como por software. Este dispositivo funciona conectando las dos interfaces del Tap al dispositivo y éste se encarga de balancear el tráfico de red a diferentes interfaces  manteniendo la sesión de la comunicación y siendo capaz de transmitir a las interfaces de red casi/la totalidad del tráfico que circule por la red (¡sin perdidas!). A su vez es capaz de asignar interfaces dedicadas a cierto tráfico como es el HTTP o SMTP permitiendo asegurar que no se producen perdidas en protocolos críticos. El funcionamiento sería el siguiente:
 
 

Por tanto, la solución para entornos de carga elevada sería emplear un Tap a giga o fibra, a poder ser de doble fuente redundante, y hacer la agregación por bonding empleando un NIDS por software como Snort o Suricata. Lógicamente usar el balanceador sería lo ideal, pero el precio se dispara, ya que, debemos tener en cuenta que el precio del Tap a Giga, del servidor para bonding + sonda tiene un precio aproximado ente 4000 y 7000 euros. 

Nos vemos en la próxima entrada.

Continuar...

miércoles, 25 de mayo de 2011

Reconocimiento de activos mediante herramientas pasivas (II)

Tal como vimos en la anterior entada necesitamos de alguna forma poder saber el sistema operativo, los puertos de los servicios y de que servicios se tratan, de aquellos activos que queramos proteger en nuestro IDS. Para ello necesitamos poder reconocerlos mediante herramientas pasivas que sean capaces de obtener dicha información únicamente escuchando el tráfico de red.

Después de buscar un poco sobre que herramientas podían servirme decidí empezar con “P0f”, ya que era una de las herramientas más conocida para esta tarea. P0f lee las cabeceras TCP de los paquetes, analiza su comportamiento y reconoce ciertos sistemas operativos en función de una serie de valores como el valor de inicialización del ack, el comportamiento del host ante ciertos flags tcp, tamaño de ventana, etc. Veamos como funciona.

Para instalarla sobre un entorno Debian solo es necesario usar apt-get:
# apt-get install p0f

Para ejecutarla se puede hacer con la siguiente sentencia:
# p0f -f /etc/p0f/p0f.fp -i eth0 -t -p -i eth0

Al ejecutarla veremos los paquetes TCP que está leyendo p0f mostrando valores de las cabeceras TCP que normalmente usa para el reconocimiento del sistema operativo. Veamos ejemplos que me encontré haciendo las pruebas:

Navegación a SAW:
<Sun May 15 15:34:45 2011> 192.168.XXX.XXXX:58793 - UNKNOWN [S10:64:1:60:M1460,S,T,N,W6:.:?:?] (up: 7 hrs)
-> 62.97.78.24:80 (link: ethernet/modem)
<Sun May 15 15:34:46 2011> 192.168.XXX.XXX:58794 - UNKNOWN [S10:64:1:60:M1460,S,T,N,W6:.:?:?] (up: 7 hrs)
-> 62.97.78.24:80 (link: ethernet/modem)

Conexión a servidor SSH:
<Sun May 15 15:36:05 2011> 192.168.XXX.XXX:42113 - UNKNOWN [S10:64:1:60:M1460,S,T,N,W6:.:?:?] (up: 7 hrs)
-> 147.XXX.XXX.XXX:22 (link: ethernet/modem)

Nmap -O -sS:
<Sun May 15 15:37:24 2011> 192.168.2.101:53536 - UNKNOWN [1024:40:0:44:M1460:.:?:?]
-> 62.97.78.24:1723 (link: ethernet/modem)
<Sun May 15 15:37:24 2011> 192.168.2.101:53536 - SunOS 4.1.x
-> 62.97.78.24:8888 (distance 9, link: ethernet/modem)

Como vemos, solo cuando realizo un reconocimiento activo con nmap despierto a P0f, en los anteriores casos no es capaz de reconocer el sistema operativo. Al probarlo sobre un entorno de 100 mbits/s de ancho de banda durante una hora, observe que no se detectaron apenas sistemas operativos, así como, que se detectaron falsos positivos. 

Personalmente p0f no cumplió con lo que esperaba, entiendo que su comportamiento es complejo pero no cumple los requisitos necesarios para lo que buscamos. Por ello seguí buscando nuevas herramientas y encontré SANCP: Security Analyst Network Connection Profiler.

SANCP permite crear estadísticas de los datos leídos, en función de puertos y IPs, justo lo que necesitamos para tener un buen inventario de la red que estamos leyendo. La aplicación genera tres ficheros, uno es el tráfico pcap leído, el segundo es una estadística de la red (el que principalmente nos interesa) y el último es un resumen en tiempo real del tráfico leído.

Por desgracia SANCP no se encontraba en los repositorios por lo que decidí instalarlo a partir de las fuentes desde el CVS (es una herramienta que se ha dejado de desarrollar):

# apt-get install libpcap0.8-dev cvs
# cvs -d:pserver:anonymous@sancp.cvs.sourceforge.net:/cvsroot/sancp login
# cvs -d:pserver:anonymous@sancp.cvs.sourceforge.net:/cvsroot/sancp co sancp
# make linux
# ./install

 
El siguiente paso consistirá en editar el fichero de configuración del SANCP con unas líneas básicas. Primeramente indicamos el valor, siempre en hexadecimal, del tipo de protocolo soportado en la capa de enlace, y para este caso IPv4 (var ip 8 del valor 0x0800 del Protocol Address Type), seguidamente indicamos que protocolos debe soportar IPv4 (icmp, tcp o udp en sus valores hexadecimales del campo Protocol de la cabecera IPv4), a continuación los servicios, y por tanto los puertos que queremos que escuche, las zonas de red y para finalizar los filtros que nos interese con formato “proto_red ip_src dst_ip proto_transporte puerto_src puerto_dst, acción” (hay filtros realmente complejos):

# vim /etc/sancp/mio.conf
var ip 8
var icmp 1
var tcp 6
var udp 17
var http 80
var https 443
var smtp 25
var dns 53
var HOME_NET 192.168.0.0/16
ip HOME_NET any udp any dns, stats pass


Cuidado con la configuración que creamos porque por ejemplo, indicar dos puertos como “var icmp X, Y” o indicar dos subredes como “var HOME_NET [192.168.0.0/16 10.0.0.0/8]” da lugar a que la aplicación falle mostrando una traza del fallo como el siguiente sin indicar porque falla, hay que ir línea a línea:

sancp: Retrieved last connection ID: 5606918228258572233 8 0
*** glibc detected *** sancp: free(): invalid pointer: 0x082b5294 ***


Para finalizar ejecutaremos la aplicación indicándole el usuario y grupo, la interfaz, donde se encuentra el fichero de configuración, que no guarde ni el volcado pcap del tráfico de red ni las estadísticas en tiempo real y que muestre el valor de la IP en un formato humano (no network):
# sancp -i eth0 -P -R -H -u sancp -g sancp -c /etc/sancp/mio.conf

Si eliminamos la opción “-R” obtendremos las estadísticas en tiempo real con formato “realtime.interfaz.timestamp”, si eliminamos la variable “-P” capturaremos el tráfico de red en el fichero “pcap.interfaz.timestamp”. El fichero que nos interesa es el de estadísticas llamado “stats.interfaz.timestamp”:

# head -1 stats.eth0.1305468039
|192.168.XXX.XXX|48708|62.97.78.24|80|2|300|10|8|1522|5939|1F|1A|05|60|64|89|14600|||||60|53|89|5792|||||8665|1|0|0|0|N|N|Y|3|1067|0|0|0|0|0|N|65:37:XX:XX:0:0|0:1:0:XX:XX:6f

Con un simple script podemos parsear las entradas del fichero y obtener mucha información a nivel de red útil que puede permitirnos detectar nuevos puertos en ciertas IP's, así como, comportamientos anómalos de la red.

Sería una herramienta muy muy útil de no ser por la limitación en las opciones del fichero de configuración, por lo menos, hasta lo que he podido investigar. Creo que estaría muy bien poder añadir al código las funcionalidades para que permita poder indicarle a una misma variable más de una IP o un puerto, así como, la capacidad de depurar los errores del fichero de configuración de una forma más adecuada.

Buscando un poquito más encontré la herramienta PADS o Passive Asset Detection System, la cual lee el payload de los paquetes y comprueba si coincide con una serie de firmas escritas mediante expresiones regulares, que identifican baners de respuesta de una serie de servicios y sistemas operativos.

Para instalar la herramienta es necesario usar “apt-get”:
# apt-get install pads

El fichero de firmas se encuentra en “/etc/pads/pads-signature-list”. Un ejemplo de expresión regular sería el siguiente:

smtp,v/Microsoft Exchange SMTP/$2/$1/,220 ([-.\w]+) Microsoft ESMTP MAIL Service, Version: ([\S]+)

El siguiente paso consistirá en configurar el fichero de configuración “/etc/pads/mio.conf” de la siguiente forma:

# vim /etc/pads/mio.conf
daemon 0
pid_file /var/run/pads.pid
interface eth0
network 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12
output screen
output csv: /var/lib/pads/assets.csv


Para finalizar lo ejecutaremos con la siguiente orden:
# pads -c /etc/pads/mio.conf -i eth0

Ésta escribirá el resultado de los activos descubiertos en el fichero “/var/lib/pads/assets.csv”. Un ejemplo del fichero sería el siguiente:

84.246.212.91,80,6,www,Apache,1306270559
84.246.212.92,80,6,www,lighttpd/1.4.28,1306270561
178.33.42.161,80,6,www,nginx,1306270561
195.158.241.126,80,6,www,Apache,1306270565
149.20.54.15,80,6,www,Debian),1306270567
85.152.32.141,49182,6,unknown,unknown,1306270568
213.27.222.7,80,6,www,lighttpd/1.4.26-devel-109890:109892M,1306270570
208.67.238.238,80,6,www,bit_asic/3.8/r4c1-bitcast-b,1306270572
94.102.156.82,80,6,www,Ubuntu),1306270572


Los resultados han sido bastante mejores que en las anteriores herramientas basadas en protocolos de red y no en firma como PADS. Pero la capacidad de reconocimiento de puertos y equipos que tenia herramientas como SANCP no las tiene PADS.

Creo que la combinación de SANCP y PADS sería una herramienta auxiliar perfecta para los IDS, pero para ello sería necesario juntar los dos códigos y aplicar las mejoras comentadas durante la entrada. ¿Alguien se anima?

Continuar...

sábado, 21 de mayo de 2011

Reconocimiento de activos mediante herramientas pasivas (I)

Uno de los principales problemas que nos encontramos a la hora de implantar sondas de detección de intrusos a nivel de red, es la configuración correcta del entorno para evitar inclusiones o evasiones en nuestras sondas. Por ello nos interesa conocer que tipo de sistema operativo está corriendo en un cierto host así como que servicio está ofreciendo.

El objetivo de conocer que sistema operativo se encuentra en cierta IP, es para saber como el IDS debe tratar los paquetes a nivel de cabeceras del protocolo, y por tanto, de la pila. Ésto es debido a los huecos o distintas interpretaciones del estándar establecido en los RFC por los desarrolladores de los SSOO. Por ello no es lo mismo la implementación de la pila IP en un Windows, que en una Solaris, BSD o en un Linux.

Ésto hecho se aprecia cuando recibimos paquetes fragmentados donde en una misma posición puede existir más de un dato, lo que se conoce como overlapping, un entorno Windows siempre se quedará con el fragmento que ha llegado primero, un BSD con el que tenga un offset menor y a igual ofsset se quedará con el primero, por otro lado Linux funciona igual que BSD pero a igual ofsset se quedará con el que ha llegado el último. El IDS debe conocer como ensamblará los paquetes fragmentados el host para poder detectar posibles ataques.

Este hecho se puede aplicar también en paquetes fragmentados donde antes de tener el paquete completo, y por tanto todos los fragmentos, nos llega al menos dos paquetes con un “Not More Fragments” con distinto ofsset o tamaño. Solaris aceptará el último paquete que nos llegue con ese valor, en cambio otros sistemas operativos solo aceptarán el primero que llego. A este fenómeno se conoce como inclusión y evasión en los IDS. Tenéis una explicación más extensa en ésta entrada.


Así mismo, es importante conocer que servicios están corriendo en el servidor para indicar al IDS la existencia de dichos servicios y como debe procesar los paquetes relacionados con dicho servicio.

Por ejemplo, si nos encontramos con un FTP sabemos que por cada carácter introducido por el cliente, éste es enviado al servidor, por ello si se quiere detectar la autenticación del usuario “anonymous” hay que indicar al preprocesador que en cierto puerto hay un servicio tipo FTP o Telnet y que debe juntar el payload del TCP hasta que llegue el “salto de línea”, y ésa suma de caracteres corresponde a un comando, y en este caso, corresponderá al usuario introducido.

Otro ejemplo serían los punteros de los DNS, si nosotros tenemos un puntero de DNS y por tanto si en la zona de petición o respuesta de una consulta DNS detectamos que empieza por el valor hexadecimal “C” (los dos bits del nibble alto a 1), en vez de identificar con un valor de 63 o inferior los caracteres que vamos a leer a continuación, sabemos que se trata de un puntero. Si éste apunta a otro puntero el cual apunta al puntero anterior, estamos ante un bucle recursivo que podría generar una denegación de servicio del servidor DNS. Por ello el IDS debe  ser consciente de como tratar los datos el servicio para detectar un ataque de este tipo.

También es importante conocer exactamente que aplicación está corriendo en ese puerto, y no únicamente saber que en el puerto 80 corre un servidor Web, puesto que dependiendo del servidor Web este acepta una serie de codificaciones y las interpreta de forma distinta.

Para que se entienda el problema veremos un ejemplo que leí hace poco en Twitter donde se indicaba que “Nintendo.com” fue atacada por un path transversal. Los atacantes codificaron el “..” como “%252e%252e”, es decir que el “.” fue codificado como “%252e”, ¿y que es esto? Pues fue un double decoding de ASCII a hexadecimal, es decir, cuando pasamos un valor ASCII a hexadecimal se traduce con %XX donde X corresponde al valor hexadecimal del carácter. En este caso “.” es “%2e”. A continuación se vuelve a realizar esa conversión (por eso el double) del valor hexadecimal “%2e” de forma parcial (como fue el caso de Nintendo) o total. En el ejemplo que estamos viendo se paso de ASCII a Hexadecimal el carácter “%” cuyo valor era “%25” dando lugar al “%252e”. Un entrada más detallada sobre lo expuesto en este párrafo lo podéis leer aquí.

Por tanto es necesario configurar el IDS indicándole el sistema operativo y los servicios de los paquetes que leen las sondas. Para ello se debe disponer de una CMDB actualizada donde se aporte toda esta información, algo prácticamente imposible en entornos grandes. La otra posibilidad sería mediante reconocimiento activo de la red, lo que implicaría tener que abrir todos los puertos a cierto host o una serie de hosts, algo que va en contra de cualquier política de seguridad. Por ello la única solución viable es el reconocimiento mediante herramientas pasivas, que leyendo el trafico de red sean capaces de obtener dicha información.

Pero esto en la próxima entrada.



Continuar...

jueves, 5 de mayo de 2011

Preprocesador de Snort para la geolocalización

Antes de empezar pedir perdón por estar más 20 días sin publicar nada pero las certificaciones y el trabajo me impiden tener casi tiempo para el blog. Pero no me olvido de vosotros ni de la entrada de DNS prometida.

Ahora ya sí, en la siguiente entrada vamos a tratar la herramienta de seguridad Snort, la cual es una aplicación de detección de intrusos a nivel de red (IDS). Su función es leer el tráfico de red, normalizarlo, catalogarlo y analizarlo mediante un motor de reglas en busca de una serie de patrones en el tráfico que identifiquen un posible ataque; por tanto se trata de un IDS basado en firmas. Así, dada una amenaza previamente conocida se crea una firma que permita la detección del tráfico malintencionado. Es por ello que la herramienta no dispone de la capacidad de detectar anomalías en el tráfico que permitan identificar vulnerabilidades no conocidas o malware dirigido.

Veamos lo expuesto con anterioridad en el siguiente ejemplo: se realiza una conexión saliente desde el equipo del gerente hacia China empleando el protocolo cifrado SSL a las tres de la madrugada. Es posible que este hecho requiera la intervención del equipo de gestión de incidentes, aunque implique inicialmente la actuación del primer nivel, para comprobar el motivo de esta conexión. ¿Pero cómo alertamos de esta conexión? Snort lo único que ve es una conexión desde un equipo a un servidor de Internet que emplea el protocolo SSL, es decir, una navegación web con protocolo HTTPS. Un IDS basado en reglas no entiende ni conoce los siguientes puntos:


  • Geolocalización: todas las IPs de Internet son iguales para él, no entiende de países.
  • Horarios: para él una conexión a las 12:00 es lo mismo que a las 3:00.
  • Patrones de conexión: desconoce el comportamiento de la red y por tanto no puede detectar anomalías.

Ante esta situación el equipo de seguridad analiza cómo poder añadir estas funcionalidades al motor de Snort, permitiendo detectar amenazas como las expuestas con anterioridad. Así, se decide crear una serie de preprocesadores dinámicos empleando para ello el lenguaje de programación C y la API proporcionada por Snort. Cierto es que nos encontramos con el escollo de que la documentación es escasa, por lo que hay que recurrir al estudio del código fuente de la herramienta para comprender el funcionamiento de estos.

Dentro de estos preprocesadores quiero mostrarles el funcionamiento del preprocesador de geolocalización, el cual permite marcar el país de procedencia y destino de los paquetes que son tratados por Snort, permitiendo aplicar ciertas reglas dependiendo del origen o destino del país mediante los tag “CountryS” para el origen y “CountryD” para el destino.

Veamos un ejemplo para entender el comportamiento de este preprocesador. Para ello crearemos dos reglas de Snort, donde la primera, con identificador “10000001”, generará alerta si detecta paquetes ICMP hacia Rusia (codificado como RUS) y la segunda regla,“10000002”, detectará paquetes ICMP que vengan de Rusia:

# cat /etc/snort/rules/local.rules
alert icmp any any -> any any (msg:"Destino de Rusia";
countryD: RUS; sid:10000001; rev:2;)
alert icmp any any -> any any (msg:"Origen de Rusia"; countryS: RUS; sid:10000002; rev:2;)
#

Si se fijan, hemos indicado en la primera regla que genere alerta si el país destino es Rusia (countryD: RUS;) y en la segunda regla si el país origen es Rusia (countryS: RUS;). El siguiente paso consistirá en compilar nuestro preprocesador y tenerlo en el directorio de preprocesadores dinámicos indicados en el fichero de configuración de Snort:

# cd /usr/src/snort-2.9.0.1/src/dynamic-preprocessors/geolocalizacion/
# make clean
# make
# make install
# ls /usr/local/lib/snort_dynamicpreprocessor/ | grep geolocalizacion 

lib_sfdynamic_geolocalizacion.a
lib_sfdynamic_geolocalizacion.la
lib_sfdynamic_geolocalizacion.so
lib_sfdynamic_geolocalizacion.so.0
lib_sfdynamic_geolocalizacion.so.0.0.0
#


A continuación se debe incluir el preprocesador en el fichero de configuración de Snort para que sea cargado por éste en su arranque; tengan en cuenta que el orden de los preprocesadores importa, por lo que se recomienda que esté después de “frag3”. En nuestro caso vamos a indicar que queremos que únicamente marque aquellos paquetes con origen o destino de Rusia, China, Iraq y Irán (con el tag ALL marcaría todos los paquetes):

preprocessor Geolocalizacion: country RUS CHN IRN IRQ

De esta forma ya podremos ejecutar Snort con su preprocesador:

# /usr/local/bin/snort -A console -u snort -g snort -c /etc/snort/snort.conf -i eth0 
...
Configuración del preprocesador Geolocalizacion
Listado de paises: IRQ IRN CHN RUS
BBDD GeoIP cargada en memoria

...
+++++++++++++++++++++++++++++++++++++++++++++++++++
Initializing rule chains...
2 Snort rules read 
2 detection rules
0 decoder rules
0 preprocessor rules
2 Option Chains linked into 1 Chain Headers
0 Dynamic rules
+++++++++++++++++++++++++++++++++++++++++++++++++++
...
--== Initialization Complete ==--



,,_ -*> Snort! < *-
o" )~ Version 2.9.0.1 IPv6 (Build 82)
'''' By Martin Roesch & The Snort Team: http://www.snort.org/snort/snort-team
Copyright (C) 1998-2010 Sourcefire, Inc., et al.
Using libpcap version 1.1.1
Using PCRE version: 8.02 2010-03-19
Using ZLIB version: 1.2.3.4
Rules Engine: SF_SNORT_DETECTION_ENGINE Version 1.12 <Build 18>
Preprocessor Object: SF_SMTP (IPV6) Version 1.1 <Build 9>
Preprocessor Object: SF_FTPTELNET (IPV6) Version 1.2 <Build 13>
Preprocessor Object: SF_DNS (IPV6) Version 1.1 <Build 4>
Preprocessor Object: SF_SSLPP (IPV6) Version 1.1 <Build 4>
Preprocessor Object: SF_DCERPC2 (IPV6) Version 1.0 <Build 3>
Preprocessor Object: SF_SDF (IPV6) Version 1.1 <Build 1>
Preprocessor Object: Geolocalizacion Version 1.1 <Build 1> 
Preprocessor Object: SF_SSH (IPV6) Version 1.1 <Build 13>
Commencing packet processing (pid=17271)
#


Para finalizar vamos a comprobar que el preprocesador funciona correctamente, y para ello emplearemos Scapy o Hping3 para el envío de paquetes ICMP con IP’s orígenes falsificadas de distintos países hasta que finalmente enviamos una trama con IP rusa (62.5.128.1), generando así la alerta del paquete ICMP procedente de Rusia y seguidamente en del paquete ICMP de respuesta:

04/29-19:33:22.973577 [**] [1:10000002:2] Origen de Rusia [**] [Priority: 0] {ICMP} 62.5.128.1 -> 10.10.0.8
04/29-19:33:22.973648 [**] [1:10000001:2] Destino de Rusia [**] [Priority: 0] {ICMP} 10.10.0.8 -> 62.5.128.1


Como vemos, con preprocesadores de estas características podemos aportar lógica a Snort para detectar patrones anómalos que permitan descubrir posible malware dirigido, fugas de información y 0 days, permitiendo de esta forma que Snort no sea un simple IDS basado en la detección de patrones. Esperamos que les haya parecido interesante la entrada.

PD: entrada publicada también para securityartwork. 

Continuar...