Cuando se utiliza una plataforma como Ruby OnRails, es conveniente tener presente que hay ciertas “buenas practicas” que se deben seguir para desarrollar de forma segura, muchas de esas practicas, como prácticamente todo en el mundo de la seguridad informática, son simplemente de sentido común, otras resultan un poco más complicadas de entender y de cumplir. Sin embargo, en el caso de las sesiones que se pueden manejar en Ruby OnRails, es importante para un desarrollador, entender, cumplir y comprobar que se siguen las pautas adecuadas para tener la información segura y el sistema funcionando como corresponde. La razón por la que es importante prestarle atención a las sesiones en Ruby OnRails, radica en que existen varios métodos de almacenamiento que pueden ser implementados y que si no somos lo suficientemente prudentes, nos podemos encontrar con que la información que tenemos almacenada en dichas sesiones puede ser fácilmente comprometida por un atacante, que es justo lo que ocurre con HackMe Casino. Antes de entrar en la parte practica de está publicación, intentaré explicar un poco, como es el funcionamiento de las Sesiones en Ruby OnRails (que es más flexible que en otros lenguajes de programación tradicionales como JSP o PHP)

Sesiones en Ruby OnRails

Las sesiones normalmente, son tablas hash que representan una relación de clave-valor que permiten el almacenamiento y posterior acceso a la información. Como seguramente el lector ya sabrá, la necesidad de tener sesiones en el lado del servidor, radica en la naturaleza del protocolo HTTP, el cual es un protocolo sin estado, lo que significa que el protocolo en si mismo, no tiene ningún tipo de mecanismo o primitiva que permita llevar a cabo transacciones entre clientes y servidores, es decir, cada vez que un cliente envía una petición al servidor, es el servidor el encargado de almacenar la información que se consideré relevante, ya que el protocolo no mantiene estos datos entre múltiples peticiones y respuestas. Ahora bien, normalmente los lenguajes de programación web clásicos, tales como PHP, JSP, ASP, etc. Utilizan el concepto de sesión para almacenar datos en el servidor, por ejemplo, información sobre usuarios y otros detalles que es importante conservar durante la interacción con un cliente determinado. En los mencionados lenguajes, dicha información se almacena en memoria (del proceso del servidor) y se puede acceder a ella por medio del mecanismo clave-valor mencionado anteriormente, sin embargo, en el framework Ruby OnRails, la gestión de las sesiones cambia y se vuelve mucho más flexible con respecto a las tecnologías anteriormente mencionadas, dando la posibilidad de almacenar las sesiones en el lado del cliente por medio de cookies, en base de datos, en ficheros de texto o en memoria como se hace de forma convencional. Por defecto, a partir de Ruby onRails 2.x las sesiones se almacenan utilizando el mecanismo de Cookies, lo que ha traído a numerosos debates relacionados especialmente con la seguridad, dado que si no se tiene cuidado, se pueden estar enviado al cliente (que también puede ser un atacante) información que le puede ayudar a descubrir el funcionamiento interno de la aplicación, un efecto que desde luego, es del todo desagradable.

Por otro lado, las cookies tienen una restricción sobre la cantidad de datos pueden contener (4Kb) por este motivo, los desarrolladores tienen que tener muy bien definidos los elementos que conviene almacenar en dichos campos, además, la información que se almacena allí no debería ser información sensitiva, ya que como se ha mencionado en la entrada anterior, las sesiones en Ruby OnRails, cuando utilizan el mecanismo de almacenamiento de sesiones basado en cookies (CookieStore) solamente firma la información pero no la cifra solamente la codifica en Base64. Esto quiere decir que al firmar la cookie, está aunque puede ser modificada, deja de ser valida para el servidor, dado que el hash generado por la firma, cambia, sin embargo, al estar la información codificada y no cifrada los usuarios pueden decodificar la cookie y ver que se almacena en ella. En resumen, un atacante puede ver los datos que se almacenan en la sesión cuando se utiliza el mecanismo CookieStore, además de que se facilitan las cosas para él a la hora de realizar ataques de replicación, simplemente por tener acceso a dicha cookie.

