Seguridad en Ruby variables de session

24 views
Skip to first unread message

@gr-sinatra

unread,
Jun 15, 2016, 3:30:27 PM6/15/16
to rubysur
Hola Gente.

Quisiera saber si es posible que un usuario modifique del lado del cliente, desde su navegador el valor de una variable de sessión creada del lado del servidor en Sinatra

por ejemplo una variable session[:usuario]="pepe" 

Hay forma que un usuario desde su navegador la cambie y cuando se hace un post llegue al server session[:usuario]="xxxx" 

Estoy usando :

use Rack::Session::Pool 


En tal caso , la forma de evitarlo seria usando HTTPS ?

Muchas Gracias.

Andrés Arana

unread,
Jun 15, 2016, 4:29:51 PM6/15/16
to rub...@googlegroups.com
Buenas!

`Rack::Session::Pool` guarda los contenidos de la session en un hash en la memoria del server, usando como clave un `session_id`, y envía al cliente una cookie con ese id. En subsiguientes requests, la cookie llega al server y `Rack::Session::Pool` usa el `session_id` que viene en la misma para obtener los valores guardados en el hash este, que es una especie de variable global en donde todas las sessions están guardadas, y con eso accede a los valores de la sesion (por ejemplo, que el usuario es pepe).

O sea, cuando vos hacés `session[:usuario]`, a rack le llega una cookie con el session id `asdf2gqow423`, va a la variable global `pool`, hace `pool["asdf2gqow423"][:usuario]` y te devuelve eso.

La pregunta entonces es: Puede un usuario enviar una cookie con un `session_id` que le corresponda a otro usuario? Para hacer esto, el atacante tiene que adivinar el `session_id` de otro usuario. Por lo que estuve revisando en el código, rack genera los session id's con un `SecureRandom`, por lo que adivinar un `session_id` de otro usuario me parece difícil, incluso prácticamente imposible.

Desde el punto de vista del atacante no puedo adivinar la `session_id` de otro usuario, pero quizás pueda interceptar algún request de un usuario y leer la cookie. Ahí si podría obtener el `session_id` de la otra persona, y a partir de ahí si puedo hacerme pasar por este otro usuario. Ahí entra https en juego: cuando la comunicación con el server es por https, las cookies (y todo el contenido que se envía, ya que estamos) está encriptado, y por más que intercepte el request, no voy a poder obtener la cookie ni ningún otro dato que vaya adentro del request.

Así que, como regla general, cualquier request a un sistema productivo tiene que ser por https. Si bien esto no es necesariamente cierto, por el tipo de pregunta que estás haciendo no estás en condiciones de evaluar si realmente vale la pena usar https o no. Por otro lado, incluso si estuvieras en condiciones de evaluar si vale la pena o no, todavía no escuché ningún argumento válido para no usar https en todos lados (si alguien conoce alguno comente!).



Más allá de esta pregunta particular, si vas a estar haciendo webdev tenés que aprender de punta a punta cómo funciona http, que incluye los cookie headers. Invertí el tiempo en aprender esto y te vas a ahorrar una tonelada de dolores de cabeza.

Por ejemplo, `Rack::Session::Pool` guarda las sessions en memoria, lo que implica que todas las sesiones desaparecen cuando restarteas el server, lo que puede pasar todo el tiempo y sin previo aviso si estás en una Paas tipo heroku. Además, si tenés una arquitectura con load balancers adelante de varios servers, no hay garantía de que los requests vayan todos al mismo server, por lo que te puede pasar que dos requests lleguen a dos servers distintos que no comparten memoria, y por lo tanto session information. Por otro lado, `Rack::Session::Cookie` no tiene estos problemas, pero cada byte que metés adentro de la session tiene que ir y venir en todos los requests, por lo que cargas el peso de de la comunicación con el server. Además tenés un límite de 4k para la cookie, y necesitás usar algún tipo de DS para firmar el contenido de la cookie. Sino podrías meter la session information en otro lado (memcache es una pésima idea, pero lo usan en varios lugares, un redis quizás es una mejor alternativa en la mayoría de los casos) pero entonces te comprás tener que mantener otra pieza de infraestructura, y quizás no vale la pena para lo que estás haciendo particularmente... tradeoffs, tradeoffs everywhere.

En fin, entendé qué es lo que está pasando atrás de lo que hacés, no te quedes con "un flaco en internet me dijo que tengo que usar https". Si empezás a leer y tenés dudas consultá que para eso estamos.

Saludos!


Andrés Arana

--
Has recibido este mensaje porque estás suscrito al grupo "rubysur" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a rubysur+u...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

@gr-sinatra

unread,
Jun 15, 2016, 5:02:17 PM6/15/16
to rubysur
Hola Andrés,

Te comento , en realidad mi pregunta surje porque tengo un ambiente de factura electrónica en producción y una parte de ese ambiente donde permito generar facturas de prueba a cualquier usuario (idTennant genérico), que obviamente no son facturas reales sino solo de prueba, me llamó la atención que un atacante pudo generar una factura con punto_de_venta=VACIO

En el código de lado del servidor el punto de venta (siempre el mismo) por ejemplo 0001 está en una variable de sessión => session[:punto_de_venta] y ese es el valor que guardo en cada factura nueva generada, por eso pienso que el atacante tiene que haber podido modificarlo

Pienso que tiene que haber logrado hacerlo de una forma simple, no creo que un hacker avanzado se haya molestado en ingresar a mi sitio y hacer algo muy complejo.

Lo cierto es no estoy usando https porque aún no compré un certificado ssl (de paso me gustaría saber donde me recomiendan comprar un certificado SSL)

nelson fernandez

unread,
Jun 15, 2016, 5:02:52 PM6/15/16
to rub...@googlegroups.com
Como decía mi abuela.. todo depende... pero el Session Hijacking es tan viejo como internet [1] o más o menos.
El aumento de uso de https en el último tiempo viene dado más que nada por el uso de espacios compartidos y movilidad.
Pensa que cuando usas una red abierta (wifi, señales de humo), hay mucha gente que esta en la misma red y hacer este ataque es bastante simple.[2][3][4].. En redes de cable o 3g 4g es lo mismo, lo que cambia es que es más complicado meterse en el medio.
Ahora que esta LetsEncrypt [5] no hay mucha escusa para no migrar todo a https.

[5] https://letsencrypt.org/
--
:: nelson

Martín Salías

unread,
Jun 19, 2016, 9:38:07 PM6/19/16
to rub...@googlegroups.com
¡Hola, Gaby!

¿Probaste a usar session_secret?

enable :sessions
set :session_secret, "No jodan con el Padrino"

Y por otro lado, usaría HTTPS por dafault, sobre todo en el caso de tu aplicación.

Abrazo desde Montevideo,
2016-06-15 16:30 GMT-03:00 @gr-sinatra <prologic...@gmail.com>:

--

@gr-sinatra

unread,
Jun 20, 2016, 1:45:49 PM6/20/16
to rubysur
Hola Martín,

No, no lo tenia session_secret,

Lo pruebo.

Avisame cuando volves de Montevideo así arreglamos para morfar.

Abrazote
Reply all
Reply to author
Forward
0 new messages