Evasión en IDS (III)

Tal como vimos en la anterior entrada, una forma sencilla de evadir el motor de reglas es emplear distintas codificaciones para intentar que el ataque no coincida con el patrón buscado por el IDS. Junto a lo visto con anterioridad, existen otros métodos sobre el protocolo TCP/IP para intentar evadir el motor de reglas. Veremos cuatro de los principales métodos de evasión a nivel de TDP/IP:

Explotar el tiempo de vida (TTL)

El TTL es un campo de las cabecera TCP/IP que se encarga de evitar que un paquete permanezca en la red para siempre. El TTL es un campo de 8 bits que indica el número máximo de enrutadores por los cuales puede pasar. Al llegar a un enrutador el TTL disminuye en 1, si el número resultante después de restarle 1 es igual a 0 el paquete es descartado, informando al emisor con un paquete ICMP de tipo Time Exceeded Message. A muchos de ustedes les sonará el campo porque es empleado por herramientas de tipo traceroute (véase esta entrada sobre las curiosidades del traceroute) para conocer los enrutadores por los que pasamos antes de llegar a nuestro destino.

Un atacante puede aprovechar dicho campo para enviar paquetes idénticos donde cambian dos cosas: el valor del TTL y los datos que se quieren solicitar. El objetivo del atacante es que ambos paquetes lleguen al IDS pero no lleguen al servidor final. Supongamos que del atacante al IDS hay 3 saltos y del IDS al servidor final hay 2 saltos. El atacante enviará el ataque real con TTL superior a 5 y enviará paquetes idénticos con TTL igual a 4, de tal forma que todos los paquetes lleguen al IDS pero al servidor solo llegarán los paquetes del ataque. El IDS no sabrá cual es la cadena real.

Siguiendo el ejemplo del anterior post (“/etc/passwd”) veamos un ejemplo:

Paquetes con flag RST y checksum inválido

El objetivo del atacante es intentar engañar al IDS para que deje de controlar una comunicación. Para ello el atacante envía un paquete RST (fin de conexión no educada) de una conexión legítima previamente establecida, pero de tal forma que el checksum del paquete sea incorrecto. Cuando el paquete llega al IDS, éste entiende que la conexión ha finalizado y termina de monitorizar la conexión, pero cuando dicho paquete llega al servidor y éste comprueba que el checksum es incorrecto, descarta el paquete y continúa manteniendo la conexión con el atacante.

Paquetes fragmentados simples

El protocolo TCP/IP acepta paquetes fragmentados, de tal forma que podemos partir un paquete original en otros paquetes mas pequeños. El MTU de una trama ethernet tiene un tamaño máximo de 1530 byte pero existen otras tecnologías de red (Token Rin y X25 por ejemplo) donde no tiene porque tener el mismo tamaño, es por ello que se implementaron los paquetes fragmentados para permitir la conectividad entre distintas tecnologías. Un atacante puede aprovechar esta ventaja para enviar un ataque en varios paquetes fragmentados, de tal forma que si el IDS no reensambla el paquete y busca el patrón del ataque uno a uno sobre los paquetes fragmentados, el atacante conseguirá evadir el motor de reglas.

Siguiendo el ejemplo anterior, podríamos enviar la cadena “/etc/passwd” dividida en dos paquetes fragmentados: “/etc/p” y “asswd”. Si el IDS busca “/etc/passwd” en el primer paquete fragmentado la cadena no coincidirá, si luego lo busca en el segundo paquete tampoco coincidirá y dejará pasar el paquete. Pero cuando el servidor reensamble los paquetes fragmentados tendrá la cadena “/etc/passwd”:

Overlapping, el extremo de los paquetes fragmentados

El estándar TCP/IP no asegura el orden de llegada de los paquetes y esto también afecta a los paquetes fragmentados. Con este objetivo, la cabecera TCP/IP dispone de varios campos que indican que un grupo de paquetes fragmentados pertenecen al mismo paquete original, y permitir así al receptor poder reconstruir el paquete de nuevo. De la misma manera, existe un campo que indica si existen más paquetes fragmentados y qué posición ocupan en el datagrama original.

