Creación de paquetes con Scapy

CiberseguridadBeginner
Practicar Ahora

Introducción

Scapy es un potente programa y biblioteca interactiva de manipulación de paquetes escrita en Python. Te permite forjar o decodificar paquetes de una amplia gama de protocolos, enviarlos a través de la red, capturarlos y hacer coincidir solicitudes con respuestas.

Lo que hace especial a Scapy es que te permite trabajar en la capa de construcción de paquetes en lugar de limitarte a la capa de socket o de aplicación. Esto significa que puedes controlar explícitamente encabezados, flags, campos y combinaciones de protocolos de una manera que las bibliotecas de cliente convencionales suelen ocultar.

En este laboratorio, aprenderás los fundamentos de la creación de paquetes utilizando Scapy. Comenzarás importando los módulos necesarios, luego pasarás a forjar paquetes ICMP (ping) y TCP capa por capa. Finalmente, enviarás estos paquetes personalizados y analizarás las respuestas de la red. Esta experiencia práctica te brindará una comprensión más profunda de cómo funcionan los protocolos de red internamente y cómo los profesionales de la seguridad prueban las defensas de una red.

Importar módulos de Scapy

En este paso, configurarás tu entorno de Python e importarás los módulos necesarios de Scapy. Aunque Scapy puede utilizarse como una consola interactiva, escribir scripts te permite guardar, modificar y reutilizar tu lógica de creación de paquetes fácilmente.

Este es un cambio de paradigma: pasas de usar protocolos a construirlos. En lugar de pedirle a una aplicación existente que envíe tráfico por ti, tú mismo defines cómo debe ser ese tráfico.

Primero, asegúrate de estar en tu directorio de trabajo predeterminado. Puedes usar el comando pwd para verificarlo, pero ya deberías estar en ~/project.

Crea un nuevo archivo de Python llamado packet_crafter.py usando el editor de texto nano.

nano packet_crafter.py

Dentro de este archivo, necesitas importar la biblioteca Scapy. La forma estándar de usar Scapy en scripts es importar todas las funciones del módulo scapy.all. Añade las siguientes líneas a tu script:

from scapy.all import *

print("Módulos de Scapy importados correctamente.")

Guarda el archivo con Ctrl+O y Enter. Si deseas seguir construyendo el script antes de probarlo, puedes permanecer en nano. Usa Ctrl+X cuando estés listo para volver a la terminal.

Ahora, ejecuta tu script usando Python para asegurarte de que no haya errores de sintaxis y que la biblioteca Scapy se cargue correctamente. Debido a que la creación de paquetes de red en bruto requiere privilegios elevados, debes ejecutar el script con sudo.

sudo python3 packet_crafter.py

Deberías ver una salida similar a la siguiente, lo que indica éxito:

Módulos de Scapy importados correctamente.

En algunos entornos de laboratorio, Scapy puede imprimir una advertencia adicional de paquetes opcionales de Python, como matplotlib, antes del mensaje de éxito. Si aún ves Módulos de Scapy importados correctamente., puedes continuar con el siguiente paso.

Forjar una solicitud de eco ICMP

En este paso, forjarás un paquete de solicitud de eco ICMP (ICMP Echo Request), comúnmente conocido como "ping". Los paquetes de red se construyen en capas, siguiendo el modelo OSI. En Scapy, puedes apilar estas capas usando el operador /.

La estratificación es uno de los conceptos más importantes que debes asimilar aquí. Cada capa añade sus propios campos y responsabilidades. Scapy refleja ese modelo directamente, razón por la cual su sintaxis facilita la comprensión de la estructura de los paquetes.

Un ping ICMP requiere una capa IP (capa de red) para especificar las direcciones de origen y destino, y una capa ICMP para definir el tipo de mensaje.

Si packet_crafter.py sigue abierto en nano, continúa editándolo. De lo contrario, ábrelo de nuevo:

nano packet_crafter.py

Añade el siguiente código al final de tu script. Este código crea un objeto IP dirigido al servidor DNS público de Google (8.8.8.8), crea un objeto ICMP y los apila juntos. El método show() imprimirá un desglose detallado de la estructura del paquete.

## Crear una capa IP dirigida al DNS de Google
ip_layer = IP(dst="8.8.8.8")

## Crear una capa ICMP (Echo Request)
icmp_layer = ICMP()

## Apilar las capas para formar el paquete final
icmp_packet = ip_layer / icmp_layer

print("\n--- Estructura del paquete ICMP ---")
icmp_packet.show()

Guarda el archivo con Ctrl+O y Enter. Puedes permanecer en nano y continuar con el siguiente paso si deseas completar más partes del script antes de ejecutarlo.

Ejecuta tu script actualizado para ver la estructura del paquete que acabas de forjar.

sudo python3 packet_crafter.py

Verás una salida detallada que muestra los valores predeterminados que Scapy completó automáticamente por ti, como la versión del protocolo, el TTL (Time To Live) y el tipo de ICMP.

--- Estructura del paquete ICMP ---
###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     =
  frag      = 0
  ttl       = 64
  proto     = icmp
  chksum    = None
  src       = 10.0.2.15
  dst       = 8.8.8.8
  \options   \
