Skip to main content

Correct code

Para protegerse frente a ataques CSRF, es recomendable implementar un sistema con las siguientes características:

  • Generar un token CSRF único para cada solicitud de formulario.
  • Almacenar el token en la sesión y en una cookie con el flag HttpOnly.
  • Validar el token y la URL de origen en cada solicitud POST.
  • Regenerate the token after each successful request.

Generación del token CSRF

Se genera un token CSRF único y se configura como una cookie HttpOnly con una vida útil de 30 minutos.

session_start();

function generateCSRFToken() {
if (empty($_SESSION['csrf_token'])) {
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
setcookie('X-XSRF-TOKEN', $token, time() + 1800, '/', '', true, true); // 30 minutos de vida, HttpOnly
}
}

generateCSRFToken();

Verificación del token CSRF y del origen de la solicitud en el servidor

Se verifica que el token CSRF enviado en la cookie coincida con el token almacenado en la sesión y que la solicitud provenga del mismo dominio.

session_start();

function verifyCSRFToken() {
if (!isset($_SESSION['csrf_token']) || !isset($_COOKIE['X-XSRF-TOKEN']) || $_COOKIE['X-XSRF-TOKEN'] !== $_SESSION['csrf_token']) {
throw new Exception("Token CSRF no válido");
}
}

function validateRequestOrigin() {
if (!isset($_SERVER['HTTP_ORIGIN']) && !isset($_SERVER['HTTP_REFERER'])) {
throw new Exception("Origen de la solicitud no válido");
}

$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : $_SERVER['HTTP_REFERER'];
$parsed_url = parse_url($origin);
if ($parsed_url['host'] !== 'tu-dominio.com') {
throw new Exception("Origen de la solicitud no válido");
}
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
validateRequestOrigin();
verifyCSRFToken();
// Regenerar el token para la siguiente solicitud
generateCSRFToken();
// Procesar el formulario
echo "Formulario procesado correctamente.";
} catch (Exception $e) {
// Manejar el error
echo $e->getMessage();
}
}