Fallas de seguridad en Prey, herramienta de rastreo de dispositivos

Prey es una herramienta que permite el rastreo de computadores y dispositivos móviles, pensado para encontrar tu portátil, tablet o teléfono móvil cuando se te pierde o te lo roban.

Basicamente, y como todo software o herramienta de rastreo, lo que hace es enviar información a un servidor centralizado con la ubicación y otros datos que te pueden ayudar a identificar dónde está tu dispositivo. Lo que me llamó la atención fue querer conocer cómo envia la información y cómo funciona la “api” de comunicación, por lo que me lo descargué y comencé a analizar el código.
La versión analizada es la 0.5.9 (md5: 1ff6cb6bb0de36415fde3382e72a8a6d), pero imagino que la información que voy a exponer afecta a todas las versiones anteriores.

El principal problema es que el protocolo que se pensó para la interacción entre los usuarios y el servidor centralizado es demasiado básico y no cuenta con los controles de seguridad necesarios.

Primero, para entender un poco como funciona de manera simple, los clientes (usuarios) interactuan con el servidor control.preyproject.com, habilitado bajo los protocolos HTTP y HTTPS. Se comunica bajo el User-Agent=Prey Configurator/Version y se envían los parámetros  requeridos mediante POST. Las peticiones se envian a distintos archivos xml bajo el subdominio de control; por ejemplo users.xml, devices.xml, prey-last-response.xml o “device_key“.xml. Este último, se remplaza device_key por la llave o identificador del dispositivo.

Segundo, existen parámetros de autenticación que se envian en las cabeceras de la petición http. Corresponden al mecanismo de autenticación HTTP mediante la cabecera Authorization. Aquí está el primer problema y debilidad de la herramienta: Se envían cifrados en Base64.
Todos sabemos que base64 es un algorítmo de doble vía, que permite cifrar y descifrar sin mayores esfuerzos, por lo que no se recomienda utilizarlo como medida de seguridad para claves o tokens.

Existen distintos tipos de autentificación http, el que implementa Prey es el más inseguro y el menos recomendado, su nombres es “Basic“. Los datos enviados mediante el mecanismo básico de autenticación puede ser fácilmente interceptado y descifrado, permitiendo conocer la ApiKey y que, capturando los datos enviados por POST, ya tenemos toda la información para hacer consultas sobre el o los dispositivos de nuestra víctima.
Por ejemplo, esta es una petición enviada al servidor de control de Prey, usando un ApiKey aleatorio:

Si desciframos la segunda linea, despues de “Basic”, obtenemos lo siguiente: syrjbqk7z6w:x. El primer elemento, antes de los dos puntos (:) corresponde al usuario y el segundo a la clave.
Algunos pueden pensar que si el tráfico va por SSL no deberíamos poder leerlo, sin embargo, aquí existe otro problema mas.
El segúndo problema es que las peticiones que hace Prey a su servidor “seguro” son de forma insegura, aceptando certificados inválidos, permitiendo a un atacante realizar ataques Man-in-the-Middle al protocolo HTTPS y conocer el contenido de la petición sin ningun problema. Por ejemplo, esta es una de las llamadas que hace la herramienta usando cURL:

command = '/usr/bin/curl -A "' + USER_AGENT + '" -i -s -k --connect-timeout 5 ' + CONTROL_PANEL_URL_SSL + '/' + path + data

El parámetro “-k” de cURL significa: aceptar certificados inválidos. La línea corresponde a la número 479 del archivo platform/linux/prey-config.py.

El impacto de estas vulnerabilidades o debilidades es que por ejemplo si tienes Prey instalado en tu celular o en tu notebook y te conectas a una red publica (con o sin clave) como la de un café, centro comercial, bar o lo que sea, toda la información que Prey envía sobre tu ubicación puede ser intersectado por un tercero. Además, esa persona podría quedarse con tus tokens y consultar la ubicación y los datos de los dispositivos registrados cuando quiera.

La tercera vulnerabilidad, afecta al proceso de registro de un nuevo usuario o dispositivo. Para realizar este proceso se envia una petición a users.xml pasando mediante POST las variables name, email, password y password_confirmation. No cuenta con ningún tipo de control de seguridad, lo que permite registrar tantos usuarios como queramos, pudiendo saturar el servidor si se realizan miles de peticiones de forma simultanea. Esta información fue obtenida del archivo platform/linux/prey-config.py, función create_user.

