25 octubre 2008

Esteganografía de red

La esteganografía es el arte de esconder información en cosas de uso habitual como fotos, sonidos, imágenes de vídeo, etc.

El hombre ha inventado multitud de técnicas esteganográficas a lo largo de la historia. El arte está repleto de mensajes ocultos en cuadros, esculturas y edificios (¿Aún queda alguien que no haya leído el Código Da Vinci?). El mundo del espionaje utiliza técnicas esteganográficas constantemente (desde la técnica del micropunto a los mensajes escritos en espejos que sólo se ven al exponerlos al vaho). Recientemente Internet ha abierto una ventana universal al conocimiento y al intercambio de opiniones e ideas. Precisamente por eso, muchos gobiernos dictatoriales intentan controlar los datos intercambiados entre sus redes nacionales e Internet para detectar rebeldes y pensadores discrepantes. En este tipo de casos la confidencialidad no basta, porque el mero hecho de cifrar algo ya resulta sospechoso para la policía política (“¿si no tiene nada que ocultar por qué lo cifra?”). Es necesario no sólo asegurar la confidencialidad de la información sino evitar en lo posible su detección, de ahí la renovada importancia de las técnicas esteganográficas.

Se han escrito muchos artículos acerca de la ocultación de datos en imágenes y fotografías. También resulta bastante conocida la posibilidad de guardar información en el ruido de fondo de una canción, de manera imperceptible al oído humano, o en el de una secuencia de vídeo. La que resulta menos conocida es la denominada esteganografía de red, la cual utiliza determinadas características de los protocolos de red para encapsular datos y transmitirlos camuflados por Internet.

La esteganografía de red se basa en tres métodos principales:
  • Encapsulación de un protocolo en otro.
  • Encapsulación de información en el campo de datos de un protocolo.
  • Encapsulación de información en un campo numérico de un protocolo.

El primer caso, encapsulación de un protocolo en otro, es relativamente conocido y muy utilizado hoy día para el ocultamiento de sistemas de descargas P2P. Un ejemplo es el encapsulado en el protocolo HTTP para eludir las restricciones de los cortafuegos perimetrales. Este último es el enfoque de herramientas como HTTP-Tunnel que, mediante la instalación de un servidor de SOCKS en el PC, permiten establecer un túnel cifrado con un servidor remoto, que hace de intermediario, a través del puerto de HTTP (abierto generalmente en el cortafuegos) simulando que es tráfico web. El servidor que hace de intermediario, situado en el exterior del cortafuegos, desencapsula luego el tráfico y lo remite a sus destinatarios originales.

El segundo caso se da cuando un protocolo de uso común en la red incluye un campo de datos que nosotros podemos llenar con nuestro mensaje. Alguien que vigilase la red advertiría el uso del protocolo pero a no ser que se pusiera a investigar el contenido de los campos de los paquetes intercambiados sería incapaz de detectar que se está transmitiendo información.

Un claro ejemplo de este tipo de técnicas es el protocolo ICMP. Este protocolo se utiliza para tareas de mantenimiento y control interno de redes. La herramienta más conocida que utiliza este protocolo es Ping. Como ya es sobradamente conocido, la herramienta ping permite averiguar si un determinado equipo está alcanzable a través de la red. Para ello se le lanza un Ping y si se recibe respuesta significa que hay conectividad con dicho equipo. Lo que ocurre entre bastidores es que el equipo que lanza el ping emite un paquete de tipo ICMP ECHO-REQUEST y el equipo destino, al recibir este paquete, genera otro de respuesta denominado ICMP ECHO-REPLY. Cuando el equipo que lanza los pings comienza a recibir paquetes ICMP ECHO-REPLY puede concluir que el equipo destino está “vivo”. Dado lo habitual de este protocolo en las redes modernas resulta un candidato interesante como cobertura a nuestro enlace de datos. Para ello se puede utilizar el campo de 56 bytes con el que cuentan los paquetes ICMP ECHO. El propósito original de este campo no está muy claro. En apariencia, los sistemas operativos actuales lo usan como una firma llenándolo con una secuencia de datos más o menos predefinida (p.ej. Windows mete siempre el abecedario “abcd...” mientras que Linux que he probado usan una secuencia más aleatoria pero acabada siempre por los caracteres “01234567”) con la idea de que si los paquetes de respuesta contienen la misma secuencia de datos entonces son correctos. Sin embargo, nadie dice cuál debe ser esa secuencia de datos por lo que nosotros podemos meter los que queramos y enviárselos al equipo destino en un Ping.

