A finales del verano pasado, justo antes de las vacaciones, y de la importante decisión de abandonar mi cálida isla de
Tenerife para trasladarme a León e incorporarme a la disciplina de
INTECO, me entró curiosidad por analizar el protocolo de comunicación de
Whatsapp, que a lo largo de los últimos años se ha erigido como líder absoluto e indiscutible en el trono de los sistemas de mensajería móvil - y si no que se lo digan a
Mark Zuckerberg -.
 |
| Figura 1: WhatsApp se ha erigido en app por excelencia para chatear |
A lo largo de su historia este popular aplicativo ha sido noticia constantemente por sus problemas relacionados tanto con la seguridad de la información transmitida, que
en su día llegó a viajar en texto plano, como por la
privacidad de las diferentes versiones de WhatsApp para Android o de
las versiones de WhatsApp para iPhone. Conocidas estas debilidades, todo el mundo siempre ha tenido mucho interés en saber cómo se pueden
espiar las conversaciones de WhatsApp. No obstante, desde finales de 2012, la comunicación entre servidor y clientes van cifradas a día de hoy, aunque es conocido que
todavía existen debilidades graves con el cifrado que se usa por la red, así que mi interés se encontraba precisamente en analizar cómo se producía el cifrado de dicha comunicación.
Para ello, el primer paso era investigar y obtener toda la información disponible en la red acerca del protocolo
FunXMPP utilizado por
WhatsApp, que en aquel momento no era tanta como ahora, así que tras un poco de investigación llegué a la conclusión de que en primer lugar tenía que descubrir la clave de cifrado que utiliza el dispositivo con el que iba a realizar el análisis, (en este caso mi
iPhone 4S), y que se transmite únicamente la primera vez a la hora de instalar la
app en el terminal.
Esta clave se intercambia mediante
SSL, pero el tráfico correspondiente a las conversaciones puede discurrir por los puertos
443, 5222 y
5223 así que para poder inspeccionar no sólo el tráfico
SSL sino todos los paquetes, hice pasar el tráfico de mi móvil a través de mi equipo implementando un esquema de
ataque de red tipo
"machine" in the middle como el que monté en la famosa
historia del vecino que me robaba la WiFi y acabo hackeado, utilizando además el famoso
proxy Burp, instalando el certificado
PortSwigger como enseñaba
Alejandro Ramos (
@aramosf) en
este post en Security By Default.
Tras reinstalar la
app de
WhatsApp y obtener la interacción de mensajes entre cliente y servidor, pude tener acceso a la clave de cifrado de mi dispositivo, como se puede observar en la siguiente imagen:
 |
| Figura 2: Capturando el tráfico de WhatsApp de un iPhone |
Además de esto, en esta conexión el cliente enviaba también otras peticiones entre las que incluía la información correspondiente a los teléfonos que tenía en su agenda para actualizar los estados de todos sus contactos, pero no voy a profundizar en estas cuestiones para no dispersarme del tema central de este artículo, porque además
ya se han escrito otros al respecto y realmente
cualquiera que conozca tu número puede consultar tu perfil.
Una vez tenía en mano mi propia clave de cifrado, me dispuse a analizar el tráfico generado entre mi móvil y los servidores de
WhatsApp. Para esto, decidí utilizar
WhatsAPI, una
API desarrollada por
Max Kovaljov utilizando ingeniería inversa para poder conectar con
WhatsApp desde
PHP de cara a implementar un cliente de escritorio o cualquier cosa que a alguien se le pueda ocurrir. Cuando me puse en contacto con él, y le conté que estaba usando
WhatsAPI para analizar el tráfico generado por mi propio dispositivo, se quedó a cuadros, porque según me comentaba
Max, el uso habitual que la gente hacía de esta
API era intentar registrar un teléfono desde el
PC para poder enviar y recibir mensajes.
 |
| Figura 3: WhatsAPI en PHP |
La verdad que tras las vacaciones, así como con el ajetreo del cambio de vida y rumbo a
León, no pude llegar a concluir mi investigación y llegar a descifrar completamente una conversación que había capturado. Hice algunos avances empezando a entender el protocolo
FunXMPP, a decodificar los paquetes transmitidos en busca del inicio de la comunicación, y los
challenge_node enviados por los servidores de
WhatsApp para proceder al cifrado de los mensajes:
 |
