Cómo funciona el ataque de restablecimiento de TCP

Un ataque de restablecimiento de TCP se realiza utilizando un único paquete de datos de no más de unos pocos bytes de tamaño. El segmento TCP reemplazado por suplantación de identidad, creado y transmitido por el atacante, engaña a las dos víctimas para finalizar la conexión TCP, interrumpiendo la conexión entre ellas, lo que podría ser crítico.


Este ataque tuvo consecuencias en el mundo real. Los temores de su uso fueron causados ​​por la introducción de cambios en el protocolo TCP. Se cree que el ataque es un componente esencial del Gran Firewall Chino (el Escudo de Oro), que es utilizado por el gobierno chino para censurar Internet fuera de China. A pesar de su impresionante experiencia, comprender los mecanismos detrás de este ataque no requiere necesariamente un conocimiento profundo de TCP. Por supuesto, una comprensión de sus sutilezas puede enseñarle mucho sobre las características de la implementación del protocolo TCP y, como veremos pronto, incluso puede llevar a cabo este ataque contra usted mismo usando solo una computadora portátil.

En esta publicación nosotros:

  • Aprenda los conceptos básicos de TCP
  • Aprende cómo funciona el ataque.
  • Hagamos un ataque contra nosotros mismos con un simple script de Python.

Antes de comenzar a analizar la mecánica del ataque, primero veamos cómo se usa en el mundo real.

¿Cómo se usa el ataque de reinicio TCP en el Gran Firewall?


Great Firewall (GFW) es un conjunto de sistemas y técnicas utilizados por el gobierno chino para censurar Internet para los usuarios chinos internos. GFW bloquea y rompe activamente las conexiones con servidores dentro y fuera del país, y también monitorea pasivamente el tráfico de Internet de contenido prohibido.

Para evitar que los usuarios se conecten incluso a servidores prohibidos, GFW utiliza técnicas como la contaminación de DNS y el bloqueo de IP(ambos cuestan artículos separados). Sin embargo, a veces se debe permitir que el firewall GFW realice una conexión, pero luego la interrumpa en el medio. Por ejemplo, esto es necesario si desea realizar un análisis lento y pendiente de la conexión, por ejemplo, su correlación con otras acciones. O se usa si el firewall necesita analizar los datos intercambiados durante el proceso de conexión, y luego usar esta información para decidir si continuar o bloquearlo. Por ejemplo, puede permitirse el tráfico a un sitio web de noticias, pero los videos que contengan palabras clave prohibidas serán censurados.

Para esto, GFW necesita herramientas capaces de interrumpir las conexiones ya establecidas. Una de esas herramientas es un ataque de reinicio de TCP.

¿Cómo funciona un ataque de reinicio de TCP?


En un ataque de reinicio de TCP, el atacante rompe la conexión entre las dos víctimas, enviando uno o ambos mensajes falsos diciéndoles que se desconecten inmediatamente. Estos mensajes se denominan segmentos de restablecimiento de TCP . En funcionamiento normal sin la participación de un atacante, las computadoras envían segmentos de caída de TCP cuando reciben tráfico TCP inesperado y desean que el remitente deje de enviarlo.

El ataque de reinicio de TCP explota maliciosamente este mecanismo, engañando a las víctimas para que terminen las conexiones de TCP prematuramente, enviándoles segmentos de reinicio falsos. Si el segmento de restablecimiento falso se realiza correctamente, el destinatario lo tomará como el segmento real y cerrará la conexión por su parte, interrumpiendo la transmisión adicional de información sobre esta conexión. Para continuar con el intercambio de datos, las víctimas pueden intentar crear una nueva conexión TCP, pero el atacante puede tener la oportunidad de restablecer esta nueva conexión. Afortunadamente, dado que un atacante necesita tiempo para construir y enviar un paquete falso, los ataques de caída son realmente efectivos solo contra conexiones a largo plazo. Conexiones a corto plazo. por ejemplo, utilizado para transferir pequeñas páginas web, generalmente tiene tiempo para cumplir su misión para cuandocuándo el atacante podrá restablecerlos.

