Arxiu de la categoria: Apps

Cómo ganar siempre al “Apalabrados” (para Hackers)

Confieso que no he entrado en el tema “Apalabrados”, pero conozco a mucho enfermo del tema. Este artículo, extraido íntegramente de Security by Default, no pretende que hagáis trampas, o no siempre, ni va de las famosas aplicaciones para que os lo den hecho. En realidad va de ver las tripas de como funciona el juego y cómo hackearlo, o sea que aquí os lo dejo por si quereis experimentar…

Esto es lo que nos cuentan desde Security by Default:

Apalabrados, o “Angry Words”, el juego de moda. Muchos lo hemos descubierto como un desafío más. Algo a lo que se puede jugar con cualquiera y que consiste en exprimirse el cráneo pensando, con las letras que tienes, cómo completar palabras en un tablero. El concepto ya existía con el Scrabble de toda la vida, pero en este caso jugando de forma online contra amigos/conocidos o incluso contra personas seleccionadas de forma aleatoria.
Así que empecé a jugar y ví como ganaba algunas partidas, pero perdía otras. Y he de reconocer que no me gusta mucho perder ;DCon el tiempo, incluso aparecieron aplicaciones online o servicios que te “ayudaban” con la generación de palabras, en base a las letras que dispones, y las ya colocadas en el tablero, para que efectúes la mejor de las jugadas. Pese a que nunca llegué a hacer uso de estas aplicaciones, pensé en echar un vistazo a las tripas del juego, por aquello de ver cómo funciona y buscar alguna otra debilidad que me permitiese hacer esto de las palabras cruzadas algo más divertido.

Para ello, y como se jugaba desde un dispositivo móvil, monté una herramienta de intercepción de tráfico, que me permitiese analizar los mensajes intercambiados entre la aplicación, y el servidor correspondiente. Una vez identifiqué que las peticiones eran simples llamadas a una API web, dispuse el conocido proxy Paros para poder estudiar las mismas.
Os cuento mis findings principales:
  • El servidor hacia el que realiza las peticiones el juego es api.apalabrados.com y se encuentra en Amazon EC2, aunque tiene configurado el timezone de Argentina, tal cual denotan la hora de algunas respuestas del servidor. Tiene cierta lógica, puesto que la empresa desarrolladora de Apalabrados, es de las latitudes de la tierra del exquisito dulce de leche.
  • El proceso de login se puede hacer a través de usuario facebook (dando privilegios a la aplicación para el login) o mediante correo electrónico y contraseña. No he probado a fuzzear el acceso mediante correo electrónico con contraseñas, para ver si existe bloqueo de cuentas al hacer ataques de diccionario o fuerza bruta, pero CAPTCHA, no hay. Por mi parte, y aunque me he centrado en intentar trampear el juego con sesiones ya iniciadas, podemos ver que la contraseña de login viaja completamente en claro en una petición POST.

 

  • El protocolo utilizado es HTTP en plano, sin SSL, sin nada de nada. Meras peticiones web, sin autenticación con certificados de por medio que pongan la cosa un poco más complicada (saltable, pero con algo más de dedicación y esfuerzo). Impresionante que ni siquiera el login en la aplicación tenga un nivel mínimo de cifrado.
  • Al tratarse de un juego al que se puede acceder desde diferentes dispositivos a la vez de forma simultánea, lógicamente, las partidas y el estado del usuario ha de almacenarse en los servidores de Apalabrados, siendo los clientes, quienes piden información en cada ocasión. Analizando el tráfico web intercambiado, se ve que, en el login, se establece una sesión web corriente y moliente, el servidor nos inyecta una cookie con un sessionID (ap_session) que los clientes tendrán que utilizar en todas las peticiones que hagan hacia el servidor.

 

  • Si situamos a un cliente en una situación MiTM sencillo, forzando a jugar a los usuarios mediante una red wireless, podemos interceptar el identificador de usuario enviado en todas las peticiones GET y POST, y la cookie de sesión necesaria, así podríamos hacer peticiones del tipo: GET http://api.apalabrados.com/api/users/[mi_usuario_ID]/games con la cookie “ap_session” con el valor interceptado y obtendríamos la lista completa de los juegos de un usuario, con un montón de información de cada uno, el usuario contra el que se juega, su identificador Facebook (si se conectó haciendo login en facebook en vez de con correo electrónico), si ha de mostrar o no foto, la fecha de creación del juego, los turnos pasados, el número de fichas que quedan, la última palabra jugada, etc,…
  • Si pulsamos en cada uno de los juegos disponibles, podemos ver que se hace una petición al servidor para rellenar el mismo. La petición es del tipo: GET http://api.apalabrados.com/api/users/[mi_usuario_ID]/games/ Como bien podéis imaginar, con la cookie de sesión, podemos ver directamente la configuración de juego del usuario interceptado, y por supuesto, podemos actuar, como si fuera él.
  • Cuando se crea una palabra, con nuestras letras y las del tablero, el cliente envía una primera petición GET a http://api.apalabrados.com/api/dictionaries/ES?words=palabra. Así comprueba en su diccionario (depende del idioma) si la palabra existe o no. La respuesta es del tipo {“answer”:true,”wrong”:[],”ok”:[“palabra“]} si es válida; o del tipo {“answer”:false,”wrong”:[“palabra“],”ok”:[]} cuando es incorrecta.
  • Es posible manipular las peticiones y las respuestas entre el cliente y el servidor, de manera que le llegue al cliente lo que nosotros queramos, y que lógicamente, la aplicación ejecutará sin comprobar nada más. Es decir, que podemos modificar la respuesta del servidor diccionario, para que devuelva por válida cualquier palabra que le pongamos, sin problemas, pero los desarrolladores han tenido en cuenta estas trampitas, y hacen que, cuando confirmas posición de las letras, se comprueben, de nuevo, en el diccionario internamente y claro, dará un error por no existir la palabra. De momento, no he encontrado forma de engañar al servidor para que acepte palabras que no existen.
  • En la siguiente imagen podéis ver que se puede enviar al usuario el texto en las posiciones que queramos, cuando simplemente el cliente pregunte por un juego en concreto. No es necesario ni modificar el ID de la respuesta para que coincida con el que el cliente espera. Directamente, se le envía cualquier cosa y se la come,… incluso es posible enviarnos las letras que nos convengan para la siguiente jugada.

 

