Saltar al contenido principal

Código correcto

Para evitar que se pueda robar el token de CSRF mediante ataques XSS u otro tipo de ataques tenemos que crear el sistema con las siguientes caracteristicas:

  • Generar un token CSRF único por cada solicitud de formulario.
  • Almacenar el token en la sesión y en un una cookie con el flag httpolny
  • Validar el token y la URL referida en la solicitud POST.
  • Regenerar el token después de cada solicitud exitosa.

Generación Token CSRF

Genera un token CSRF único y configúralo 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 origen de la solicitud en el servidor

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();
}
}