En numerosas ocasiones hemos visto como establecer filtros para nuestro capturador favorito ó sniffer tal como Wireshark, Tshark, Snort, Windump y Scapy. Como sigo recibiendo muchos mail con consultas sobre como establecer determinados filtros para diferentes cometidos, me animo a preparar este artículo de como crear filtros pcap para nuestro capturador de paquetes favorito desde lo más básico a lo más avanzado. Centralizando en un solo artículos todo lo que hemos estudiado sobre filtros y filtros avanzados. Y, como siempre, avanzando un poco más.
Actualización. Añadido filtro y explicación para captura datos SMTP.
Nos centraremos en el uso de los filtros / filtros avanzados y no en el uso y comandos de Windump (para los ejemplos)., ya que el prosposíto de este artículo es usar los filtros para cualquier capturador o sniffer basado en libpcap o winpcap.
Libpcap y BPF.
Es más complicado, pero de básicamente. Los filtros que vamos a comentar, están basados en la librería de funciones Libpcap, cuyos procesos se realizan a nivel de usuario. Los procesos de captura, sin embargo, se realizan e niveles más bajos, a nivel de Kernel. Los filtros establecidos mediante las librería libpcap los gestiona, intercediendo entre los dos nieveles comentados, BPF (BSD Packet Filter).
Primitivas y modificadores.
La sintaxis que conforma un filtro está compuesta de primitivas y modificadores. Las primitivas son datos, que pueden ser un número, o un nombre que está precedido un uno o más modificadores.
Modificadores.
Los mpodificadores los podemos dividir en tres tipos. modificadores de tipo, de dirección y de protocolo.
Modificadores de tipo.
- host que especifica una máquina
- net se refiere a una red
- port refierido a puertos
Como ejemplos de host podenos establecer host 192.168.1.5 ó host midominio.com
Net puede ser net 192.168.1.0 ó 192.168.1.0/24 ó net 192.168. También se puede indicar una mascara: net 192.168.1.0 mask 255.255.0.0
Con port indicamos un puerto: port 24 ó port 443 ó también podemos indicar de esta forma:
dst port http para puerto destino 80
dst port imap para puerto destino 143
Modificadores de dirección.
- scr espcifica la dirección del flujo de tráfico que se va a tener en cuenta. En esta caso scr indica origen del flujo.
- dst espcifica la dirección del flujo de tráfico que se va a tener en cuenta. En esta caso dst indica destino del flujo del flujo.
Por ejemplo, con dst host 192.168.1.1 establecemos un filtro para capturar el tráfico con destino al host 192.168.1.1. con scr port 25 establecemos un filtro para capturar todo el flujo de paquetes cuyo orgen es el puerto 25.
Modificadores de protocolo.
Indicamos el protocolo del flujo o trafico a capturar. Puede ser IP, ICMP, UDP, TCP, arp, etc.
Por ejemplo: proto \udp ó proto \tcp
Primitivas especiales.
Tenemos, además, una serie de primitivas especiales que son:
- gateway nombre-equipo
- broadcast referido al tráfico broadcast
- less tamaño_bytes para especificar si el tamaño del paquete es menor que el indicado
- greater tamaño_bytes para especificar si el tamaño del paquete es mayor que el indicado
Otras primitivas. Banderas TCP.
Otras primitivas pueden ser: tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack,
tcp-urg. Ejemplos:
En el siguiente ejemplo capturamos los paquetes tcp con origen y destino puerto 80 y con el flag TCP SYN activado. (Quitamos de las opciones el -q para deshabilitar la salida rápida y obervar la notación S que indica SYN).
NOTA: Para ilustrar estas primitivas usaré los operadores lógicos que explico un poco más abajo.
Vamos con los ejemplos:
windump -i1 -tn tcp and port 80 and «tcp[tcpflags] & tcp-syn !=0»
IP 192.168.1.5.9163 > 209.85.229.147.80: S 3039346897:3039346897(0) win 64512
ss 1460,nop,nop,sackOK>
IP 209.85.229.147.80 > 192.168.1.5.9163: S 233934048:233934048(0) ack 3039346898
win 16384
IP 192.168.1.5.9165 > 209.85.227.99.80: S 3343761330:3343761330(0) win 64512
s 1460,nop,nop,sackOK>
IP 209.85.227.99.80 > 192.168.1.5.9165: S 2556988707:2556988707(0) ack 334376133
1 win 16384
Capturamos ahora SYN-ACK:
windump -i1 -tn tcp and port 80 and «tcp[tcpflags] & (tcp-syn|tcp-ack) ==
(tcp-syn|tcp-ack)»
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
IP 209.85.229.105.80 > 192.168.1.5.9177: S 2072283203:2072283203(0) ack 37790426
24 win 16384
IP 209.85.229.102.80 > 192.168.1.5.9179: S 2500730366:2500730366(0) ack 1387012
win 16384
Push activado:
windump -i1 -tn tcp and port 80 and «tcp[tcpflags] & tcp-push == tcp-push»
IP 192.168.1.5.9181 > 209.85.229.106.80: P 2359059300:2359059982(682) ack 115692
6173 win 64512
IP 209.85.229.106.80 > 192.168.1.5.9181: P 1:267(266) ack 682 win 64853
IP 209.85.229.106.80 > 192.168.1.5.9181: P 267:544(277) ack 682 win 64853
IP 192.168.1.5.9183 > 209.85.229.106.80: P 4285501829:4285502505(676) ack 126691
8661 win 64512
IP 209.85.229.106.80 > 192.168.1.5.9183: P 1:225(224) ack 676 win 64859
IP 209.85.229.106.80 > 192.168.1.5.9183: P 1685:2048(363) ack 676 win 64859
IP 209.85.229.106.80 > 192.168.1.5.9183: P 2048:3037(989) ack 676 win 64859
Combinación de expresiones. Operadores lógicos. Agrupación.
Los filtros o expresiones pueden ser combinadas de las siguientes formas:
- Negación ! ó not
- Concatenación && ó and
- Alternativa || ó or
Ejemplos:
host 192.168.1.5 and host 192.168.1.45
host user01 && host user03
host 192.168.1.5 && !host 192.168.1.56
host user02 or host user56
host 192.168.5 and port 80 and !host 192.168.1.245
host 192.168.1.5 and !port 80
Podemos agrupar las expresines con paréntesis:
tcp and (dst port 80 or dst port 143) con lo que filtramos para que solo nos aparezca el tráfico tcp con destino al puerto 80 o destino puerto 143:
IP 192.168.1.5.6883 > 67.15.36.37.80: tcp 1294
IP 192.168.1.5.6879 > 72.233.113.162.80: tcp 0
IP 192.168.1.5.6879 > 72.233.113.162.80: tcp 0
IP 192.168.1.5.6879 > 72.233.113.162.80: tcp 0
IP 192.168.1.5.6879 > 72.233.113.162.80: tcp 0
IP 192.168.1.5.6883 > 67.15.36.37.80: tcp 0
IP 192.168.1.5.6883 > 67.15.36.37.80: tcp 0
IP 192.168.1.5.6879 > 72.233.113.162.80: tcp 0
IP 192.168.1.5.6889 > 192.168.2.41.143: tcp 0
IP 192.168.1.5.6889 > 192.168.2.41.143: tcp 0
IP 192.168.1.5.6889 > 192.168.2.41.143: tcp 20
IP 192.168.1.5.6889 > 192.168.2.41.143: tcp 18
IP 192.168.1.5.6889 > 192.168.2.41.143: tcp 124
IP 192.168.1.5.6889 > 192.168.2.41.143: tcp 198
Ejemplos com primitivas y modificadores.
- Capturamos el tráfico con destino u origen MAC 00:04:75:ED:89:DF
windump -i1 -qtn ether dst 00:04:75:ED:89:DF
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
IP 192.168.1.245.53 > 192.168.1.5.64878: UDP, length 183
IP 192.168.1.245.53 > 192.168.1.5.32780: UDP, length 148
IP 209.85.229.103.80 > 192.168.1.5.7603: tcp 0
IP 192.168.1.245.53 > 192.168.1.5.58703: UDP, length 153
IP 192.168.1.245.53 > 192.168.1.5.35411: UDP, length 151
IP 192.168.1.245.53 > 192.168.1.5.12444: UDP, length 136
IP 192.168.1.245.53 > 192.168.1.5.62124: UDP, length 55
24 packets captured
77 packets received by filter
0 packets dropped by kernel
windump -i1 -qtn ether src 00:04:75:ED:89:DF
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
IP 192.168.1.5.7603 > 209.85.229.103.80: tcp 682
IP 192.168.1.5.7603 > 209.85.229.103.80: tcp 0
IP 192.168.1.5.7605 > 209.85.229.103.80: tcp 676
IP 192.168.1.5.7605 > 209.85.229.103.80: tcp 0
IP 192.168.1.5.7603 > 209.85.229.103.80: tcp 0
IP 192.168.1.5.22178 > 192.168.1.245.53: UDP, length 36
IP 192.168.1.5.7605 > 209.85.229.103.80: tcp 0
Errores al usar ether. Mejor con un ejemplo:
windump -i1 -qtn ether host 192.168.1.5
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
windump: illegal link layer address
windump -i1 -qtn ether host 00:04:75:ED:89:DF
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
IP 192.168.1.5.17963 > 192.168.1.245.53: UDP, length 42
IP 192.168.1.5.8600 > 209.85.227.147.80: tcp 0
IP 192.168.1.245.53 > 192.168.1.5.17963: UDP, length 183
IP 209.85.227.147.80 > 192.168.1.5.8600: tcp 0
windump -i1 -qtn host 00:04:75:ED:89:DF
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
windump: ethernet address used in non-ether expression
- Capturamos los paquetes dirigidos a las direcciones de broadcast y multicast:
windump -i1 -qtn broadcast
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
arp who-has 192.168.1.201 tell 192.168.1.250
arp who-has 192.168.1.10 tell 192.168.1.245
arp who-has 192.168.1.29 tell 192.168.1.245
IP 192.168.2.3.137 > 192.168.2.255.137: UDP, length 50
02:01:00:00:00:00 > ff:ff:ff:ff:ff:ff, Unknown Ethertype (0x886f), length 66:
IP 192.168.1.136.138 > 192.168.1.255.138: UDP, length 209
IP 192.168.2.2.137 > 192.168.2.255.137: UDP, length 50
C:\wd>windump -i1 -qtn multicast
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
IP 192.168.1.36.138 > 192.168.1.255.138: UDP, length 201
02:01:00:00:00:00 > ff:ff:ff:ff:ff:ff, Unknown Ethertype (0x886f), length 66:
windump -i1 -qtn ip multicast
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
IP 192.168.1.1 > 224.0.0.1: igmp
IP 192.168.1.89 > 224.0.0.2: igmp
IP 192.168.1.136 > 239.255.255.250: igmp
IP 192.168.1.202 > 224.0.1.60: igmp
- Capturamos paquetes dependiendo del protocolo:
windump -i1 -qtn arp
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
arp who-has 192.168.1.36 tell 192.168.1.239
arp who-has 192.168.1.55 tell 192.168.1.239
windump -i1 -qtn tcp
windump: listening on \Device\NPF_{024A36DD-4864-4F08-918F-2C5CBA916541}
IP 192.168.1.5.7924 > 72.233.113.162.80: tcp 0
IP 72.233.113.162.80 > 192.168.1.5.7924: tcp 0
IP 192.168.1.5.7924 > 72.233.113.162.80: tcp 0
- A continuación una tabla con algunos ejemplos más que ya vimos en el artículo dedicado a los Filtros de captura y visualización en Wireshark:
Filtros basados en hosts
|
|
---|---|
Sintaxis | Significado |
host host | Filtrar por host |
src host host | Capturar por host origen |
dst host host | Capturar por host destino |
Ejemplos | |
host 192.168.1.20 | Captura todos los paquetes con origen y destino 192.168.1.20 |
src host 192.168.1.1 | Captura todos los paquetes con origen en host 192.1681.1 |
dst host 192.168.1.1 | Captura todos los paquetes con destino en host 192.168.1.1 |
dst host SERVER-1 | Captura todos los paquetes con destino en host SERVER-1 |
host http://www.terra.com | Captura todos los paquetes con origen y distino http://www.terra.com |
Filtros basados en puertos
|
|
Sintaxis | Significado |
port port
|
Captura todos los paquetes con puerto origen y destino port
|
src port port
|
Captura todos los paquetes con puerto origen port
|
dst port port
|
Captura todos los paquetes con puerto destino port
|
not port port
|
Captura todos los paquetes excepto origen y destino puerto port
|
not port port and not port port1
|
Captura todos los paquetes excepto origen y destino puertos port y port1
|
Ejemplos | |
port 21
|
Captura todos los paquetes con puerto origen y destino 21
|
src port 21
|
Captura todos los paquetes con puerto origen 21
|
not port 21 and not port 80
|
Captura todos los paquetes excepto origen y destino puertos 21 y 80
|
portrange 1-1024
|
Captura todos los paquetes con puerto origen y destino en un rango de puertos 1 a 1024
|
dst portrange 1-1024 | Captura todos los paquetes con puerto destino en un rango de puertos 1 a 1024 |
Filtros basados en protocolos Ethernet / IP
|
|
Ejemplos | |
ip | Captura todo el trafico IP |
ip proto \tcp | Captura todos los segmentos TCP |
ether proto \ip | Captura todo el trafico IP |
ip proto \arp | Captura todo el trafico ARP |
Filtros basados en red
|
|
Sintaxis | Significado |
net net | Captura todo el trafico con origen y destino red net |
dst net net | Captura todo el trafico con destino red net |
src net net | Captura todo el trafico con origen red net |
Ejemplos
|
|
net 192.168.1.0 | Captura todo el trafico con origen y destino subred 1.0 |
net 192.168.1.0/24 | Captura todo el trafico para la subred 1.0 mascara 255.0 |
dst net 192.168.2.0 | Captura todo el trafico con destino para la subred 2.0 |
net 192.168.2.0 and port 21 |
Captura todo el trafico origen y destibo puerto 21 en subred 2.0 |
broadcast | Captura solo el trafico broadcast |
not broadcast and not multicast |
Captura todo el trafico excepto el broadcast y el multicast |
.
Filtros Avanzados.
El formato genérico para crear un filtro avanzado es el siguiete:
expresión relación expresión
relación puede ser >,= <=, = y !=
expresión puede ser el protocolo, una expresión aritmética, operadores binarios, palabra reservada, etc,
De esta manera, si estudiamos el filtro siguiente:
windump icmp[0] = 8
- vemos que la expresión es la palabra reservada icmp (protocolo) junto a un valor 0
- la relación que es = y otra expresión cuyo valor es 8
Además. Podemos especificar el tamaño de lo datos.Para ello tenemos la siguiente sintaxis:
[expresión:tamaño]
De esta manera, si estudiamos el filtro siguiente:
windump udp[0:2] < 1024
- vemos que la expresión es la palabra reservada udp (protocolo) junto a un valor 0:2
- la relación que es = y otra expresión cuyo valor es1024
Que significa este filtro udp[0:2] < 1024:
[0:2] Esto significa que se sitúe en el comienzo del octeto 0 o primer octeto de la cabecera udp y a partir de ahí lea 2 octeos, es decir, que lea el campo de «Puerto de origen». < 1024 y que ese puerto de origen sea menor que 1024.
Es decir que la notación [x:y] significa: x es el octeto ó byte de comienzo y significa: «leer» y bytes a partir del byte x. Si sólo aparece [x] es lo mismo que decir [x:1], es decir leer sólo el byte x. Esto lo hace TCPDump por defecto.
Estos dos octetos serían, según el gráfico de más abajo, los bits 0 al 15.
Si queremos establecer un filtro para que nos muestre solo los paquetes cuyo puerto de destino sea mayor que 4000:
windump «udp[2:2] > 4000″
Como veis es bastante sencillo y solo hay que tener en cuenta y saber «leer» las cabeceras de los protocolos.
Seguimos. Vamos a analizar ahor el filtro tcp[13] = 2
Vamos a echarle un ojo al octeto 13 y simulemos que el flag SYN está activo, pero antes, recordemos el Formato de la cabecera del TCP.
¿Qué significa realmente tcp[13] = 2?
En el flag SYN, que es utilizado para la sincronización de los números de la secuencia tendremos:
….U A P R S F
——————
0 0 0 0 0 0 1 0 (en binario)
——————
7 6 5 4 3 2 1 0
vemos que el byte 7 y 6 están reservados, el 5 es para URGENT, el 4 es para ACK, el 3 es para PUSH, el 2 es para RESET y el byte 0 para FIN. Tenemos entonces el octeto completo.
En binario quedaría como acabamos de ver: 0 0 0 0 0 0 1 0, que pasado a base decimal, vemos que es el 2, de ahí viene tcp[13] = 2.
Es fácil deducir entonces que para detectar un SYN/ACK: 0 0 0 1 0 0 1 0, el 18 en base decimal, entonces tcp[13] = 18.
Ya sabemos que significa cada uno de los valores. Vamos entonces a averiguar de dónde sacamos el 13 de la expresión tcp[13] = 2.
Vamos a analizar la cabecera TCP del gráfico anterior por filas:
- puerto origen = 2 bytes u octetos o 16 bits
- puerto destino = 2 bytes u octetos. La cuenta siempre empieza por el 0, con lo cual los octetos van del 0 al 3
- número secuencia = 4 bytes u octetos, es decir del 4 al 7
- número acuse recibo = 4 bytes u octetos del 8 al 11
OJO: Tenemos doce octetos (0,1, …11) Hemos de tener en cuenta que se empieza a contar desde cero, es decir, el primer byte es el octeto 0.
El siguiente octeto es el 12 (el décimo tercero) va desde el bits 0 al 7 que corresponden a la posición de datos u offset (4 bits) y a Reservado (4+2); dos bits de Reservado pertenecen ya al siguiente octeto el 13, que tiene los 2 bits reservados anteriores y 6 que son los flags (UAPRSF). 6 + 2 = 8 bits que es el octeto o byte 13 (o décimo cuarto).
Vamos a analizar ahora de donde viene el valor 2 de la expresión tcp[13] = 2
Esta es la representación de octeto ó byte 13. Si ponemos el flag SYN activado y el resto NO activados, resulta que SYN lo ponemos a 1 y el resto a 0:
Queda entonces: 0 0 0 0 0 0 1 0 (los dos primeros bits dijimos que eran reservados y siempre están a 0)
….U A P R S F
——————
0 0 0 0 0 0 1 0 (en binario)
——————
7 6 5 4 3 2 1 0
Si pasamos este número (0 0 0 0 0 0 1 0 ), que es binario, a decimal nos queda el número decimal 2 (2 elevado a 1), que es el valor que debemos de introducir para que la expresión quede así:
tcp[13] = 2
Esto le dice a Windump o TCPDump que busque en la cabecera TCP el valor 2 que se encuentra en el byte u octeto 13. Y ya sabemos que corresponde al flag SYN activado (y los otros flags/banderas estarán desactivados).
Seguimos avanzando.
Expresiones en formato Hexadecimal.
Para especificar una dirección IP, TCPdump / Windump, etc trabaja mejor con el formato hexadecimal.
Para una dirección 192.168.1.5, su equivalente en hexadecimal sería:
- 192 > C0
- 168 > A8
- 1 > 01
- 5 > 05
es decir:C0A80405
Para windump añadimos el indicativo de que se trata de formato hexadecimal: 0x
y nos quedaría: 0xC0A80105
Apliquemos esto a nuestros ejemplos de filtros y a lo ya estudiado:
Datagramas IP cuyo IP de origen sea 0xC0A80105 o 192.168.1.5
windump -i1 -qtn «ip[12:4] = 0xC0A80105»
IP 192.168.1.5.26495 > 192.168.1.245.53: UDP, length 30
IP 192.168.1.5.5879 > 192.168.1.245.53: UDP, length 31
IP 192.168.1.5.12565 > 209.85.229.99.80: tcp 0
IP 192.168.1.5.12565 > 209.85.229.99.80: tcp 0
IP 192.168.1.5.12565 > 209.85.229.99.80: tcp 621
IP 192.168.1.5.12565 > 209.85.229.99.80: tcp 0
IP 192.168.1.5.12565 > 209.85.229.99.80: tcp 0
IP 192.168.1.5.12565 > 209.85.229.99.80: tcp 0
IP 192.168.1.5.12567 > 209.85.229.102.80: tcp 0
IP 192.168.1.5.12567 > 209.85.229.102.80: tcp 0
IP 192.168.1.5.12567 > 209.85.229.102.80: tcp 640
Datagramas IP cuyo IP de origen sea mayor que 192.168.1.5
windump -i1 -qtn «ip[12:4] > 0xC0A80105″
IP 192.168.1.200 > 224.0.0.251: igmp
IP 192.168.1.11 > 239.255.255.250: igmp
IP 192.168.1.202 > 224.0.0.251: igmp
IP 192.168.1.201 > 224.0.1.60: igmp
IP 209.85.229.99.80 > 192.168.1.5.12565: tcp 0
IP 209.85.229.99.80 > 192.168.1.5.12565: tcp 0
Datagramas Ip cuyo valor TTL sea mayor que 5
windump -i1 -qnt «ip[8]> 5″
IP 192.168.1.239.138 > 192.168.1.255.138: UDP, length 201
IP 192.168.1.30.138 > 192.168.1.255.138: UDP, length 201
Creación de máscaras para filtros.
Ocurre que en ocasiones nos encontramos con un byte que está dividido en dos partes, es decir, en dos campos de 4 bits cada uno.
Todo lo comentado anteriormente referente a filtros para extraer datos de las cabeceras, sólo es válido para un byte completo. Así que nos encontraremos con un problema cuando tengamos que descartar en un byte una parte de éste.
Lo vemos con un ejemplo:
Observemos el primer byte (8 bits primeros) de una cabecera IP.
Vemos que consta de dos partes:
|
Entonces queremos descartar los 4 bits de la versión IP y filtrar el tamaño del encabezamiento. ¿Cómo hacemos esto?.
La respuesta está en la creación de máscaras. Es decir, enmascarar unos bits para dejar «ver» el resto, y estas máscaras la hacemos usando operaciones booleanas.
Lo vemos, como siempre, con un ejemplo:
Nos centramos en el primer byte de un encabezamiento IP. Tenemos los grupos de 4 bits. Vamos a explicar esto usando la misma técnica que en capítulos anteriores.
Dado que la versión de IP actualmente es la 4 y el tamaño del encabecamiento es 20 bytes … vaya, pero ¿cómo puede ser que tenga 20 bytes? si los bits destinados a este campo son sólo 4. La razón está en que la medida de este campo se hace representándolo en palabras de 32 bits, o sea, en 4 bytes. Así que el valor real almacenado es de 5. Este 5 lo multiplicamos por 4 bytes y nos dá como resultado 20 bytes.
Representamos en binario abajo los dos valores; el 4 de la versión y el 5 del tamaño (con una calculadora podemos ver su valor en binario).
Versión IP Tamaño encabezamiento IP
0 1 0 0 0 1 0 1 (101: «4»)
como queremos descartar la versión IP, vamos a realizar una operación booleana. Esta operación es un AND con 0 0 0 0 1 1 1 1
0 1 0 0 0 1 0 1
0 0 0 0 1 1 1 1
0 0 0 0 0 1 0 1
Razonemos este resultado. Si recordamos las operaciones booleanas:
0 AND 0 = 0
1 AND 0 = 0
1 AND 1 = 1
0 AND 1 = 0
Sólo en el caso de que los dos bits estén a 1 el resultado será 1.
Esta es la técnica que usa TCPdump / Windump para enmascarar bits. Pero ¿cómo traducimos esto a un filtro?
Recordemos que para crear un filtro de extración de datos de una cabecera se usa la expresión proto[x:y] = valor. En general, como hemos visto más arriba, expresión relación expresión. Hemos visto también filtros como este:
tcp[13] = 2 and port 110
expresión: tcp[13]
relación: =
expresión: 2
pues bien, como ahora hablamos de encabezamiento IP y el primer byte, el filtro sería de esta forma:
expresión: ip[0]
Vamos ahora con el resto de la expresión. Como realizamos una operación boolena de AND (&):
expresión: ip[0] &
como el valor binario, la máscara que vamos a aplicar es 0000 1111 en hexadecimal es 0F e indicamos que es un valor hexadecimal con el valor 0x, entonces:
expresión: ip[0] & 0x0F
y ahora la relación. Vamos a filtrar los valores de longitud de encabecamiento IP mayores que 5:
expresión: ip[0] & 0x0F > 5
Este filtro sería un caso de comportamiento anormal. Para probrarlo usaremos otro valor:
expresión: ip[0] & 0x0F = 5
que sería el normal en una cabecera IP sin datos. Lo probamos:
windump -qn «ip[0] & 0x0f = 5»
windump: listening on \Device\NPF_{604C8AE3-5FAC-45A5-BFAA-81175A8C32BF}
18:40:02.766513 IP 192.168.4.15.8080 > 192.168.4.5.4261: tcp 1460
18:40:02.876720 IP 192.168.4.5.4261 > 192.168.4.15.8080: tcp 0 (DF)
18:40:02.891493 IP 192.168.2.70.1025 > 192.168.2.60.139: tcp 88 (DF)
18:40:02.891720 IP 192.168.2.60.139 > 192.168.2.70.1025: tcp 80 (DF)
18:40:02.896319 IP 192.168.2.70.1025 > 192.168.2.60.139: tcp 176 (DF)
18:40:02.896540 IP 192.168.2.60.139 > 192.168.2.70.1025: tcp 39 (DF)
18:40:02.901594 IP 192.168.4.15.8080 > 192.168.4.5.4261: tcp 1140
18:40:02.946950 IP 192.168.2.70.1025 > 192.168.2.60.139: tcp 64 (DF)
18:40:02.947377 IP 192.168.2.60.139 > 192.168.2.70.1025: tcp 1460 (DF)
18:40:02.947442 IP 192.168.2.60.139 > 192.168.2.70.1025: tcp 1460 (DF)
18:40:02.947543 IP 192.168.2.60.139 > 192.168.2.70.1025: tcp 1240 (DF)
18:40:02.947620 IP 192.168.2.70.1025 > 192.168.2.60.139: tcp 0 (DF)
18:40:03.010696 IP 192.168.4.15.8080 > 192.168.4.5.4227: tcp 190
18:40:03.069269 IP 192.168.2.70.1025 > 192.168.2.60.139: tcp 0 (DF)
Es un tanto difícil de comprender el enmascaramiento pero lo vemos con otro ejemplo práctico.
Acabo de crear un filtro para TCP lo ejecuto y me da como respuesta:
windump -qn «tcp[13] & 0x02 != 0»
windump: listening on \Device\NPF_{604C8AE3-5FAC-45A5-BFAA-81175A8C32BF}
18:58:52.992949 IP 192.168.4.5.4483 > 192.168.4.15.8080: tcp 0 (DF)
18:58:52.993085 IP 192.168.4.15.8080 > 192.168.4.5.4483: tcp 0
18:58:55.909550 IP 192.168.2.5.3028 > 192.168.4.15.110: tcp 0 (DF)
18:58:55.909650 IP 192.168.2.5.3028 > 192.168.4.15.110: tcp 0 (DF)
18:58:55.909777 IP 192.168.4.15.110 > 192.168.2.5.3028: tcp 0
18:58:55.909879 IP 192.168.4.15.110 > 192.168.2.5.3028: tcp 0
18:58:56.130273 IP 192.168.2.5.3029 > 192.168.4.15.110: tcp 0 (DF)
18:58:56.130343 IP 192.168.2.5.3029 > 192.168.4.15.110: tcp 0 (DF)
18:58:56.130483 IP 192.168.4.15.110 > 192.168.2.5.3029: tcp 0
18:58:56.130560 IP 192.168.4.15.110 > 192.168.2.5.3029: tcp 0
18:58:56.348314 IP 192.168.2.5.3030 > 192.168.4.15.110: tcp 0 (DF)
18:58:56.348379 IP 192.168.2.5.3030 > 192.168.4.15.110: tcp 0 (DF)
18:58:56.348522 IP 192.168.4.15.110 > 192.168.2.5.3030: tcp 0
18:58:56.348598 IP 192.168.4.15.110 > 192.168.2.5.3030: tcp 0
18:58:58.003782 IP 192.168.4.5.4485 > 192.168.4.15.8080: tcp 0 (DF)
18:58:58.003924 IP 192.168.4.15.8080 > 192.168.4.5.4485: tcp 0
18:58:58.008186 IP 192.168.4.5.4487 > 192.168.4.15.8080: tcp 0 (DF)
El filtro aplicado a la captura anterior es «tcp[13] & 0x02 != 0»
Como ya sabemos de donde viene la expresión tcp[13], lo hemos visto más arriba, seguimos con el resto. Vemos en la expresión que realizamos una operación booleana de tipo AND (&) y que la expresión 02 está expresada en hexadecimal (0x). El valor binario de la expresión 02 es 10. Si miramos el cuadro anterior:
U A P R S F
——————
0 0 0 0 0 0 1 0 (en binario)
——————
7 6 5 4 3 2 1 0
Vemos que se trata de la activación del flag SYN. Seguimos con el filtro y vemos que además tiene != 0, es decir, que sea distinto de 0. Realicemos la operación de enmascaramiento.
0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0
Según esto, si aplicamos la máscara 0x02, el resultado es 0, pero si nos dá como resultado algo distinto de 0 entonces no estaría activado el flag SYN.
Este filtro es por tanto para detectar el flag SYN activado en una conexión TCP. Es decir es el mismo filtro que el siguiente ejemplo que ejmplo que vimos más arriba: «tcp[13] = 2»
Ambos filtros son lo mismo. Nos devuelven el mismo resultado. Es decir «tcp[13] = 2» y «tcp[13] & 0x02 != 0» son lo mismo.
Otras formas de creación de filtros
Observemos nuevamente la cabecera IP.
Y esta captura de un datagrama IP:
Observamos (reseñado con círculo rojo) que en la posición del byte 9 y con longitud de 1 byte tenemos la identificación del protocolo, en este caso 06 (tcp). De esta manera el filtro quedaría:
windump -qtn -X -s 0 ip[9:1] = 6
ó
windump -qtn -X -s 0 ip[9] = 6
NOTA: se elimina el :1 al ser de longitud 1 byte
De esta forma y siguiendo la misma técnica, para filtrar por el protocolo UDP:
windump -qtn -X -s 0 ip[9:1] = 17
también:
windump -qtn -X -s 0 ip[9:1] & 0x11 != 0
Esta última notacion de debe al uso de máscaras que ya hemos estudiado en capítulos anteriores. Veámoslo:
0x11 es la notación hexadecimal del binario 00010001 y decimal 17. Sabemos que la longitud del campo protocolo es de 1 byte, es decir 8 bites. Así pues la notación quiere decir:
Filtrar según si en la posición ip[9:1] con mascara 00010001 es distinto de 0 ó no activo.
Si quisieramos filtrar por el protocolo tcp, la mascara sería 00000110 al ser el tipo 6 o hexadecimal 0x06. El tipo de protocolo nos lo dice las RFCs.
Otro ejemplo.
Según el mismo datagrama la dirección IP de destino se situa
en el byte 16 y tiene una longitud de 32 bits ó 4 bytes. Si queremos
filtrar por dirección de destino 192.168.1.3 el filtro quedaría:
windump -qtn -X -s 0 ip[16:4] = 0xc0a80103
NOTA: ponemos 0x antes para indicar que es una notación hexadecimal.
el dato de IP destino lo sacamos de (0x0010 c0a8 0103) del datagrama.
Seguimos. Para filtrar por número de secuencia en un segmento TCP vemos que:
El número se secuencia se situa en el octeto o byte 4 y tiene una longitud
de 4 bytes. El filtro quedaría:
tcp[4:4]
Vamos a analizar ahora icmp con windump:
NOTA: He marcado de color desde el comienzo de la cabecera icmp y lo que nos interesa.
ICMP se transmiten como datagramas de IP con una cabecera normal de IP, con el campo IP de Protocolo con el valor 1.
El campo que determina dentro de icmp el tipo de que se trata tiene una longitud de 8 bits ó 1 byte situado al comienzo. En las trazas del ejemplo tenemos un echo request y un echo reply con valores 08 en el primero y 00 en el segundo.
De esta forma para filtrar los icmp de tipo echo request pondríamos:
windump -qtn -X -i2 -s 0 icmp[0:1] = 08
Como nota informativa: Algunos tipos de icmp que nos servirán parala creación de nuestros filtros icmp:
- 0 Respuesta de ECO
- 3 Destino inaccesible
- 4 Disminución de origen (source quench –
- datagrama eliminado por congestión)
- 5 Redireccionar (cambiar una ruta)
- 8 Solicitud de ECO
- 11 Tiempo excedido para un datagrama
- 12 Problema de parámetros de un datagrama
- 13 Solicitud de TIMESTAMP
- 14 Respuesta de TIMESTAMP
- 15 Solicitud de Información (obsoleto)
- 16 Respuesta de Información (obsoleto)
- 17 Solicitud de Máscara de dirección
- 18 Respuesta de máscara de dirección
Mas filtros.
Complicamos un poco más ya que algunos de anteriores filtros pueden ser obviados debido a que windump/tcpdump tienen, como hemos visto al principio, una serie de primitivas para ciertos filtros:
windump -qtn tcp
para que solo filtrar por el protocolo tcp
windump -qtn tcp
igualmente para filtrar por el protocolo udp
Sin embargo sacar información de otros campos del datagrama IP o de segmentos TCP, etc. es más complicado al no proveer la herramienta de las primitivas necesarias. Veamos un ejemplo:
Filtrar los paquetes quetengan el bit de no Fragmentar (DF):
windump -qtn «ip[6] & 64 != 0»
Vamos a explicarlo.
ip[6] & 64 es lo mismo que ip[6] & 0x40 la mascara sería 01000000.
Sabemos que el primer bit que compone los tres que forman el campo Flag de IP es siempre 0, los otros dos son DF y MF de verificación que el datagrama llega a su destino.
El resto forma parte del siguiente campo de 13 bits que forman el Fragment Offset. Como las máscaras las aplicamos como octetos o conjuntos de 8 bits, para saber si el bit de DF está activado la
máscara sería 01000000 (el segundo bit activado). Para saber si el activado es el MF entonces la máscara sería 00100000.
Para filtrar por el bit activado de MF sería:
windump -qtn «ip[6] & 32 != 0»
ó
windump -qtn «ip[6] & 0x20 != 0» (hexadecimal)
Veámoslo en la práctica:
windump -qtn «ip[6] & 32 != 0»
windump: listening on\Device\Packet_{52BFAEB8-D80F-4700-AC56-9C97BC7083B5}
10.164.138.11 > 192.168.1.33: icmp: echo request (frag 34819:552@0+)
10.209.1.224.16 > 192.168.1.33.2222: FP 1585299871:1585301027(1156) ack 39..276 win 8460 (frag 93…@0+)
10.193.250.165 > 192.168.1.33: icmp: echo request (frag 45828:552@0+)
10.193.250.165 > 192.168.1.33: icmp: echo request (frag 3333:552@0+)
Aplicando los filtros a la realidad
Bien, es el momento de aplicar todo lo que hemos aprendido a la realidad. Vamos, pues, a situarnos en una serie de escenarios para filtrar según nuestras necesidades. Algunos ya los hemos visto en ejemplos anteriores, nos servirá como chuleta. Estos filtros, como ya hemos comentados son validos para Wireshark, Tshark, Snort, etc,.
Establecer un filtro para la función sniffer de Snort sería tan facil como esto:
snort -v «tcp[13] & 64 != 0»
Otros ejemplo de filtros. Entre todos iremos porponiendo filtros:
Mostrar todos paquetes con el flag URG activado:
windump «tcp[13] & 32 != 0»
Mostrar todos paquetes con el flag ACK activado:
windump «tcp[13] & 16 != 0»
Mostrar todos paquetes con el flag PSH activado:
windump «tcp[13] & 8 != 0»
Mostrar todos paquetes con el flag RST activado:
windump «tcp[13] & 4 != 0»
Mostrar todos paquetes con el flagll SYN activado:
windump «tcp[13] & 2 != 0»
Mostrar todos paquetes con el flag FIN activado:
windump «tcp[13] & 1 != 0»
Mostrar todos paquetes con el flag SYN-ACK activado:
windump «tcp[13] = 18»
ICMP petición y respuesta de Echo. Echo Request y Echo Reply: windump «(icmp[0:1]=0)» or «(icmp[0:1]=8)»
Filtro por campo TTL. windump ip and «ip[8]<2"
Filtro por campo TOS. windump ip and «ip[1]!=0»
Ping de la muerte. Ping of Death. windump icmp and «((ip[2:2]-((ip[0:1]&0x0f)*4)+((ip[6:2]&0x1fff)*8))>65535)»
Ataque Smurf. windump «(ip[19]=0xff)» or «(ip[19]=0x00)»
Filtrar por tamaño del paquete (Length). windump ip and «(ip[2:2]<60)" (si es menor de 60)
Otra forma de captura banderas tcp (flags) SYN+ACK. windump «tcp[tcpflags] & (tcp-syn|tcp-ack) ==(tcp-syn|tcp-ack)»
Puch activado. windump «tcp[tcpflags] & tcp-push == tcp-push»
Capturando datos diálogo smtp.
Para ello establecemos el siguiente filtro que ahora explicaremos:
tcp[20:4] = 0x4D41494C
Cuando capturamos el paquete completo:
.
Obeservamos que:
- la cabecera TCP está marcada con azul.
- La zona de datos correspondiente a SMTP en amarillo
- los datos que necesitamos están enmarcados en rojo.
El dato que buscamos en nuestra captura corresponde al comando SMTP MAIL, bueno, en realidad el comando es MAIL FROM, pero con MAIL nos basta.
Establecemos el filtro tcp[], contamos los bits que son empezando en 0, serían 20, ponemos entonces tcp[20:] y ahora, como la longitud de MAIL es 4 bit, etonces quedaría tcp[20:4]. Ya tenemos la expresión que indica donde, ahora la relación sería = y la siguiente expresión es el dato que buscamo, que es MAIL y en hexadecimal es: 4D41494C. Para que Windump lo entienda como haxadecima, ponemos 0x delante, con lo que el giltro final queda, como hemos dicho: tcp[20:4] = 0x4D41494C
iré / iremos añadiendo filtros…
Pingback: Modificando ficheros de tráfico de red .pcap con Bittwiste. | Seguridad y Redes
Pingback: Analizando capturas .pcap TCP con tcptrace. Generación de gráficas con Xplot. Parte 4. Avanzando. | Seguridad y Redes
Pingback: Análisis de tráfico de red de sesiones TCP con Streams. | Seguridad y Redes
saludo amigo la verdad tengo un problema, realice una captura con wireshark y necesito saber datos acerca de los paquetes perdidos, delay y jitter
Pingback: Justniffer. Un sniffer que reensambla, reordena y muestras los flujos TCP. | Seguridad y Redes
Pingback: Netsniff-ng. Un sniffer diferente de alto rendimiento. Parte I. | Seguridad y Redes
Pingback: Vortex IDS. Detección de intrusiones y análisis forense tráfico de red. Parte I | Seguridad y Redes
Pingback: Bro–IDS. Un sistema de detección de intrusiones basado en políticas especializadas. Parte 3. Bro 2.0. | Seguridad y Redes
Pingback: Bro–IDS. Un sistema de detección de intrusiones basado en políticas especializadas. Parte 4. Bro 2.0. | Seguridad y Redes
Pingback: Vortex IDS. Detección de intrusiones y análisis forense tráfico de red. Parte I « seguridadyinformatica
Pingback: Bro – IDS. Un sistema de detección de intrusiones basado en políticas especializadas. « seguridadyinformatica
Pingback: Bro–IDS. Un sistema de detección de intrusiones basado en políticas especializadas. Parte 3. Bro 2.0. « seguridadyinformatica
Pingback: Tcpick un sniffer que realiza seguimiento y reensamblado de flujos tcp. Mostrando datos payload. | Seguridad y Redes
Pingback: PRADS. Passive Real-time Asset Detection System. | Seguridad y Redes
Pingback: Sistema de detección de intrusiones basado en políticas especializadas | B1nary0's Web
Pingback: Netsniff-ng. Un sniffer diferente de alto rendimiento. Parte 2. | Seguridad y Redes
Pingback: Visualización y análisis de tráfico de red con Malcom Malware Communication Analyzer y Bro IDS. Parte I. | Seguridad y Redes
Pingback: TNV. Herramienta gráfica de visualización e interpretación de tráfico de red. | Seguridad y Redes
Pingback: Tshark. Extrayendo información de imágenes en capturas HTTP. | Seguridad y Redes