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 GET
un 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?
fuente
Respuestas:
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,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
403
y 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.403
está en contraste con401 Authorization Required
, lo que sí revela que el servidor manejará la solicitud siempre que pase las credenciales correctas. Esto es generalmente lo que piensan las personas cuando escuchan403
.También está en contraste con lo
404 Page Not Found
que, 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
401
y404
, 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,
404
es 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/bar
yusers/baaz
el trabajo, el servidor de devolución de una401
,403
o404
parausers/quux
no quiere decir que no voy a probarlo, especialmente si tengo motivos para creer que es unquux
usuario. 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 regrese404
a 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
401
o una404
solicitud es lo más apropiado.fuente
quux
existe. 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.De acuerdo con RFC2616
También tenga en cuenta que al acceder a recursos prohibidos, la autorización no ayudará .
fuente
HttpUnauthorizedResult
que 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.Deberías? Sí .
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.
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.
Esto no es seguridad por oscuridad. Está utilizando la oscuridad además de las medidas de seguridad adecuadas.
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.
fuente
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 delid
parámetro y la cantidad de información que contiene por sí mismo.id
es 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.id
es 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).id
es 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.id
es 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 ...).
fuente