Situation actuelle : PHP2Shell. Deux failles PHP critiques (CVSS 9.2) permettent d'exécuter du code malveillant sans authentification. Correctifs disponibles depuis le 21 octobre 2026.Ce qu'il faut faire maintenant →

Sécuriser les sessions en PHP : la sécurité des sessions PHP en pratique

Les sessions maintiennent les utilisateurs connectés et constituent donc une cible intéressante. Comment configurer cookies, ID de session et lieux de stockage en sécurité, et appliquer l'avis PHP2Shell sur le suivi des uploads.

État 7 min de lectureGuides

En bref : pour la sécurité des sessions PHP, quatre choses comptent : des réglages de cookie sûrs, un nouvel ID de session après chaque connexion, des lieux de stockage séparés et protégés, ainsi que des durées courtes. À cause de PHP2Shell, session.upload_progress.enabled=0 devrait en outre être défini côté serveur, tant qu'il n'y a aucune raison d'utiliser cette fonction.

Pourquoi les sessions sont une cible intéressante

Une session mémorise qu'un utilisateur est connecté. Techniquement, le navigateur reçoit pour cela un ID de session aléatoire dans un cookie, et le serveur conserve les données associées. Qui connaît cet ID est pour l'application le même utilisateur, sans mot de passe et sans second facteur.

Pour les exploitants, cela signifie : une gestion de session faible peut neutraliser la protection de la connexion, même si les mots de passe et l'authentification à deux facteurs sont correctement mis en œuvre. C'est particulièrement critique pour les zones d'administration, les comptes clients et les portails contenant des données personnelles.

Les risques typiques sont l'interception de l'ID de session (détournement de session), l'imposition d'un ID connu avant la connexion (fixation de session) et des sessions valables trop longtemps sur des ordinateurs partagés.

Réglages de base sûrs dans php.ini

Les valeurs les plus importantes peuvent être définies de façon centralisée dans php.ini ou, par site, dans le pool FPM. Dans le pool, utilisez php_admin_value ou php_admin_flag afin que l'application ne puisse pas écraser les valeurs.

; Renforcement de base des sessions
session.use_strict_mode   = 1
session.use_only_cookies  = 1
session.use_trans_sid     = 0
session.cookie_httponly   = 1
session.cookie_secure     = 1
session.cookie_samesite   = "Lax"
session.cookie_lifetime   = 0
session.gc_maxlifetime    = 1800
session.name              = "APPSESSID"

; Avis PHP2Shell de php.net, puis redémarrer tous les workers
session.upload_progress.enabled = 0

use_strict_mode fait en sorte que PHP n'accepte pas d'ID inconnus imposés par le navigateur. cookie_httponly empêche JavaScript de lire l'ID, ce qui limite les conséquences du cross-site scripting. cookie_secure n'envoie le cookie que via HTTPS. SameSite=Lax complique les requêtes inter-sites avec session valide ; pour les zones purement administratives, Strict peut convenir.

La durée de 1 800 secondes est une valeur d'exemple. Fixez-la selon le besoin de protection : plus courte pour l'administration et les données clients, plus longue seulement là où c'est nécessaire sur le plan fonctionnel.

Notez que gc_maxlifetime ne définit que le moment à partir duquel d'anciennes données de session peuvent être supprimées. Sur certaines distributions, ce n'est pas PHP lui-même mais une tâche système régulière qui nettoie les fichiers de session. Vérifiez alors quelle valeur cette tâche utilise afin que votre réglage soit réellement effectif. Pour la déconnexion après inactivité, ne vous fiez en outre pas uniquement à la fonction de nettoyage, mais vérifiez l'heure de la dernière action dans l'application elle-même, comme le montre l'exemple suivant.

Renouveler l'ID de session après la connexion

La règle la plus importante dans le code est de régénérer l'ID de session à chaque changement d'autorisation, donc à la connexion, lors du passage en mode administrateur et à la déconnexion. L'exemple suivant montre un modèle de base propre avec password_verify() :

<?php
declare(strict_types=1);

session_start();

function anmelden(PDO $db, string $email, string $passwort): bool
{
    $stmt = $db->prepare('SELECT id, passwort_hash FROM benutzer WHERE email = :email');
    $stmt->execute(['email' => $email]);
    $nutzer = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$nutzer || !password_verify($passwort, $nutzer['passwort_hash'])) {
        return false; // même message pour une adresse erronée et un mot de passe erroné
    }

    session_regenerate_id(true);           // nouvel ID, supprimer l'ancien
    $_SESSION['benutzer_id']   = (int) $nutzer['id'];
    $_SESSION['letzte_aktion'] = time();
    return true;
}

function pruefeLeerlauf(int $sekunden = 900): void
{
    if (isset($_SESSION['letzte_aktion']) && time() - $_SESSION['letzte_aktion'] > $sekunden) {
        abmelden();
        return;
    }
    $_SESSION['letzte_aktion'] = time();
}

function abmelden(): void
{
    $_SESSION = [];
    $p = session_get_cookie_params();
    setcookie(session_name(), '', [
        'expires'  => time() - 3600,
        'path'     => $p['path'],
        'domain'   => $p['domain'],
        'secure'   => $p['secure'],
        'httponly' => $p['httponly'],
        'samesite' => $p['samesite'],
    ]);
    session_destroy();
}

En complément, protégez les formulaires qui modifient quelque chose avec un jeton CSRF. Il est généré avec bin2hex(random_bytes(32)), conservé dans la session et comparé à l'envoi avec hash_equals().

Lieux de stockage et séparation des clients