def create_user(self):
self.email = self.text('email')
params = urllib.urlencode({'user[name]': self.text('user_name'), 'user[email]': self.email, 'user[password]': self.text('password'), 'user[password_confirmation]' : self.text('password_confirm')})
# params = 'user[name]='+self.text('user_name')+'&user[email]='+self.email+'&user[password]='+self.text('password')+'&user[password_confirmation]='+self.text('password_confirm')
result = self.make_request('users.xml', params, None, None)

if result.find("<key>") != -1:
self.get_api_key(result)
self.device_key = ""
elif result.find("Email has already been taken") != -1:
self.show_alert(_("Email has already been taken"), _("That email address already exists! If you signed up previously, please go back and select the Existing User option."))
return
else:

Por ejemplo, en la siguiente Prueba de Concepto (PoC) crearé 10 nuevos usuarios y el sistema me devolverá sus respectivas llaves. Usando cURL de la siguiente forma:

for num in $(seq 1 10); do curl -A "Prey Configurator/222 (Linux)" https://control.preyproject.com/users.xml -d "user[name]=user_$num&amp;user[email]=correodeprueba$num@gmail.com&amp;user[password]=123456&amp;user[password_confirmation]=123456"; done

Obtenemos: Con esto hemos creado los usuarios user_1, user_2, user_3, user_4, user_5, user_6, user_7, user_8, user_9 y user_10 con los correos respectivos correodeprueba1@gmail.com, correodepruebaN@gmail.com. El servidor devolvió los siguientes tokens:

  • hjxdp3k46u2j
  • v6lijlbx3tc8
  • qow7eih39ymb
  • cvrealg9vu09
  • t5nd017drwmi
  • irsiauu5msc2
  • t8u9jrtvmxbh
  • 31gqe0h3fiy2
  • glua8bsl8wtg
  • 295y3at88e0w

Los cuales cumplen el mismo patrón: Largo 13 caracteres, numeros y letras en minusculas. Ahora podemos generar tokens aleatorios segun este patron e ir probando. Con esto ya tenemos nuestra cuarta vulnerabilidad que debido a la fatla de controles de seguridad es posible realizar fuerza bruta y obtener las ApiKey de los usuarios. Si hacemos una petición a devices.xml entregando mediante la cabecera de autentifiación básica un token aleatorio el servidor nos devolverá el código 401 Unauthorized, de lo contrario nos devolverá 200 OK. De esta forma podemos enviar tantas peticiones queramos hasta obtener el codigo 200. Como podemos ver en la función verify_keys() del archivo core/pull, si el servidor devuelve 200 OK o 404 Not Found, significa que la ApiKey es válida, de lo contrario nos dice que es incorrecta:

if [[ "$response_status" == "200" || "$response_status" == "404" ]]; then

log  ' ** API key is valid. Your user account is correctly set up.'

Por lo tanto, lo único que debemos hacer es un script que genere strings alfa-numéricos en minúsculas de largo 13 y que haga las peticiones correspondientes hasta dar con un token valido.

Con el siguiente script hacemos la prueba de concepto:

for x in $(cat keylist.txt);
do
echo "Trying $x ..."
response=$(curl --write-out %{http_code} --silent --output /dev/null https://control.preyproject.com/devices.xml -u $x:x);
if [ $response -eq 200 ]; then
echo "Found: "$x;
fi;
if [ $response -eq 404 ]; then
echo "Found: "$x;
fi
done

Y este fue el resultado:

De los 20 tokens aleatorios probados, encontró 3:

  • Found: s3519t12vsch
  • Found: irsiauu5msc2
  • Found: 717i8cmeq698

En resumen, la implementación del protocolo de Prey tiene bastantes debilidades como el uso de mecanismos de autentificacion demasiado basicos y falta de mecanismos de control como por ejemplo manejar el throttling de peticiones.

Antes de publicar este artículo, me contacté con el equipo de PreyProject para hacerles llegar la información y que tuvieran tiempo para poder analizar y solucionarlo. Tomás Pollak, la persona que responsable de Prey, respondió lo siguiente:

1) El uso de -k en un llamado a Curl en el configurador de Linux: 100% de acuerdo y para serte honesto esta se me pasó. Hace unos meses subí un cambio precisamente para dejar de hacer esto esto en las llamadas HTTP que hace el cliente (commit e7cff53d90ea4d8f1f2adfb89f34f1e37648ebc0). Acabo de arreglar esto.

