none
Página no redirecciona a Page Default cuando no está autorizado. RRS feed

  • Pregunta

  • Hola a todos,

    La URL para ir al principal mientras estoy autenticada es la siguiente.

    http://localhost:50909/Principal/Index?idUser=1

    Pero cuando cierro sesión, y a travéz de la ruta quiero ir a esa dirección no lo deja ir (hasta ahí todo bien), pero la ruta se modifica a esto :

    http://localhost:50909/Index/Login?ReturnUrl=%2fPrincipal%2fIndex%3fidUser%3d1&idUser=1

    Me devuelve al Login pero con esa ruta, aunque funciona todo normal, si no estoy autenticada no tendría que redireccionarme a la página 401 por defecto que establecí en el web.config ?

    Mi controlador Principal, solo permite a usuarios autenticados.

    Si inicio sesión este si funciona correctamente, el problema es que no redirecciona cuando no hay autenticación.

    Espero puedan ayudarme.

    Gracias de antemano.

    viernes, 12 de agosto de 2016 18:58

Respuestas

  • La razón de que te redirija al Login en lugar de darte un 401 está en la línea que tienes un poco más arriba en el web.config, en donde configuras la autenticación por Forms y tienes puesto el loginUrl. Eso lo que hace es que cada vez que se detecta un acceso sin permisos, el sistema en lugar de dar el error de acceso denegado "rebota" a la url indicada en loginUrl para que el usuario pueda autenticarse y recibir los permisos que habían sido denegados. Este es el comportamiento normal, y es así como funciona la autenticación por Forms. No supone un riesgo de seguridad, el usuario no podrá acceder de todas maneras a la dirección restringida mientras no haya hecho login.

    Lo que sí es bastante peligroso es lo de poner ?IdUser=1 en la Url; un usuario podría cambiar ese valor y enviar al sistema un IdUser distinto.

    • Propuesto como respuesta Sergio ParraModerator sábado, 13 de agosto de 2016 12:18
    • Marcado como respuesta Gladys CM lunes, 15 de agosto de 2016 21:46
    sábado, 13 de agosto de 2016 8:18
  • Es válido este método?

    Es válido en el sentido de que hace más difícil para un usuario inexperto el cambiar el ID, pero no es realmente seguro porque no utiliza criptografía con una clave secreta, sino que meramente ofusca el ID concatenándole un valor aleatorio (el guid). Cualquier hacker que se precie probará a decodificar el Base64 (esta codificación es obvia con solo observar el valor de la URL), y examinar los 20 bytes recibidos. Usando el sistema varias veces, verá que los primeros 16 bytes cambian de manera aleatoria mientras que los cuatro últimos son algo así como 0 0 0 1 (para el userid=1). Un experimento obvio es el de cambiar esa última parte (el 1) y ver si funciona (que sí funcionará).

    Para que la protección fuera efectiva, tendrías que salvar el Guid, por ejemplo, usando el Session, y luego usar ese mismo valor para decodificar el dato recibido. Pero puestos a salvar el Guid en el Session, para eso podrías salvar directamente el UserId y quitarlo de la querystring, y sería mucho más limpio y sencillo.

    • Marcado como respuesta Gladys CM martes, 16 de agosto de 2016 20:21
    martes, 16 de agosto de 2016 6:16