Vamos a ilustrar esto con un ejemplo usando Scapy. Supongamos que Alice quiere enviarle a Bob (10.0.0.105) el siguiente mensaje: “Creo que sospechan de ti.”. Podríamos encapsular este mensaje en un paquete ICMP de la siguiente manera desde la consola de Scapy:

Welcome to Scapy (v1.1.1 / -)
>>> ip = IP()
>>> ip.dst = "10.0.0.105"
>>> icmp = ICMP()
>>> mensaje = "Creo que sospechan de ti."
>>> icmp.add_payload(mensaje)
>>> packet = ip / icmp
>>> sr1(packet)
Begin emission:
.*Finished to send 1 packets.

 
Received 2 packets, got 1 answers, remaining 0 packets
<\IP  version=4L ihl=5L tos=0x0 len=53 id=53122 flags= frag=0L ttl=64 proto=icmp chksum=0x96d9 src=10.0.0.105 dst=10.0.0.4 options='' |<\ICMP  type=echo-reply code=0 chksum=0xd436 id=0x0 seq=0x0 |>>
>>> 



Bob podría visualizar este mensaje activando un tcpdump en su interfaz que capturase todos los paquetes icmp que le llegasen.

Si un administrador estuviese monitorizando la red sólo vería un ping, tráfico que no tiene por qué ser sospechoso ya que, a priori, no es un protocolo susceptible de transportar información (aunque vemos que en realidad sí puede). Además, un ping y su respuesta resultan imperceptibles dentro del maremagnum que es una red moderna. Si aún con todo el administrador ha sido tan minucioso como para detectar el intercambio de paquetes y capturarlos con un sniffer, esto sería lo que vería:


Como se puede apreciar, la captura del paquete ICMP sí que muestra claramente el contenido del mensaje en el campo Data. Para evitar la detección y además dotar de confidencialidad el mensaje lo normal es que en vez de encapsular el mensaje en claro en el campo Data, se cifre primero (por ejemplo con una clave simétrica conocida por ambos extremos) y luego se empaquete en el ping. De esta manera el administrador lo que vería sería un amasijo de bytes aparentemente aleatorios que no tienen por qué hacerle sospechar de que lo que está viendo realmente es un mensaje cifrado... a no ser que haya leído este artículo y por tanto sepa que si todo su parque de ordenadores es Windows los campos de datos de los pings deben contener, por fuerza, el abecedario “abcdefghi... “.

¿Qué pasaría con los mensajes con longitud superior a 56 bytes? Pues nada, los trocearíamos en lotes de 56 bytes y meteríamos cada uno en un ping. En vez de enviar un único ping mandaremos varios, lo cual sigue entrando dentro de lo normal cuando se utiliza legítimamente este protocolo. Dado que Scapy está pensado tanto para su uso interactivo por consola como para importarlo como librería en nuestros scripts de Python resulta sencillísimo automatizar todo este proceso en un programa que añada características añadidas como por ejemplo control de errores y corrección mediante reenvíos de paquetes (dado que no es raro que se pierda un ping incluso en redes locales). Sin embargo hay que tener en cuenta cuando integremos todo lo dicho en un programa que muchos dispositivos IDS/IPS controlan cuantos pings se pueden enviar entre dos puntos durante un intervalo de tiempo bloqueando los que excedan este umbral. Por eso, los programas que creemos para transmitir datos por ICMP deberán contar con un parámetro que permita configurar cuantos pings por segundo queremos enviar de manera que podamos asegurarnos de que nuestro envío nunca supere el umbral de los dispositivos IDS/IPS que pudieran encontrarse por el camino.

