Creando un Sistema de Protección CSRF en Aplicaciones PHP
En el desarrollo web con PHP, la seguridad es fundamental. Uno de los ataques más comunes es el Cross-Site Request Forgery (CSRF), que permite a un sitio malicioso realizar acciones en nombre del usuario autenticado. En este artículo, aprenderemos a crear un sistema de protección CSRF paso a paso, generando y validando tokens seguros.
¿Qué es un Ataque CSRF?
Un ataque CSRF ocurre cuando un atacante engaña al usuario para que ejecute acciones no deseadas en una aplicación web donde está autenticado, como transferir fondos o cambiar contraseñas. La protección se basa en tokens únicos por sesión que deben coincidir entre el formulario y el servidor.
Generando Tokens CSRF Seguros
Usaremos la función random_bytes() de PHP (disponible desde PHP 7) para generar tokens criptográficamente seguros. Almacenaremos el token en la sesión del usuario.
<?php
session_start();
function generarTokenCSRF() {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
?>
Incluyendo el Token en Formularios HTML
Inserta el token como un campo oculto en tus formularios:
<form method="POST" action="procesar.php">
<input type="hidden" name="csrf_token" value="<?php echo generarTokenCSRF(); ?>">
<input type="text" name="nombre" placeholder="Nombre">
<button type="submit">Enviar</button>
</form>
Validando el Token en el Servidor
Antes de procesar cualquier acción POST, verifica que el token enviado coincida con el de la sesión:
<?php
session_start();
function validarTokenCSRF($token) {
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!validarTokenCSRF($_POST['csrf_token'] ?? '')) {
die('Token CSRF inválido. Posible ataque detectado.');
}
// Procesar formulario aquí
echo 'Formulario procesado exitosamente.';
}
?>
Mejores Prácticas
- Regenera tokens periódicamente: Llama a
generarTokenCSRF()en cada carga de página o usa un TTL (Time To Live). - Usa HTTPS: Siempre en producción para evitar MITM.
- Tokens por acción: Genera tokens específicos para formularios sensibles (ej. login, pagos).
- SameSite Cookies: Configura
session_set_cookie_params(['samesite' => 'Strict']);para mayor protección. - Integración con Frameworks: En Laravel usa
@csrf; en Symfony, el componente Form.
Ejemplo Completo
Combina todo en un archivo index.php para probar:
<?php
session_start();
function generarTokenCSRF() { /* como arriba */ }
function validarTokenCSRF($token) { /* como arriba */ }
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (validarTokenCSRF($_POST['csrf_token'])) {
echo '<p style="color:green">¡Éxito! Acción segura.</p>';
unset($_SESSION['csrf_token']); // Opcional: regenerar
} else {
echo '<p style="color:red">Error de seguridad.</p>';
}
}
?>
<!DOCTYPE html>
<html>
<body>
<h3>Formulario Protegido</h3>
<form method="POST">
<input type="hidden" name="csrf_token" value="<?php echo generarTokenCSRF(); ?>">
<button type="submit">Probar Protección</button>
</form>
</body>
</html>
Implementa esta protección en tus apps PHP para blindarlas contra CSRF. ¡La seguridad proactiva salva vidas digitales!
¿Quieres comentar?
Inicia sesión con Telegram para participar en la conversación