###[ ICMP ]###
     type      = echo-request
     code      = 0
     chksum    = None
     id        = 0x0
     seq       = 0x0
     unused    = ''

Crear un paquete TCP SYN personalizado

En este paso, crearás un paquete TCP SYN. Este tipo específico de paquete se utiliza con frecuencia en el escaneo de redes (como el escaneo sigiloso de Nmap) para comprobar si un puerto específico está abierto en una máquina objetivo sin establecer una conexión completa.

Este es un buen ejemplo de cómo pequeños cambios en el encabezado producen comportamientos de red muy diferentes. No estás cambiando el host o puerto de destino, solo los flags y los campos del protocolo, pero esos detalles definen el significado del paquete y cómo lo interpretará el objetivo.

Al igual que con el paquete ICMP, un paquete TCP requiere una capa IP subyacente. Encima de ella, añadirás una capa TCP donde podrás especificar el puerto de destino y los flags TCP. El flag S significa SYN (Synchronize).

Si sigues en la misma sesión de nano, continúa editando packet_crafter.py. De lo contrario, ábrelo de nuevo:

nano packet_crafter.py

Añade el siguiente código a tu script. Reutilizaremos el ip_layer que creaste en el paso anterior y apilaremos una nueva capa TCP encima, apuntando al puerto 80 (HTTP).

## Crear una capa TCP dirigida al puerto 80 con el flag SYN
tcp_layer = TCP(dport=80, flags="S")

## Apilar las capas IP y TCP
tcp_packet = ip_layer / tcp_layer

print("\n--- Estructura del paquete TCP SYN ---")
tcp_packet.show()

Guarda el archivo con Ctrl+O y Enter. Sal con Ctrl+X solo cuando quieras ejecutar el script desde la terminal, o sigue editando y continúa con el paso final.

Ejecuta el script de nuevo para inspeccionar la estructura de tu nuevo paquete TCP SYN.

sudo python3 packet_crafter.py

La salida ahora incluirá los detalles de la capa TCP, mostrando el puerto de destino configurado como http (puerto 80) y los flags configurados como S.

--- Estructura del paquete TCP SYN ---
###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     =
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 10.0.2.15
  dst       = 8.8.8.8
  \options   \
###[ TCP ]###
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = []

Enviar y analizar la respuesta de la red

En este paso final, enviarás realmente el paquete ICMP que forjaste a través de la red y capturarás la respuesta.

Enviar el paquete completa el modelo mental: definir capas, construir el paquete, transmitirlo y luego interpretar la respuesta. Ese es el mismo ciclo de alto nivel detrás de muchas herramientas personalizadas de prueba de red.

Scapy proporciona varias funciones para enviar paquetes. La función sr1() es particularmente útil porque envía un paquete y espera a recibir la primera respuesta que llegue. La "s" significa send (enviar), "r" significa receive (recibir) y "1" indica un solo paquete.

Si mantuviste el archivo abierto, continúa editándolo. De lo contrario, abre packet_crafter.py:

nano packet_crafter.py

Añade el siguiente código para enviar el icmp_packet y analizar la respuesta. Incluimos un parámetro timeout para que el script no se quede bloqueado indefinidamente si el paquete se pierde o es bloqueado.

print("\n--- Enviando paquete ICMP ---")
## Enviar el paquete y esperar 1 respuesta, con un tiempo de espera de 2 segundos
## verbose=0 oculta la salida predeterminada de envío de Scapy para obtener resultados más limpios
response = sr1(icmp_packet, timeout=2, verbose=0)

if response:
    print(f"Respuesta recibida de: {response[IP].src}")
    print("\n--- Estructura del paquete de respuesta ---")
    response.show()
else:
    print("No se recibió respuesta. Es posible que el paquete haya sido descartado.")

Guarda el archivo y sal del editor.

Ejecuta tu script para enviar el paquete a Internet y esperar a que el servidor DNS de Google responda.

sudo python3 packet_crafter.py

Si la red permite la solicitud ICMP, verás la estructura del paquete de respuesta. Observa que el tipo de ICMP en la respuesta es echo-reply.

--- Enviando paquete ICMP ---
Respuesta recibida de: 8.8.8.8

--- Estructura del paquete de respuesta ---
###[ IP ]###
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 28
  id        = 0
  flags     =
  frag      = 0
  ttl       = 114
  proto     = icmp
  chksum    = 0x67d8
  src       = 8.8.8.8
  dst       = 10.0.2.15
  \options   \
###[ ICMP ]###
     type      = echo-reply
     code      = 0
     chksum    = 0xffff
     id        = 0x0
     seq       = 0x0
     unused    = ''
###[ Padding ]###
        load      = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

Resumen

Aprendiste a configurar un script de Python con Scapy, a forjar manualmente paquetes ICMP y TCP capa por capa usando el operador /, y a enviar estos paquetes a través de la red para analizar las respuestas en bruto. Este conocimiento fundamental es crucial para comprender cómo operan los protocolos de red, realizar evaluaciones de seguridad y desarrollar herramientas personalizadas de análisis de red.