El tercer método de esteganografía de red, el uso de un campo numérico, no es sino una variante del anterior. La diferencia es que en vez de utilizar un campo específicamente destinado a datos se trata de utilizar uno dedicado a contener valores numéricos, como por ejemplo:
  • El campo de Identificación de la cabecera IP. Con 16 bits de longitud, se utiliza para darle un número identificativo a cada paquete de manera que sea posible reconstruirlo en caso de que se tenga que realizar fragmentación en alguno de los nodos intermedios del trayecto.
  • El campo de Número Inicial de Secuencia de la cabecera TCP. Sus 32 bits de longitud nos permitirían enviar cuatro caracteres ASCII por paquete. Se utiliza para establecer el número inicial a partir del cual se numerarán el resto de paquetes, de manera que se puedan detectar pérdidas o llegadas desordenadas de paquetes. Lo fija el que envía el paquete inicial.
  • El campo de Número de Secuencia Reconocido de la cabecera TCP. También de 32 bits, lo fija el extremo que responde al paquete inicial cogiendo el Número Inicial de Secuencia de ese paquete y sumándole uno. Este campo, como se verá después, se utiliza en para realizar transmisiones ocultas de datos de manera indirecta.
Los dos primeros campos se utilizarían igual que el de datos del ping que veíamos antes, sólo habría que tener en cuenta la menor longitud de los campos y que habría que codificar las cadenas a un valor numérico de la longitud necesaria en función de sus valores ASCII (y posteriormente decodificarlos en el extremo receptor). Stegtunnel utiliza precisamente estos dos campos.

El uso del campo de Número de Secuencia Reconocido de la cabecera TCP/IP es más interesante y es el que utilizan herramientas como Ncovert. Supongamos que Alice quiere enviarle un mensaje a Bob, pero ella sabe que hay un administrador de red muy paranóico que no le quita el ojo de encima a Bob y monitoriza todo el tráfico de su ordenador. Resulta que Alice no conoce oficialmente a Bob y sabe que cualquier acercamiento a él levantaría sospechas y lo mismo pasaría a nivel de red si se detectase tráfico desde el PC de Alice hacia el de Bob. Pero Alice ha leído estas líneas y sabe que puede ocultar su mensaje entre el tráfico “legal” de Bob. Para ello Alice eligiría un servidor al que acceda usualmente Bob, llamemoslo por ejemplo Mercurio, y lo utilizaría de intermediario para pasarle el mensaje.

La idea es la siguiente:
  1. Alice crearía sucesivos paquetes SYN (de establecimiento de conexión) con Mercurio poniendo en el campo de Número Inicial de Secuencia TCP (o en el de Identificación IP) los caracteres de su mensaje tal y como veíamos antes pero falsificaría el origen del paquete SYN poniendo que proviene de la dirección IP de Bob.
  2. Mercurio iría creando paquetes de SYN+ACK con destino a Bob (ya que él cree que es Bob el que le envía los paquetes SYN), utilizando en el campo de Número de Secuencia Reconocido el número fijado por Alice más 1.
  3. Bob sólo tendría que ir recopilando dichos paquetes SYN+ACK, extraer sus campos de Número de Secuencia Reconocido, restarle 1 y pasarlo a ASCII.


La ventaja de este sistema es que el acechante administrador sólo vería un flujo de paquetes entre Bob y Mercurio por lo que no sospecharía nada. Además, no es necesario dirigir los paquetes a un puerto a la escucha de Mercurio, ya que en caso de utilizar un puerto cerrado, Mercurio reenviará los datos a Bob en un paquete RST+ACK en vez de en un SYN+ACK. La pega es que los paquetes RST+ACK llaman bastante más la atención en una captura de red que los de SYN+ACK al señalar errores en las conexiones, por lo que si Alice quisiese minimizar la probabilidad de llamar la atención del administrador fijaría un puerto de destino abierto (por ejemplo, si Mercurio fuese un servidor Web utilizaría el puerto 80).

La creación de herramientas para realizar este tipo de comunicaciones es extremadamente sencilla. A continuación se muestra un ejemplo programado con Python y Scapy.

La herramienta que utilizaría Alice podría ser:


############################################ # STEGTRANSPORT # # Programado por: Dante Signal31 # # Stegtransport permite transferir datos camuflados # en las cabeceras TCP de paquetes SYN de apariencia # perfectamente normal. # ############################################ ########## # LIBRERIAS ########## import scapy import time import random ############ # CONSTANTES ############
# Por simplicidad marcamos el final del mensaje con una '#'.
MENSAJE = "Creo que sospechan de ti. Sera / mejor que tengas cuidado.#" IP_DESTINO = "192.168.10.105" IP_INTERMEDIARIO = "192.168.10.106" PUERTO_ESCUCHA_INTERMEDIARIO = 80 INTERVALO_DE_ESPERA=0.1 ################## # PROGRAMA PRINCIPAL ################## print "Mensaje a enviar: " + MENSAJE print "Destinatario del mensaje: " + IP_DESTINO print "Intermediario: " + IP_INTERMEDIARIO for caracter in MENSAJE: caracter_valor_ascii = ord(caracter) print "Enviando caracter: " + caracter + /" con valor ASCII: " + str(caracter_valor_ascii) + "..." paquete_ip = scapy.IP() paquete_ip.dst = IP_INTERMEDIARIO
    # Falsificamos el origen del paquete