Enviar segmentos TCP falsos es, en cierto sentido, un proceso fácil, porque ni TCP ni IP tienen ninguna de sus propias formas de verificar la identidad del remitente. Hay una extensión de IP llamada IPSec que proporciona autenticación, pero no se usa tanto. Los proveedores de servicios de Internet deben negarse a transmitir paquetes IP que provengan de una dirección IP obviamente falsa, pero se alega que esta verificación es muy mediocre. Todo lo que el destinatario puede hacer es tomar la dirección IP de origen y el puerto dentro del paquete o segmento a su valor nominal y, si es posible, usar protocolos de nivel superior, como TLS , para identificar al remitente . Sin embargo, dado que los paquetes de volcado TCP son parte del protocolo TCP en sí, no se pueden verificar utilizando estos protocolos de alto nivel.

A pesar de la simplicidad de enviar segmentos falsos, hacer un segmento falso y ejecutar un ataque de reinicio TCP exitoso puede ser una tarea desalentadora. Para comprender por qué sucede esto, debemos comprender el funcionamiento del protocolo TCP.

Cómo funciona TCP


El propósito del protocolo TCP es enviar al destinatario una copia exacta del bloque de datos. Por ejemplo, si mi servidor envía HTML a través de TCP a su computadora, entonces la pila TCP de su computadora (la parte de su sistema operativo que procesa TCP) debería generar mi HTML exactamente en la misma forma y orden en que mi servidor lo envió.


Sin embargo, mi HTML no se transmite por Internet de una manera tan perfectamente ordenada. Está dividido en muchos fragmentos pequeños (llamados segmentos TCP ), cada uno de los cuales se transmite individualmente a través de Internet y se recrea en el orden transferido por la pila TCP de su computadora. Esta salida restaurada se denomina flujo TCP . Cada segmento TCP se transmite en su propio paquete IP , sin embargo, para comprender el ataque, no necesitamos conocer ningún detalle sobre IP.


La conversión de segmentos en una secuencia requiere cuidado porque Internet no es confiable. Los segmentos TCP pueden perderse. Pueden salir de servicio, enviarse dos veces, dañarse y experimentar muchas otras desventuras. Por lo tanto, el propósito del protocolo TCP es garantizar una transmisión de datos confiable a través de una red poco confiable. TCP realiza esta tarea, requiriendo que ambos lados de la conexión mantengan un contacto cercano entre sí y transmitan constantemente información sobre qué bloques de datos se recibieron. Esto permite a los remitentes comprender qué datos aún no ha recibido el destinatario y volver a transmitir los datos que se perdieron.

Para comprender cómo funciona el proceso, debemos comprender cómo los remitentes y receptores usan los números de secuencia TCP para marcar y rastrear datos transmitidos a través de TCP.

Números de secuencia TCP


Cada byte transmitido a través de una conexión TCP tiene un número de secuencia asignado por el remitente. Las máquinas receptoras usan números de serie para mover los datos recibidos al pedido original.


Cuando dos máquinas negocian una conexión TCP, cada máquina envía otro número de secuencia de inicio aleatorio . Este es el número de secuencia que la máquina asignará al primer byte que envía. A cada byte subsiguiente se le asigna el número de secuencia del byte anterior más 1. Los segmentos TCP contienen encabezados TCP , que son metadatos adjuntos al comienzo del segmento. El número de secuencia del primer byte en el cuerpo del segmento se incluye en el encabezado TCP de este segmento.

Cabe señalar que las conexiones TCP son bidireccionales, es decir, los datos se pueden transmitir en ambas direcciones, y cada máquina en una conexión TCP actúa como emisor y receptor. Debido a esto, cada máquina debe asignar y procesar su propio conjunto independiente de números de secuencia.

Confirmación de recibo de datos


Cuando una máquina recibe un segmento TCP, le dice al remitente del segmento que se recibió. El destinatario hace esto enviando un segmento ACK(abreviatura de "reconocimiento"), que contiene el número de secuencia del siguiente byte que espera recibir del remitente. El remitente utiliza esta información para comprender que el receptor ha recibido con éxito todos los demás bytes hasta este número.

