¿Debería MVC / REST devolver un 403 o 404 para los recursos que pertenecen a otros usuarios?


33

Cuando trabajamos con un sitio basado en recursos (como una aplicación MVC o un servicio REST), tenemos dos opciones principales cuando un cliente intenta GETun recurso al que no tiene acceso:

  • 403 , que dice que el cliente no está autorizado ; o
  • 404 , que dice que el recurso no existe (o no se pudo localizar).

La sabiduría común y la práctica común parecen ser responder con la verdad, es decir, un 403. Pero me pregunto si esto es realmente lo que hay que hacer.

Los sistemas de inicio de sesión seguro nunca le dicen el motivo de un error de inicio de sesión. Es decir, en lo que respecta al cliente, no hay una diferencia detectable entre un nombre de usuario inexistente y una contraseña incorrecta. El propósito de esto es no hacer que las ID de usuario, o peor, las direcciones de correo electrónico, sean reconocibles.

Desde el punto de vista de la privacidad , parece mucho más seguro devolver un 404. Recuerdo el incidente en el que, según los informes, alguien descubrió a los ganadores de un reality show (Survivor, creo) al observar qué recursos no existían en el sitio vs. cuáles lo hicieron. Me preocupa que un 403 pueda revelar información confidencial como un número de serie o un número de cuenta.

¿Hay razones de peso para no devolver un 404? ¿Podría una política 404 tener efectos secundarios negativos en otros lugares? Si no, ¿por qué la práctica no es más común?


1
Razón convincente para no devolver 404: si el servicio está inactivo o hay un error / error en la autenticación, obtendría un 404, pero la persona del cliente / usuario / probador / desarrollador / soporte que intenta diagnosticar el problema puede no tener idea qué hay de malo en el mensaje de error.
Steven Evers

@Snorfus: Ese es un buen punto, lo habría puesto en una respuesta. Aunque Josh ya se añadía un buen contrapunto ...
Aaronaught

Otro aspecto a tener en cuenta es este: ¿cómo se tratan los 404 aguas abajo? ¿Hay un CDN o algún tipo de almacenamiento en caché? Si alguna vez desea poder almacenarlos en caché, entonces probablemente no desee que se almacenen en caché sus 404s "usuarios no tienen permiso".
pc1oad1etter

Respuestas:


15

Hay una idea errónea (y mal uso) general asociada con 403 Forbidden: no se supone que revele nada sobre lo que el servidor piensa sobre la solicitud. Está específicamente diseñado para decir,

Recibo lo que está solicitando, pero no voy a manejar la solicitud, no importa lo que intente. Así que deja de intentarlo.

Cualquier UA o cliente debe interpretar que eso significa que la solicitud nunca funcionará y responder adecuadamente.

Esto tiene implicaciones para los clientes que manejan solicitudes en nombre de los usuarios: si un usuario no está conectado o escribe incorrectamente, el cliente que maneja la solicitud debe responder: "Lo siento, pero no puedo hacer nada" después de la primera vez obtiene 403y deja de manejar solicitudes futuras. Obviamente, si desea que un usuario aún pueda solicitar acceso a su información personal después de una falla, este es un comportamiento hostil del usuario.

403está en contraste con 401 Authorization Required, lo que revela que el servidor manejará la solicitud siempre que pase las credenciales correctas. Esto es generalmente lo que piensan las personas cuando escuchan 403.

También está en contraste con lo 404 Page Not Foundque, como señalaron otros, está diseñado no solo para decir "No puedo encontrar esa página" sino para sugerirle al cliente que el servidor no hace reclamos de éxito o fracaso para futuras solicitudes.

Con 401y 404, el servidor no le dice nada al cliente o UA sobre cómo deben proceder: pueden seguir intentándolo con la esperanza de obtener una respuesta diferente.

Entonces, 404es la forma adecuada de manejar una página que no desea mostrar a todos, pero no quiere revelar nada sobre por qué no la mostrará en ciertas situaciones.

Por supuesto, esto supone que el cliente que realiza la solicitud se preocupa por la insignificancia de RFC. Un cliente suficientemente malicioso no se preocupará por el código de estado devuelto, excepto de manera incidental. Uno sabrá que es una página de usuario oculta (o una página de usuario oculta potencial) al compararla con otras páginas de usuario conocidas.