Todas las respuestas

  • La razón de que te redirija al Login en lugar de darte un 401 está en la línea que tienes un poco más arriba en el web.config, en donde configuras la autenticación por Forms y tienes puesto el loginUrl. Eso lo que hace es que cada vez que se detecta un acceso sin permisos, el sistema en lugar de dar el error de acceso denegado "rebota" a la url indicada en loginUrl para que el usuario pueda autenticarse y recibir los permisos que habían sido denegados. Este es el comportamiento normal, y es así como funciona la autenticación por Forms. No supone un riesgo de seguridad, el usuario no podrá acceder de todas maneras a la dirección restringida mientras no haya hecho login.

    Lo que sí es bastante peligroso es lo de poner ?IdUser=1 en la Url; un usuario podría cambiar ese valor y enviar al sistema un IdUser distinto.

    • Propuesto como respuesta Sergio ParraModerator sábado, 13 de agosto de 2016 12:18
    • Marcado como respuesta Gladys CM lunes, 15 de agosto de 2016 21:46
    sábado, 13 de agosto de 2016 8:18
  • Gracias por su respuesta, ya entendí el funcionamiento.

    Con lo referente a poner el id?User=1, he hecho unos cambios y tengo como resultado :

    http://localhost:50909/Principal/Index?idUser=AQAAAKnhRkr55kZLvhVZ6h6vpSE%3D

    Lo que hice fue generarme una clase que creara un token junto con el Id del usuario :

    Cuando envío el valor :

    Y cuando realizo alguna acción, obtengo el id del token generado.

          public ActionResult Index(string idUser)
            {
                int id = GenerateTokenHelper.decryptToken(idUser);
                return View(_usuario.getUserById(id));
            }

    Es válido este método?

    Gracias.


    • Editado Gladys CM martes, 16 de agosto de 2016 4:43
    martes, 16 de agosto de 2016 4:39
  • Es válido este método?

    Es válido en el sentido de que hace más difícil para un usuario inexperto el cambiar el ID, pero no es realmente seguro porque no utiliza criptografía con una clave secreta, sino que meramente ofusca el ID concatenándole un valor aleatorio (el guid). Cualquier hacker que se precie probará a decodificar el Base64 (esta codificación es obvia con solo observar el valor de la URL), y examinar los 20 bytes recibidos. Usando el sistema varias veces, verá que los primeros 16 bytes cambian de manera aleatoria mientras que los cuatro últimos son algo así como 0 0 0 1 (para el userid=1). Un experimento obvio es el de cambiar esa última parte (el 1) y ver si funciona (que sí funcionará).

    Para que la protección fuera efectiva, tendrías que salvar el Guid, por ejemplo, usando el Session, y luego usar ese mismo valor para decodificar el dato recibido. Pero puestos a salvar el Guid en el Session, para eso podrías salvar directamente el UserId y quitarlo de la querystring, y sería mucho más limpio y sencillo.

    • Marcado como respuesta Gladys CM martes, 16 de agosto de 2016 20:21
    martes, 16 de agosto de 2016 6:16
  • Gracias por la ayuda.

    Abusando de su amabilidad, he decidido encriptar el valor usando MD5, o debería usar SHA1 ?

    ** Lo que hice es generar un token con el ID del usuario, y después encriptarlo.

    Y cuando voy a obtener el valor :

    Clase que encriptará los valores :


    Los métodos de encriptar y/o desencriptar lo saqué de un ejemplo :

    Encriptación con MD5

    *** Talvéz se pregunte porque no encriptar directamente el idUser ?

    A continuación muestro la forma de encryptar el Id mediante MD5 directamente, y la otra encryptar el token generado con el id.

    //Resultado : Encriptación con MD5 del id
    id = 1   => idUser=Bv9IQ9%2BXVN4%3D
    Id = 2   => idUser=HgXS7ekXygo%3D
    id = 3   => idUser=FvkiSh6vUP8%3D
    
    
    //Resultado : Generar token con el ID y encriptarlo con MD5
    id = 1 => idUser=lK6uCWLkO05ZrdHGFA1A8%2B%2BT0KMHFK0bprB8ZIvV%2FGk%3D
    id = 2 => idUser=TbBEUYTOiZnL490kPlHE9AaW95NSTNMGwzvx1ksdvQQ%3D
    id = 3 => idUser=6TrARhjdafPO624aURBPPcHNWC3hSyP%2FBkPomBliVgI%3D

    Aunque no se porque todos terminan en %3D.

    -> Cuál de las dos opciones cree que es la mejor?

    En caso alguna de las dos opciones sea correcto, como puede ver mi key="12345" (sólo lo puse de ejemplo, lo cambiaré después jeje) tendría que encryptarlo también? o puede quedar así en la clase.

    Gracias por la ayuda que pueda brindarme.

    Saludos.

    martes, 16 de agosto de 2016 21:26
  • Sigue teniendo un problema de seguridad (menor que el anterior). Como la clave es fija y es la misma para todos los usuarios, una cadena que se encriptó para un usuario puede ser usada por otro usuario distinto. Esto hace que si se consigue la URL de otro usuario (por ejemplo, leyendo el historial del navegador, o mirando los logs de IIS, o usando un sniffer en la red), entonces se puede impersonar a ese usuario copiando el texto "encriptado" de la url. Por cierto, tanto MD5 como SHA1 son algoritmos de hashing, no de cifrado.

    Para que fuera realmente seguro, la clave debería ser cambiante y distinta para cada usuario. Eso nos lleva a la misma situación anterior, es decir, debe arrastrarse esa clave de una navegación a la siguiente, lo cual requiere usar para ello técnicas de conservación del estado, tales como el Session o una Cookie. Pero ya puestos a usar el Session o una Cookie para guardar la clave, para eso podrías guardar ahí directamente el id de usuario y ahorrarte toda la complejidad de la encriptación. De hecho, eso es lo que hace internamente el propio sistema de Membership de asp.net: guarda el ID en una cookie encriptada (y usa otra cookie criptográficamente pseudo-aleatoria para controlar la sesión).

    miércoles, 17 de agosto de 2016 6:06