Un segmento se ACKindica mediante la presencia de una bandera ACKy el número de confirmación correspondiente en el encabezado TCP del segmento. Solo hay 6 banderas en el protocolo TCP, incluyendo (como veremos en breve) una bandera RST(abreviatura de "reinicio" - "reinicio"), que indica el segmento de reinicio.


Nota: TCP también permite el uso de ACK selectivos , que se transmiten cuando el receptor ha recibido algunos, pero no todos, segmentos en el rango de números. Por ejemplo, "Recibí los bytes 1000-3000 y 4000-5000, pero no 3001-3999". Para simplificar, no consideraré ACK selectivos en nuestra discusión sobre los ataques de reinicio de TCP.

Si el remitente transmite datos pero no recibeACKpara ellos durante un cierto intervalo de tiempo, supone que los datos se han perdido y los reenvía, dándoles los mismos números de serie. Esto significa que si el receptor acepta los mismos bytes dos veces, entonces trivialmente usa números de secuencia para deshacerse de los duplicados sin romper la secuencia. El destinatario puede aceptar datos duplicados porque el segmento original se recibió más tarde, después de que se envió nuevamente, o porque el segmento original se recibió con éxito, pero el correspondiente se ACKperdió en el camino hacia el remitente.


Si bien estos datos duplicados son bastante raros, el desperdicio excesivo de recursos causado por ellos no genera problemas. Si todos los datos llegan tarde o temprano al destinatario y los datos correspondientes ACKllegan al remitente, entonces la conexión TCP hace su trabajo.

Elegir un número de serie para un segmento falso


Al crear un segmento falso, el RSTatacante debe darle un número de serie. Los destinatarios están muy contentos de que necesite aceptar segmentos con números de serie inconsistentes y conectarlos independientemente en el orden correcto. Sin embargo, sus capacidades son limitadas. Si el destinatario recibe un segmento con un número de secuencia que está "demasiado" fuera de servicio, descarta dicho segmento.

Por lo tanto, para un ataque de reinicio TCP exitoso, se requiere un número de secuencia plausible. Pero, ¿qué se considera tal número? Para la mayoría de los segmentos (aunque, como veremos más adelante, no para RST), la respuesta está determinada por el tamaño de la ventana TCP .

Tamaño de la ventana TCP


Imagine una computadora antigua de principios de la década de 1990, conectada a una red moderna de fibra óptica gigabit. Una red ultrarrápida puede transferir datos a esta computadora antigua a una velocidad asombrosa, más rápido de lo que la máquina puede procesarlo. Esto nos molestará, porque el segmento TCP no puede considerarse recibido hasta que el receptor pueda procesarlo.


Las computadoras tienen un búfer TCP en el cual los nuevos datos que llegan esperan ser procesados ​​mientras la computadora está trabajando en los datos que llegan antes. Sin embargo, este búfer tiene un tamaño limitado. Si el destinatario no puede hacer frente a la cantidad de datos que le transmite la red, el búfer se desbordará. Cuando el búfer está lleno, el destinatario no tiene más remedio que deshacerse de los datos redundantes. El destinatario no envía ACKlos datos descartados, por lo que el remitente debe volver a enviarlos cuando haya espacio libre en el búfer del destinatario. No importa qué tan rápido la red pueda transmitir datos si el destinatario no tiene tiempo para hacer frente a ellos.

Imagine a un amigo excesivamente celoso que le envía un flujo completo de cartas a su correo más rápido de lo que puede leerlo. Hay un cierto espacio de amortiguación dentro de su buzón, pero una vez que esté lleno, todas las letras no colocadas caerán al suelo, donde los zorros y otras criaturas las comerán. Un amigo tendrá que reenviar las cartas que ha comido, pero por ahora tendrá tiempo de recibir sus mensajes anteriores. Enviar demasiadas letras o volumen de datos que el destinatario no puede procesar es un desperdicio de energía y canal de transmisión.