# para que el intermediario responda al
# destinatario del mensaje oculto (IP_DESTINO)
# y no a nosotros.
paquete_ip.src = IP_DESTINO paquete_tcp = scapy.TCP() paquete_tcp.seq = caracter_valor_ascii paquete_tcp.dport = PUERTO_ESCUCHA_INTERMEDIARIO
    # Si no fijamos un puerto origen, Scapy utilizará
# siempre el 20, lo que puede ser muy sospechoso.
paquete_tcp.sport = random.randint(49152, 65535) paquete = paquete_ip / paquete_tcp scapy.sr1(paquete) print "enviado caracter."
    # Esperar entre un paquete y otro reduce la probabilidad
# de pérdidas, de llegadas desordenadas y de detecciones
# por parte de los IDS.
time.sleep(INTERVALO_DE_ESPERA) print "Mensaje enviado." print "¡Que tenga un buen dia!"

En su lado Bob ejecutaría el siguiente programa:



############################################
# STEGRECEIVE
#
# Programado por: Dante Signal31
#
# Stegreceive permite recibir datos camuflados en
# las cabeceras TCP de paquetes SYN de apariencia
# perfectamente normal.
#
############################################

##########
# LIBRERIAS
##########
import scapy
import sys

############
# CONSTANTES
############
TRUE = 1
FALSE = 0
IP_INTERMEDIARIO = "192.168.10.106"

##################
# PROGRAMA PRINCIPAL
##################
print "Esperando mensaje desde el intermediario: " /+ IP_INTERMEDIARIO + "\n---"
fin_mensaje = FALSE
# Fijamos el filtro de captura del tcpdump.
filtro_captura = "ip src host " + IP_INTERMEDIARIO
while (not fin_mensaje):
    paquete_recibido = scapy.sniff( /
filter=filtro_captura , count = 1)
    # Accedemos al campo ACK del subpaquete TCP recibido.
    caracter_valor_ascii = /
paquete_recibido[0][scapy.TCP].ack  - 1
    caracter = chr(caracter_valor_ascii)
    if (caracter == '#'): 
        fin_mensaje = TRUE
    sys.stdout.write(caracter)
    sys.stdout.flush()
print "\n---\nMensaje recibido."
print "¡Que tenga un buen dia!"

He dejado en googlecode un laboratorio descargable de Netkit listo para probar estas herramientas. Estas herramientas son meros ejemplos de laboratorio y son francamente mejorables. Por ejemplo, el campo de Número de Secuencia Reconocido de la cabecera TCP/IP tiene cuatro bytes y sólo estamos aprovechando uno para enviar el carácter del mensaje. Podríamos mejorar el programa utilizando los 3 bytes restantes: el primero podría rellenarse con un número de identificación de manera que se pudiera distinguir entre el tráfico legítimo entre Bob y Mercurio del tráfico esteganográfico; el segundo byte podría ser un mini-numero de secuencia para que pudiesen ordenarse los paquetes en caso de que llegasen desordenados o bien detectarse pérdidas si las hubiera; el tercer y el cuarto byte se podrían usar para enviar dos caracteres en vez de uno. Otra mejora sería utilizar sockets DIVERT en el lado receptor para evitar que el kernel de Bob llame la atención del administrador enviando al intermediario paquetes de RST por recibir paquetes de SYN+ACK inesperados (debemos recordar que el receptor, Bob, no envió realmente el SYN inicial sino que lo hizo Alice). Queda como ejercicio para el lector desarrollar estas mejoras o cualquier otra que se le ocurra. Con esto damos por terminado el presente artículo en que se ha realizado una breve introducción a la esteganografía de red o dicho, de otra manera, el arte de ocultar información en tráfico de red aparentemente normal. Se pueden utilizar otras herramientas, otros protocolos u otros campos de los paquetes pero por lo general la mayor parte de las técnicas de esteganografía de red se basarán en los fundamentos aquí presentados.