Teniendo en cuenta que es una matriz de 15×15, la posición de cada letra viene dado por la posición de la 0 a 224. Así que si queremos, podemos devolver el mapa de caracteres que queramos (ni siquiera han de ser sólo letras) y/o cuantos comodines nos venga en gana.
 
  • El problema está en que, como las partidas quedan grabadas en el servidor, cada vez que la aplicación cliente pida el estado de la partida, deberemos modificar el cuerpo de la respuesta que queramos. En otro caso, machacará en la aplicación cliente toda la creatividad que hayamos creado anteriormente y se verá la partida real.
  • Entonces, ya que el servidor no permite modificaciones de las letras disponibles, del número de fichas o que se coma aquellas palabras que yo quiera, está claro: si no puedo engañar al servidor ,engañemos a los clientes!  Aquí ya viene la parte maliciosa. En Apalabrados, la API permite preguntarle al servidor por la situación de algún juego (o de todos) mediante GET, y también ejecutar un comando, mediante POST, pasando en el POST DATA la acción. Las más agresivas son “Paso” o “Rendirse”, de manera que enviaríamos al servidor, falseando al cliente, en nuestro entorno MiTM una petición POST a  http://api.apalabrados.com/api/users/[mi_usuario_ID]/games/[juego_ID]/turns con el POST DATA el valor {“type”:”PASS”}, y estaremos simulando que el cliente ha pasado. Si hacemos esto por cada vez que sea el turno del usuario, a éste podemos devolverle un error cualquiera de conexión al servidor, mientras vamos jugando alegremente una partida en la que la víctima siempre pasará, perdiendo la partida por goleada.
  • Otra opción más agresiva aún es forzar a un usuario a Rendirse a una partida. ¿Cómo? pues enviando la petición POST a http://api.apalabrados.com/api/users/[usuario_ID]/games/[juego_ID]/turns el valor {“type”:”RESIGN”} en el cuerpo del POST. Con esto al servidor le llega, la petición fraudulenta de Rendirse, por lo que forzaremos que esa partida se pierda y se deprecie el valor del usuario en su perfil, por partidas renunciadas. Por contra, si estamos jugando contra la víctima, ganaremos automáticamente la partida, porque el contrario renunció.
  • Otra forma de forzar a un usuario a perder la partida es no devolver ninguna letra a nuestro contrincante,… Para ello, la devolución de letras en el caso de una jugada sería del tipo
    {“type”:”NORMAL”,”turns_played”:44,”replacement_tiles”:””,”my_score”:221,”opponent_score”:199,”game_status”:”ACTIVE”,”expiration_date”:”07/08/2012 08:51:21 EDT”,”id”:85302734} es decir, sin “letras de recambio”. En este caso, directamente es un Game Over para la víctima, puesto que no tiene ninguna letra para jugar y sólo le quedarán las opciones de darle al botón “Pasar” o “Rendirse”.
  • En estos tres últimos casos, estamos causando un perjuicio a un jugador, en nuestro beneficio. Sin embargo, también podemos enviarle lo que queramos a la víctima, o a nosotros mismos. Desde un “Has Ganado” o un “Has perdido”, aunque sea ficticio puesto que el servidor conoce el estado real de la partida. Pero, en cualquier caso, siempre es divertido enviarle mensajes malformados a un usuario para ver su reacción….

 

