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 →

open_basedir et isolation par site web

Comment empêcher, avec open_basedir, des utilisateurs système dédiés et des pools PHP-FPM séparés, qu'une intrusion dans un site n'atteigne tous les autres sur le serveur.

État 6 min de lectureGuides

En bref : open_basedir limite les répertoires auxquels PHP peut accéder. Seul, ce n'est qu'une barrière supplémentaire. Une isolation efficace par site n'apparaît que par l'ensemble : utilisateur système dédié, pool PHP-FPM dédié, dossier temporaire dédié et accès dédiés à la base de données. Une intrusion dans un site reste alors limitée à ce site.

Pourquoi, après PHP2Shell, l'isolation décide de l'ampleur des dégâts

Sur de nombreux serveurs, plusieurs sites tournent côte à côte : le site de l'entreprise, une boutique, une ancienne page de campagne et, chez les agences, souvent des dizaines de projets clients. Ils partagent fréquemment un utilisateur système et un processus PHP. Si l'un d'eux est compromis, tous les autres sont exposés.

PHP2Shell rend ce risque tangible. Les failles CVE-2026-109618 et CVE-2026-109619 permettent l'exécution de code malveillant sans authentification, indépendamment du CMS. Selon des articles de presse, une première tentative d'attaque a eu lieu dès le 17 octobre 2026, les correctifs ont suivi le 21 octobre. La solution est la mise à jour. Mais qu'une attaque menée auparavant touche un ou dix sites, c'est l'isolation qui en décide.

Pour la seconde faille notamment, une autre idée s'ajoute : selon le projet PHP, un état interne d'une requête peut subsister dans un worker et être utilisé par une requête ultérieure dans le même worker. Des pools séparés par site font en sorte que les sites ne partagent de toute façon aucun worker.

Ce qu'apporte open_basedir

Avec open_basedir, vous définissez une liste de répertoires. Les fonctions de fichiers de PHP comme fopen, include ou file_get_contents refusent alors l'accès à tout ce qui se trouve en dehors de cette liste. Un script introduit ne peut ainsi pas lire sans difficulté les fichiers de configuration du site voisin.

Les limites sont importantes : le contrôle a lieu à l'intérieur de PHP. Les programmes lancés en dehors de PHP n'y sont pas soumis, et des erreurs de l'interpréteur peuvent le contourner. C'est pourquoi open_basedir doit toujours aller de pair avec des fonctions système bloquées, comme décrit dans le guide Bien utiliser disable_functions, et surtout avec une séparation au niveau du système d'exploitation.

L'isolation par site en quatre couches

Une séparation solide repose sur plusieurs couches. Chacune intercepte ce que la précédente ne fait pas.

Couche Mesure Effet
Système d'exploitation utilisateur système dédié par site Les fichiers des autres sites sont illisibles
Processus PHP pool PHP-FPM dédié avec socket dédié aucun worker partagé, réglages propres
Configuration PHP open_basedir, dossier tmp et de sessions dédiés barrière supplémentaire, pas de fichiers temporaires partagés
Données utilisateur de base de données dédié avec droits uniquement sur sa propre base aucun accès aux données clients d'autres sites

Pour un besoin de protection élevé, par exemple des boutiques avec paiement ou des portails contenant des données de santé, s'ajoutent des conteneurs ou des serveurs distincts.

Configurer open_basedir dans le pool PHP-FPM

L'exemple suivant montre un pool pour un site avec son propre utilisateur seite1. Adaptez les chemins et le numéro de version à votre système.

; /etc/php/8.3/fpm/pool.d/seite1.conf
[seite1]
user = seite1
group = seite1
listen = /run/php/seite1.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = ondemand
pm.max_children = 10

php_admin_value[open_basedir] = /var/www/seite1/:/var/www/seite1-tmp/
php_admin_value[upload_tmp_dir] = /var/www/seite1-tmp/
php_admin_value[sys_temp_dir] = /var/www/seite1-tmp/
php_admin_value[session.save_path] = /var/www/seite1-tmp/sessions
php_admin_value[error_log] = /var/log/php/seite1.error.log
php_admin_flag[session.upload_progress.enabled] = off

La dernière ligne applique aussitôt la mesure transitoire PHP2Shell de php.net. Elle ne fonctionne que depuis le pool, php.ini ou la configuration du serveur, pas via ini_set() ni .user.ini. Vous créez les dossiers avec les droits appropriés :

