49 lines
2.0 KiB
PHP
49 lines
2.0 KiB
PHP
<?php
|
|
// Sécurité transverse : cookie de session durci, en-têtes anti-clickjacking et
|
|
// protection CSRF. A inclure à la place d'un simple session_start() sur toute
|
|
// page ou script qui utilise une session (remplace l'appel direct partout).
|
|
|
|
// Règle les paramètres du cookie de session AVANT de démarrer la session (ils
|
|
// n'ont aucun effet une fois la session déjà démarrée) :
|
|
// - httponly : empêche le JavaScript de lire le cookie (limite le vol de session via une XSS)
|
|
// - samesite=Lax : bloque une partie des requêtes intersites (CSRF)
|
|
// - secure : n'est activé que si la connexion est déjà en HTTPS (sinon le cookie ne partirait jamais en HTTP)
|
|
function configureSecureSessionCookies() {
|
|
session_set_cookie_params([
|
|
'lifetime' => 0,
|
|
'path' => '/',
|
|
'httponly' => true,
|
|
'samesite' => 'Lax',
|
|
'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
|
|
]);
|
|
}
|
|
|
|
// Anti-clickjacking : interdit d'afficher le site dans une <iframe> d'un autre site
|
|
header('X-Frame-Options: SAMEORIGIN');
|
|
header('X-Content-Type-Options: nosniff');
|
|
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
configureSecureSessionCookies();
|
|
session_start();
|
|
}
|
|
|
|
// Génère (si besoin) et retourne le jeton CSRF de la session en cours, à
|
|
// placer dans un champ caché de chaque formulaire admin ou dans les liens
|
|
// GET qui déclenchent une action (suppression, export...)
|
|
function csrfToken() {
|
|
if (empty($_SESSION['csrf_token'])) {
|
|
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
|
}
|
|
return $_SESSION['csrf_token'];
|
|
}
|
|
|
|
// Vérifie le jeton CSRF reçu (POST ou GET) ; arrête le script si invalide.
|
|
// A appeler juste après la vérification du rôle admin dans chaque script d'action.
|
|
function requireCsrfToken() {
|
|
$recu = $_POST['csrf_token'] ?? $_GET['csrf_token'] ?? '';
|
|
if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $recu)) {
|
|
http_response_code(403);
|
|
die("Requête refusée : jeton de sécurité invalide ou expiré. Recharge la page et réessaie.");
|
|
}
|
|
}
|