22 octubre 2008

Creación de laboratorios virtuales con Netkit (II)

En el anterior artículo sobre Netkit vimos un ejemplo sencillo de sus posibilidades para simular una red con varios dispositivos. Las posibilidades son casi infinitas, pero es cierto que necesitamos algún tipo de automatización si queremos simular topologías complejas, con muchos nodos y sobre todo si queremos pasarle estas topologías a otros investigadores para que experimenten con ellas. Netkit aporta este nivel de automatización mediante laboratorios, estructuras de directorios que contienen ficheros para configurar cada uno de los nodos de manera automática. Lo bueno es que podemos comprimir este árbol de directorios y pasárselo a otros investigadores los cuales podrán arrancar el laboratorio y tener todos los nodos configurados y funcionando con apenas un único comando. Además, este fichero comprimido no ocuparía practicamente nada ya que los ficheros de configuración de cada nodo son sólo texto.

Vamos a preparar como ejemplo un laboratorio en el que simularemos un escenario en el que Alice se conecta a Internet desde la red conmutada de su organización. Lo que ella no sabe es que un intruso ha conseguido acceso a la red y pretende lanzar un ataque de arp-spoofing contra Alice para averiguar qué páginas de internet visita.

Antes de nada debemos configurar Netkit para que funcione correctamente en nuestro sistema operativo en modo laboratorio. Lo primero son las variables globales que usa Netkit. En el artículo anterior las configuramos correctamente, el problema es que cuando arrancamos un laboratorio en el que uno de los equipos se conecta a Internet tenemos que usar sudo el cual ignora por seguridad la mayor parte de las variables globales, entre ellas las que nosotros configuramos y usamos como usuarios normales. Para solucionarlo hay que configurar el sudo para que no ignore las variables de Netkit editando el fichero /etc/sudoers. En la sección "Default" de este fichero hay que poner:

Defaults:dante env_keep+="NETKIT_HOME", env_keep+="MANPATH"

Por supuesto en vez de dante hay que poner nuestro nombre de usuario. Faltaría la variable PATH y el sentido común dice que se debería poder configurar en el sudoers como las otras dos... el problema es que no es así y sudo sigue ignorando la variable PATH del usuario por mucho que nosotros configuremos en sudoers lo contrario. Es algo que de hecho ya está reportado en el Launchpad de Ubuntu como un bug largamente arrastrado. La solución es crear un alias que incluya el PATH de usuario cada vez que usemos sudo. Para ello editamos el fichero .bash_aliases de nuestro home e introducimos:

#Para que funcione el NETKIT.
alias sudo="sudo env PATH=$PATH"

Con eso Netkit cuenta con todas las variables necesarias, tanto si usamos sudo como si lo arrancamos como usuario normal.

Por otro lado, la versión 2.6 tiene un bug que hace que no se levante bien la salida a Internet de la máquina virtual, la solución es un patch que sacó uno de los autores de la aplicación en la lista de correo:
======================================================== diff -Naur netkit-old/bin/script_utils netkit-new/bin/script_utils --- netkit-old/bin/script_utils 2007-12-19 10:55:58.000000000 +0100 +++ netkit-new/bin/script_utils 2008-02-02 12:48:46.000000000 +0100 @@ -317,8 +317,8 @@ # This function starts all the hubs inside a given list runHubs() { local HUB_NAME BASE_HUB_NAME ACTUAL_HUB_NAME TAP_ADDRESS GUEST_ADDRESS - HUB_NAME="$1" while [ $# -gt 0 ]; do + HUB_NAME="$1" BASE_HUB_NAME="`varReplace HUB_NAME \".*_\" \"\"`" if [ "${BASE_HUB_NAME#tap${HUB_SOCKET_EXTENSION},}" != "$BASE_HUB_NAME" ]; then # This is an Internet connected hub @@ -328,7 +328,7 @@ startInetHub "$ACTUAL_HUB_NAME" "$TAP_ADDRESS" "$GUEST_ADDRESS" else # This is a normal hub - startHub "$1" + startHub "$HUB_NAME" fi shift done ========================================================
Una manera de aplicar este patch es crear un fichero de texto en $NETKIT_HOME/bin/ llamado patch2_6_bug con el texto del patch y acto seguido hacer:

dante@Hades:/usr/share/netkit/bin$ sudo patch script_utils patch2_6_bug patching file script_utils dante@Hades:/usr/share/netkit/bin$

