Tutorial de Scapy con Python Desarrollo

Guía: Uso de Scapy con Python

01/07/20 9 min. de lectura

Introducción a Scapy 🤘

En este artículo voy a hacer una breve introducción acerca de lo que es Scapy y sus funcionalidades. Además, vas a aprender con un par de ejemplos básicos cómo integrarlo en programas de Python, de tal forma que cualquier tipo de acción pueda automatizarse.

Scapy es considerado por muchos como una de las herramientas más importantes de manipulación de paquetes. Además, permite muchas posibilidades dado su potencial.

Si quieres mejorar tus conocimientos en redes, es tu oportunidad, sigue leyendo 🙂

Primero te voy a explicar el uso y funcionamiento de la interfaz de línea de comandos, y posteriormente cómo importar y utilizar dichas librerías en un programa escrito en Python.

Contenido

¿Qué es Scapy? 🙄

Scapy es una librería realizada en Python, con su propio interprete de línea de comandos (CLI), que permite crear, modificar, enviar y capturar paquetes de red.

Se puede utilizar de manera interactiva mediante dicha interfaz o como librería importándola en programas de Python. Se puede ejecutar en sistemas Linux, Mac OS x y Windows.

¿Para que sirve? 😮

Aplicado al ámbito de la seguridad informática, esta herramienta nos permite realizar escaneos y/o ataques de red.

La principal ventaja de Scapy es que, a diferencia de otras herramientas, nos proporciona la capacidad  de modificar los paquetes de red a bajo nivel, permitiéndonos utilizar los protocolos de red existentes y parametrizarlos en base a nuestras necesidades.

Y en el caso de que decidamos utilizar sus librerías en Python, podremos desarrollar nuestras propias herramientas, y de esta forma, podríamos realizar otros desarrollos de más alto nivel e integrarlos todos en función de nuestras necesidades.

Primeros pasos con Scapy 👣

Uso del Intérprete de Línea de Comandos (CLI) ⚙️

Para empezar a utilizar esta herramienta deberemos:

  1. Descargar e instalar el software de Scapy
  2. Ejecutarlo directamente desde la línea de comandos (con permisos de administrador):

Funciones básicas mediante Línea de Comandos (CLI) 🔧

Las principales funciones básicas que deberemos conocer son:

  • ls() : listado de capas disponibles
  • explore() : interfaz gráfica para visualizar capas existentes
  • lsc() : funciones disponibles
  • help() : menú de ayuda.

Y dentro del grupo de funciones, las más habituales son:

  • send(): envía paquetes a nivel 2.
  • sendp(): envía paquetes a nivel 3.
  • sr(): envía y recibe paquetes a nivel 3.
  • srp(): envía y recibe paquetes a nivel 2.
  • sr1(): envía y recibe solo el primer paquete a nivel 3.
  • srp1(): envía y recibe solo el primer paquete a nivel 2.
  • sniff(): sniffing de paquetes.
  • traceroute(): comando trace route.
  • arping(): Envío de solicitudes ‘who-has’ ARP para determinar que equipos están levantados en la red.

Ejemplo de uso mediante Interprete de Línea de Comandos (CLI) 💻

La construcción más sencilla podría ser crear un paquete de tipo ICMP. En este caso construiremos un paquete cuyo valor almacenaremos en una variable (P), y el cual lo parametrizaremos usando la capa IP (ip de destino), una segunda capa ICMP y posteriormente un payload (“hello SanExperts”).

Posteriormente lo enviaremos mediante el comando: sr1(p)

Si ejecutamos el comando ‘show()’ nos desglosará por capas el contenido del paquete:

En este caso hemos utilizado la IP del propio equipo, pero podríamos modificar los parámetros del paquete para hacerlo utilizando otras direcciones ip o MAC. En base a nuestras necesidades, el envío podríamos hacerlo a nivel 3 (sr) o nivel 2 (srp) del modelo TCP.

Por ejemplo, para hacer un escaneo de los hosts de nuestra subred, bastaría con ejecutar el siguiente comando (srp) y mostrar los valores de lo que si hayan respondido (ans):

Si necesitamos ayuda sobre cualquiera de los comandos, podemos mostrarla utilizando el comando ‘help()’:

Casos Prácticos de uso con Python ⌨️

A continuación, se muestran un par de ejemplos de casos de uso.

Caso de Uso 1: Escaneo de puertos 🖨️

Objetivo

Realizar un programa para escaneo de puertos tanto a nivel TCP como UDP mediante Scapy. Ello nos permitirá hacer nuestra propia herramienta personalizada para revisión de servicios a la escucha en nuestra red.

Ejemplo

Para hacer este ejemplo de uso, comenzamos creando un programa en Python que admitirá parámetros por la línea de comandos. Para ello comenzamos desarrollando un programa que permita que le indiquemos el objetivo a escanear, así como los puertos, tanto de manera unitaria como en forma de rango (1-n), indicando si el escaneo va a realizarse del protocolo TCP o UDP.

Como requisito, debemos importar las librerías de Scapy.