Par défaut, PHP enregistre les sessions sous forme de fichiers dans un répertoire commun. Sur un serveur hébergeant plusieurs sites, cela peut signifier qu'un site compromis peut lire les sessions d'un autre. C'est pourquoi chaque site doit avoir son propre pool avec son propre utilisateur et son propre chemin de sessions.

; dans le pool FPM du site concerné
php_admin_value[session.save_path] = /var/lib/php/sessions/kunde-a

Le répertoire devrait appartenir à l'utilisateur du pool et avoir les droits 0700. Le guide open_basedir et isolation par site web décrit comment isoler en outre les sites les uns des autres. Si les sessions sont stockées dans Redis ou une base de données, les mêmes principes s'appliquent : un accès dédié par application, aucun accès réseau ouvert.

Sécurité des sessions PHP et PHP2Shell

Les failles PHP2Shell CVE-2026-109618 et CVE-2026-109619 se trouvent dans PHP lui-même. Parmi les mesures transitoires, php.net indique de définir session.upload_progress.enabled=0 dans php.ini, dans le pool FPM ou dans la configuration du serveur, puis de redémarrer tous les workers. Expressément pas via ini_set() ni un .user.ini.

Le 23 octobre 2026 a suivi un avis sur CVE-2026-115560. Une exécution de code possible n'y existe qu'avec une combinaison inhabituelle de sérialisation de session, de changement par ini_set() avant session_start() et de suivi de progression des uploads actif. Le contournement est le même réglage, jusqu'à la prochaine version corrective régulière.

Important

Ce réglage est une mesure transitoire et non une protection complète. Ce qui reste décisif, c'est la mise à jour vers une version de PHP corrigée, suivie du redémarrage de tous les workers PHP.

Vérifiez après la modification quelle valeur s'applique réellement. La ligne de commande affiche souvent une autre configuration que le serveur web ; une page de contrôle protégée, supprimée ensuite, ou la configuration du pool elle-même est plus parlante.

Erreurs typiques avec les sessions dans les applications PHP

De nombreuses vulnérabilités ne naissent pas de réglages manquants, mais de la manière dont les applications utilisent les sessions. Interrogez de façon ciblée ces schémas dans votre propre code et chez vos prestataires :

  • Trop de choses dans la session : mots de passe, données de paiement complètes ou grands jeux de données n'ont pas leur place dans la session. Ne stockez que ce qui est nécessaire à l'identification, par exemple l'ID utilisateur et les rôles.
  • Droits tirés uniquement de la session : qui est administrateur devrait être vérifié dans la base de données pour les actions critiques. Sinon, des droits retirés restent actifs jusqu'à l'expiration de la session.
  • ID de session dans l'adresse : les ID dans les URL se retrouvent dans les journaux, les historiques de navigateur et les indications de référent. use_only_cookies et use_trans_sid = 0 l'empêchent.
  • Pas de fin de session : sans délai d'inactivité, un administrateur reste connecté indéfiniment sur un ordinateur partagé.
  • HTTPS mal détecté derrière un proxy : si le chiffrement se termine au répartiteur de charge, l'application doit le savoir. Sinon, elle définit peut-être des cookies sans l'indicateur Secure.

Après un incident de sécurité, il faut en outre invalider toutes les sessions existantes. Le plus simple est de supprimer le contenu du répertoire de sessions ou de changer le nom de session. Tous les utilisateurs doivent alors se reconnecter, et les sessions volées deviennent sans valeur.

Comment PHP SOS aide-t-il concrètement ?

  • Nous examinons les réglages de session, les indicateurs de cookie et les lieux de stockage sur tous les sites d'un serveur et documentons les valeurs réellement effectives.
  • Nous mettons en place les mesures transitoires PHP2Shell par pool, redémarrons les workers de façon contrôlée et apportons la preuve du résultat.
  • Nous séparons les sites avec des pools et des chemins de sessions dédiés dans le cadre du renforcement de serveur.
  • Pour les développements maison, nous examinons dans le code la connexion, la déconnexion et le changement de session et recommandons des modifications concrètes.

Questions fréquentes

Qu'est-ce que le détournement de session ?

Dans le détournement de session, un attaquant reprend la session d'un utilisateur connecté en obtenant son ID de session. Avec l'ID, il est pour l'application cet utilisateur, sans connaître le mot de passe. Des indicateurs de cookie sûrs et des durées courtes le compliquent nettement.

Pourquoi faut-il régénérer l'ID de session après la connexion ?

Si l'ID reste le même avant et après la connexion, un ID connu à l'avance ou imposé pourrait rester valable après l'authentification. session_regenerate_id(true) crée un nouvel ID et supprime l'ancien.

Puis-je désactiver session.upload_progress.enabled par ini_set() ?

Non, selon php.net, cela ne suffit pas. Le réglage doit figurer dans php.ini, le pool FPM ou la configuration du serveur, pas dans ini_set() ni dans un .user.ini. Tous les workers PHP doivent ensuite être redémarrés.

Où faut-il stocker les fichiers de session ?

Dans un répertoire en dehors de la racine web que seul l'utilisateur du pool PHP concerné peut lire. Sur les serveurs hébergeant plusieurs sites, chaque site devrait avoir son propre répertoire de sessions.

Sources

Contact immédiat

Chaque heure compte. Écrivez-nous maintenant.

Décrivez brièvement votre système, votre version de PHP et ce que vous avez observé. Nous vous répondons, faisons le point et travaillons à distance jusqu'à la clôture et la documentation de l'incident.

Aide immédiate