Analyse · Exposition
PHP2Shell, ce que le correctif ne règle pas
Images figées, panneaux d'hébergement, appareils, Windows sans binaire corrigé. Là où PHP2Shell reste ouvert après la mise à jour, et comment l'inventorier.
Par Sentrix · Publié le 2026-10-22
Le 21 octobre 2026, le projet PHP a publié les versions 8.5.12, 8.4.27, 8.3.36 et 8.2.35 pour corriger CVE-2026-109618 et CVE-2026-109619, connues sous le nom de PHP2Shell. Les 2 permettent l'exécution de code à distance sans authentification, et PHP considère à risque toute installation qui sert des requêtes web. Presque tout ce qui s'est publié depuis se résume à une consigne, mettre PHP à jour. Elle est juste et elle est incomplète. Une bonne partie du PHP en production n'appartient pas à l'organisation qui l'exploite, n'a aucune version corrigée à installer ou affiche un numéro qui ne dit rien de son état réel. Cet article porte sur ces angles morts.
Ce qui est établi au 22 octobre
Les versions. Le projet PHP ne publie plus de mises à jour pour 8.1 et les versions antérieures. Vu la gravité, il a fourni des rétroportages minimaux en code source pour 7.4, 8.0 et 8.1, à compiler soi-même. Il précise que les distributions Linux et les fournisseurs de soutien prolongé ont reçu les correctifs à l'avance.
Qui est à risque. Selon PHP, toutes les installations qui servent des requêtes web, que ce soit PHP-FPM, Apache avec mod_php, php-cgi, FrankenPHP ou LiteSpeed. Le risque est jugé le plus élevé pour mod_php.
L'exploitation. Les sources ne disent pas la même chose, et l'heure compte. Le 21 octobre, la CISA et le Centre canadien pour la cybersécurité n'avaient observé aucune exploitation au moment de publier. Le même soir, Amazon a rapporté une première tentative le 17 octobre dans ses pots de miel, 4 jours avant la divulgation, et une exploitation désormais large, tout en précisant ignorer si ces tentatives auraient réussi. Le 22 octobre, aucune des 2 CVE n'était encore au catalogue KEV de la CISA. Le même jour, Sansec a revu son évaluation à la baisse. Une attaque demande une connaissance précise du serveur visé, et les démonstrations publiques ne fonctionnent pas contre une installation PHP par défaut. Sansec maintient tout de même la consigne de mettre PHP à jour.
Ce qui sort par la mémoire. Wiz a démontré qu'un attaquant peut lire la mémoire du processus PHP sans même exécuter de code, et y trouver des mots de passe, des jetons et des clés d'API. Sansec ajoute les clés privées TLS, venant d'autres requêtes que celle de l'attaquant.
Le correctif ne dit pas ce qui est déjà sorti
Mettre PHP à jour ferme la porte. Ça ne dit rien de ce qui a pu sortir avant. Wiz note que ces failles agissent sous la couche applicative et que les journaux de l'application peuvent contenir peu de contexte. Un serveur sans trace suspecte n'est donc pas un serveur propre.
Pour chaque serveur exposé à Internet et resté sans correctif après le 17 octobre, il faut une décision explicite sur les secrets que ses processus PHP manipulent, soit les mots de passe de bases de données, les clés d'API, les jetons et les sessions ouvertes. Les changer coûte quelques heures. Ne pas les changer est un risque accepté, qui se documente avec sa justification et sa date.
Là où il n'y a rien à installer
C'est le cœur du problème. Pour une partie du parc, la consigne de mise à jour ne mène nulle part.
| Situation | Ce que dit la source | Conséquence |
|---|---|---|
| WordPress sur un vieux PHP | WordPress.org compte 35,8 % des sites WordPress sur PHP 8.1 ou plus ancien, dont 5,7 % sur 7.3 ou plus ancien | WordPress n'a rien à corriger. Tout dépend du PHP en dessous et de qui le gère |
| PHP 7.4, 8.0 et 8.1 sous Windows | Les dernières publications Windows datent de novembre 2022, août 2023 et décembre 2025 | Aucun binaire corrigé n'existe. Migrer ou retirer |
| XAMPP | Les installateurs Windows et Linux proposent encore PHP 8.0.30, 8.1.25 et 8.2.12 | Une pile de développement souvent restée en production, sans version corrigée |
| Images Docker officielles | Une étiquette qui n'est plus prise en charge ne sera « jamais reconstruite ». Sansec confirme qu'aucune image officielle 8.1 ou plus ancienne ne sera corrigée | Une image figée sur php:7.4, php:8.0 ou php:8.1 reste vulnérable, même redéployée |
| Catalogue Bitnami | Depuis le 28 août 2025, les images par version sont dans bitnamilegacy, qui ne reçoit plus de mises à jour. Les images gratuites restantes, prévues pour le développement, n'existent que sous l'étiquette « latest » | Une image Bitnami épinglée sur une version précise, une bonne pratique en soi, est gelée, sauf abonnement payant à Bitnami Secure Images |
| cPanel | Mises à jour pour ea-php74 et plus récent, et versions corrigées de cPanel & WHM pour le PHP du panneau lui-même. Pour les versions antérieures à 7.4, cPanel renvoie vers TuxCare, un service payant | Le PHP des sites et celui du panneau se corrigent séparément. Un compte encore sur PHP 5.6 à 7.3 dépend d'un abonnement que l'hébergeur a pris ou non |
| CloudLinux | Le correctif est rétroporté dans les branches alt-php et ea-php, y compris en fin de vie. alt-php44 et alt-php51 n'ont aucune version corrigée | Les vieux PHP sont corrigés pour les clients de CloudLinux, pas pour les autres |
| Plesk | Sous Linux, 7.4, 8.0 et 8.1 sont corrigés. Sous Windows, seulement 8.2 à 8.5. Pour 5.6, 7.2 et 7.3, Plesk recommande TuxCare, payant | Le même panneau ne protège pas de la même façon selon le système |
| NAS QNAP | Tous les correctifs sont « à venir ». QNAP précise que le PHP intégré ne peut pas être mis à jour à la main, seulement par le micrologiciel | Le client attend le fabricant, sans autre levier que l'exposition |
| Pare-feu Palo Alto | L'interface web de gestion de PAN-OS 10.2 à 12.2 et Panorama est touchée, sans date de correctif le 21 octobre | Le PHP de l'interface de gestion de votre pare-feu est un PHP de plus à suivre |
| Instances AWS Lightsail | « AWS cannot update running Lightsail instances in place » | Une instance déjà déployée se corrige par son exploitant, ou se reconstruit |
Le numéro de version ment
Les vérificateurs qui lisent le numéro affiché par le serveur se trompent dans les 2 sens.
Corrigé, mais l'air vulnérable. Nous avons vérifié le paquet php8.3-common d'Ubuntu 24.04. Sa version 8.3.6-0ubuntu0.24.04.13 contient le correctif de CVE-2026-109618, mais il affiche toujours PHP 8.3.6, très loin du 8.3.36 du projet PHP. CloudLinux l'écrit en toutes lettres, le correctif est rétroporté dans chaque branche alt-php et ea-php, « which is why the version numbers do not change ». cPanel corrige de la même façon ea-php74, ea-php80 et ea-php81 sans changer leur numéro de version.
Vulnérable, mais l'air corrigé. Un serveur peut avoir le bon paquet sur disque et faire tourner l'ancien code en mémoire. Un processus PHP-FPM ou Apache démarré avant la mise à jour garde l'ancienne version jusqu'à son redémarrage. Sansec le rappelle dans sa procédure, installer le paquet puis redémarrer PHP-FPM ou Apache.
La seule preuve fiable est le journal des modifications du paquet ou l'avis du fournisseur, suivi du redémarrage. Sous Debian et Ubuntu, zgrep CVE-2026-109618 /usr/share/doc/php8.3-common/changelog.Debian.gz. Sous Red Hat et ses dérivés, rpm -q --changelog php-common | grep CVE-2026-109618.
Ce que vous ne contrôlez pas
L'hébergeur. Sur un hébergement mutualisé, le client ne choisit ni la version ni le moment de la mise à jour, et il ne voit pas les processus. C'est le panneau d'hébergement qui décide quelles vieilles versions restent offertes et à quelles conditions. Voici 5 questions à poser par écrit.
- Quel paquet PHP sert mon site, en version exacte, et quel avis confirme la correction des 2 CVE pour ce paquet ?
- Quand les processus PHP qui servent mon site ont-ils été redémarrés après la mise à jour ?
- Si mon site tourne sur une version antérieure à 7.4, quel correctif s'applique, et de qui ?
- Mon site a-t-il ses propres processus PHP, sous son propre compte, ou les partage-t-il avec d'autres clients ?
- Avez-vous relevé des tentatives contre mon site depuis le 17 octobre, et pouvez-vous me remettre les journaux ?
Les fournisseurs. La CISA l'écrit simplement. PHP est souvent un composant d'autres logiciels, et sa présence n'est pas toujours visible. Le Centre canadien demande de repérer les produits, appareils et conteneurs tiers qui intègrent un PHP vulnérable. C'est le même scénario que Log4j en 2021. La liste publique de la CISA a reçu des entrées pendant 4 mois et a dépassé 4 000 produits. Pour PHP2Shell, le centre néerlandais NCSC-NL tient une liste semblable depuis le 21 octobre. Le 22 octobre à 15 h 28 UTC, elle comptait 724 entrées de 456 fournisseurs, dont 440 encore en enquête. Sur les 216 entrées marquées vulnérables, 185 portent une étiquette générique, vulnérable si le PHP qui la sert l'est. La cascade ne fait que commencer, et chaque fournisseur publiera son avis à son rythme.
La méthode tient en 4 gestes.
- Dresser la liste des fournisseurs dont un produit embarque PHP, appareils compris.
- S'abonner à leurs avis de sécurité et vérifier la liste du NCSC-NL chaque semaine.
- Noter au registre la réponse de chacun, touché, pas touché ou corrigé dans telle version, avec la date.
- Relancer par écrit ceux qui n'ont rien publié, et fixer une date limite.
Chercher une compromission
Le Centre canadien recommande d'examiner les journaux des serveurs web, des applications, de l'authentification et des postes, et d'enquêter sur tout processus, commande, fichier, compte ou connexion sortante inattendus associés à PHP ou aux services web. Wiz signale un indice à surveiller, des requêtes multipart inhabituelles suivies d'erreurs de limite de mémoire ou d'erreurs HTTP 500 répétées. Comme les journaux de l'application peuvent rester muets, l'absence d'indice ne prouve rien. Les fichiers PHP apparus dans les dossiers web depuis le 17 octobre méritent une revue à part.
Inventorier votre parc
Les vérificateurs publiés depuis le 21 octobre répondent à une question précise, cette adresse est-elle vulnérable. Ils ne disent pas où PHP vit dans votre parc, ce qui s'en sert ni à qui revient le correctif. Nous publions 2 scripts d'inventaire pour combler ce manque, un pour Windows et un pour Linux.
Les 2 suivent les mêmes règles.
- Lecture seule. Ils n'exécutent jamais PHP, ne modifient rien et n'envoient rien sur Internet.
- Ils trouvent les moteurs et modules PHP sur les disques locaux, puis ce qui s'en sert, comme les services, les tâches planifiées, IIS, Apache, les processus en cours et les conteneurs.
- Ils indiquent l'état selon la source la plus fiable disponible, soit le journal du paquet sous Linux, et la version du fichier sous Windows, où les binaires officiels portent le numéro réel de la version publiée.
- Pour les images de conteneurs, ils lisent la version que l'image déclare, une indication à confirmer. Ils ignorent volontairement les moteurs Docker ou Podman distants.
- Ils ne voient ni l'intérieur des appareils, ni les sites hébergés ailleurs, ni les images qui ne sont pas sur la machine. Ceux-là passent par la liste des fournisseurs.
Lisez un script avant de l'exécuter, celui-ci comme les autres.
Windows (PowerShell 5.1 ou 7, en administrateur)
Collez le script dans une fenêtre PowerShell ouverte en administrateur. Comptez quelques minutes par disque.
# PHP inventory for Windows (Sentrix). Read-only: it lists files, services,
# scheduled tasks, IIS settings and processes. It never runs php, never
# changes anything and sends nothing over the network.
# Run in an elevated PowerShell 5.1 or 7 window. A full scan can take minutes.
# Folders to scan: every local fixed disk by default, or a list such as @('D:\Apps').
$Roots = (Get-CimInstance Win32_LogicalDisk -Filter 'DriveType=3').DeviceID
$fixed = @{ '8.5' = 12; '8.4' = 27; '8.3' = 36; '8.2' = 35 }
function Get-Status([string]$v) {
if ("$v".Trim() -notmatch '^(\d+)\.(\d+)\.(\d+)$') { return 'Unknown version: ask the vendor' }
$branch = "$($Matches[1]).$($Matches[2])"; $patch = [int]$Matches[3]
if ($fixed.ContainsKey($branch)) {
if ($patch -ge $fixed[$branch]) { return 'Fixed version' } else { return 'Update required' }
}
return 'No fixed Windows build: upgrade or retire'
}
function Get-Origin([string]$p) {
switch -Regex ($p) {
'xampp' { return 'XAMPP' }
'wamp' { return 'WampServer' }
'laragon' { return 'Laragon' }
'filemaker' { return 'FileMaker Server' }
'plesk' { return 'Plesk' }
default { return 'Other: check the parent folder' }
}
}
# Walk each disk folder by folder: a folder we may not read is skipped, never
# the whole disk, and junctions are not followed (no loops, no duplicates).
$pattern = '^(php|php-cgi|php-win)\.exe$|^php\d?(ts)?\.dll$|^php\d+apache[\d_]*\.dll$'
function Find-PhpFile([string]$root) {
$stack = New-Object System.Collections.Generic.Stack[string]
$stack.Push($root)
while ($stack.Count -gt 0) {
$dir = $stack.Pop()
try { foreach ($f in [IO.Directory]::GetFiles($dir)) { if ([IO.Path]::GetFileName($f) -match $pattern) { $f } } } catch { }
try { $subs = [IO.Directory]::GetDirectories($dir) } catch { continue }
foreach ($s in $subs) {
try { if (-not ([IO.File]::GetAttributes($s) -band [IO.FileAttributes]::ReparsePoint)) { $stack.Push($s) } } catch { }
}
}
}
$report = foreach ($root in $Roots) {
Write-Progress -Activity 'Searching for PHP' -Status $root
Find-PhpFile "$root\" | ForEach-Object {
$file = Get-Item -LiteralPath $_ -Force
$v = $file.VersionInfo.ProductVersion
[pscustomobject]@{
Kind = 'File'
Path = $file.FullName
Version = $v
Status = Get-Status $v
Origin = Get-Origin $file.FullName
Detail = "Modified $($file.LastWriteTime.ToString('yyyy-MM-dd'))"
}
}
}
# Who uses PHP: services, scheduled tasks, IIS handlers and running processes.
$uses = @()
$uses += Get-CimInstance Win32_Service | Where-Object { $_.PathName -match 'php|httpd|apache' } |
ForEach-Object { [pscustomobject]@{ Kind = 'Service'; Path = $_.PathName; Version = ''; Status = $_.State; Origin = Get-Origin $_.PathName; Detail = $_.Name } }
$uses += Get-ScheduledTask -ErrorAction SilentlyContinue | ForEach-Object {
$task = $_
$task.Actions | Where-Object { "$($_.Execute) $($_.Arguments)" -match 'php' } |
ForEach-Object { [pscustomobject]@{ Kind = 'Scheduled task'; Path = "$($_.Execute) $($_.Arguments)"; Version = ''; Status = "$($task.State)"; Origin = Get-Origin $_.Execute; Detail = "$($task.TaskPath)$($task.TaskName)" } }
}
$iis = Join-Path $env:windir 'System32\inetsrv\config\applicationHost.config'
if (Test-Path $iis) {
$uses += Select-String -Path $iis -Pattern '(fullPath|scriptProcessor)="([^"|]*php[^"|]*)' -AllMatches |
ForEach-Object { $_.Matches } | ForEach-Object { $_.Groups[2].Value } | Sort-Object -Unique |
ForEach-Object { [pscustomobject]@{ Kind = 'IIS FastCGI'; Path = $_; Version = ''; Status = 'Configured'; Origin = Get-Origin $_; Detail = 'applicationHost.config' } }
}
$listen = @{}
Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue | ForEach-Object { $listen[[int]$_.OwningProcess] += @($_.LocalPort) }
$uses += Get-CimInstance Win32_Process |
Where-Object { $_.ProcessId -ne $PID -and ($_.Name -match '^(php|httpd|w3wp)' -or $_.CommandLine -match 'php(-cgi|-win)?\.exe|php\.ini') } |
ForEach-Object {
$ports = ($listen[[int]$_.ProcessId] | Sort-Object -Unique) -join ','
# The PHP build this process really runs: its php*.exe or loaded php*.dll.
$mod = $null
try { $mod = (Get-Process -Id $_.ProcessId -ErrorAction Stop).Modules | Where-Object { $_.ModuleName -match $pattern } | Select-Object -First 1 } catch { }
$ver = if ($mod) { $mod.FileVersionInfo.ProductVersion } else { '' }
$state = if ($mod) { Get-Status $ver } else { 'Running' }
$runs = if ($mod) { $mod.FileName } else { $_.ExecutablePath }
[pscustomobject]@{ Kind = 'Process'; Path = $runs; Version = $ver; Status = $state; Origin = Get-Origin "$runs"; Detail = "$($_.Name) PID $($_.ProcessId), ports $ports" }
}
$all = @($report) + @($uses)
if (-not $all) { Write-Output 'No PHP found in the scanned folders.' }
$all | Sort-Object Kind, Path | Format-List Kind, Status, Version, Origin, Path, Detail
# To keep a copy: $all | Export-Csv "$env:USERPROFILE\Desktop\php-inventory.csv" -NoTypeInformation
Linux (bash, avec sudo)
Enregistrez le script sous find-php.sh, puis lancez sudo bash find-php.sh. Sans sudo, les processus des autres comptes restent invisibles.
#!/usr/bin/env bash
# PHP inventory for Linux (Sentrix). Read-only: it lists files, packages,
# processes, web server settings and local container images. It never runs
# php, never changes anything and sends nothing over the network. Run with sudo.
ROOTS=${ROOTS:-$(findmnt -ln -o TARGET -t ext2,ext3,ext4,xfs,btrfs,zfs,squashfs)}
row() { printf '%-10s %-40s %-30s %s\n' "$1" "$2" "$3" "$4"; }
upstream() { # status of an upstream version number, without vendor backports
local b=${1%.*} p=${1##*.}
case "$b" in
8.5) [ "$p" -ge 12 ] && echo "Fixed version" || echo "Update required" ;;
8.4) [ "$p" -ge 27 ] && echo "Fixed version" || echo "Update required" ;;
8.3) [ "$p" -ge 36 ] && echo "Fixed version" || echo "Update required" ;;
8.2) [ "$p" -ge 35 ] && echo "Fixed version" || echo "Update required" ;;
"") echo "Version unknown: ask the vendor" ;;
*) echo "End of life: vendor fix or upgrade" ;;
esac
}
origin() {
case "$1" in
/opt/cpanel/ea-php*) echo "cPanel EA4" ;;
/opt/alt/php*) echo "CloudLinux alt-php" ;;
/opt/plesk/php/*) echo "Plesk" ;;
/usr/local/php*) echo "DirectAdmin CustomBuild?" ;;
/usr/local/lsws/*) echo "LiteSpeed lsphp" ;;
/var/lib/docker/*|/var/lib/containers/*) echo "Container layer" ;;
/snap/*) echo "Snap" ;;
*) echo "Unknown origin" ;;
esac
}
fixproof() { # $1 package, $2 file: is the fix documented, and is the file the packaged one?
local log
if command -v rpm >/dev/null && rpm -q "$1" >/dev/null 2>&1; then
log=$(rpm -q --changelog "$1"); rpm -Vf "$2" 2>/dev/null | grep -q " $2\$" && { echo "File differs from its package"; return; }
elif [ -f "/usr/share/doc/$1/changelog.Debian.gz" ]; then
log=$(zcat "/usr/share/doc/$1/changelog.Debian.gz"); dpkg --verify "$1" 2>/dev/null | grep -q " $2\$" && { echo "File differs from its package"; return; }
else echo "No changelog: check the vendor"; return; fi
if grep -q 109618 <<<"$log" && grep -q 109619 <<<"$log"; then echo "Fixed: both CVEs in changelog"
else echo "Not in changelog: see vendor advisory"; fi
}
row KIND STATUS DETAIL PATH
# 1. PHP engines and modules on local disks. The version is read from the
# file itself (the X-Powered-By string compiled into PHP), never by running it.
while IFS= read -r root; do
[ -n "$root" ] || continue
find "$root" -xdev -type f \( -name php -o -name 'php[0-9]*' -o -name 'php-fpm*' -o -name 'php-cgi*' \
-o -name 'lsphp*' -o -name 'libphp*.so' -o -name 'mod_php*.so' -o -name frankenphp \) 2>/dev/null
done <<<"$ROOTS" | sort -u | while IFS= read -r f; do
[ "$(head -c4 "$f" 2>/dev/null | od -An -c | tr -d ' ')" = '177ELF' ] || continue
ver=$(grep -aom1 -E 'X-Powered-By: PHP/[0-9]+\.[0-9]+\.[0-9]+' "$f" | sed 's#.*/##')
pkg=$(dpkg -S "$f" 2>/dev/null | head -1 | cut -d: -f1)
[ -z "$pkg" ] && command -v rpm >/dev/null && pkg=$(rpm -qf --qf '%{NAME}' "$f" 2>/dev/null | grep -v 'not owned')
if [ -n "$pkg" ]; then row File "$(fixproof "$pkg" "$f")" "PHP ${ver:-?}, package $pkg" "$f"
else row File "$(upstream "$ver")" "PHP ${ver:-?}, $(origin "$f")" "$f"; fi
done
# 2. Processes still running PHP code that was replaced on disk since they started.
ps -eo pid=,comm= | awk '$2 ~ /^(php|lsphp|frankenphp|apache2|httpd)/ {print $1, $2}' | while read -r p comm; do
exe=$(readlink "/proc/$p/exe" 2>/dev/null) || continue
stale=no
grep -qE 'php[^ /]*\.so \(deleted\)' "/proc/$p/maps" 2>/dev/null && stale=yes
[[ "$comm" =~ ^(php|lsphp|frankenphp) && "$exe" == *" (deleted)" ]] && stale=yes
[ "$stale" = yes ] && echo "Restart needed: old PHP in memory|$exe" || echo "Running|$exe"
done | sort | uniq -c | while read -r n line; do row Process "${line%%|*}" "$n process(es)" "${line#*|}"; done
# 3. mod_php, the setup PHP rates highest risk, and sockets held by PHP.
grep -rshE '^\s*LoadModule\s+php' /etc/apache2 /etc/httpd /usr/local/apache/conf 2>/dev/null | sort -u |
while read -r l; do row Apache "mod_php loaded" "-" "$l"; done
ss -ltnpH 2>/dev/null | grep -E '"(php|lsphp|frankenphp)' | while read -r l; do row Listener "Listening" "-" "$l"; done
# 4. Local container images that declare PHP (PHP_VERSION of the official image).
# Remote Docker or Podman endpoints are ignored on purpose.
for c in docker podman; do
command -v "$c" >/dev/null || continue
if [ "$c" = docker ]; then cli=(env -u DOCKER_HOST docker --context default); else cli=(env -u CONTAINER_HOST -u CONTAINER_CONNECTION podman); fi
for id in $("${cli[@]}" image ls -q 2>/dev/null | sort -u); do
ver=$("${cli[@]}" image inspect -f '{{range .Config.Env}}{{println .}}{{end}}' "$id" 2>/dev/null | sed -n 's/^PHP_VERSION=//p')
[ -n "$ver" ] || continue
row Image "$(upstream "$ver")" "PHP $ver declared by the image" "$("${cli[@]}" image inspect -f '{{index .RepoTags 0}}' "$id" 2>/dev/null) $id"
done
done
Lire le résultat. Une ligne « Update required » ou « No fixed Windows build » demande une action. Une ligne « Restart needed » sous Linux signale un processus qui fait encore tourner l'ancien code. Une ligne « Not in changelog » renvoie à l'avis du fournisseur, puisque certains paquets corrigés ne mentionnent pas les CVE dans leur journal. Une ligne « File differs from its package » signale un fichier modifié après son installation, à examiner. L'origine est déduite du dossier et reste une piste à confirmer.
Ce que nous en pensons chez Sentrix
PHP2Shell n'est pas d'abord une affaire de correctif. C'est une affaire d'inventaire et de responsabilité, comme Log4j l'était. Voici notre ordre de travail.
- Inventorier tout le PHP, y compris celui qui n'est pas à vous. Serveurs, postes, conteneurs, appareils et sites hébergés, avec pour chacun le responsable de la correction. C'est l'étape de découverte du module CTEM.
- Prouver la correction par le paquet et le redémarrage, jamais par le numéro.
- Décider des secrets pour chaque serveur exposé avant son correctif, et consigner la décision.
- Sortir les versions sans correctif de l'exposition directe. Migrer, isoler ou retirer, et inscrire la décision au registre des risques.
- Tenir le registre des réponses de fournisseurs, avec la même rigueur que pour les risques tiers. Le SBOM est la bonne question à poser au prochain renouvellement.
- Ne pas attendre le catalogue KEV. PHP demande déjà une mise à jour immédiate et Amazon rapporte des tentatives. La méthode décrite dans prioriser les correctifs avec le catalogue KEV s'applique dès maintenant, sans attendre une inscription.
Notre service de gestion des vulnérabilités et des correctifs applique cette méthode, de l'inventaire à la preuve de correction.
La prochaine étape
Exécutez l'inventaire sur vos serveurs et vos postes, envoyez les 5 questions à votre hébergeur et ouvrez le registre des fournisseurs qui embarquent PHP. Chaque ligne sans preuve de correction et sans date de suivi est un angle mort. Si vous voulez faire l'exercice avec nous, contactez-nous.
Sources
- PHP, Security advisory: Critical remote code execution vulnerabilities, update now (21 octobre 2026)
- Centre canadien pour la cybersécurité, AL26-026 Vulnérabilités critiques touchant PHP (21 octobre 2026)
- CISA, Critical Vulnerabilities in PHP Require Immediate Patching (21 octobre 2026)
- Amazon Threat Intelligence, PHP2Shell exploitation prior to public disclosure in MadPot (21 octobre 2026)
- Wiz Research, PHP2Shell (21 octobre 2026)
- Sansec, PHP2Shell (mis à jour le 22 octobre 2026)
- CloudLinux, PHP2Shell fixed alt-php and ea-php packages and how to verify (22 octobre 2026)
- cPanel, Critical PHP Security Release CVE-2026-109618 and CVE-2026-109619 (22 octobre 2026)
- Plesk, PHP2Shell, Remote code execution in PHP shipped with Plesk (22 octobre 2026)
- Docker Official Images, FAQ sur les versions prises en charge
- Bitnami, Upcoming changes to the Bitnami catalog (issue 83267, 16 juillet 2025)
- QNAP, QSA-26-18 (22 octobre 2026)
- QNAP, Can I update the built-in PHP version on QTS and QuTS hero? (5 mars 2024)
- Palo Alto Networks, CVE-2026-109618 (21 octobre 2026)
- AWS, Security Bulletin 2026-143-AWS (21 octobre 2026)
- PHP for Windows, versions publiées et archives
- Apache Friends, téléchargements XAMPP
- WordPress.org, versions de PHP des sites WordPress (statistiques consultées le 22 octobre 2026)
- NCSC-NL, liste des logiciels touchés par PHP2Shell (22 octobre 2026)
- CISA, liste des produits touchés par Log4j (archivée)
Questions fréquentes
- Mon site WordPress est-il touché par PHP2Shell ?
- Oui, si le PHP qui le fait tourner n'est pas corrigé. WordPress.org précise qu'aucune mise à jour de WordPress n'est requise, parce que la faille est dans PHP. Selon les statistiques de WordPress.org, 35,8 % des sites WordPress tournent sur PHP 8.1 ou plus ancien, des versions que le projet PHP ne publie plus. Demandez à votre hébergeur quelle version sert votre site et quelle preuve de correction il peut vous donner.
- Mon serveur affiche PHP 8.3.6. Suis-je vulnérable ?
- Le numéro seul ne permet pas de le dire. Ubuntu 24.04 corrige PHP2Shell dans le paquet 8.3.6-0ubuntu0.24.04.13, qui garde le numéro 8.3.6 alors que la version corrigée du projet PHP est 8.3.36. CloudLinux, cPanel et Plesk font de même pour d'anciennes versions. La preuve est dans le journal des modifications du paquet ou dans l'avis du fournisseur, puis dans le redémarrage des processus PHP.
- J'utilise PHP 7.4, 8.0 ou 8.1 sous Windows. Que faire ?
- Il n'existe aucun binaire Windows officiel corrigé pour ces versions. Les dernières publications Windows sont 7.4.33 en novembre 2022, 8.0.30 en août 2023 et 8.1.34 en décembre 2025. Le projet PHP n'a fourni que des correctifs en code source. Il reste à migrer l'application vers 8.2 ou plus récent, ou à retirer le serveur d'Internet jusqu'à la migration, et à inscrire la décision au registre des risques.
- Mon hébergeur dit avoir corrigé PHP. Comment le vérifier ?
- Demandez-lui la version exacte du paquet qui sert votre site et l'avis qui confirme la correction des 2 CVE pour ce paquet. Demandez aussi la date du redémarrage des processus PHP après la mise à jour, puisqu'un processus démarré avant garde l'ancien code en mémoire. Si vous êtes sur une version antérieure à 7.4, demandez quel correctif s'applique, puisque cPanel et Plesk renvoient ces versions vers un service payant.
- Faut-il changer nos mots de passe et nos clés ?
- C'est une décision à prendre serveur par serveur. Wiz et Sansec ont démontré qu'une des failles permet de lire la mémoire du processus PHP, où peuvent se trouver des mots de passe, des jetons de session et des clés d'API. Pour un serveur exposé à Internet et resté sans correctif après le 17 octobre, date de la première tentative relevée par Amazon, changer ces secrets est la position prudente.
- Un pare-feu applicatif web suffit-il ?
- Non. Il réduit l'exposition pour le trafic qui passe par lui, mais ne corrige rien. Sansec rappelle que les failles se déclenchent dans PHP lui-même, avant le code de l'application, et recommande de ne pas attendre une règle de filtrage pour mettre PHP à jour. Un serveur joignable directement, sans passer par le pare-feu, reste exposé.
Pages liées
Analyse · Vulnérabilités
Prioriser les correctifs avec le catalogue KEV et l'EPSS
Le CVSS dit la gravité, pas l'urgence. Comment le catalogue KEV de la CISA et l'EPSS de FIRST changent l'ordre des correctifs, et ce que le BOD 26-04 impose.
Analyse · Chaîne logicielle
SBOM : ce qu'il faut demander à un fournisseur
Une SBOM n'est utile que si elle est complète, lisible par machine et livrée à chaque version. Ce que les éléments minimaux CISA et NTIA permettent d'exiger.
Plateforme · CTEM
Votre surface d'exposition, vue en continu.
Sentrix gère l'exposition aux menaces en continu (CTEM) sur six domaines, des applications au réseau interne, à côté de la conformité et des risques tiers.
Plateforme · Risques tiers
Connaissez votre risque fournisseur avant votre auditeur.
Sentrix vous offre une visibilité continue sur la posture de risque de chaque fournisseur, pas un questionnaire ponctuel périmé le lendemain de son envoi.
Services · Implémentation
Vulnérabilités et correctifs : réanalysés pour confirmer
Analyse, priorisation selon l'exploitabilité et déploiement des correctifs, avec une réanalyse indépendante avant de fermer un ticket : fermé n'est pas corrigé.
Parlons de votre programme de conformité.
Dernière mise à jour :