Dentro del programa, en la función main() validamos la correcta sintaxis e iniciamos la función que realizará dicho escaneo.

Posteriormente, definimos la clase que realizara el escaneo, haciendo diferencia entre TCP y UDP:

Para construir nuestro paquete definimos las diferentes capas con los datos de envío, así como los parámetros adecuados:

  • ip destino (dst)
  • puerto origen random (sport)
  • puerto destino (dport)
  • flags: S, SA, FPU.
  • timeout

Y realizamos el envío mediante (sr1) almacenando el resultado en una variable (resultado).

Posteriormente revisaremos los flags obtenidos para discernir si el puerto está abierto o cerrado en base a la respuesta.

** Antes de continuar, es importante conocer el funcionamiento del protocolo TCP y como se establecen las conversaciones y los flags utilizados, de tal forma que podamos saber en función de cada tipo de respuesta el estado del puerto.

A modo de resumen, estos serán los flags que vamos a utilizar para el ejemplo:

  • NULL = 0x00
  • FIN = 0x01
  • SYN = 0x02
  • RST = 0x04
  • PSH = 0x08
  • ACK = 0x10
  • SYN + ACK = 0x12
  • RST + ACK = 0x14
  • PSH + ACK = 0x18

Por lo que en base a los flags obtenidos, el estado de los puertos se resume en lo siguiente:

  • Puerto abierto: El puerto no está bloqueado por un FW y existe un servicio escuchando por él.

Se reciben flags: SYN y ACK (0x12).

  • Puerto cerrado:  El puerto no está bloqueado y no existe un servicio a la escucha.

Se reciben flags: RST y ACK (0x14).

  • Puerto filtrado: Un FW bloquea el acceso al puerto.

No se recibe nada.

Por lo que, volviendo al código de ejemplo, así se evaluaría la respuesta.

En el ejemplo se examina la respuesta buscando el flag “SYN, ACK” y en caso de encontrarse, se determina que se ha establecido la comunicación y que el puerto está abierto.

Para el caso de UDP, utilizaremos un proceso similar. Por tratarse de un protocolo sin conexión, enviaremos el paquete y esperaremos algo de tiempo para ver si se reciben los datos. Posteriormente y dependiendo del tipo de respuesta, tendremos que determinar si el puerto se encuentra abierto o cerrado.

Si quisiéramos tener un mayor nivel de detalle y saber si los puertos se encuentran “filtrados”, deberíamos incluir esa información como parte de la salida en los siguientes evaluadores, tanto para TCP como UDP:

Y ya para terminar, el resultado normal del script después de ejecutarlo sería este:

Caso de Uso 2: ARP Spoofing 🖱️

Objetivo

Realizar un envenenamiento de las tablas de la cache ARP de nuestra víctima. Ello nos permitiría mediante otras técnicas realizar ataques de tipo: MiTM (Man In The Middle), DoS (Denial of Service) o Session Hijacking.

Este ataque consiste en enviar mensajes ARP falsos. La finalidad es asociar la dirección MAC del atacante con la dirección IP de otro nodo, como por ejemplo la puerta de enlace predeterminada.

Ello nos permitiría mediante otras técnicas realizar ataques de tipo: MiTM (Man In The Middle), DoS (Denial of Service) o Session Hijacking.

Ejemplo

Comenzamos creando nuestro programa en Python e importando las librerías de Scapy, tal y como se mostraba en el caso anterior. Definimos funciones y solicitamos al comienzo de la ejecución las ips del gateway y del equipo víctima y comenzamos la ejecución:

Lo primero que debemos hacer es obtener las MAC de ambas IPs. Para ello ejecutamos la siguiente función:

Ya conociendo las MAC address, podemos manipular los paquetes mediante Scapy.

Para ello se envían los paquetes usando los siguientes parámetros:

  • Dirección ip origen (psrc): Gateway IP
  • Dirección ip destino (pdst): target IP
  • Dirección MAC origen (hwsrc): se omite, por defecto la MAC del equipo emisor.
  • Dirección MAC destino (hwdst): target mac

Con este envío se pretender enviar un paquete al equipo victima (referenciados por ip y mac) asociando la ip del Gateway con nuestra MAC address (equipo atacante).

Como resultado, las tablas ARP del equipo víctima, pasan de contener este valor:

A contener este otro.

Para deshacerlo, deberemos volver a enviar todos los datos correctos al equipo:

  • Dirección ip origen (psrc)
  • Dirección ip destino (pdst)
  • Dirección MAC origen (hwsrc)
  • Dirección MAC destino (hwdst)
Javier Gomez

Javier Gómez

Santander Global Tech

Ingeniero de sistemas con más de 20 años de experiencia en diferentes roles como arquitecto de sistemas, gestionando soluciones de virtualización de Apps & VDIs y proporcionando soluciones end-to-end, así como administrando sistemas y automatizando tareas mediante PowerShell.

Me considero una persona inquieta y un infatigable explorador del universo IT, que ha sabido hacer de su trabajo su pasión.

 

Otros posts