| Figura 4: Obtención del challenge_node |
Uno de los problemas añadidos al evidente que supone trabajar desde el otro lado, es que además los desarrolladores de
WhatsApp introducen constantemente cambios tanto en su plataforma como en el comportamiento de sus clientes, y durante el tiempo que estuve investigando este tema descubrí con
Max algunas de estas modificaciones, que además variaban dependiendo del sistema operativo del dispositivo móvil (
iOS,
Android,
BlackBerry,
Windows Phone...) y la versión del cliente. Un ejemplo de estas modificaciones es que, al retomar la investigación tras un tiempo, pude ver que al menos conectando desde mi
iPhone, ya no se enviaba ningún
challenge_node por parte de los servidores de
WhatsApp, por lo que concluimos que se había pactado en una sesión anterior.
Durante esta etapa, además de
Max, me puse en contacto con
Pablo San Emeterio, que estaba haciendo algo parecido estudiando también el protocolo por su cuenta, utilizando
Yowsup en lugar de
WhatsAPI, y quien junto a
Jaime Sánchez hace tan sólo unos meses, consiguió llegar al final y publicar este excelente trabajo.
No he descrito con excesivo detalle el protocolo
FunXMPP porque no es el objeto de este artículo, y porque a día de hoy, pasado un tiempo, ya
Pablo y
Jaime se han encargado de explicarlo con pelos y señales para quien quiera echarle un vistazo.
De todo lo que pude deducir durante esta fase de análisis, una de las cosas que más me llamó la atención es que cuando un cliente establece la conexión con los servidores de
WhatsApp, antes de iniciar la comunicación cifrada se envía siempre un paquete previo en texto plano para iniciar la comunicación, que comienza con la cadena “
WA”, y en el que se envían además de otros parámetros que van codificados como la versión del protocolo o el mecanismo de autenticación, la siguiente información legible a simple vista:
- Sistema operativo del cliente
- Versión del aplicativo Whatsapp
- Puerto utilizado para la transmisión: 443, 5222 o 5223 (salvo en Android)
- Número de teléfono con prefijo del país
 |
| Figura 6: Paquete con el número de teléfono enviada desde un terminal iPhone |
El paquete que se puede observar en la imagen corresponde al enviado por mi teléfono móvil durante la sesión en la que capturaba el tráfico, pero inmediatamente pensé en cuántos de estos paquetes se transmitirían en redes
WiFi públicas. Tras realizar algunas pruebas y obtener capturas en diferentes lugares y momentos a lo largo de este tiempo, por aquello de los posibles cambios que han podido introducir los desarrolladores de
WhatsApp en el protocolo, he podido confirmar que a día de hoy esto sigue igual - a expensas de lo que pueda pasar ahora tras la compra de
WhatsApp por parte de
Facebook -. A continuación muestro algunos ejemplos de paquetes de diferentes dispositivos obtenidos en capturas aleatorias: 
 |
| Figura 7: Paquete enviado desde WhatsApp para Android con el número de teléfono |
 |
| Figura 8: Paquete enviado desde WhatsApp para Symbian con el número de teléfono |
Tras confirmar esto, pensé en el uso potencial que esta característica de la implementación del protocolo de
WhatsApp puede tener para detectar números de teléfonos de personas que se encuentren usando alegremente esas redes
WiFi abiertas de cafeterías, centros comerciales, hoteles o aeropuertos, sobretodo para mis amigos solteros. Esa rubia que se encuentra en la mesa enfrente de nosotros, tecleando compulsivamente como si se le fuera la vida en ello, seguramente utilizando
WhatsApp. ¿Se imaginan poder obtener su teléfono para primero ver su estado, foto de perfil, confirmar que es ella y enviarle un mensaje?
 |
