Scapy es una potente librería escrita y soportada en Python la cual permite la creación, manipulación e inyección de paquetes de un entorno de red, sin embargo esta definición se queda corta a la hora de hablar de Scapy, dado que las funcionalidades que soporta le hacen una librería ideal para escribir aplicaciones que permitan realizar diferentes tareas tales como Fingerprinting, Discovering, Enumeration, entre otras. Similar a lo que hace Nmap? Si, con la diferencia de que con esta librería se tiene muchísimo más control sobre los paquetes enviados y recibidos. Con Scapy se pueden crear, capturar, manipular y analizar una gran cantidad de paquetes con varios protocolos de red existentes.
Con Scapy no es necesario aprender un lenguaje de programación nuevo, solamente es necesario tener conocimientos sobre la sintaxis y estructura de los programas escritos en Python. Su uso es simple, puede hacerse de forma interactiva (del mismo modo que se hace con el interprete de Python) o directamente desde una rutina completa de código utilizando un fichero (.py). Por otro lado, el funcionamiento principal de Scapy también es muy simple y puede resumirse en dos pasos claramente definidos, La creación de un conjunto de paquetes (1 o muchos) y la captura de respuestas emitidas desde el destinatario de dichos paquetes, es así de simple, dichas respuestas posteriormente pueden ser analizadas y tratadas, lo cual es una gran ventaja con respecto a herramientas como Nmap o HPing que intentan realizar una interpretación de las respuestas recibidas y solamente proporcionan estados tales como Open|Filtered|Closed sin dar demasiada información sobre lo que realmente ha ocurrido.
Como el lector podrá intuir, se trata de una herramienta que permite un alto grado de control y esta específicamente enfocada a aquellos profesionales “que saben lo que están haciendo” ya que solamente realiza el trabajo de codificar paquetes para su envío y decodificar respuestas, el trabajo analítico e interpretativo queda a criterio del programador, por lo tanto dicha persona debe de tener un buen nivel de conocimientos sobre protocolos de red y paquetes de lo contrario, no podrá sacar el máximo provecho a esta herramienta. También es posible crear cualquier tipo de paquete especificando valores para cada uno de los campos disponibles en dicho tipo de paquete, así como también crear un tipo de paquete nuevo que herede y extienda características propias de un tipo determinado (por ejemplo TCP, UDP, ICMP, etc) y por si fuera poco, dado que se encuentra escrita en Python su uso resulta muy simple y con muy pocas lineas de código pueden hacerse rutinas que en otros lenguajes pueden resultar complejas.
Ahora es el momento de utilizar Scapy.
INSTALACIÓN DE SCAPY
Es posible hacerlo desde los repositorios oficiales de Debian, sin embargo para muchos programas es una buena practica instalar las ultimas versiones disponibles desde código fuente, repositorios o ficheros ejecutables de distribución, en este caso concreto, se utilizará la última versión de Scapy, tan simple como:
>wget scapy.net>mv index.html scapy-lastest.zip
>chmod +x scapy-lastest.zip >./scapy-latest.zip INFO: Can’t import python gnuplot wrapper . Won’t be able to plot. INFO: Can’t import PyX. Won’t be able to use psdump() or pdfdump(). WARNING: Failed to execute tcpdump. Check it is installed and in the PATH WARNING: No route found for IPv6 destination :: (no default route?) /opt/scapy-latest.zip/scapy-2.2.0/scapy/crypto/cert.py:10: DeprecationWarning: the sha module is deprecated; use the hashlib module instead /opt/scapy-latest.zip/scapy-2.2.0/scapy/crypto/cert.py:11: DeprecationWarning: The popen2 module is deprecated. Use the subprocess module. Welcome to Scapy (2.2.0) >>> |
Ahora es posible comenzar a utilizar Scapy desde el interprete disponible, también puede apreciarse que aparecen algunos mensajes de advertencia indicando que faltan algunas librerías necesarias para el uso de ciertas funciones disponibles en Scapy y hasta que dichas librerías no se instalen, dichas funciones lanzarán un error o no funcionarán adecuadamente, la instalación de estas y otras librerías se detallarán en próximas publicaciones.
USO BASICO DE SCAPY
A continuación se detalla el uso básico de esta librería, que consta principalmente de una serie de funciones bastante simples pero que requieren de conocimientos sobre redes y protocolos de comunicación tales como TCP, IP, UDP, ICMP, etc.
Como se ha indicado anteriormente, es posible crear uno o varios paquetes de datos apilados en un único conjunto que posteriormente puede enviarse a un destino determinado, estos paquetes pueden ser altamente personalizados utilizando esta API, por ejemplo para crear un paquete IP, se puede emplear el siguiente comando:
>>> ipPacket = IP()>>> ipPacket
<IP |> |
Muy simple, con esto se ha creado un paquete IP con sus valores por defecto y dicha estructura se almacena en la variable “ipPacket”, posteriormente es posible manipular dicho paquete accediendo de forma directa a sus campos y asignando valores o utilizando algunas de las funciones disponibles en Scapy para tal fin.
>>> ipPacket.src=»192.168.1.33″>>> ipPacket.dst=»192.168.1.1″
>>> ls(ipPacket) version : BitField = 4 (4) ihl : BitField = None (None) tos : XByteField = 0 (0) len : ShortField = None (None) id : ShortField = 1 (1) flags : FlagsField = 0 (0) frag : BitField = 0 (0) ttl : ByteField = 64 (64) proto : ByteEnumField = 0 (0) chksum : XShortField = None (None) src : Emph = ‘192.168.1.33’ (None) dst : Emph = ‘192.168.1.1’ (‘127.0.0.1’) options : PacketListField = [] ([]) |
Como puede apreciarse, se ha accedido directamente a los campos “src” y “dst” del paquete IP y posteriormente se le han asignado valores, así como también se ha utilizado la función “ls” para listar el valor de todos los campos disponibles en el paquete (como puede verse, los valores modificados anteriormente se encuentran reflejados en este comando).
No solamente es posible crear paquetes IP, con Scapy es posible crear una gran cantidad de tipos distintos de paquetes siguiendo la misma sintaxis descrita en las lineas anteriores, algunos ejemplos de otros tipos de paquetes que pueden crearse son:
>>> tcpPacket=TCP()>>> etherPacket=Ether()
>>> icmpPacket=ICMP() >>> dnsPacket=DNS() >>> tcpPacket <TCP |> >>> etherPacket <Ether |> >>> icmpPacket <ICMP |> >>> dnsPacket <DNS |> >>> tcpPacket <TCP |> |
También es posible crear paquetes con algunos valores indicados por parámetro, por ejemplo:
>>> tcpPacket=TCP(sport=22,dport=80)>>> ipPacket=IP(ttl=64,src=»192.168.1.33″,dst=»192.168.1.1″)
>>>etherPacket=Ether(dst=»11:22:33:44:55:66″,src=»00:22:44:66.88:99″,type=5) >>> icmpPacket=ICMP(gw=»192.168.1.1″,addr_mask=»255.255.255.128″) >>>dnsPacket=DNS(ns=»127.0.0.1″) |
Se han creado una serie de paquetes que contienen una inicialización previa sobre algunos de los campos disponibles para cada tipo de paquete, de esta forma, crear un paquete completamente personalizado con todos los campos necesarios es tan sencillo como escribir una sola linea de código.
Ahora bien, aunque más adelante se hablará en profundidad sobre el tema de las funciones disponibles en Scapy, resulta conveniente en este punto conocer algunas de las más empleadas (tales como “ls”) ejemplos del uso de algunas de estas funciones son:
>>> ipPacket = IP();>>> ls(ipPacket)
version : BitField = 4 (4) ihl : BitField = None (None) tos : XByteField = 0 (0) len : ShortField = None (None) id : ShortField = 1 (1) flags : FlagsField = 0 (0) frag : BitField = 0 (0) ttl : ByteField = 64 (64) proto : ByteEnumField = 0 (0) chksum : XShortField = None (None) src : Emph = ‘127.0.0.1’ (None) dst : Emph = ‘127.0.0.1’ (‘127.0.0.1’) options : PacketListField = [] ([]) >>> str(ipPacket) ‘E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01’ >>> hexdump(ipPacket) 0000 45 00 00 14 00 01 00 00 40 00 7C E7 7F 00 00 01 E…….@.|….. 0010 7F 00 00 01 …. >>> del(ipPacket.ttl) >>> _ ‘E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01’ >>> readed=rdpcap(«/root/Desktop/sshcapture.cap») >>> readed <sshcapture.cap: TCP:1 UDP:0 ICMP:0 Other:0> |
La función “ls” permite listar el contenido del paquete, la función “str” permite obtener una representación String del paquete, “hexdump” permite volcar el contenido del paquete en formato hexadecimal, “del” permite restablecer el valor por defecto de alguno de los atributos del paquete, la función “rdpcap” permite leer y cargar un fichero con paquetes capturados con una herramienta como tpcdump, wireshark o cualquier sniffer de red. Estas son solamente unas pocas funciones para que el lector se haga una idea de como funcionan y la sintaxis que estas siguen, sin embargo para prácticamente cada modulo en Scapy existen funciones especificas que permiten realizar tareas concretas, esto se vera más adelante.
Por otro lado, también es posible crear una pila de paquetes (hasta este punto solamente se ha venido trabajando con un único paquete) este es el escenario más común, especialmente cuando se trata de ejecutar un proceso de fingerprint o enumeration para determinar que servicios o puertos se encuentran disponibles en un objetivo, para ello usualmente se crean conjuntos de paquetes que son enviados a dicho objetivo y posteriormente se analizan las respuestas recibidas, como se ha dicho anteriormente esta es una de las actividades más comunes en Scapy y se consigue fácilmente utilizando el operador “/”entre cada paquete de la pila. Por ejemplo:
>>> layer = IP()/TCP()/Ether()>>> layer
<IP frag=0 proto=tcp |<TCP |<Ether |>>> >>> ls(layer) version : BitField = 4 (4) ihl : BitField = None (None) tos : XByteField = 0 (0) len : ShortField = None (None) id : ShortField = 1 (1) flags : FlagsField = 0 (0) frag : BitField = 0 (0) ttl : ByteField = 64 (64) proto : ByteEnumField = 6 (0) chksum : XShortField = None (None) src : Emph = ‘127.0.0.1’ (None) dst : Emph = ‘127.0.0.1’ (‘127.0.0.1’) options : PacketListField = [] ([]) — sport : ShortEnumField = 20 (20) dport : ShortEnumField = 80 (80) seq : IntField = 0 (0) ack : IntField = 0 (0) dataofs : BitField = None (None) reserved : BitField = 0 (0) flags : FlagsField = 2 (2) window : ShortField = 8192 (8192) chksum : XShortField = None (None) urgptr : ShortField = 0 (0) options : TCPOptionsField = {} ({}) — WARNING: Mac address to reach destination not found. Using broadcast. dst : DestMACField = ‘ff:ff:ff:ff:ff:ff’ (None) src : SourceMACField = ’00:00:00:00:00:00′ (None) type : XShortEnumField = 0 (0) |
Como puede apreciarse, la variable “layer” contiene un conjunto de 3 paquetes los cuales se encuentran apilados, los valores por defecto de las capas inferiores son sobre cargados por los valores de las capas superiores (evidentemente si se trata del mismo tipo de paquete), además se cuenta con la ventaja de que este conjunto de paquetes puede tratarse como si se tratase de un único paquete, utilizando las mismas funciones (y algunas otras funciones adicionales) a la variable que tiene almacenada la estructura correspondiente.
En esta publicación se ha indicado el uso básico de Scapy, sin embargo esta librería cuenta con un buen conjunto de funciones que permiten realizar actividades bastante interesantes en un segmento de red y personalizar paquetes a un nivel bastante fino. En próximas publicaciones intentaré explicar estos conceptos en mayor detalle.