Y por supuesto podemos escribir lo que queramos en los puntos, el nombre del adversario, o incluso el mapa de letras que queramos que queden reflejados… Quise probar cuánto era el mayor puntaje que podía obtenerse en Apalabrados, así que probé rellenando con todo Z (valen 10 puntos) todo el tablero… Al forzar un WIN, el programa se pasa de largo sumando y calculando las triple/doble letra/palabra y da un resultado de 248, que obviamente es un resultado incorrecto,…
 
  • El apartado de ver perfiles de los usuarios (incluso del propio) también es susceptible de modificaciones, pudiendo modificar cualquier campo, poniéndonos los puntos que queramos en mejor juego, mejor jugada, palabra más larga, o incluso el número de partidas ganadas, perdidas o renunciadas, apareciendo el palmarés que queramos. Evidentemente, esto es sólo a ojos del cliente, porque en el servidor no se modifican estos stats

 

Estuve probando por si, por debajo, la aplicación llamase a Safari y fuese posible generar un XSS… pero no hubo suerte con la única prueba que hice.

Bueno, pero… ¿y cómo lo pueden arreglar?
El problema fundamental de Apalabrados, es que no han tenido en cuenta ningún tipo de checksum, o lo que sería aún mejor, una firma digital del hash de cada mensaje recibido. Las manipulaciones o tampering de los datos enviados por el servidor a los clientes, deberían ser comprobadas por el mismo, de manera que, si alguien ha dado rienda suelta a su creatividad por el camino, debería dar un error de integridad y no interpretar el contenido del mensaje.
Respecto al envío de mensajes por parte del cliente hacia el servidor, tanto con las jugadas con letras que se envían, como con los mensajes de “Rendirse” o “Pasar”, deberían ir cifrados, por ejemplo, con una contraseña de sesión. Otra opción, sería hacerlo con un hash de la contraseña del usuario que se mantenga en el cliente y que al estar ya almacenada en el servidor, pudiese dar la capa de confidencialidad necesaria a los mensajes. La opción optima sería firmar digitalmente todos los mensajes, pero eso implicaría un despliegue de certificados por cada usuario, que posiblemente hiciera inviable el juego.Ni siquiera se han preocupado que, cuando el login se hace mediante usuario-correo/contraseña, el envío de la misma se efectúe mediante un canal SSL, sino que la contraseña viaja en claro para que cualquiera, en determinadas condiciones, pueda acceder a ella cómodamente. Como recomendación, no uséis la misma contraseña que utilizáis para otras cosas, y por supuesto, ya que el nombre de usuario es una dirección de correo, haced el favor que la contraseña no sea la del servicio de correo!

La única “medida de seguridad” implementada (que yo creo que ha sido por casualidad) es el escaso tiempo de time-out, que obliga a hacer la manipulación de los parámetros en tiempo récord, o tener hecho el mensaje antes, para inyectarlo en la respuesta cuanto antes. La otra opción es diseñar un programa que cuando detecte las peticiones, formatee las respuestas según nuestras necesidades de forma automática.
Pensé en buscar un BOFen la devolución de alguno de los parámetros, ya que, como habéis podido comprobar, es posible modificarlos todos a nuestro gusto. Así que a base de pruebas, quizá sea posible ejecutar código remoto en el dispositivo de la víctima. Mi intención eran los fines académicos y lúdicos para conseguir la victoria en el juego, no en el dispositivo completo.Cierto es, que en el lado servidor, han tenido en cuenta “alguna” medida de seguridad, como la doble comprobación de que la palabra existe. Sin embargo, no han controlado todas las posibles reacciones de un usuario con un pelín de mala uva.

Recordad además que esto sólo es posible en aquellas situaciones en las que se utilice una red wireless para la comunicación de datos y sea posible el MiTM. En caso de jugar con 3G no habría forma de efectuar estas manipulaciones, y en caso de GPRS, hay que mirar que los @Taddong no estén cerca.
Noticia extraida de: Security by Default