sudo useradd --system --home /var/www/seite1 --shell /usr/sbin/nologin seite1
sudo mkdir -p /var/www/seite1-tmp/sessions
sudo chown -R seite1:seite1 /var/www/seite1-tmp
sudo chmod 700 /var/www/seite1-tmp

Le guide Droits des fichiers sur le serveur web décrit à quoi devraient ressembler les droits dans le répertoire web proprement dit.

Raccorder le serveur web et vérifier le résultat

Dans Nginx, chaque site renvoie vers son propre socket. Ainsi, aucune requête n'atterrit dans le pool d'un autre site.

server {
    server_name seite1.example;
    root /var/www/seite1/public;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/seite1.sock;
    }
}

Vous trouverez d'autres indications sur cette combinaison sous Sécuriser Nginx avec PHP-FPM. Après le redémarrage, vérifiez que les pools tournent réellement de façon séparée :

sudo systemctl restart php8.3-fpm
# Chaque pool devrait tourner sous son propre utilisateur
ps -eo user,pid,cmd | grep "[p]hp-fpm: pool"

Testez ensuite toutes les fonctions du site : uploads, traitement d'images, caches, tâches planifiées. Des messages d'erreur mentionnant open_basedir restriction dans le journal d'erreurs montrent quel chemin manque encore. N'ajoutez que les chemins dont l'application a réellement besoin, et jamais l'ensemble du système de fichiers.

Astuce

Les agences avec de nombreux sites clients devraient entretenir la configuration des pools comme modèle. Ainsi, chaque nouveau site obtient automatiquement la séparation, au lieu de devoir la rajouter plus tard. Des informations de fond sur ce cas figurent sous Partenaire de sécurité pour les agences.

Écueils typiques lors du changement

Le passage à des pools séparés est planifiable, mais comporte quelques pièges récurrents. Le plus fréquent concerne les bibliothèques partagées : si, par exemple, un framework ou un dossier de polices se trouve en dehors du répertoire du site, ce chemin doit être ajouté en lecture à open_basedir. Mieux vaut intégrer de telles dépendances dans le projet lui-même.

Le deuxième piège, ce sont les sessions. Si l'emplacement de stockage change, tous les visiteurs sont déconnectés une fois et les paniers en cours sont perdus. Planifiez donc le changement dans une plage calme et annoncez-le en interne.

Troisièmement, les tâches planifiées passent souvent par la ligne de commande et donc sous un autre utilisateur que le site. Vérifiez les tâches cron et les files d'attente et faites-les tourner sous le nouvel utilisateur du site, sinon des fichiers au mauvais propriétaire apparaissent, que PHP ne pourra plus modifier ensuite.

Enfin, chaque pool devrait avoir ses propres limites de processus et de mémoire. Un site qui subit une charge ou une attaque ne peut ainsi pas mettre les autres à genoux.

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

  • Nous recensons quels sites partagent aujourd'hui utilisateurs, processus et bases de données.
  • Nous mettons en place pour chaque site des utilisateurs, pools, dossiers temporaires et accès à la base de données dédiés, sans modifier les applications.
  • Nous testons chaque site après le changement et corrigeons de façon ciblée les chemins manquants.
  • Nous documentons la séparation comme modèle pour les projets futurs.

La prestation Renforcement de serveur pour serveurs web PHP décrit comment cela s'inscrit dans un concept global.

Questions fréquentes

open_basedir suffit-il à séparer les sites les uns des autres ?

Non. open_basedir est une barrière supplémentaire à l'intérieur de PHP, pas une séparation étanche. L'isolation ne devient fiable qu'avec des utilisateurs système et des pools dédiés par site, et, pour un besoin de protection plus élevé, avec des conteneurs ou des serveurs distincts.

Pourquoi les uploads ne fonctionnent-ils plus après avoir défini open_basedir ?

Le plus souvent, le dossier des fichiers temporaires manque dans la liste. Créez pour chaque site un dossier tmp dédié, ajoutez-le à open_basedir et définissez upload_tmp_dir et sys_temp_dir sur ce dossier.

Une application peut-elle lever open_basedir elle-même ?

À l'exécution, une application ne peut que restreindre davantage le réglage, pas l'assouplir. Définissez néanmoins open_basedir via php_admin_value dans le pool afin que la valeur soit clairement fixée.

L'isolation est-elle aussi possible sur un hébergement mutualisé ?

Cela dépend de l'hébergeur. De nombreuses offres séparent les clients par des utilisateurs et des processus PHP dédiés. Demandez comment la séparation est mise en œuvre, surtout si plusieurs de vos sites se trouvent dans une même offre.

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