Correct code
To prevent the CSRF token from being stolen by XSS attacks or other types of attacks we have to create the system with the following characteristics:
- Generate a unique CSRF token for each form request.
- Store the token in the session and in a cookie with the flag httpolny
- Validate the token and the URL referenced in the POST request.
- Regenerate the token after each successful request.
CSRF Token Generation
Generate a unique CSRF token and set it as an HttpOnly cookie with a lifetime of 30 minutes.
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();
Verification of the CSRF token and origin of the request on the server
Verify that the CSRF token sent in the cookie matches the token stored in the session and that the request comes from the same domain.
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();
}
}