El parámetro state en el framework OAuth protege contra ataque CSRF, que ocurren cuando un atacante engaña a un usuario para que ejecute acciones no deseadas en una aplicación web donde están siendo autentificadas. Esto puede conllevar a la divulgación de información sensible. El parámetro state permite mitigar este riesgo manteniendo la integridad del proceso de autorización.
Vulnerabilidad de Parámetro State Débil o Flatante
El parámetro state es una string arbitraria que la aplicación cliente incluye en la petición de autorización. Cuando el servidor de autorización redirige al usuario de vuelta a la aplicación cliente con el código de autorización, también incluye el parámetro state. Entonces la aplicación cliente verifica que el parámetro state en la respuesta coincide con con la mandada originalmente.
Por ejemplo, considera una implementación OAuth donde el parámetro state falta o es predecible. Un atacante puede iniciar un flujo OAuth y ofrecer su URI de redirección maliciosa. Después de que el usuario se autentifique y autorice a la aplicación, el servidor de autorización redirige el código de autorización a la URI controlada por el atacante, como se especifica en el parámetro state débil o faltante.
Práctica
En este ejercicio, exploraremos cómo la ausencia del parámetro state en el proceso de autorización OAuth puede llevar a ataques CSRF. Usaremos la app mycontacts.thm:8080 que permite sincronizar contactos de cualquier plataforma.
Antes de empezar asegúrate de haber cerrado sesión visitando http://coffee.thm:8000/admin/logout
Perspectiva del Atacante
Primero visita http://mycontacts.thm:8080/csrf/index.php con las credenciales attacker:attacker. Una vez que inicies sesión, verás una página que permite sincronizar contactos a CoffeeShopApp. Una vez que las cuentas estén sincronizadas, se transferirá todos los contactos a la cuenta CoffeeShopApp.

Si haces click en "Sync Contacts" serás redirigido a un servidor de autorización OAuth con la URL http://coffee.thm:8000/o/authorize/?response_type=code&client_id=kwoy5pKgHOn0bJPNYuPdUL2du8aboMX1n9h9C0PN&redirect_uri=http%3A%2F%2Fcoffee.thm%2Fcsrf%2Fcallbackcsrf.php.
Como pentester, te das cuenta de que a la petición le falta, sugiriendo la posibilidad de un ataque CSRF. Aquí no necesitas sincronizar tu cuenta. Explotaremos esta vulnerabilidad para ligar la cuenta de la víctima a la del atacante.
Explotando la Vulnerabilidad
Sin el parámetro state, el proceso de autorización es vulnerable a CSRF. El atacante puede explotar esta vulnerabilidad obteniendo el código de autorización de la víctima y mandándolo al atacante. El servidor de autorización no tiene manera de saber si el código de autorización pertenece al atacante o la víctima y tampoco de saber si la petición viene de uno o de otro.
Preparando el Payload
Para preparar el payload, el atacante debe obtener el código de autorización. Esto puede hacerse interceptando el proceso de autorización usando una herramienta como Burp Suite o cualquier otra. El link http://coffee.thm:8000/o/authorize/?response_type=code&client_id=kwoy5pKgHOn0bJPNYuPdUL2du8aboMX1n9h9C0PN&redirect_uri=http://coffee.thm:8000/oauthdemo/callbackforcsrf/ te permite obtener el código de autorización sin completar el flujo OAuth. El código del flujo es bastante directo como se muestra abajo:
def oauth_logincsrf(request): app = Application.objects.get(name="ContactApp") redirect_uri = request.POST.get("redirect_uri", "http://coffee.thm/csrf/callbackcsrf.php") authorization_url = ( f"http://coffee.thm:8000/o/authorize/?client_id={app.client_id}&response_type=code&redirect_uri={redirect_uri}" ) return redirect(authorization_url) def oauth_callbackflagcsrf(request): code = request.GET.get("code") if not code: return JsonResponse({'error': 'missing_code', 'details': 'Missing code parameter.'}, status=400) if code: return JsonResponse({'code': code, 'Payload': 'http://coffee.thm/csrf/callbackcsrf.php?code='+code}, status=400)
Obtendrás la siguiente respuesta una vez que visites dicho link para obtener el código de autorización con las credenciales attacker:tesla@123.

El código de autorización de arriba permitiría a cualquier persona obtener el token. El parámetro URL en la respuesta es el payload que debemos mandar a la víctima. Copia el valor Payload.
Lanzando el Ataque
- Una vez que el atacante ha obtenido el código de autorización, puede preparar el payload CSRF. Supón que el atacante manda un email a la víctima con el link
http://bistro.thm:8080/csrf/callbackcsrf.php?code=xxxx. - Después de recibir el email, si la víctima hace click en el o lo ejecuta en su navegador, (donde
xxxxes el código de autorización del atacante), la cuenta OAuth deCoffeShopAppdel atacante será ligada con la de la víctima, obteniendo así todos sus contactos.
Perspectiva de la Víctima
-
Para comprobarlo como víctima, inicia sesión en http://bistro.thm:8080/csrf/ con las credenciales
victim:victim. Como el código de autorización es único, ejecuta el exploit del atacante con su código de autorización pegándolo directamente en el navegador (http://bistro.thm:8080/csrf/callbackcsrf.php?code=xxxx). -
Como hemos visto arriba, el mismo link mandado a la víctima es el parámetro URL recibido durante el proceso de "Preparando el Payload". Una vez ejecutado, el código hará una llamada para obtener el token de acceso y mandar los contactos a la cuenta del atacante.

