Cuando las ballenas vuelan (episodio II) – Creando un entorno de análisis GSM usando Docker (parte 1)
Esta serie de entradas (parte 2 y parte 3) surge inspirada por ésta entrada de Fox Glove Security: When Whales Fly – Building a Wireless Pentest Environment using Docker donde se explica cómo utilizar contenedores Docker para hacer más fácil el uso de algunas herramientas de pentesting WiFi. En este caso lo que se ha querido «contenizar» son herramientas para analizar comunicaciones GSM.
Aunque en esa entrada hay un excelente resumen sobre contenedores, Docker, imágenes y la filosofía de trabajo, aquí se rescatan algunos aspectos importantes para quien no sepa de que va el tema:
- A nivel usuario, Docker (o LXC) no deja de comportarse como una especie de hypervisor, aunque son conceptos diferentes. Una analogía que me ayudó a entender la diferencia en el aislamiento que proporcionan es: cuando se virtualiza con un hypervisor «clásico» las máquinas virtuales son como casa individuales; los contenedores, en cambio, se parecen más a los apartamentos de un mismo edificio (Containers are not VMs).
- Docker es el motor sobre el que corren los contenedores y estos comparten recursos, a través del kernel, con el host y con los otros contenedores.
- Docker permite ejecutar versiones específicas de aplicaciones sin la penalización de rendimiento que suponen las máquinas virtuales.
- Las imágenes Docker serían el equivalente a los binarios tradicionales en los SO, a partir de ellas se pueden crear contenedores (el equivalente a los procesos en los SO tradicionales).
- Los contenedores pueden ser efímeros o perdurar tanto como quiera el usuario.
- Los contenedores se pueden ejecutar de forma interactiva o como servicios.
Toda la información sobre Docker puede encontrarse en su propia sección de documentación:
Software Defined Radio
Contenedor base
El primer paso ha sido crear un contenedor con las herramientas básicas para trabajar con SDRs (Software Defined Radio), como por ejemplo los basados en hardware RTL, y con soporte para ejecutar aplicaciones gráficas aceleradas por hardware. El motivo para crear este contenedor base es poder aprovecharlo a la hora de trabajar con aplicaciones para otros protocolos de radio.
Nota: RTL-SDR es un tipo de SDR muy barato que utiliza dongles USB basados en el chip RTL2832U pensados para ver la TV y escuchar la radio. Mediante los esfuerzos combinados de Antti Palosaari, Eric Fry y Osmocom se descubrió que era posible acceder directamente a los datos de la señal I/Q de estos dispositivos, lo que permitió convertirlos en SDRs mediante un nuevo driver.
El código para crear la imagen Docker está en este repositorio:
Así como ésta ya compilada en Docker Hub:
docker pull pachulo/xenial-gnuradio-rtl-toolkit
Como se puede ver en el Dockerfile la imagen:
- Está basada en una imagen oficial de Ubuntu Xenial (16.04) con VirtualGL instalado (la explicación del porqué es necesario este componente está en la sección «Why do we need VirtualGL?» del Setting up a hw accelerated desktop on AWS G2 instances).
- Utiliza los drivers UHD del PPA de Ettus Research.
- Utiliza la última versión de los drivers SDR y de GNU-Radio empaquetados por la gente de Myriad-RF.
- Utiliza la última versión de Wireshark del PPA de los propios desarolladores.
- Compila este fork de los drivers rtl-sdr (más información aquí).
- Compila este fork del kalibrate-rtl, una herramienta para calibrar el error a la hora de sintonizar de los dispositivos RTL (más información sobre los diferentes forks).
Una vez compilada la imagen o descargada de Docker Hub, ya podremos realizar las primeras pruebas: por ejemplo, para comprobar que podemos acceder al dispositivo RTL desde el contenedor, podemos ejecutar el comando rtl_test dentro de un contenedor efímero:
docker run --rm --device=/dev/bus/usb/002 --entrypoint rtl_test pachulo/xenial-gnuradio-rtl-toolkit
Nota: una forma fácil de averiguar en que HUB USB hemos conectado nuestro dispositivo es ejecutar el comando dmesg justo después de conectarlo. Para el ejemplo de arriba me he guiado por esta información:
... [10891.158562] usb 2-1.3: new high-speed USB device number 14 using ehci-pci [10891.279033] usb 2-1.3: New USB device found, idVendor=0bda, idProduct=2838 [10891.279039] usb 2-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [10891.279041] usb 2-1.3: Product: RTL2838UHIDIR [10891.279043] usb 2-1.3: Manufacturer: Realtek [10891.279045] usb 2-1.3: SerialNumber: 00000001 ...
GR-GSM
Basado en la anterior se ha creado una imagen con gr-gsm, un software basado en GNURadio y cuyo objetivo es (según su propio autor):
The aim is to provide set of tools for receiving information transmitted by GSM equipment/devices.
En el siguiente enlace su pueden obtener los ficheros para compilar la imagen Docker:
Así como ésta ya compilada en Docker Hub:
docker pull pachulo/xenial-gr-gsm
Tal y como se puede observar en el Dockerfile, para crear la imagen se compila el software desde el código fuente y se copian un par de archivos para su correcto funcionamiento.
Antes de poder utilizar la imagen habrá que explicar un par de cosas sobre ejecutar aplicaciones basadas en X11 dentro de contenedores.
Aplicaciones gráficas dentro de contenedores
Ejecutar aplicaciones con GUI dentro de contenedores es un problema que ya se ha abordado anteriormente y para el que existen varias soluciones. Y si queremos obtener aceleración por hardware para utilizar aplicaciones OpenGL (como por ejemplo GNURadio) la cosa se complica un poco más, tal y como se explica en HW accelerated GUI apps on Docker.
Además de todo esto, si el sistema utiliza una tarjeta gráfica NVIDIA con el driver privativo, hará falta instalar en el host nvidia-docker, una utilidad de NVIDIA para crear y ejecutar imágenes Docker con acceso a sus GPUs (el porqué es necesaria la utilidad está explicado en su wiki).
La solución que se ha utilizado para este caso es la siguiente:
- Antes de crear el contenedor:
- Se crea un nuevo fichero Xauthority, en base a ~/.Xauthority, eliminando de la cookie las restricciones para clientes locales (idea extraída de Can you run GUI apps in a docker container?
y Authentication with X cookie instead of xhost +LOCAL). - Se crea un fichero para hacer de socket X.
- Se crea un nuevo fichero Xauthority, en base a ~/.Xauthority, eliminando de la cookie las restricciones para clientes locales (idea extraída de Can you run GUI apps in a docker container?
- Y al crearlo:
- Se monta el nuevo fichero Xauthority dentro del contenedor.
- Se configura la variable de entorno XAUTH en el contenedor para que apunte al nuevo fichero Xauthority.
- Se pasa la variable de entorno DISPLAY al contenedor con el mismo valor que la del host.
- Se monta el fichero que hará de socket X dentro del contenedor.
- Se monta el fichero de caracteres que representa a la tarjeta gráfica dentro del contenedor (de esto se encarga nvidia-docker para GPUs NVIDIA).
Ya que creo que ofrece suficiente aislamiento: el contenedor solo tendrá acceso de lectura-escritura al socket X y al fichero Xauthority y solo se podrá acceder al servidor X11 con la cookie creada para el nuevo fichero Xauthority, además de funcionar con la aceleración por hardware.
Nota: El contenedor creado funciona en mi máquina Ubuntu, que utiliza una tarjeta NVIDIA y el driver privativo, con nvidia-docker pero lo suyo sería ver si en otros sistemas basados en Linux con gráficas Intel y ATI también funciona (utilizando los drivers basados en MESA en esos casos, tal y como se explica aquí). Los usuarios de Windows y MacOS pueden probar alguna de las cosas que se comentan en este issue de Docker.
gr-gsm livemon
Una vez compilada o descargada la imagen y instalado nvidia-docker en el host ya se podrá realizar alguna prueba, como por ejemplo sintonizar el canal de broadcast (BCCH) de estaciones base próximas con la aplicación grgsm_livemon, ejecutando el siguiente script:
# Video support XAUTH=/tmp/.docker.xauth touch $XAUTH xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge - XSOCK=/tmp/.X11-unix # Launch container nvidia-docker run \ --volume $XAUTH:$XAUTH \ --env XAUTHORITY=$XAUTH \ --env DISPLAY \ --volume $XSOCK:$XSOCK \ --env="QT_X11_NO_MITSHM=1" \ --device=/dev/bus/usb/002 \ --rm \ --entrypoint grgsm_livemon \ pachulo/xenial-gr-gsm
Si todo ha ido bien, se tendría que abrir una ventana como esta:
OsmocomBB
Otra de las imágenes que se ha creado ha sido una con OsmocomBB listo para usar. Toda la información sobre OsmocomBB se puede encontrar en su wiki, pero básicamente:
OsmocomBB is an Free Software / Open Source GSM Baseband software implementation. It
intends to completely replace the need for a proprietary GSM baseband software, such as
– drivers for the GSM analog and digital baseband (integrated and external) peripherals
– the GSM phone-side protocol stack, from layer 1 up to layer 3
In short: By using OsmocomBB on a compatible phone, you will be able
to make and receive phone calls, send and receive SMS, etc. based on Free Software only.
En el siguiente enlace su pueden obtener los ficheros para compilar la imagen Docker:
Así como ésta ya compilada en Docker Hub:
docker pull pachulo/xenial-osmocombb
Nota: Para poder utilizar esta imagen hará falta un teléfono compatible y un cable/adaptador USB-serie.
Cargar firmware y ejecutar la aplicación mobile
Una vez descargada (o compilada) la imagen y conectado el teléfono con el adaptador USB-serie, podemos arrancar un contenedor con la misma:
docker run --device=/dev/ttyUSB0 --rm -it --name test-osmocombb pachulo/xenial-osmocombb
Podemos probar a cargar un firmware en el teléfono ejecutando el comando osmocon dentro del contenedor:
cd /osmocom-bb/src/host/osmocon && ./osmocon -p /dev/ttyUSB0 -m c123xor ../../target/firmware/board/compal_e88/layer1.compalram.bin
Y haciendo una pulsación corta del botón de encendido del teléfono.
Si el firmware se ha cargado de forma correcta, el siguiente paso será conectarse al contenedor desde otro terminal:
docker exec -ti test-osmocombb /bin/bash
Y ejecutar «mobile», la implementación de la funcionalidad de un teléfono móvil normal que correrá en el contenedor:
cd /osmocom-bb/src/host/layer23/src/mobile && ./mobile -i 127.0.0.1
Que permitirá conectarse, desde otro terminal:
docker exec -ti test-osmocombb /bin/bash
E interactuar con el teléfono a través de telnet:
telnet 127.0.0.1 4247
Kraken
Otra de las herramientas que se utilizan para el análisis de seguridad de redes GSM es Kraken, un software que:
… allows the ‘cracking’ of A5/1 keys used to secure GSM 2G calls and SMS.
Nota: Para poder ejecutar esta herramienta será necesario un disco de 2TB para almacenar las rainbow tables (y unos 1.8TB de espacio de disco en otro sitio para descargarlas y poder volcarlas luego). Todo el proceso está explicado en Passive GSM interception Part 1. Para el volcado de las tablas se puede utilizar el contenedor.
Los ficheros para compilar la imagen están aquí:
Así como ésta ya compilada en Docker Hub:
docker pull pachulo/xenial-kraken
Y para arrancar el contenedor se podrá hacer con un comando similar a este:
docker run -ti --rm \ --device=/dev/disk/by-id/wwn-0x5000c50091dc385d-part2:/dev/xvdc2 \ -v /media/$USER/DRIZZLECHAIR/kraken/indexes/:/kraken/indexes/ pachulo/xenial-kraken
Conclusión
En las siguientes partes de la seríe se demostrará cómo ejecutar algunos escenarios de análisis y ataque en GSM utilizando estos contenedores.
Pingback: Cuando las ballenas vuelan (episodio II) – Creando un entorno de análisis GSM usando Docker (parte 2) | Testpurposes
Pingback: Cuando las ballenas vuelan (episodio II) – Creando un entorno de análisis GSM usando Docker (parte 3) | Testpurposes