Friday, April 13, 2018

Polymorph: Modificando paquetes ICMP en tiempo real

@santiagohramos

https://github.com/shramos/polymorph


En este post vamos a ver lo sencillo que sería modificar el contenido de paquetes pertenecientes al protocolo ICMP utilizando Polymorph.

Lo primero de todo, vamos a instalar la herramienta y a establecer el entorno de pruebas. Para empezar todos en el mismo punto, vamos a utilizar el despliegue con Docker que incorpora Polymorph:

cd polymorph
docker-compose up -d

Una vez ejecutados los commandos se empezará a formar el entorno, cuando termine, accedemos a las tres máquinas mediante:

docker exec -ti polymorph bash
docker exec -ti bob bash
docker exec -ti alice bash

Las tres maquinas se encuentran en la misma red, que tiene una estructura muy sencilla:
  • Polymorph: 10.24.0.2
  • Alice: 10.24.0.3
  • Bob: 10.24.0.4 

Vamos a instalar la utilidad traceroute en la máquina bob, y vamos a ejecutarlo para ver la ruta que siguen los paquetes hasta alice:

apt-get install traceroute
Traceroute 10.24.0.3

Como podéis ver, el primer y ultimo salto es alice:


Nos situamos en la maquina polymorph, y desde cualquier parte ejecutamos el comando polymorph, esto abrirá la herramienta. Una vez abierta, vamos a utilizar el módulo de arp spoofing para interceptar la comunicación entre alice y bob:


Si ahora nos situamos en bob y volvemos a ejecutar el comando traceroute, veremos que la comunicación pasa por la máquina polymorph:


Ya tenemos la comunicación interceptada entre las dos máquinas legítimas, ahora los paquetes están fluyendo por la máquina polymorph y siendo reenviados. Vamos a poner la herramienta a hacer sniffing con el objetivo de capturar un paquete ICMP, para ello utilizamos el comando capture y tras ejecutarlo, haremos un ping desde bob a alice o viceversa.


Utilizamos Ctr-C para terminar el proceso de sniffing, y automáticamente la herramienta genera una plantilla para cada uno de los paquetes capturados. Podemos verlo mediante el comando show.


Como inciso, recalcar que esta primera disección y generación de la plantilla se hace con los disectores de Scapy, que muchas veces no serán capaces de diseccionar algunos protocolos complejos, para utilizar disectores más avanzados sobre las plantillas, utilizaríamos el comando dissect.


Volviendo al ejemplo, vamos a buscar entre las plantillas una que se corresponda con el paquete que queremos modificar y vamos a acceder a ella mediante el comando template:


Ahora estamos en el contexto de una plantilla, y podemos realizar modificaciones sobre ella. El concepto de plantilla es importante, es lo que le permite al usuario acceder en tiempo real a paquetes de distintos protocolos mediante una sintaxis sencilla. Vamos a verlo con el ejemplo.
Si ejecutamos el comando show, podemos ver el contenido de la plantilla generada a partir del paquete, en este caso, vamos a modificar el campo load de la capa RAW, que es donde se encuentran los datos.


En este punto es donde entran en juego las funciones condicionales (precondiciones, postcondiciones y ejecuciones). Cuando el usuario, en el contexto de la plantilla introduzca el comando intercept, la máquina polymorph dejará de reenviar los paquetes a nivel del kernel y comenzará a enviar esos paquetes a la herramienta para que los procese antes de que sean reenviados, sobre cada uno de los paquetes que pasen por la máquina,  se ejecutarán las funciones condicionales que hayamos definido. Vamos a ver un ejemplo sencillo, vamos a añadir la siguiente precondición a nuestra plantilla actual mediante el comando precs -a condición_prueba. 

Si utilizais el editor por defecto, pico, recordad no meter tabulaciones y espacios mezclados, mejor tabular el código con espacios. (podéis indicar otro editor que este en el path con la opción -e):


Introducimos "y" para mantenerla en disco e introducimos precs -s para ver la precondición añadida.


Ahora introducimos el comando intercept:


Fijaros como todos los paquetes que fluyen a través de la máquina son procesados por la herramienta y se ejecuta la precondición que hemos añadido, como estamos interceptando la comunicación entre la máquina alice y bob, si hacemos un ping de una a otra, los paquetes pasan por la máquina polymorph y la herramienta ejecuta la precondición sobre ellos.

Una vez entendido esto, vamos a salir del modo interceptar con Ctr-C (de tal forma que la máquina polymorph únicamente reenvie los paquetes sin pasarlos por la herramienta) y vamos a añadir las siguientes precondiciones, ejecuciones y postcondiciones, que, insisto, cuando estemos interceptando se ejecutarán sobre todos los paquetes que se intercepten (para eliminar la precondición de prueba precs -d condición_prueba). 

Si utilizais el editor por defecto, pico, recordad no meter tabulaciones y espacios mezclados, mejor tabular el código con espacios. (podéis indicar otro editor que este en el path con la opción -e)
  • Precondición
  • Ejecución
  • Postcondición 


Las funciones condicionales funcionan de la siguiente forma, primero se ejecutan las precondiciones en el orden en el que las hayamos metido, después las ejecuciones y por último las postcondiciones. Si algún punto de la ejecución de cualquiera de las tres se devuleve el valor None, se rompe la cadena de ejecución y se reenvía el paquete tal cual esté en ese momento, si por el contrario, se devuelve el paquete que se recibe como argumento, la cadena de ejecución de condiciones continúa. El paquete que se recibe como arguemento es el paquete que se ha interceptado en tiempo real en ese momento.

En este caso hemos añadido una precondición que dice: 
"si en el paquete que llegue existe una capa IP con un campo proto con el valor 1 (que indica que se trata de un paquete ICMP), retorna el paquete y continua ejecutando funciones condicionales, en el caso contrario retorna None y reenvía el paquete sin ejecutar nada más."

La ejecución dice: 
"en la capa RAW y el campo load del paquete que ha pasado la precondición introdúceme este nuevo valor. Si os fijais en la plantilla cuado ejecutamos el comando show, el tipo del campo load es hex, es muy importante que los tipos que se asignan o comparan sean los mismo, sino se producirá un error de tipos."

Por último la postcondición dice:
"el paquete que me llega después de ejecutar la precondición y ejecución sobre él, transfórmamelo a un paquete scapy, recalculame los campos de control para que quede consistente, vuelve a asignarlo a la variable paquete de polymorph y retornalo para que sea reenviado."

Como ya no hay más condiciones después de la postcondición el paquete se reenvía.

Una vez añadidas las funciones, vamos a la máquina bob e instalamos tcpdump mediante apt-get install tcpdump y ejecutamos el siguiente comando.


Una vez que tcpdump este escuchando, vamos a alice y enviamos un ping a bob, (aun no hemos ejecutado el comando intercept en la máquina polymorph), en bob deberíamos ver el contenido de los paquetes.


Ahora vamos a la máquina polymorph y ejecutamos el comando intercept, regresamos a alice y hacemos un ping a bob, fijaros como no se pierde ningún paquete pero el contenido del ICMP que recibe bob es el introducido por el atacante.



Una vez terminado, podemos pulsar Ctr-C para salir del modo intercept en la herramienta y con el comando save guardar la plantilla, que podremos intercambiar o transportar a otro pc. Para importarla en la herramienta utilizamos la sentencia polymorph -t plantilla.json desde la consola de comandos.



No comments:

Post a Comment