"Demasiado": ¿cuántos datos hay? ¿Cómo entiende el remitente cuándo enviar más datos y cuándo vale la pena esperar? Aquí es donde resulta útil el tamaño de la ventana TCP .. El tamaño de la ventana del destinatario es el número máximo de bytes no reconocidos que el remitente puede transferirle en cualquier momento. Supongamos que el destinatario informa que su tamaño de ventana es 100,000 (pronto descubriremos cómo pasa este valor), por lo que el remitente envía 100,000 bytes. Supongamos que para cuando el emisor transmitió cien milésimos bytes, el receptor envió los segmentos ACKpara los primeros 10,000 de estos bytes. Esto significa que 90,000 bytes aún no han sido confirmados. Como el tamaño de la ventana es de 100,000, el remitente puede transferir otros 10,000 bytes antes de que tenga que esperar por otros nuevos ACK. Si después de enviar estos 10,000 bytes adicionales másACKSi no se recibió, el remitente se encontrará con su límite de 100,000 bytes sin confirmar. En consecuencia, el remitente tendrá que esperar y dejar de enviar datos (excepto la retransmisión de datos que considera perdidos) hasta que reciba otros nuevos ACK.


Cada lado de la conexión TCP notifica al otro el tamaño de su ventana durante el proceso de reconocimiento que se realiza cuando se abre la conexión. Además, los tamaños de las ventanas se pueden cambiar dinámicamente durante el proceso de conexión. Una computadora con un gran buffer TCP puede anunciar un gran tamaño de ventana para maximizar el rendimiento. Esto permite que la máquina que se comunica con ella transmita datos continuamente a través de una conexión TCP sin pausar o esperar la confirmación. Una computadora con un búfer TCP pequeño puede verse obligada a informar un tamaño de ventana pequeño. A veces los remitentes llenan completamente la ventana y se ven obligados a esperar hasta que se confirmen algunos de los segmentos. El ancho de banda sufre debido a esto, pero es necesario que los búferes TCP no se desborden.


El tamaño de la ventana TCP es un límite estricto en la cantidad de datos no confirmados transmitidos. Podemos usarlo para calcular el número de secuencia máximo posible (que en la ecuación a continuación designé como max_seq_no), que el remitente puede enviar en el momento actual:

max_seq_no = max_acked_seq_no + window_size

max_acked_seq_no- Este es el número máximo de secuencia para el cual el destinatario ha enviado ACK. Este es el número de secuencia máximo que el remitente sabe que el destinatario ha recibido exactamente. Como el remitente solo puede transmitir window_sizebytes sin confirmar, el número máximo de secuencia que puede enviar es max_acked_seq_no + window_size.

Debido a esto, la especificación TCP establece que el destinatario debe ignorar cualquier dato que reciba que tenga números de serie fuera de la ventana válida. Por ejemplo, si el destinatario ha confirmado todos los bytes hasta 15,000, y su tamaño de ventana es 30,000, entonces recibirá cualquier dato con un número de serie en el rango de 15,000 a (15,000 + 30,000 = 45,000). Además, el destinatario ignora por completo los datos con números de serie fuera de este intervalo. Si el segmento contiene datos, algunos de los cuales están dentro de esta ventana, y otros fuera de ella, entonces los datos dentro de la ventana serán aceptados y confirmados, pero los datos fuera de ella serán descartados. Tenga en cuenta que todavía ignoramos la posibilidad de los selectivosACK que se mencionaron brevemente al comienzo de la publicación.

En el caso de la mayoría de los segmentos TCP, esta regla nos da un intervalo de números de secuencia aceptables. Sin embargo, como se mencionó anteriormente, las RSTrestricciones impuestas a los segmentos son incluso más estrictas que las restricciones a los segmentos de transmisión de datos ordinarios. Como veremos pronto, esto se hizo para complicar la realización de una variante de un ataque de reinicio de TCP llamado "ataque de reinicio de TCP ciego" .

Números de secuencia aceptables para segmentos RST