Con esto se acaba la peor parte: la configuración previa de Netkit. Lo bueno es que sólo hay que hacerlo una vez, a partir de ahora sólo tendremos que preocuparnos de crear buenos laboratorios.

Para empezar con el nuestro, tendremos que crear una carpeta para contener el árbol de directorios y los ficheros de configuración. En esa carpeta crearemos el fichero principal de configuración del laboratorio: lab.conf. Ese fichero podemos meter todos aquellos parámetros que usaríamos con vstart para definir una máquina individual. Podemos definir cuantos interfaces tendrá cada nodo y a qué dominio de colisión pertenecerá cada uno (hay que recordar que, a diferencia de los hubs, los switches definen un dominio de colisión diferente para cada uno de sus puertos). Otro elemento que se puede definir es la memoria RAM que usará cada máquina. También se puede incluir información para catalogar el laboratorio como su autor, una sinopsis, versión, etc. En nuestro caso, el fichero lab.conf será el siguiente:

dante@Hades:~/netkit_labs/lab_sniffing_sw$ cat lab.conf LAB_DESCRIPTION="Laboratorio para simular un ataque de ARP-Spoofing" LAB_VERSION="0.1" LAB_AUTHOR="Dante" LAB_EMAIL="dante.signal31@gmail.com" LAB_WEB="http://danteslab.blogspot.com/" PC-Alice[mem]=100 PC-Sniffer[mem]=100 Router[mem]=100 Switch[mem]=100 PC-Alice[0]=CD-A Switch[1]=CD-A PC-Sniffer[0]=CD-C Switch[2]=CD-C Router[1]=CD-B Switch[0]=CD-B Router[0]=tap,192.168.10.1,192.168.10.2

La última línea configura el interfaz eth0 del Router como tap. Eso equivale a establecer una línea punto a punto entre la máquina virtual Router (192.168.10.2) y nuestro PC real (192.168.10.1 ) a través de la cual Router podrá salir a Internet utilizando nuestro PC como puerta de enlace. De hecho si cuando arranquemos el laboratorio hacemos un ifconfig en nuestro PC veremos que se ha creado un interfaz llamado nk_tap_root con la IP 192.168.10.1. En cuanto a la ruta por defecto, Netkit se encarga de meter una ruta estática en Router apuntando a la 192.168.10.1. Todo esto permite que el Router salga a Internet normalmente pero si además queremos que salgan el resto de los PCs de la red virtual (utilizando a Router y a nuestro PC como saltos hacia Internet) tendremos que añadir una ruta en nuestro PC real hacia la red virtual:


dante@Hades:~$ sudo route add -net 192.168.0.0 netmask 255.255.255.0 gw 192.168.10.2

Ahora, dentro de la carpeta del laboratorio crearemos un subdirectorio por cada máquina virtual que vaya a utilizarse.

dante@Hades:~/netkit_labs$ mkdir lab_sniffing_sw dante@Hades:~/netkit_labs$ cd lab_sniffing_sw/ dante@Hades:~/netkit_labs/lab_sniffing_sw$ mkdir Routerdante@Hades:~/netkit_labs/lab_sniffing_sw$ mkdir Switch dante@Hades:~/netkit_labs/lab_sniffing_sw$ mkdir PC-Alice dante@Hades:~/netkit_labs/lab_sniffing_sw$ mkdir PC-Snifferdante@Hades:~/netkit_labs/lab_sniffing_sw$ ls PC-Alice PC-Sniffer Router dante@Hades:~/netkit_labs/lab_sniffing_sw$

Los subdirectorios de las máquinas virtuales pueden quedarse vacíos o utilizarse para depositar ficheros que luego aparecerían en la máquina virtual. Por ejemplo si quisieramos que PC-Alice contase con el script X en /usr/bin, crearíamos la carpeta "/netkit_labs/lab_sniffing_sw/PC-Alice/usr/bin" y depositaríamos ahí una copia del script. En nuestro caso lo que haremos será poner en el directorio /etc/ de cada equipo los ficheros necesarios para que se configuren los recursos de red de manera adecuada.
Para el caso de Alice, quedará de la siguiente manera:

dante@Hades:~/netkit_labs/lab_sniffing_sw$ cat ./PC-Alice/etc/network/interfaces auto lo eth0 iface lo inet loopback address 127.0.0.1 netmask 255.0.0.0 iface eth0 inet static address 192.168.0.2 netmask 255.255.255.0 gateway 192.168.0.1


El PC-Sniffer tendrá la siguiente configuración de red:


dante@Hades:~/netkit_labs/lab_sniffing_sw $ cat ./PC-Sniffer/etc/network/interfaces auto lo eth0 iface lo inet loopback address 127.0.0.1 netmask 255.0.0.0 iface eth0 inet static address 192.168.0.3 netmask 255.255.255.0 gateway 192.168.0.1

El Router tendrá la siguiente configuración de red:


dante@Hades:~/netkit_labs/lab_sniffing_sw $cat ./Router/etc/network/interfaces auto lo eth1 iface lo inet loopback address 127.0.0.1 netmask 255.0.0.0 iface eth1 inet static address 192.168.0.1 netmask 255.255.255.0

Además, si queremos que nuestras máquinas virtuales puedan hacer resoluciones DNS (indispensable si queremos instalar paquetes con apt o navegar con lynx), tendremos que incluir un fichero /etc/resolv.conf en cada una de las máquinas virtuales igual que hicimo s con /etc/network/interfaces. Una copia del contenido del fichero /etc /resolv.conf de nuestro PC real valdrá.

Por último queda configurar el switch y decidir qué servicios se van a arrancar en cada máquina virtual. Precisamente para eso, Netkit permite definir qué comandos se ejecutarán durante el arranque y el apagado de las máquinas virtuales mediante los scripts startup y shutdown respectivamente. Para nuestro laboratorio crearemos los siguie
ntes scripts:

dante@Hades:~/netkit_labs/lab_sniffing_sw$ cat Switch.startup ifconfig eth0 up ifconfig eth1 up ifconfig eth2 up brctl addbr br0 brctl addif br0 eth0 brctl addif br0 eth1 brctl addif br0 eth2 brctl stp br0 on ifconfig br0 up

Este script configura un bridge tras el arranque de la máquina Switch incorporando a dicho bridge los puertos eth0, eth1 y eth2 y activando también el
spanning-tree (innecesario en este caso porque sólo hay un switch pero se trata de una costumbre que deberíamos adquirir).

Los comandos de startup del resto de las máquinas son más sencillos ya que lo único que hacen es iniciar el servicio de red:


dante@Hades:~/netkit_labs/lab_sniffing_sw$ cat Router.startup /etc/init.d/networking start dante@Hades:~/netkit_labs/lab_sniffing_sw$ cat PC-Alice.startup /etc/init.d/networking start dante@Hades:~/netkit_labs/lab_sniffing_sw $ cat PC-Sniffer.startup /etc/init.d/networking start

Este ejemplo es muy sencillo, pero gracias a estos scripts podemos hacer que un laboratorio se configure sólo sin que el usuario final que lo pruebe tenga que molestarse en tocar o instalar nada. De hecho lo más cómodo es configurar las direcciones IP de los interfaces y las rutas a través de estos scripts en vez de copiando los ficheros de configuración en la carpeta /etc de cada máquina, pero dar ese rodeo me ha permitido explicar la posibilidad de introducir archivos en el árbol de directorios de las máquinas virtuales.

