Un breve resumen de la seguridad OAuth
¿Qué tan bien informado estás sobre las medidas de protección empleadas por OAuth? ¿Su sistema se adhiere al estándar abierto de OAuth? ¿Estás consciente de los posibles riesgos que pueden surgir durante la implementación del flujo de autenticación del usuario? Repasemos brevemente lo que hemos aprendido sobre OAuth
Introducción
Hace unos días, nos llegó un interesante artículo sobre una vulnerabilidad de OAuth. Una nueva vulnerabilidad oauth que puede impactar a cientos de servicios en línea por el laboratorio SALT. Esta publicación específica resalta la vulnerabilidad descubierta en Expo, un marco de trabajo ampliamente utilizado para implementar OAuth y otras funcionalidades. Se dirige específicamente a una vulnerabilidad en la biblioteca expo-auth-session, que ha sido asignada y resuelta correctamente.
Si tienes interés en OAuth o estás trabajando en un producto relacionado con CIAM como nosotros, te recomendamos mucho que leas este artículo. Es bastante inspirador y proporciona perspectivas útiles. Estos informes de sombrero blanco sirven como un recordatorio de cómo incluso la característica más simple puede causar vulnerabilidades. Cuando se trata de ciberseguridad y autorización, nunca podemos ser demasiado cuidadosos al garantizar la seguridad y la privacidad de la información del usuario. Si este artículo capta tu atención, creo que estarás fuertemente de acuerdo con nosotros.
Me recuerda al tiempo en que empezamos. Pasamos mucho tiempo aprendiendo e investigando los detalles de los protocolos OAuth y OIDC. Fue doloroso y tedioso, pero los beneficios fueron inmensos. Aunque quizás no todos en nuestro equipo son expertos en OAuth, todos están comprometidos a poner un esfuerzo continuo hacia la seguridad y meticulosidad. Con esos esfuerzos dedicados, el producto Logto ha evolucionado a lo que es hoy.
Agradeciendo a esta gran oportunidad, nos gustaría refrescar nuestra memoria en algunos detalles de seguridad de OAuth aquí.
Un vistazo al Flujo de Código de Autorización de OAuth
OAuth 2.0 proporciona varios flujos de autorización que se adaptan a diferentes tipos de clientes y requerimientos. Estos incluyen el Flujo Implícito, Flujo de Credenciales de Cliente, Flujo de Contraseñas Credenciales de Propietario de Recurso y Flujo de Autorización de Dispositivo. Sin embargo, el Flujo de Código de Autorización se destaca como el más seguro y ampliamente utilizado. A diferencia de otros flujos, separa la autenticación del usuario de la aplicación del cliente e involucra el intercambio de un código de autorización por tokens. Este enfoque brinda una capa adicional de seguridad, ya que los tokens sensibles nunca se exponen al cliente. Además, el Flujo de Código de Autorización admite la gestión de tokens en el lado del servidor, lo que lo hace adecuado para aplicaciones web que requieren una seguridad robusta y un control mejorado sobre el acceso del usuario.
Aquí hay un diagrama más simple del Flujo de Código de Autorización:
Echemos un vistazo a los dos pedidos más cruciales realizados en el Flujo de Concesión de Código de Autorización y los fragmentos aparentemente triviales dentro de ellos pero juegan un papel crítico en la protección contra el fraude.
El punto final de autorización:
El punto final de intercambio de token:
Credenciales del cliente
En OAuth, las Credenciales del Cliente se refieren a las credenciales utilizadas por una aplicación cliente para autenticarse e identificarse al servidor de autorización. Estas credenciales se obtienen durante el proceso de registro del cliente y se utilizan para validar la identidad del cliente al hacer solicitudes al servidor de autorización. (Puede encontrar su credencial de cliente en la consola de administración de Logto cuando registra su aplicación por primera vez.)
Las credenciales del cliente suelen estar compuestas por dos componentes:
- ID del cliente: Un identificador único asignado a la aplicación del cliente por el servidor de autorización. Es un valor público que generalmente no se considera sensible.
- Secreto del cliente: Un valor confidencial y almacenado de forma segura que solo conocen el cliente y el servidor de autorización. Sirve como una forma de autenticación para la aplicación cliente y se utiliza para verificar la identidad del cliente al hacer solicitudes al servidor de autorización.
Como puedes encontrar, la combinación de ID del cliente y Secreto del cliente se utiliza durante la solicitud del token para autenticar al cliente y obtener Tokens de acceso.
Las credenciales del cliente juegan un papel vital en garantizar la seguridad del flujo de OAuth. Ayudan al servidor de autorización a verificar la autenticidad de las aplicaciones cliente y a controlar el acceso a recursos protegidos. Es importante manejar las credenciales del cliente de forma segura y protegerlas contra el acceso no autorizado. Logto categoriza las aplicaciones del cliente en dos niveles de seguridad diferentes:
- Clientes confidenciales: Estos incluyen aplicaciones web procesadas por el servidor y aplicaciones de maquina a maquina (M2M). En el caso de los clientes confidenciales, todas las credenciales relacionadas con la autorización, incluidas las credenciales del cliente, se almacenan de forma segura en el lado del servidor. Además, todas las solicitudes de intercambio intermedias están encriptadas para garantizar la confidencialidad de los datos. El riesgo de fuga de las credenciales del cliente para los clientes confidenciales es muy bajo, lo que los hace intrínsecamente más seguros. Por lo tanto, los clientes confidenciales se tratan con un nivel de seguridad más alto por defecto. En el flujo de intercambio de tokens, presentar el Secreto del Cliente es OBLIGATORIO.
- Clientes públicos: Estos incluyen aplicaciones web de una sola página (SPA) y aplicaciones nativas. Para los clientes públicos, las credenciales del cliente suelen estar codificadas en el lado del cliente, como dentro de un paquete JavaScript o un paquete de aplicación en una plataforma nativa. El riesgo de fuga de credenciales es mayor en comparación con los clientes confidenciales debido a la exposición inherente de las credenciales del cliente en el código del lado del cliente. En el flujo de intercambio de tokens, presentar el Secreto del Cliente es OPCIONAL. Logto no confiará en esas credenciales de un cliente público por defecto.
Estado
En el flujo de OAuth, el parámetro state
es un valor generado aleatoriamente que se incluye en la solicitud de autorización enviada por el cliente al servidor de autorización. Su propósito es mantener el estado o contexto de la solicitud del cliente durante el proceso de autorización.
El parámetro state
actúa como una medida de seguridad para prevenir ataques de falsificación de solicitudes entre sitios (CSRF). Cuando el servidor de autorización redirige al usuario de vuelta a la aplicación del cliente después de la autenticación y autorización, incluye el mismo valor de estado en la respuesta. La aplicación del cliente DEBE
comparar este valor con el valor de state
original que envió en la solicitud de autorización.
Al verificar el parámetro de estado, el cliente puede asegurarse de que la respuesta recibida del servidor de autorización corresponde a la solicitud inicial que hizo. Esto ayuda a prevenir ataques donde un atacante intenta engañar al cliente para que acepte una respuesta destinada a otro usuario o aplicación.
Toma el siguiente ejemplo de ataque CSRF en un caso de uso ficticio:
Ataque CSRF: Fraude para vincular cuenta social - problema
Con un mecanismo de validación de estado adecuado, el cliente puede detectar el ataque y evitar que el usuario sea redirigido al sitio web del atacante:
Ataque CSRF: Fraude para vincular cuenta social - solución
PKCE
Como se mencionó anteriormente, los clientes públicos como las aplicaciones web SPA y las aplicaciones nativas corren un mayor riesgo de fuga de credenciales de autenticación, incluyendo el Código de Autorización emitido por el servidor de autorización.
PKCE significa Proof Key for Code Exchange. Es una extensión del Flujo de Código de Autorización de OAuth 2.0 que mejora la seguridad de los clientes públicos.
PKCE fue introducido para mitigar el riesgo de que un atacante intercepte el Código de Autorización e intercambie por un token de acceso sin el conocimiento del cliente. Este tipo de ataque, conocido como ataque de interceptación de código de autorización, es más frecuente en entornos donde la aplicación cliente no puede almacenar de forma segura un secreto de cliente.
Para implementar PKCE, la aplicación cliente genera un verificador de código aleatorio y deriva un desafío de código a partir de él utilizando un algoritmo de hash específico (generalmente SHA-256). El Desafío de Código se incluye en la solicitud de autorización inicial enviada al servidor de autorización.
Cuando el servidor de autorización emite el Código de Autorización, la aplicación cliente incluye el Verificador de Código original en la solicitud del token. El servidor verifica que el Verificador de Código coincide con el Desafío de Código almacenado y solo entonces emite el Token de Acceso.
Al usar PKCE, la aplicación del cliente asegura que el Código de Autorización solo no es suficiente para obtener un Token de Acceso. Este mecanismo agrega una capa extra de seguridad al flujo de autorización, especialmente para clientes públicos donde el almacenamiento de Secretos de Cliente es desafiante.
Logto usa PKCE como el ÚNICO flujo de autorización para todas las aplicaciones de tipo cliente público. Sin embargo, PKCE puede ser omitido para esos clientes confidenciales.
URI de redirección
Un URI de redirección (Uniform Resource Identifier) es un endpoint o URL específico al que el servidor de autorización redirige al usuario después del proceso de autenticación y autorización en OAuth.
Durante el flujo de OAuth, la aplicación del cliente incluye un URI de redirección como parte de la solicitud de autorización inicial. Este URI sirve como la URL de callback donde se redirigirá al usuario después de autenticarse con éxito y otorgar permisos al cliente.
Una vez que el usuario completa el proceso de autenticación, el servidor de autorización genera una respuesta que incluye un Código de Autorización, y redirige al usuario de vuelta al URI de redirección especificado.
La validación del URI de redirección es un paso esencial para garantizar la seguridad e integridad del flujo de OAuth. Implica verificar que el URI de redirección utilizado en la solicitud de autorización y redirecciones subsecuentes es válido y confiable.
Volviendo atrás y echando un vistazo al informe original de vulnerabilidad de OAuth. (La siguiente sección se referencia del post original)
Cuando el usuario hace clic en "iniciar sesión con facebook" usando la APP Móvil en Expo Go, redirige al usuario al siguiente enlace:
https://auth.expo.io/@moreisless3/me321/start?authUrl=https://www.facebook.com/v6.0/dialog/oauth?code_challenge=...&display=popup&auth_nonce=...&code_challenge_method=S256&redirect_uri=https://auth.expo.io/@moreisless3/me321&client_id=3287341734837076&response_type=code,token&state=gBpzi0quEg&scope=public_profile,email&returnUrl=exp://192.168.14.41:19000/--/expo-auth-session
En la respuesta, auth.expo.io establece la siguiente cookie: ru=exp://192.168.14.41:19000/--/expo-auth-session. El valor RU será utilizado más tarde como Url de retorno en el paso 5. Luego le muestra al usuario un mensaje de confirmación, y si el usuario aprueba - lo redirige al inicio de sesión de Facebook para continuar el flujo de autenticación
…
Esta página lee el parámetro de consulta "returnUrl" y establece la cookie en consecuencia.
Intentemos cambiar el returnUrl a
hTTps://attacker.com
(https no está permitido, así que traté de insertar letras mayúsculas y funcionó), que establece la RU (Url de Retorno) en la cookie enhttps://attacker.com
.…
En el caso de arriba, descartándose de los parámetros de redirect_uri
originales, Expo introdujo un nuevo parámetro llamado returnUrl sin una validación adecuada. Este descuido proporcionó una oportunidad para que los atacantes ganaran acceso al Código de Autorización retornado por Facebook. Para más detalles, por favor refiérase al post original.
La validación del URI de redirección cumple varios propósitos importantes:
- Prevención de ataques de phishing: Al validar el URI de redirección, el servidor de autorización asegura que el usuario es redirigido de vuelta a un punto final confiable y autorizado. Esto ayuda a prevenir que los atacantes redirigan a los usuarios a ubicaciones maliciosas o no autorizadas.
- Protección contra redirecciones abiertas: Las redirecciones abiertas son vulnerabilidades que pueden ser explotadas para redirigir a los usuarios a sitios web maliciosos. Al validar el URI de redirección, el servidor de autorización puede asegurar que la redirección permanezca dentro de los límites del dominio autorizado o del conjunto de dominios confiables.
- Asegurando la correcta dirección de las respuestas de autorización: Validando el URI de redirección ayuda a garantizar que el servidor de autorización redirige al usuario de vuelta a la aplicación del cliente prevista. Asegura que la respuesta, como un código de autorización o token de acceso, se entregue al destino correcto.
En Logto, el registro redirect_uri
es obligatorio para todos los tipos de aplicaciones. Comparamos y hacemos coincidir el valor recibido con los registrados en el servidor Logto. Eso incluye cualquier parámetro de búsqueda personalizado. Si una solicitud de autorización falla la validación debido a un valor redirect_uri
faltante, inválido o no coincidente, se retornará un error de URI de redirección inválida al redirect_uri
registrado en el archivo.
Resumen
Debido a su complejidad y matices, es comprensible que estos detalles a menudo se pasen por alto. Algunos son solo una cadena aleatoria como state
.
Sin embargo, es importante notar que estas medidas de seguridad añaden capas de protección a la autorización del usuario, mitigando riesgos como ataques CSRF, interceptación de código de autorización y redirecciones no autorizadas.
Estos son solo una pequeña parte de las características de seguridad exhaustivas que ofrece el protocolo OAuth. OAuth proporciona un marco robusto para autenticación segura y autorización. También ofrece puntos finales flexibles y abiertos para satisfacer diversas necesidades en aplicaciones de productos del mundo real.
Como desarrolladores y proveedores de servicio, es imperativo continuamente priorizar la seguridad del flujo de autorización del usuario. Mantenerse vigilante, adherirse a las mejores prácticas y mantenerse actualizado con los últimos desarrollos en el ecosistema OAuth son esenciales para garantizar la integridad y protección de las identidades del usuario y datos sensibles. Nosotros nos mantendremos comprometidos a mantener los más altos estándares de seguridad en la implementación de OAuth y a proteger la privacidad y confianza de nuestros usuarios.