OAuth2 falsificación de solicitudes entre sitios, y parámetro de estado

30

enlace dice:

  

El cliente DEBE implementar la protección CSRF [...] que normalmente se realiza al requerir que cualquier solicitud enviada al punto final de URI de redirección incluya un valor que vincule la solicitud al estado autenticado del agente de usuario (por ejemplo, un hash de la cookie de sesión [ ...]

Sin embargo, no dice mucho sobre la implementación. Solo aclara cómo funciona el CSRF:

  

Un ataque CSRF contra el URI de redirección del cliente permite a un atacante inyectar su propio código de autorización o token de acceso, lo que puede hacer que el cliente use un token de acceso asociado con los recursos protegidos del atacante en lugar del de la víctima (por ejemplo, guardar el banco de la víctima información de la cuenta a un recurso protegido controlado por el atacante)

Pero el uso de la palabra "más bien" hace que la declaración no valga nada.

Estoy pensando en cómo implementar el "estado" en GAE (usando Webapp2). Sería más fácil comenzar por cómo un pirata informático podría usar un CSRF contra OAuth2. Encontré solo un buen artículo sobre el asunto: "Falsa de solicitud de sitios cruzados y OAuth2 ".

Lamentablemente, aunque esta publicación de blog está bien escrita, no hay mucha información más allá de explicar OAuth2. Los ejemplos no funcionan, y no sé Spring. Aún así, encontré una recomendación interesante: el servidor que se conecta a un proveedor OAuth2 debería almacenar "estado" como una clave de sesión aleatoria (por ejemplo, "this_is_the_random_state": "this_doesn't_matter") , y no es un valor bajo una clave estática (por ejemplo, "estado": "random_state_string").

Mi pregunta es, ¿cuál es la implementación sensata del "estado"?

  • ¿Se debe marcar el estado generado aleatoriamente, o se puede almacenar el mismo valor y enviarlo al proveedor de OAuth2?
  • ¿Hay alguna diferencia aquí si el backend de la sesión es cookies seguras o una tecnología de almacenamiento del lado del servidor (por ejemplo, en GAE Memcache o base de datos)?
  • ¿Se debe almacenar el estado como una clave como se sugiere?
  • ¿Debería el estado tener un período de validez o la sesión (si hay una) es suficiente para toda la vida?
pregunta Markus von Broady 14.09.2012 - 12:17
fuente

3 respuestas

13

Voy a simplificar este problema. falsificación de solicitudes entre sitios y Clikjacking son útiles porque pueden forzar al navegador de la víctima a realizar acciones contra su voluntad.

La mención de 10.12. Cross-Site Request Forgery y 10.13. Clickjacking en la OAuth v2 RFC tienen fundamentalmente la misma preocupación. Si un atacante puede forzar la autenticación del navegador de la víctima, es un paso útil para obligar al navegador de la víctima a realizar otras acciones.

   in a clickjacking attack, an attacker registers a legitimate client
   and then constructs a malicious site in which it loads the
   authorization server's authorization endpoint web page in a
   transparent iframe overlaid on top of a set of dummy buttons, which
   are carefully constructed to be placed directly under important
   buttons on the authorization page.  When an end-user clicks a
   misleading visible button, the end-user is actually clicking an
   invisible button on the authorization page (such as an "Authorize"
   button).  This allows an attacker to trick a resource owner into
   granting its client access without their knowledge.

Fuente: 10.13. Clickjacking

Por ejemplo, Stack Overflow usa OAuth y es vulnerable a este ataque. Si visita StackOverflow y actualmente está conectado a su proveedor de OAuth, iniciará sesión automáticamente en StackOverflow. Por lo tanto, un atacante podría iniciar sesión automáticamente en una víctima cargando Stack Oveflow dentro de un iframe. Si Stack Overflow también tenía una vulnerabilidad CSRF ( y los ha tenido ! ), luego un atacante podría autenticar automáticamente el navegador de una víctima y llevar a cabo un ataque CSRF (Session Riding), Clickjacking o XSS contra stackoverflow.com en un Chained Attack .

    
respondido por el rook 01.10.2012 - 02:35
fuente
28

Veamos cómo funciona este ataque.

El ataque

  1. Visito el sitio web de cliente y comienzo el proceso de autorización para que ese cliente acceda a algún proveedor de servicios utilizando OAuth

  2. El cliente solicita permiso al proveedor de servicios para solicitar acceso en mi nombre, que se concede

  3. Me redirigen al sitio web del proveedor de servicios, donde normalmente ingresaría mi nombre de usuario / contraseña para autorizar el acceso

  4. En su lugar, capturo / prevengo esta solicitud y guardo su URL

  5. De alguna manera, hago que visites esa URL en su lugar. Si ha iniciado sesión en el proveedor de servicios con su propia cuenta, entonces sus credenciales se utilizarán para emitir un código de autorización

  6. El código de autorización se intercambia por un token de acceso

  7. Ahora mi cuenta en el cliente está autorizada para acceder a su en el proveedor de servicios

Entonces, ¿cómo podemos evitar esto usando el parámetro state ?

Prevención

  1. El cliente debe crear un valor que de alguna manera se base en la cuenta del usuario original (un hash de la clave de sesión del usuario, por ejemplo). No importa lo que sea, siempre que sea único y se genere utilizando información privada sobre el usuario original.

  2. Este valor se pasa al proveedor de servicios en la redirección del paso tres arriba

  3. Ahora, puedo visitar la URL que guardé (paso cinco arriba)

  4. El código de autorización se emite y se envía de vuelta al cliente en su sesión junto con el parámetro state

  5. El cliente genera un valor state basado en la información de la sesión su y lo compara con el valor state que se envió desde la solicitud de autorización al proveedor de servicios. Este valor no coincide con el parámetro state en la solicitud, porque ese valor de state se generó basándose en la información de la sesión mi , por lo que se rechaza.

Sus preguntas

  • ¿Se debe marcar el estado generado aleatoriamente o se puede almacenar y enviar el mismo valor al proveedor OAuth2?

El punto es que el atacante no debe poder generar un valor de estado que sea específico para un usuario determinado. Debería ser indiscutible.

  • ¿Hay alguna diferencia aquí, si el back-end de la sesión es cookies seguras o un almacenamiento del lado del servidor (en Memcache o base de datos GAE)?

No creo que esto importe (si te entiendo correctamente)

  • ¿Se debe almacenar el estado como una clave como se sugiere?

No sé qué significa esto.

  • ¿Debería el estado tener un período de validez o una sesión (si hay una) es suficiente para toda la vida?

Sí, el estado debe tener una caducidad. No necesariamente tiene que estar vinculado a la sesión, pero podría estarlo.

    
respondido por el Wayne Burkett 13.05.2014 - 20:32
fuente
2

Tomado de La importancia del parámetro de estado en OAuth2 :

Aquí es donde el objeto "estado" en OAuth 2 entra en juego. Al enviar siempre un estado no cuestionable al enviar POSTing al punto final de autorización, la aplicación cliente puede estar segura de que el Código de acceso obtenido del Servidor de autorización responde a las solicitudes realizadas por él en lugar de a otra aplicación cliente.

Ejemplo:

https://example.com/as/authorization?client_id=client1&response_type=code&scope=openid &state=7tvPJiv8StrAqo9IQE9xsJaDso4

Para que el parámetro de estado sea útil en la prevención de ataques CSRF de esta manera, todas las solicitudes realizadas al servidor OAuth deben incluir un parámetro de estado que el cliente pueda usar para autenticarse. Al enviar un parámetro de estado, la especificación de OAuth estipula que el Servidor de Autorización debe devolverlo al cliente de forma literal. Esto se hará pegándolo en la URL de devolución de llamada del cliente. El cliente debe recibir este estado y estar programado para aceptar solo redirecciones con un estado verificable. Si se trata de un diccionario guardado en la memoria o si un valor que se puede volver a calcular depende del programador del cliente.

Al decidir cómo implementar esto, una sugerencia es usar una clave privada junto con algunas variables fácilmente verificables, por ejemplo, ID de cliente y una cookie de sesión, para calcular un valor de hash. Esto resultará en un valor de byte que será difícil de adivinar sin la clave privada. Después de calcular dicho HMAC, la base-64 lo codifica y lo pasa al servidor OAuth como parámetro de estado. Otra sugerencia es marcar la fecha y hora actual. Esto requiere que su aplicación guarde el tiempo de transmisión para verificarla o permitir un período de validez variable (por ejemplo, utilizando TOTP).

El suyo es un ejemplo simple de Python que usa la segunda sugerencia usando datetime:

def generate_state_parameter(client_id, private_key):
    date = datetime.datetime.today()
    raw_state = str(date) + client_id
    hashed = hmac.new(private_key, raw_state, sha1) state = base64.b64encode(hashed.digest())
    return (state, date)
    
respondido por el Aydin K. 06.10.2016 - 12:16
fuente

Lea otras preguntas en las etiquetas