Ahora, por fin, ha llegado el momento de arrancar nuestro laboratorio. Los laboratorios se arrancan con la orden lstart y se paran con lhalt. Veamos lo que pasa en nuestro caso:
dante@Hades:~/netkit_labs/lab_sniffing_sw$ sudo lstart [sudo] password for dante: 033[1m======================== Starting lab ===========================033[0m Lab directory: /home/dante/netkit_labs/lab_sn iffing_sw Version: 0.1 Author: Dante Email: dante.signal31@gmail.com Web: http://danteslab.blogspot.com/ Description: Laboratorio para simular un ataque de ARP-Spoofing 033[1m=================================================================033[0m 033[1mStarting "PC-Alice" with options "-q --mem=100 --eth0 CD-A --hostlab=/home/dante/netkit_labs/lab_sniffing_sw --hostwd=/ho me/dante/netkit_labs/lab_sniffing_sw"... 033[0m 033[1mStarting "PC-Sniffer" with options "-q --mem=100 --eth0 CD-C --hostlab=/home/dante/netkit_labs/lab_sniffing_sw --hostwd=/hom e/dante/netkit_labs/lab_sniffing_sw"... 033[0m 033[1mStarting "Router" with options "-q --mem=100 --eth1 CD-B --eth0 tap,192.168.10.1,192.168.10.2 --hostlab=/home/dante/netkit_labs/lab_sniffing_sw --hostwd=/home/dante/netkit_labs/lab_sniffing_sw"... 033[0m 033[1mStarting "Switch" with options "-q --mem=100 --eth1 CD-A --eth2 CD-C --eth0 CD-B --hostlab=/home/dante/netkit_labs/lab_sniffing_sw --hostwd=/home/dante/netkit_labs/lab_sniffing_sw"... 033[0m 033[1mThe lab has been started.033[0m 033[1m===================== ============================================033[0m dante@Hades:~/netkit_labs/lab_sniffing_sw$

Para comprobar que la red resultante funciona podemos probar a navegar por Internet con el lynx desde PC-Alice:




Ahora que hemos comprobado que nuestra red funciona vamos darle un uso a nuestro laboratorio realizando el experimento que mencionábamos al comienzo del artículo: un ataque de ARP-Spoofing contra Alice desde PC-Sniffer.

Como se puede ver en la foto anterior
, PC-Sniffer tiene activado un tcpdump, pero sólo ve el tráfico de spanning tree (STP) emitido por el switch. A diferencia de la red del artículo anterior en la que se simulaba un hub, en esta el switch no replica el tráfico por todos sus puertos sino sólo en el puerto al que se conecta el destinatario de los datos.

Para espiar el tráfico habrá que situarse entre Router y PC-Alice haciendoles creer que hablan entre sí cuando en realidad su interlocutor es PC-Sniffer.


Usaremos la herramienta Ettercap, que ya viene instalada por defecto en el Debian que trae Netkit (si no, podríamos haberla instalado con un simple "#aptitude install ettercap", como haríamos en nuestro PC real). Ettercap permite hacer intercepciones en redes conmutadas. En realidad es una pequeña maravilla que merece un artículo para ella sola. Aquí usaremos Ettercap desde el PC-Sniffer para espiar el tráfico web de Alice. Para activar un ataque de ARP-Spoofing (también llamado ARP-Poisoning) con Ettercap la orden sería:

PC-Sniffer# ettercap -M arp:remote -T /192.168.0.1/ /192.168.0.2/

Inmediatamente la pantalla de PC-Sniffer empieza a sacar el contenido de los datos que PC-Alice intercambia con su puerta de enlace, Router, mientras navega por Internet:




Para parar el laboratorio sólo tenemos que hacer "sudo lhalt" desde el directorio raíz del laboratorio (donde lanzamos antes el lstart). Si quisieramos relanzar el laboratorio debemos tener en cuenta que hay que volver a meter la ruta hacia la red virtual ya que la que dimos de alta antes desapareció cuando lhalt desactivó el interfaz tap. Por otro lado, el lstart creo ficheros .disk en la carpeta del laboratorio para que no se pierdan los programas que hayamos instalado en las máquinas virtuales o cualquier otra modificación que hayamos hecho, eso quiere decir que las carpetas donde pusimos los ficheros de configuración dejan de tener efecto por lo que si queremos poner nuevos ficheros allí primero tendremos que borrar los ficheros .disk y hacer un lstart para que Netkit vuelva a leer esas carpetas. Existe otra opción más útil para transferir ficheros a las máquinas virtuales y es mediante la carpeta /hosthome que hay en todas las máquinas virtuales y que monta el home del usuario que lanzó el Netkit.

En otro artículo explicaré qué es lo que hace Ettercap entre bastidores y cómo funcionan esta y otras técnicas de interceptación. Este artículo lo que ha servido es para demostrar la utilidad de Netkit a la hora de simular redes complejas con las que hacer experimentos de seguridad informática con un ahorro considerable tanto en esfuerzo, como en dinero y espacio. Supone también una ayuda valiosísima para los que pretendemos divulgar el arte de la seguridad informática, ya que nos permite ofrecer a nuestros lectores laboratorios preconfigurados que les permitirán concentrarse exclusivamente en las técnicas explicadas sin que tengan que perder el tiempo montando una red de prueba propia. Por ello, mis artículos futuros incluirán enlaces a laboratorios de Netkit especialmente diseñados para probar de una manera rápida y sencilla lo que se explique en ellos.