Protección CSRF en Laravel 11: Una Guía Completa
Victor Arana Flores
06 Aug 2024
Introducción a la Protección CSRF en Laravel 11
Los ataques de falsificación de solicitudes entre sitios (CSRF) son un tipo de exploit malicioso en el que se ejecutan comandos no autorizados en nombre de un usuario autenticado. Afortunadamente, Laravel 11 facilita la protección de su aplicación contra estos ataques CSRF.
Explicación de la Vulnerabilidad CSRF
Para entender mejor la vulnerabilidad CSRF, consideremos un ejemplo. Suponga que su aplicación tiene una ruta /user/email
que acepta una solicitud POST para cambiar la dirección de correo electrónico del usuario autenticado. Esta ruta probablemente espera un campo de entrada de correo electrónico para contener la nueva dirección de correo.
Sin protección CSRF, un sitio web malicioso podría crear un formulario HTML que apunte a la ruta /user/email
de su aplicación y envíe la dirección de correo del usuario malicioso:
<form action="https://your-application.com/user/email" method="POST">
<input type="email" value="malicious-email@example.com">
</form>
<script>
document.forms[0].submit();
</script>
Si el sitio web malicioso envía automáticamente el formulario cuando se carga la página, el usuario solo necesita visitar el sitio web del atacante y su dirección de correo electrónico se cambiará en su aplicación.
Para prevenir esta vulnerabilidad, debemos inspeccionar cada solicitud POST, PUT, PATCH o DELETE entrante en busca de un valor de sesión secreto que la aplicación maliciosa no pueda acceder.
Prevención de Solicitudes CSRF en Laravel 11
Laravel 11 genera automáticamente un "token" CSRF para cada sesión de usuario activa gestionada por la aplicación. Este token se utiliza para verificar que el usuario autenticado es quien realmente está haciendo las solicitudes a la aplicación. Dado que este token se almacena en la sesión del usuario y cambia cada vez que se regenera la sesión, una aplicación maliciosa no puede acceder a él.
El token CSRF de la sesión actual se puede acceder a través de la sesión de la solicitud o mediante la función auxiliar csrf_token
:
use Illuminate\Http\Request;
Route::get('/token', function (Request $request) {
$token = $request->session()->token();
$token = csrf_token();
// ...
});
Cada vez que defina un formulario HTML "POST", "PUT", "PATCH" o "DELETE" en su aplicación, debe incluir un campo de token CSRF oculto en el formulario para que el middleware de protección CSRF pueda validar la solicitud. Para mayor comodidad, puede utilizar la directiva Blade @csrf
para generar el campo de entrada de token oculto:
<form method="POST" action="/profile">
@csrf
<!-- Equivalente a... -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>
El middleware Illuminate\Foundation\Http\Middleware\ValidateCsrfToken
, que se incluye en el grupo de middleware web por defecto, verificará automáticamente que el token en la entrada de la solicitud coincida con el token almacenado en la sesión. Cuando estos dos tokens coinciden, sabemos que el usuario autenticado es quien está iniciando la solicitud.
Tokens CSRF y SPAs en Laravel 11
Si está construyendo una SPA (Aplicación de una sola página) que utiliza Laravel 11 como backend de API, debe consultar la documentación de Laravel Sanctum para obtener información sobre cómo autenticar con su API y protegerse contra las vulnerabilidades CSRF.
Excluir URIs de la Protección CSRF en Laravel 11
A veces puede ser necesario excluir un conjunto de URIs de la protección CSRF. Por ejemplo, si está utilizando Stripe para procesar pagos y utiliza su sistema de webhook, necesitará excluir su ruta de manejo de webhook de Stripe de la protección CSRF, ya que Stripe no sabrá qué token CSRF enviar a sus rutas.
Normalmente, debería colocar estos tipos de rutas fuera del grupo de middleware web que Laravel aplica a todas las rutas en el archivo routes/web.php
. Sin embargo, también puede excluir rutas específicas proporcionando sus URIs al método validateCsrfTokens
en su archivo bootstrap/app.php
:
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'stripe/*',
'http://example.com/foo/bar',
'http://example.com/foo/*',
]);
})
Para mayor comodidad, el middleware CSRF se desactiva automáticamente para todas las rutas cuando se ejecutan pruebas.
X-CSRF-TOKEN en Laravel 11
Además de verificar el token CSRF como un parámetro POST, el middleware Illuminate\Foundation\Http\Middleware\ValidateCsrfToken
, que se incluye en el grupo de middleware web por defecto, también verificará el encabezado de solicitud X-CSRF-TOKEN
. Por ejemplo, puede almacenar el token en una etiqueta meta HTML:
<meta name="csrf-token" content="{{ csrf_token() }}">
Luego, puede instruir a una biblioteca como jQuery para que agregue automáticamente el token a todos los encabezados de solicitud. Esto proporciona una protección CSRF simple y conveniente para sus aplicaciones basadas en AJAX utilizando tecnología JavaScript heredada:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
X-XSRF-TOKEN en Laravel 11
Laravel 11 almacena el token CSRF actual en una cookie XSRF-TOKEN
encriptada que se incluye con cada respuesta generada por el framework. Puede usar el valor de la cookie para establecer el encabezado de solicitud X-XSRF-TOKEN
.
Esta cookie se envía principalmente como una conveniencia para el desarrollador, ya que algunos frameworks y bibliotecas de JavaScript, como Angular y Axios, colocan automáticamente su valor en el encabezado X-XSRF-TOKEN
en solicitudes de la misma origen.