Todos estos problemas han dado paso a muchísima controversia y discusiones entre los usuarios y desarrolladores de Ruby OnRails, aunque cabe aclarar, que el sistema en si mismo no es inseguro, solamente requiere que los desarrolladores tengan mayor responsabilidad sobre lo que deben y no deben almacenar en dicha sesión, así como saber los beneficios y los riesgos de utilizar cada sistema de almacenamiento de sesiones. Algo que en muchos casos no se cumple.

En el caso de HacMe Casino, ocurre exactamente lo mismo, la información que se almacena en la sesión, permite a sus clientes conocer detalles importantes sobre el funcionamiento de la aplicación (especialmente en el caso de algunos de los juegos disponibles). En el caso de HacMe Casino, basta con producir una excepción en alguno de los controladores disponibles y posteriormente analizar los valores de la sesión de una forma muy cómoda, dado que los mensajes de error que produce la aplicación son bastante completos.

Para esto, se puede hacer lo siguiente:

  1. Hacer una apuesta en el juego “BlackJack”.

    bj_sessions1

  2. Desde una nueva pestaña en el navegador, podemos acceder a uno de los controladores que hemos detectado en la anterior publicación y que nos permite provocar una excepción en el servidor para que de esta forma podamos acceder a los valores de la sesión. Dicho controlador puede ser: http://hacmecasino:3000/video_poker/test_deuces_wild Las siguientes imágenes son los valores que se enseñan al seleccionar el link “Show Session Dump”

    bj_sessions2

    bj_sessions3

    bj_sessions4

  1. Como podemos ver en las imágenes anteriores, parece que tenemos información sobre nuestra mano y la mano del juego, es decir, tenemos toda la información necesaria para saber cuando es conveniente apostar y cuando la mano que tenemos no es suficiente para ganar. Sabemos ahora, que los objetos que maneja la aplicación para nuestra mano son: Player → hand → Cards y los objetos utilizados para la mano del juego son: bjGame → dealer → deck → cards
  2. Aunque tenemos suficiente información sobre el juego, aun nos falta saber que significan los valores numéricos que tienen cada una de las cartas, en concreto nos interesa saber que representan los valores Suit y Rank. Para saberlo, podemos comparar los valores que vemos en la sesión y las cartas que vemos en pantalla antes de realizar la apuesta. Por ejemplo:
Suit Rank
Primera Carta (J Diamantes) 1 11
Segunda Carta (9 Picas) 0 7
Tercera Carta (4 Tréboles) 3 2
Cuarta Carta (6 Tréboles) 3 4
Quinta Carta (8 Diamantes) 1 6

De lo anterior podemos concluir inicialmente, que las cartas que son “Diamantes” tienen el valor Suit “1” y las que son Tréboles tienen el suit “3”. Desde seguir el mismo ejercicio unas pocas veces más, podemos sacar la siguiente tabla:

Carta Suit
Picas 0
Diamantes 1
Corazones 2
Tréboles 3

Ahora que ya sabemos lo que significa el valor “Suit”, después de seguir el mismo ejercicio unas cuantas veces más, nos encontramos con que “Rank” representa el valor de la carta. La siguiente tabla enseña los correspondientes valores del Rank y el valor de la carta que representa.

Carta Rank
2 0
3 1
4 2
5 3
6 4
7 5
8 6
9 7
10 8
J 9
Q 10
K 11
AS 12
  1. Con toda esta información y sabiendo como se juega al BlackJack, es posible saber cuando debemos apostar y cuando no.

Finalmente, hay 2 posts sobre seguridad en RoR escrita en el blog de s21sec por Daniel Peláez, los cuales son muy interesantes y recomiendo leer para comprender las medidas de seguridad que se deberían implementar cuando se desarrollan aplicaciones web con este framework.

http://blog.s21sec.com/2010/06/introduccion-ruby-on-rails-ror-o.html

http://blog.s21sec.com/2010/10/seguridad-en-ruby-on-rails-ii.html