2) La posibilidad de crear múltiples cuentas sin limitar: He estado pensando sobre esto y sinceramente no veo por qué podría ser una falla de seguridad. Hace harto tiempo pensamos en implementar un límite a la cantidad de consultas — para hacérsela más difícil a las empresas que crean múltiples cuentas para evitar pagar por una cuenta Pro — pero terminamos decidiendo no hacerlo al final. A la larga lo que nosotros queremos es, precisamente, que se creen más cuentas. 🙂

3) Autenticación con la llave API: Cuando leí la parte de HTTP Basic me sorprendí un poco, porque el uso HTTP Basic para el envío de credenciales en una API es algo súper común (creo que 37 Signals lo popularizó), y el uso de Base64 es parte del protocolo de HTTP Basic, no es algo que nosotros hayamos decidido. De todos modos queremos pasar a OAuth2 en el futuro una vez que hayamos lanzado el nuevo panel y cliente en que hemos estado trabajando.

4) Bruteforce: Sobre el brute force para las llaves APIs, tienes razón, y es precisamente por eso que en el XML de respuesta no entregamos ningún dato del usuario, para que incluso habiendo pillado una llave API válida un tipo no pueda hacer mucho. Al final, la llave API es realmente útil usada en conjunto la llave del dispositivo ya que eso es lo que permite activar Prey, guardar reportes, etcétera.

Mi respuesta a este correo de Tomás, fue que respecto al punto 2) y 4) deberían implementar una especia de Request Throttling ya que arriesgan ataques de DDoS, respecto al punto 1) muy bien al reconocer el problema y modificar a la brevedad las llamdas a cURL con el parametro -k, respecto al punto 3) le comenté que existen mecanismos de autenticación http más seguros que el Basic, como por ejemplo Digest o NTLM.

Tomás muy agradecido se despide y responde:

Hoy mismo actualizamos las reglas de IPTables y agregamos un throttle para limitar el número de consultas HTTP, con lo que debiera disminuir el riesgo de un DDoS para la creación de cuentas o el brute force para las llaves API.

En cuanto a la autenticación, NTLM suena como una buena idea. Voy a echarle un vistazo.

Este es un ejemplo de como deben reaccionar las pequeñas y grandes empresas ante reportes de incidentes de seguridad.

12 comentarios

  1. Muy buen análisis Zerial. Felicitaciones.

    Buena respuesta también del Sr. Pollak.-

  2. Espectacular análisis, felicitaciones compadre. Siga creciendo.

  3. Zerial, excelente investigación, excelente haberle advertido a Tomás y su equipo y excelente por Tomás, quien siendo periodista ha logrado meterse en el árido mundo de la informática con un muy buen producto (y que además ha recibido con muy buena disposición las críticas (justificadas) de Zerial).
    Prey es lo que muchas herramientas deben ser.. Nice and Easy to use…

  4. Excelente!
    Un ejemplo de buen trabajo y de la recepción de este. Ojalá fuera un estandar.

    Saludos!

  5. Buen trabajo! y felicitaciones a prey por reaccionar rápido.

    Ojo que base64 no se considera un método de cifrado moderno y usar digest sólo hace un poquito más difícil sacar la clave, pero nada más.

  6. Es que Tomas es un seco po weon… no porque sea el mejor programador ni nada, porque es inteligente y abierto a recibir critica. Ademas que es tela.

    Felicitaciones por llegar a buen puerto.

  7. entones el culpa tuya que se me allá actualizado como 3 veces el prey en mi android , vas atener que pagarme el trafico del celular .. jaujaujaujaa 😀

  8. Muy buen articulo bien explicado, muy buen analisis y se ve el profesionalismo que hay detras saludos

    PD : ROJO hacele un queque a Tomas …

  9. Excelente articulo y muy bien por prey
    que cambio de momento sus fallas y ustedes por hacercelas saber

    😀

  10. Excelente artículo!!! de principio a fin, no sólo por el trabajo que hiciste en el análisis, sino por la respuesta de la misma empresa!!!

  11. excelente articulo

  12. prey me tiene blockeado el telefono luego de clickear donde dice desactivar dentro de mi telefono,a partir de ahi soo presenta una falsa pantalla de teclado infuncional,tenia intenciones de eliminar la cuenta eliminandola de su pagina web pero ahora me he quedado sin oportunidad de recuperar mi equipo BLU studio 5.0 ,QUIEN ME AYUDA?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.