| Figura 9: Verdad verdadera |
Como esto de capturar el tráfico, abrir un
.pcap y analizar los paquetes no es para mis amigos solteros, que de esto saben lo mismo que yo de jardinería, me decidí a hacer una herramienta que pudiese capturar estos paquetes y hacer el trabajo sucio por ellos, a la que he bautizado como “
WhatsApp Discover”: 
 |
| Figura 10: WhatsApp Discover corriendo en Kali Linux |

La herramienta consiste en un sencillo
script en
Perl, que puede funcionar directamente en modo
sniffer, pasándole por parámetro una interfaz de red, o tomando como entrada ficheros de captura de paquetes, que además se pueden procesar por lotes. Lo único que hace es abrir los ficheros de captura, diferenciando entre tramas
Ethernet o
IEEE802.11, detectar los paquetes que siguen el patrón especificado anteriormente, y extraer de los mismos la información correspondiente, que dependiendo del sistema operativo de cada dispositivo, no siempre se encuentra en el mismo lugar del paquete. Gracias a la potencia de las expresiones regulares con las que mantengo un idilio desde que las conocí, esto no supone mucho problema.
 |
| Figura 11: Expresiones regulares en WhatsApp Discover |
De este modo, con un sencillo
“./whatsapp_discover.pl -f *.cap” podemos obtener los números de teléfono de todas las personas que hayan estado utilizando
WhatsApp en todas las redes
WiFi públicas (o no públicas) en las que hayamos capturado pasivamente tráfico. Y eso he hecho yo con mis propias capturas: 
 |
| Figura 12: Buscando los números de teléfono de WhatsApp las capturas de red |
Si vemos con atención la salida de
“Whatsapp Discover”, podemos ver que se obtienen números de todo tipo de dispositivos (
Blackberry y
Symbian incluidos), y que entre los teléfonos que he obtenido tras procesar mis capturas, existe uno que corresponde a un número de móvil americano. Lo curioso es que yo no había identificado este número al mirar las capturas con
Wireshark, porque obviamente no las había abierto una a una, pero gracias a haberme construido esta herramienta, pude identificar un número que me llamó la atención.
El siguiente paso fue
agregarlo en mi agenda de contactos, porque me picaba la curiosidad, ya que la captura de paquetes la había realizado en una red wifi abierta de un
Centro Comercial en mi querida isla, durante las fechas navideñas. Así que supuse que sería alguien que como yo, había vuelto a casa por
Navidad. Y parece que así era, ya que de lo que se deduce por su estado, se ve que habla español con se ve en su mensaje de estado:
 |
| Figura 13: Un número americano en el centro comercial |
He colgado el código fuente de
WhatsApp Discover en el repositorio de GitHub como
PoC, ya que de momento he eliminado la funcionalidad de
sniffer en tiempo real, porque por limitaciones de tiempo no he podido validar su comportamiento como es debido, y además así evitamos el uso malicioso e indiscriminado de la misma por
script kiddies, los que como mínimo necesitarán saber obtener una o más capturas de paquetes válidas para probar la herramienta. Podría ser muy útil en herramientas de análisis de
pcaps, como
Immunity Stalker, donde se conseguiría sacar más información de las capturas. Además, habrá que comprobar si ahora que
Mark Zuckerberg está detrás de
WhatsApp, este
leak de privacidad sigue vigente dentro de un tiempo.
Aparte de la rubia de la cafetería, imaginen qué pasaría si una
celebrity o un alto cargo público utiliza su
smartphone desde la red
WiFi de su hotel, para enviar mensajes de
WhatsApp, dado lo valioso que es para ellos preservar la privacidad de su número de teléfono. Yo por si acaso, no lo haría si no fuera
protegiendo mi WhatsApp con una conexión VPN de por medio ;).
Sólo me queda agradecer a
Chema Alonso, como en otras ocasiones, la oportunidad de poder publicar en este privilegiado espacio, así como a mi mujer e mi hija la paciencia que han mostrado estas semanas en las que les he robado el poco tiempo libre que me queda tras la jornada laboral y las tareas diarias de rigor.
Autor:
Deepak Daswanihttp://twitter.com/dipudaswanihttp://deepakdaswani.es