Teniendo en cuenta lo explicado con anterioridad, un atacante podría enviar un paquete fragmentado donde los datos de varios paquetes fragmentados ocuparan las mismas posiciones. Veamos un ejemplo gráfico:

Debido a la no existencia de un estándar para estos casos, cada sistema operativo reensambla de distintas formas y por tanto, el IDS debe ser capaz de reensamblar el paquete para todas las posibles políticas de reensamblado que existan. Veamos a continuación las tres políticas más empleadas:

BSD: tienen preferencia siempre los datos de los datagramas con offset menor. A igual offset, se toma el que ha llegado el primero.
Linux: igual que en BSD, pero a igual offset se toma el que ha llegado último.
First (Windows): acepta siempre el primer valor que llega.

(Para más información, pueden consultar el paper de Umesh Shankar, Active Mapping: Resisting NIDS Evasion Without Altering Traffic).

Siguiendo el ejemplo de la entrada, un atacante podría mandar un paquete fragmentado donde la cadena que contiene sea “/etc/passwd” y sólo pueda ser interpretado correctamente por un entorno BSD, por ejemplo, por el servidor víctima. Si nuestro IDS no soporta reensamblado BSD no reconocería el ataque. Veamos un ejemplo donde el atacante envía 6 paquetes fragmentados de tal forma que si sólo se reensambla con la política BSD se obtiene el vector de ataque real “/etc/passwd”:

  • Con política BSD obtendríamos: “/etc/passwd”
  • Con política Linux obtendríamos: “/etc/pdefgd”
  • Con política First (Windows) obtendríamos: “/etccpasswd”

Es por ello necesario indicar en la configuración de los IDS que tipos de política deben ser aplicadas para que servidor. Actualmente existen productos en el mercado (de conocidas marcas y no precisamente económicos) que solo permiten aplicar una política global para todos los hosts o incluso solo disponen de una única política. ¿Qué ocurre entonces cuando en nuestra red disponemos de IOS, Windows, Linux, Unix, etc.? Efectivamente, un atacante podrá eludir el IDS.

En el caso del Snort, éste dispone del preprocesador Frag3, el cual permite configurar mediante grupos prefijados o de forma manual qué tipo de política de reensamblado aplicar a qué host. Por ejemplo para entornos Linux y Windows habría que configurar el preprocesador de la siguiente forma:

preprocessor frag3_engine: policy first bind_to [IP1,IP2,...,IPX] 
preprocessor frag3_engine: policy linux bind_to [IP1,IP2,...,IPX]

Como ven, los IDS tienen que realizar múltiples comprobaciones antes de decidir si se trata de un ataque o de un paquete legítimo. Imagínense que nosotros como atacantes cogemos la cadena “/etc/passwd”, la pasamos a “/./etc/./passwd” y la codificamos en Bare Byte Encoding. Una vez obtenida dicha cadena, fragmentamos el paquete empleando el overlapping para que solo pueda ser reconocido por la política de reensamblado del servidor destino, e introducimos ruido con paquetes con un TTL suficiente para llegar al IDS pero no para alcanzar el servidor víctima. Añadimos a esto paquetes RST con checksum incorrecto.

¿Cuantos IDS creen ustedes que serían capaces de reconocer el patrón “/etc/passwd”? ¿Cual será el verdadero rendimiento de un IDS (throughput) que tenga la capacidad de realizar todas estas comprobaciones? Piénsenlo.

Comments

  1. Buen post!

  2. Muy bueno ximo!

Trackbacks

  1. […] Evasión en IDS (III) Tal como vimos en la anterior entrada, una forma sencilla de evadir el motor de reglas es emplear distintas codificaciones para intentar que el ataque no coincida con el patrón buscado por el IDS. Junto a lo visto con anterioridad, existen otros métodos sobre el protocolo TCP/IP para intentar evadir el motor de reglas. Veremos cuatro de los principales métodos de evasión a nivel de TDP/IP… […]