sábado, noviembre 05, 2022

Cómo romper la arquitectura de cifrado de mensajes extremo a extremo de Rocket.Chat [1 de 2]

A día de hoy, una de las aplicaciones de Software Libre de mensajería instantánea (IM) disponibles en el mercado para su uso a nivel empresa o particular, por robustez, por funcionalidades y por ser una solución multi-dispositivo, podría ser el popular Rocket.chat. En este artículo vamos a ver cómo se rompe la arquitectura de seguridad y se puede acceder a los datos enviamos en los mensajes por culpa de un fallo de seguridad que hay que corregir. 

Figura 1: Cómo romper la arquitectura de cifrado de
mensajes extremo a extremo de Rocket.Chat [1 de 2]

Rocket.chat permite varias modalidades de uso de cara a una compañía, pudiendo montar un servidor centralizado OnPremise, tu propio servidor OnCloud, o simplemente mediante,  el uso del servidor público que proporciona la propia compañía Open.rocket.chat. La conexión al servidor puede realizarse desde múltiples dispositivos como se puede ver en la imagen anterior, tiene cliente Web, aplicación de escritorio para Windows/Linux/MacOS y app móvil para Android e iOS.

Figura 2: Arquitectura de conexiones multi-cliente para Rocket.chat

La funcionalidad a revisar en el artículo, será la del cifrado Extremo a Extremo o "End-2-End" (E2E). Dicha funcionalidad, implementa una capa de seguridad adicional al cifrado TLS a nivel de red utilizado de forma común mediante el protocolo HTTPS, en la mayoría de las comunicaciones actualmente. Como veremos al final, se podrá hacer un descifrado de los mensajes, y veremos cómo se puede mejorar la arquitectura de cifrado. Para entender mejor toda la arquitectura de cifrado, tienes el libro de Cifrado de las comunicaciones digitales: de la cifra clásica a RSA 2ª Edición de 0xWord

Figura 3: Libro de Cifrado de las comunicaciones digitales:
de la cifra clásica a RSA 2ª Edición de 0xWord

El cifrado E2E, por defecto, tiene la capacidad de hacer llegar un dato de forma segura desde un origen a un destino, de un modo descentralizado. En este caso, y dado que se encuentra en una arquitectura centralizada debido al diseño del producto, todos los mensajes enviados desde un origen pasarán y se almacenarán en el servidor central antes de llegar al destinatario, siendo la funcionalidad E2EE (End 2 End Encryption) la encargada de realizar este proceso de forma segura.

Arquitectura de Rocket.Chat

Para implementar esta función, Rocket.Chat cuenta con un diseño de arquitectura E2E del cual se ha realizado un pequeño estudio, para preparar este artículo. Esta arquitectura utiliza operaciones criptográficas de varios tipos, diferenciadas por su naturaleza matemática en simétrica, asimétrica y operaciones de hashing:
  • Criptografía Simétrica: algoritmo utilizado AES, origen y destino comparten una clave de cifrado.
  • Criptografía Asimétrica: algoritmo utilizado RSA, mediante el uso de un par de claves Publica y Privada, los datos serán cifrados con la clave pública y descifrados con la la clave privada.
  • Hashing: algoritmo utilizado PBKDf2, la función derivación matemática que generará un resultado irreversible del cual no se puede obtener los datos originales de entrada.
La dirección de la implementación actual del producto a nivel arquitectura de software, por diferentes motivos, como el diseño de las funcionalidades de negocio y mantenimiento de una sola linea de código  para los diferentes dispositivos, se implementa con el framework react-native.


Dicho framework trabaja con JavascriptCore que ademas de ejecutarse en los navegadores web, permite la posibilidad de integración de librerías implementadas en otros lenguajes de programación, como puedan ser Java para sistemas operativos Android u Objetive-C para sistemas operativos iOS:

Figura 5: Arquitectura de JavascriptCore con Java  y Objetive-C

Las conexiones que se implementan entre los diferentes clientes y el servidor central de Rocket.Chat podrán ser de dos tipos diferenciados por la dirección en la que se comunican:

Figura 6: Conexiones API REST y WebSocket

La  conexión vía API Rest es Cliente → Servidor y unidireccional, mientras que la conexión vía Websocket permite en modo full-duplex transferencias bi-direccionales Servidor → ClienteCliente → Servidor.

Descripción de la arquitectura E2E