Los segmentos regulares se aceptan si su número de secuencia está entre el siguiente número de secuencia esperado y este número más el tamaño de la ventana. Sin embargo, los paquetes RSTsolo se reciben cuando su número de secuencia es exactamente igual al siguiente número de secuencia esperado. Volvamos al ejemplo anterior, en el que el destinatario envió el número de confirmación 15,000. Para que RSTse reciba el paquete , su número de secuencia debe ser exactamente 15,000. Si el destinatario recibe un segmento RSTcon un número de secuencia no igual a 15,000, entonces no lo aceptará.


Si el número de secuencia está fuera del intervalo, entonces el receptor lo ignora por completo. Sin embargo, si está dentro de la ventana de los números de secuencia esperados, el receptor envía un "desafío ACK" ("llamada ACK"). Este es un segmento que le dice al remitente que el segmento RSTtiene un número de secuencia no válido. También le dice al remitente el número de secuencia que el destinatario espera. El remitente puede usar esta información de la ACKllamada para recrear y reenviar la suya RST.

Hasta 2010, TCP no impuso estas restricciones de segmento adicionales RST. Los segmentos fueron RSTaceptados o rechazados de acuerdo con las mismas reglas que cualquier otro. Sin embargo, esto también simplificó los ataques de reinicio TCP ciego ciego .

Ataques ciegos de TCP


Si el atacante tiene la capacidad de interceptar el tráfico intercambiado entre sus víctimas, puede leer los números de serie y de confirmación de los paquetes TCP de las víctimas. Puede usar esta información para seleccionar qué números de serie dar a sus segmentos falsos RST. Sin embargo, si el atacante no puede interceptar el tráfico de las víctimas, no sabrá qué números de secuencia insertar. Pero aún puede transferir cualquier número de segmentos RSTcon cualquier número de números de serie diferentes, esperando que uno de ellos resulte ser correcto. Tal ataque se llama ataque ciego de reinicio de TCP.

Como ya dijimos, en la versión inicial del protocolo TCP, el atacante solo tenía que recoger el número de serieRSTdentro de la ventana TCP del receptor. Un artículo titulado "Deslizándose en la ventana" mostró que esto hacía que los ataques ciegos fueran demasiado fáciles, ya que para un éxito casi garantizado, un atacante solo tenía que enviar decenas de miles de segmentos. Para contrarrestar esto, la regla que obligó al destinatario a aceptar el segmento RSTfue reemplazada por el criterio más estricto descrito anteriormente. Gracias a las nuevas reglas para llevar a cabo ataques de reinicio de TCP, millones de segmentos deben enviarse a ciegas, lo que los hace prácticamente irrealizables. Ver RFC-5963 para más detalles .

Realizar un ataque de reinicio de TCP contra nosotros mismos


Nota: Probé este proceso en OSX, pero recibí algunos comentarios de que no funciona correctamente en Linux.

Ahora sabemos todo sobre la ejecución de un ataque de restablecimiento de TCP. El atacante debe:

  • Observe el tráfico de la red ( "huela" ) entre dos víctimas
  • Olfatee el segmento TCP con la bandera habilitada ACKy lea su número confirmado
  • Haga un segmento TCP falso con el indicador activado RSTy un número de secuencia igual al número confirmado del segmento interceptado (tenga en cuenta que esto implica una transmisión lenta; de lo contrario, el número de secuencia seleccionado quedará desactualizado rápidamente. (Para aumentar las posibilidades de éxito, puede transferir varios segmentos RSTcon un gran intervalo de números de secuencia) .)
  • Envíe segmentos falsos a una o ambas víctimas, esperando que esto rompa su conexión TCP

Para practicar, realicemos un ataque TCP contra nosotros mismos en la misma computadora, comunicándonos a través de nosotros localhost. Para esto necesitamos:

  1. Configurar la conexión TCP entre dos ventanas de terminal
  2. Escriba un programa de ataque que se ocupe del rastreo de tráfico.
  3. Modifique el programa para que produzca y envíe segmentos falsos RST.

Empecemos.

1. Establecer una conexión TCP entre dos ventanas de terminal


Configuraremos la conexión TCP utilizando la herramienta netcat, que por defecto está disponible en muchos sistemas operativos. Cualquier otro cliente TCP lo hará . En la primera ventana de terminal, ejecutaremos el siguiente comando:

