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






El tema es que siempre que ingrese a http://www.mail.com y a http://www.calendar.com de entrada lo vas a tener que redireccionar a accounts.cloacas.com porque no vas a saber si existe la sesión.
Por otro lado, qué pasa si hago un script que empiece a hacer GETs a http://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 http://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.
Sería genial tener algún programita loco corriendo, o algún módulo loco de apache, con el cual uno pudiera obtener información de bajo nivel del cliente (concretamente la MAC Address). Si bien no sería infalible, sería mucho más seguro. Claro que seguramente mandaría a la mierda todo el modelo OSI jajaja.
No vas a tener este problema, porque no vas a hacer 123545 la clave, va a ser un hash y con un hash no vas poder pegarle como decis.
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
Cesar estaba hablando de obtener la mac address de una manera, pero me parece muy loco, y no creo que se pueda.
La otra forma de obtener la MAC sería también ejecutando algo del lado del cliente (un applet o un activex), pero es demasiado invasivo.
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.
Perdón, publiqué cualquier URL. Ahora busco la que debería ser.
A esto me refería
http://groups.google.com/group/webandbeer/browse_thread/thread/c91d2b4f84660dd8/d396226163f8b21d?lnk=gst&q=cookie+hijacking#d396226163f8b21d
Tenes Razon, HTTPS!!!
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
El tema de redirreccionar yo lo vi y pense hace tiempo, pero no me habia convencido para nada.
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.
Estoy esperando un post completo sobre memcache en el blog de bsdsolution, o en el de web and beer.
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.
Jeje y para qué almacenás datos si no los vas a volver a requerir?
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).
Lo voy a revisar.
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.
Entonces tenés una concepción bastante limitada de cache
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).
Es cierto no lo estaba pensando de la forma correcta, por suerte te tengo a vos.
Ahora, muy bueno el post sobre cache con apache en http://www.tail-f.com.ar
La solucion es almacenar las sessiones en una base de datos.
Tengo un “wrapper” para ZF por ahí si algiuen esta interesado … que se manifesta
Pero como haces para saber que indice de tu base de datos usar para extraer los datos?
http://f-pig.blogspot.com/2008/01/try-zend-framework-vol11-save-session.html
Echa un vistazo a esta clase …
¿ Creo es lo que necesitas ?
¿Han pensado tal vez en utilizar el mismo hash como mecanismo para transmitir la información entre dominios? Mi propuesta es utilizar un modelo de encriptación asimétrica PGP o PKI entre los servidores, y enviarlo via GET de un servidor a otro obviamente con SSL. Es decir, en tu ejemplo, al conectarme a http://www.mail.com (sin parámetro GET) me redireccionaría a https://accounts.cloacas.com, aquí verificaría la cookie, de existir obtendría la información de la sesión, serializo el arreglo en una variable “info”, la codifico con mi llave privada, codifico los caracteres de manera adecuada para enviarlos via GET y redirecciono a http://www.mail.com?info=U7Jnt5q8tgg28A9j... Acá simplemente decodifico “info” con la llave pública y listo, me he ahorrado bases de datos, archivos compartidos y el requerimiento de que ambos sitios compartan recursos de un mismo servidor.
Tal vez me equivoqué en el orden de utilización de las llaves, sería primero utilizar la llave pública para la encriptación, y la privada para la desencriptación. O para reforzar la seguridad, ambos servidores pueden tener su propia llave privada, entonces en cloacas.com encriptaría “info” con la llave pública de mail.com y con su propia llave privada, y en cloacas.com la desencripta con su llave privada y la llave pública de mail.com.
Haber, en cloacas.com encriptaría “info” con la llave pública de mail.com y con su propia llave privada, y en mail.com la desencripta con su llave privada y la llave pública de cloacas.com.
Perdón por los múltiples comentarios, el sueño es mi único vicio que me adormece con su ausencia :p
Hola Edakos.
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.
muy buena la explicación! me ha sido de gran ayuda!
Gracias Lu