November 27th, 2008 Category: Programacion Uncategorized
24 Comments »
Un problema recurrente con los sistemas grandes y/o multidominio es mantener la sesion de usuarios entre diferentes dominios.
Es imposible hacerlo con las cookies ya que por cuestiones de seguridad los browser no dejan leer o escribir cookies con diferente dominio al actual.
Lo mismo pasa con las sesiones, si uno accede a una pagina y genera un sesion cuando pasa a otro dominio pierde esa sesion.
La solucion no es nada simple. En el ultimo web and beer se hablo de una solucion, pero esa solucion no me dejo nada convencido, y me quede pensando en la idea.
Actualmente en Easytech estamos trabajando en un proyecto, que inicialmente iba a tener el mismo problema, pero lo solucionamos usando un unico dominio, ya que no era necesario otro. Solo tuvimos que unir varios sistemas, bajo el mismo dominio, pero esto es mucho mas facil, ya que podemos pasar un hash que nos permita buscar la info del usuario en una base de datos o en el file system a traves de las cookies.
Pero este problema de los multidominios tiene solucion, de hecho tenemos un google account, que administra las claves de diferentes dominios, ya sea www.gmail.com, www.google.com, www.youtube.com, www.orkut.com, www.picasaweb.com, etc.. Si google lo resolvio porque no nosotros?
Una manera de resolver este probelma, es guardar los datos de sesion en una base de datos, y los enlaces a los diferentes dominios agregarle el hash que hace de indice en esta base para que pueda regenerar los datos de session. El problema es que si yo accedo directamente a un dominio eso no me va a funcionar muy bien.
Una alternativa a este problema es que todo siempre se redireccione a un dominio, cheque si hay una sesion, y despues redirigirlo, como hace google.
Por ejemplo, cada vez que nosotros accedemos a www.orkut.com, este nos redirecciona a https://www.google.com/accounts/ServiceLogin y envia todos los parametros que necesita para identificar al usuario.
Desde este dominio de autenticacion, generamos la cookie correspondiente con el hash necesario. Y lo volvemos a redireccionar al sitio que quiere acceder con un parametro hash, con el indice para que obtenga los datos.
La solucion parece bastante simple, y creo que lo es pero queria compartirla ya que se me quedo colgada en el ultimo web and beer.
Vamos a ver ahora un ejemplo practico
Yo tengo el dominio www.mail.com, el dominio www.calendar.com, y el dominio de mi empresa que se llama www.cloacas.com.
Un usuario ingresa en www.mail.com, ingresa los datos de su cuenta, este formulario envia un post a http://account.cloacas.com/, valido los datos, genero la autenticacion, y lo redirecciono a http://www.mail.com/?id=1231534232, el dominio mail.com, sabe que tiene que generar la sesion con los datos que va a obtener de la base de datos, con el indice que le paso en id.
Con esto tengo que haber logrado autenticarme en www.mail.com. Ahora el usuario, en otro tab de su browser escribe, www.calendar.com.
Calendar.com, hace lo mismo que www.mail.com, y lo redirecciona a account.cloacas.com, este se fija sino tiene ninguna cookie seteada, y si la tiene busca el hash que guardo en la cookie y la compara con el de la base de datos, si todo esta ok, redirecciona al usuario a www.calendar.com/?id=1231534232, sin la necesidad que el usuario ingrese sus datos, porque ya lo habia hecho en www.mail.com
Invitame una Cerverza
Comentar
24 Responses
Lo de la re-re-redireccion es lo que hace google, no creo que sea malo.
Tene en cuenta que ademas del hash necesitas la cookie, si vos lo ves pasar, tendrias que tener la cookie creada tambien
Es verdad que está el tema de la cookie. Tampoco había tenido en cuenta un detalle y que es fundamental: todo esto se tiene que hacer por HTTPS, sino todo es hijackeable. Si es por HTTPS hay una vulnerabilidad que te puede traer problemas (http://www.webandbeer.com.ar/2008/08/el-bug-mas-grande-de-internet/) pero es un poco más seguro.
Con lo del ID que vaya en el GET... por más que sea un hash se puede hacer un bruteforce... el tema es ver qué relación tiene o no con la cookie y de qué manera hacés para comprobar que el que te esté mandando el hash sea verdaderamente quien dice ser.
Y por último, pero no menos importante, está el tema de que mantener una sesión contra una base de datos, si bien es útil, a veces te puede traer problemas de performance. Habría que evaluar si no conviene más usar memached.
http://groups.google.com/group/webandbeer/browse_thread/thread/c91d2b4f84660dd8/d396226163f8b21d?lnk=gst&q=cookie+hijacking#d396226163f8b21d
Lo de la base lo podes obviar y tenerlo en el filesystem, pero en este caso, los dominios deberian compartir el mismo servidor, o directamente hacer session_id(), y setear la id que le corresponda o que venga por get
Articulo que explica como mantener una sesion de usuario entre diferentes dominios, aplicando la filosofia de google, y como lo implementa...
Sobre obtener la mac address no fue mi idea, no recuerdo quien la tiro.
Sobre guardar sessiones en DB esa siempre es util, pero si ven que es un bardo, les recomiendo usar memcached.
Nunca lo vi con la idea de almacenar datos que pueda volver a requerir, siempre lo vi como cache nada mas.
Estaria bueno una explicacion de como lo usuarias.
Fijate en google que hay ejemplos de cómo overridear el manejo de sesiones de PHP para usar memcached. Creo que en la misma documentación de PHP, en la parte de sesiones, hay una clase que hace eso (en las contribuciones de los usuarios).
Pero el cache lo va a requerir el usuario, no mi sistema. Es para que no tenga que volver a generar la pagina, no para que me pase datos nuevos.
Puede haber cache de muchas cosas, de archivos dinámicos (PHP), de consultas SQL, de archivos estáticos (lo que expliqué yo en mi post sobre Apache), pero también cache de información que vayas a volver a utilizar pronto.
Como digo yo en mi post, "el cache es, por lo general, una reproducción estática de un conjunto de información dinámica. Es decir, un almacenamiento temporal de una información que puede cambiar, durante un período de tiempo en el que se supone que no ha de hacerlo.". En memcached vos guardas bajo una clave un dato al que vas a volver a acceder (por ejemplo, un resultado de una consulta SQL), para poder hacerlo rápidamente y sin volver a atravesar un proceso costo (una consulta a la DB).
Ahora, muy bueno el post sobre cache con apache en www.tail-f.com.ar
Tengo un "wrapper" para ZF por ahí si algiuen esta interesado ... que se manifesta ;)
Echa un vistazo a esta clase ...
¿ Creo es lo que necesitas ?
Perdón por los múltiples comentarios, el sueño es mi único vicio que me adormece con su ausencia :p
Gracias por los multiples comentarios :)
Creo que llego a entender tu idea (creo). Me parece interesante esto, pero creo que no haria falta. Te cuento que a partir del ultimo articulo que escribi estoy desarrollando este sistemita para despues compartirlo. Y necesito una base de datos porque necesito centralizar los datos. Es decir, no solo administrar sesiones, sino ademas administrar la informacion compartida delos usuarios. Y en este caso tu ejemplo no se podria aplicar, quizas para un sistema que no necesite centralizar la info de los usuarios es mas valedero.




Por otro lado, qué pasa si hago un script que empiece a hacer GETs a www.mail.com con IDs fruta? Eventualmente le podría pegar a un ID válido y me estarías dando control sobre la sesión de otro cliente. Faltaría armar toda esa parte de validación que es lo complicado. En ningún caso te salvás de hacer un hash con los datos que tenés del cliente, lo cual nunca es infalible porque todos los datos son modificables por el cliente.
Ni hablar de que si estoy sniffeando una red y veo pasar ese handshaking puedo hacerme con la sesión del usuario sin problemas. ¿Cómo? Hago un GET a www.mail.com/?id=NNNN pasandole el ID que vi pasar y enviando los mismos headers de HTTP que mandó el otro cliente antes que yo.