nc -nvl 8000

Este comando inicia un servidor TCP que escucha en un puerto de nuestra máquina local 8000. En la segunda ventana de terminal, ejecute el siguiente comando:

nc 127.0.0.1 8000

Este comando intenta crear una conexión TCP a la máquina mediante la dirección IP del 127.0.0.1puerto 8000. Ahora, entre las dos ventanas del terminal, se debe establecer una conexión TCP. Intente ingresar algo en una ventana: los datos deberán transmitirse a través de la conexión TCP y aparecer en otra ventana.


2. Oler el tráfico


Escribiremos un programa de ataque que detecte el tráfico utilizando la scapypopular biblioteca de red Python. Este programa utiliza scapy para leer los datos transferidos entre dos ventanas del terminal, aunque no es parte de la conexión.

El código del programa se publica en mi repositorio en GitHub . El programa detecta el tráfico de conexión y lo muestra en la terminal. El núcleo principal del código es la llamada al método sniffdesde la biblioteca scapyubicada al final del archivo:

t = sniff(
        iface='lo0',
        lfilter=is_packet_tcp_client_to_server(localhost_ip, localhost_server_port, localhost_ip),
        prn=log_packet,
        count=50)

Este código nos dice scapyque olfateemos paquetes en la interfaz lo0y capturemos detalles de todos los paquetes como parte de nuestra conexión TCP. La llamada tiene los siguientes parámetros:

  • iface- órdenes scapypara escuchar la interfaz de red lo0, o localhost
  • lfilter — , scapy , IP- localhost . , , lo0. , .
  • prn — , scapy , lfilter. . , RST.
  • count — , scapy .

Para probar este programa, configure la conexión TCP desde el paso 1. Clone mi repositorio de GitHub, siga las instrucciones de configuración y ejecute el programa en la tercera ventana del terminal. Ingrese texto en uno de los terminales de la conexión TCP. Debería ver que el programa comenzará a registrar información sobre los segmentos de conexión.

3. Envío de paquetes falsos RST


Hemos establecido una conexión, y el programa puede detectar todos los segmentos TCP que la atraviesan. Lo único que nos queda es modificar el programa para que realice un ataque de restablecimiento de TCP transmitiendo segmentos falsos RST. Para hacer esto, cambiaremos la función prn(consulte la lista de parámetros anterior), scapyque requiere paquetes que cumplan los requisitos de la función lfilter. En la versión modificada de la función, en lugar de simplemente arreglar el paquete correspondiente, lo estudiamos, extraemos los parámetros necesarios y usamos estos parámetros para construir y enviar el segmento RST.

Supongamos que interceptamos un segmento que va desde (src_ip, src_port)k (dst_ip, dst_port). Él tiene un conjunto de banderas ACKy el número de confirmación es 100,000. Para fabricar y enviar un segmento, nosotros:

  • IP- , . , . , .
  • RST , , RST
  • , ,
  • send scapy — .

Para modificar nuestro programa anterior según sea necesario, elimine el comentario de esta línea y comente la línea que se encuentra arriba.

Ahora estamos listos para un ataque a gran escala. Configure la conexión TCP de acuerdo con el paso 1. Ejecute el programa de ataque desde el paso 2 en la tercera ventana del terminal. Luego ingrese un texto en uno de los terminales de la conexión TCP. En la terminal donde ingresó el texto, la conexión TCP se interrumpirá repentina y misteriosamente. El ataque está hecho!


Más trabajo


  1. Continúa experimentando con la herramienta de ataque. Realice un seguimiento de lo que sucede si suma o resta 1 del número de secuencia del paquete RST. Asegúrese de que debe coincidir exactamente con el valor del ackpaquete interceptado.
  2. Wireshark lo0 . TCP-, RST. ip.src == 127.0.0.1 && ip.dst == 127.0.0.1 && tcp.port == 8000 .
  3. , . RST, RST , . , RST, .


El ataque de reinicio de TCP es profundo y simple al mismo tiempo. Buena suerte con tus experimentos y avísame si tienes preguntas o comentarios.

All Articles