Es decir, digamos que su controlador es users/*. Si sé users/foo, users/bary users/baazel trabajo, el servidor de devolución de una 401, 403o 404para users/quuxno quiere decir que no voy a probarlo, especialmente si tengo motivos para creer que es un quuxusuario. Un escenario de ejemplo estándar es Facebook: mi perfil es privado, pero mis comentarios sobre los perfiles públicos no lo son. Un cliente malintencionado sabe que existo aunque regrese 404a mi página de perfil.

Entonces, los códigos de estado no son para los casos de uso malicioso, son para los clientes que cumplen las reglas. Y para esos clientes, una 401o una 404solicitud es lo más apropiado.


44
Sin embargo, buenos puntos sobre 401 vs. 403. No estoy de acuerdo con la finalidad de sus declaraciones sobre 404. Claro, en el ejemplo de Facebook, ya sabes que quuxexiste. Pero no siempre habrá evidencia externa, especialmente en sitios no sociales donde los datos del cliente son realmente privados . Un usuario entrometido u hostil podría finalmente ser capaz de deducir que usted está mintiendo, pero no necesariamente el que los recursos se está acostado sobre . Creo que el punto principal aquí es realmente, no se moleste en recursos 404 a menos que no haya otros métodos de descubrimiento disponibles.
Aaronaught

@Aaronaught La cuestión es que tienes que estar muy, muy seguro de que alguien no puede entender por qué el servidor engaña, o que no hay algún método de descubrimiento contra el que no te hayas endurecido. Una persona lo suficientemente inteligente será la figura hacia fuera, y en ese punto, el código de estado no tiene sentido.

1
Todavía no tengo claro cómo una persona lo suficientemente inteligente podría resolverlo si no se comparten datos entre los perfiles de usuario. Entiendo que alguien determinado finalmente se dará cuenta de "oh, un 404 realmente significa que podría existir, pero simplemente no puedo acceder a él", pero suponiendo que el servidor devuelva el mismo error para los recursos que realmente no existen, ¿cómo podría uno ¿Cuál es la diferencia entre un recurso inexistente y uno privilegiado?
Aaronaught

@Aaronaught lo único que una persona necesitaría saber es que la URL de un perfil debe existir. Puede usar las ID de perfil e incrementarlas de manera pseudo (por lo que una persona con una ID de perfil de 3333 no significa que haya una persona con una ID de perfil de 3332), pero una persona determinada debería poder predecirlo dado tamaño de muestra de identificaciones válidas. De lo contrario, e incluso dado un sistema completamente resistente que no filtra información sobre cómo genera URL para páginas de perfil, siempre existe la ingeniería social.

8

De acuerdo con RFC2616

10.4.4 403 Prohibido

El servidor entendió la solicitud, pero se niega a cumplirla. La autorización no ayudará y la solicitud NO DEBE repetirse. Si el método de solicitud no era HEAD y el servidor desea hacer público por qué la solicitud no se ha cumplido, DEBERÍA describir el motivo de la denegación en la entidad. Si el servidor no desea que esta información esté disponible para el cliente, se puede utilizar el código de estado 404 (No encontrado).

También tenga en cuenta que al acceder a recursos prohibidos, la autorización no ayudará .


Soy consciente de la RFC, aunque tiene poca semejanza con la realidad. Casi ningún servidor explica el motivo de un 403 más allá de esa primera oración ("El servidor entendió la solicitud, pero se niega a cumplirla") y la mayoría de los marcos MVC incluso tienen algo similar a lo HttpUnauthorizedResultque está destinado a ser utilizado para recursos privilegiados . También me doy cuenta (obviamente) de que 404 puede usarse en su lugar; mi pregunta es si se debe usar o no , y qué se debe considerar al tomar esa decisión.
Aaronaught

@Aaronaught: el RFC no solo le permite usar 404, sino que recomienda que se lance 404 cuando no desea reconocer nada.
Lie Ryan

3
Eso está bien, pero ¿ cuándo no debo reconocer nada? O más bien, ¿cuándo debería ? Esa es realmente la esencia de la pregunta.
Aaronaught

5

Deberías? .

Lo dijiste tú mismo, traicionar lo menos posible. Si estaba atacando un sistema y noté que el servidor respondía con 403 códigos, me concentraría en esos, en lugar de seguir adelante. Mejor que una puerta proclame que no existe, que proclamar que está prohibida.

La desventaja de usar 404 solicitudes es que externamente parecerá que la página no existe, y esto podría tener conflictos en comparación con las páginas que se supone que existen, pero que faltan. Si no le preocupan los rastreadores web (de todos modos, los sistemas autenticados deben denegarse por completo), entonces debe hacerlo. Cada API que tengo maneja el acceso no autorizado exactamente de la misma manera, y también lo hace StackOverflow . ¿No puedes ver esa página? Te aseguro que lo hace existir, a pesar de que no se pretende.

Usted debe reconocer las solicitudes cuando el recurso se conoce a existir y se deniega el acceso. Un inicio de sesión fallido no debería generar un mensaje 404. No debe acusar recibo de solicitudes cuando la existencia del recurso en sí mismo debe estar protegida. El acceso al reino existe en el público, pero los grupos de seguridad o roles dentro de él no lo son.


Razón convincente para no devolver 404: si el servicio está inactivo o hay un error / error en la autenticación, obtendría un 404, pero la persona del cliente / usuario / probador / desarrollador / soporte que intenta diagnosticar el problema puede no tener idea qué pasa con el mensaje de error

Los desarrolladores deben tener acceso a los registros, lo que indicará un intento de acceder a un recurso protegido. Los clientes / usuarios / evaluadores generarán comentarios que eventualmente afectarán a un desarrollador.

Seguridad por oscuridad ... ¿en serio?

Esto no es seguridad por oscuridad. Está utilizando la oscuridad además de las medidas de seguridad adecuadas.

Por otro lado, las solicitudes válidas para obtener un "404" solo agregan complejidad y oscuridad donde no es necesario

No son solicitudes válidas, son solicitudes no autorizadas . Estás cambiando una pequeña parte (devuelve 404 en lugar de 403) para obtener una ventaja sustancial en cualquier posible atacante.


Seguridad por oscuridad ... ¿en serio? Si alguien intenta manipular sus servicios con intención maliciosa, ya saben que está allí. Por otro lado, las solicitudes válidas para obtener un "404" solo agregan complejidad y oscuridad donde no es necesario.
Steven Evers

44
@Snorfus: Aquí hay que hacer una sutil distinción entre seguridad y privacidad . La privacidad es, casi por definición, "por oscuridad". Esto es especialmente importante en el contexto de un sistema basado en recursos , ya que la existencia o inexistencia de un recurso es información potencialmente importante. Puede haber argumentos de seguridad también, aunque estoy menos preocupado por ellos. Me gustaría gustaría saber más acerca de esta complejidad añadida; ¿Puedes entrar en detalles más allá de tu comentario inicial? (? Tal vez en una respuesta más completa ¿Ha sido mordido por 404'ed 403S?)
Aaronaught

2
@Snorfus: También me gustaría agregar, como una ocurrencia tardía, que la defensa en profundidad no es lo mismo que la seguridad por oscuridad . Esto último implica que no hay otros medios de protección. Pero agregar oscuridad a un sistema ya seguro a menudo puede ser algo bueno, siempre y cuando no cause otros problemas en el futuro. En este caso, es un hecho que el sistema ya está asegurado, ya que los 404 se emiten por código de autorización.
Aaronaught

@Aaronaught: publicaré una respuesta más profunda, pero sobre el tema: si un recurso es privado, ¿cuál es el razonamiento detrás de exponerlo públicamente?
Steven Evers

@Snorfus: un recurso es privado para un cliente , o tal vez para un grupo , no para todo el mundo.
Aaronaught

0

Realmente depende de la información dada por el código de estado 403. Si tiene un punto final de API que responde GET /myresource/{id}con un 404 cuando el recurso no existe, entonces el código de estado devuelto por el punto final cuando el recurso existe pero no está autorizado para el usuario actual debe depender de la previsibilidad del idparámetro y la cantidad de información que contiene por sí mismo.

  • Si ides un campo privado como una dirección de correo electrónico o un número de cuenta bancaria, probablemente siempre debería estar oculto detrás de un 404. En el caso de una dirección de correo electrónico, podría evitar que los bots de spam compilen una lista de direcciones de correo electrónico válidas registradas en su sitio web.
  • Si ides un nombre de usuario público, no se moleste, hay otros medios para obtener acceso a esta información (por ejemplo, simplemente navegando por la página del foro de su sitio web).
  • Si ides un identificador opaco pero predecible (p. Ej., Un entero de incremento automático), no le proporciona al atacante ninguna información que no pueda obtener por otros medios. Entonces, en mi opinión, es seguro devolver un código de estado 403.
  • Si ides un identificador opaco e impredecible (como un GUID aleatorio), la pregunta es más sutil. Personalmente, creo que no hay ningún problema en devolver un código de estado 403. Esta información solo podría explotarse si hay otro punto final defectuoso en su API usando esta ID, pero el error real ES su otro punto final.

Puede suponer que es mejor prevenir que curar en cualquier caso y ocultar la información en cualquier contexto, pero en realidad no puede confiar en este tipo de comportamiento para proporcionar ningún tipo de seguridad . Por otro lado, puede proporcionar confidencialidad (o privacidad, como han dicho otros).

Un mecanismo de seguridad no solo debe ser un obstáculo para el atacante, sino que simplemente es inútil. En este caso, incluso podría evitar que use otras funciones correctamente (rastreadores, Firewall de aplicaciones web que buscan cantidades anormales de 403 códigos de estado para bloquear usuarios ...).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.