La funcionalidad E2E, se arranca tras la autenticación inicial de un usuario (U) sobre sobre un dispositivo (D).

  • El dispositivo (D), solicitará al usuario (U) o generará unas credenciales específicas E2E (En función de si es la primera vez o no, que el usuario se autentica en el dispositivo con el servidor de Rocket.Chat).
  • Tras introducir las credenciales mediante la derivación de la contraseña junto al identificador unívoco del usuario (U) UID y el uso del algoritmo criptográfico de hashing PBKDF2, se generará la primera clave criptográfica de la aplicación master-key.
Figura 7: Generación de Master Key en dispositivo

A continuación, el dispositivo (D) como cliente del servidor de Rocket.Chat procederá con la generación o solicitud (en función de si es la primera vez en la que el usuario se autentica en el dispositivo) de un par de claves RSA de longitud 2048 que serán las claves criptográficas E2E del usuario:
  • Generación public_key, private_key: RSA-OAEP 2048
  • Utilizando la master-key, mediante criptografía simétrica utilizando el algoritmo AES-CBC el dispositivo (D), cifrará la private_key.
Figura 8: Generación de claves pública y privada para cifrado asimétrico

El dispositivo (D), mediante una llamada a la API Rest de tipo POST, sobre la API de Rocket.Chat realiza el envío del par de claves, public_key y private_key (ésta última cifrada, para garantizar la confidencialidad del usuario).
  • La función de la API Rest que proporciona este servicio, es e2e.setUserPublicAndPrivateKeys.
  • El servidor de Rocket.Chat en su BD no relacional (mongodb) almacenará estas claves asociadas al usuario (U), en la colección users.
Figura 9: Envío de claves pública y privada a servidor de Rocket.Chat

La aplicación para cifrar los datos punto a punto, requiere de una habitación o chat seguro por tanto ya sea dirigido desde el usuario (U), al usuario unívoco (U₁) o a los múltiples usuarios (U₁),(U₂)...(U_n), por lo tanto será necesario crear un grupo cifrado.
  • La operación de la API Rest del servidor de Rocket.Chat que proporciona este servicio será create.group, especificando los parámetros adecuados de grupo privado y encriptado.
  • El servidor de Rocket.Chat generará en la BD no relacional una entrada en la tabla rocketchat_subscriptions por cada usuario (U1..n), que pertenezca a la habitación segura alojada en la colección rocketchat_room.

Figura 10: Creación de un grupo de cifrado con clave simétrica

El creador del grupo seguro, será el encargado de generar la clave criptográfica de cifrado de mensajes Room-Key (el cual será cifrado simétrico), y almacenarlo únicamente de forma cifrada en la BD del servidor, en la colección rocketchat_subscriptions, mediante la operación de la API Rest e2e.UpdateGroupKey. Éste proceso se realizará N veces para cada uno de los usuarios que pertenecen al grupo:
  • Se cifrará la Room-Key: de forma asimétrica mediante el algoritmo RSA para cada usuario del chat seguro.
  • Se utilizará para el cifrado la public_key, disponible en la colección users del servidor, reportada mediante la invocación al servicio API Rest de Rocket.Chat e2e.requestSubscriptionsKeys.
Figura 11: Envío de claves Room-Key a los usuarios del grupo

Para la obtención de la clave de cifrado de mensajes E2E, en determinado grupo cualquier usuario que sea miembro de este, deberá realizar los siguientes pasos:
  • El usuario (U), ya autenticado en la aplicación y en la arquitectura E2E estando en posesión de su master-key.
  • Solicitará la clave de sesión E2EKey, almacenada para su usuario (U), en la colección rocketchat_subscription (cifrada asimétricamente con RSA).
  • Solicitara sus claves de cifrado al servidor, public_key y private_key (esta última, cifrada simétricamente con AES).
  • Descifrará con AES, la clave privada mediante el uso de la master-key.
  • Descifrará con RSA, utilizando la clave privada (private_key) descifrada y la clave E2E (E2EKey) obteniendo la room-key o session-key.
Visto todo esto, si eres amante de la seguridad informática, el hacking y te gusta la criptografía, supongo que ya has visto algunos puntos débiles de esta arquitectura que, si se pueden atacar, pueden romper la seguridad de la plataforma. En la segunda parte de este artículo lo vemos.

Saludo,

Autor: Ildefonso González Sánchez, pentester.

1 comentario: