Bastionado, seguridad en sistemas: Filtros BFP con Tcpdump 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

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.

1 comentario:

  1. Guapetón, mándame un correíto para hablar.

    Por cierto, me apunto el RSS, tiene buena pinta ^^

    ResponderEliminar