D-OPEN

2 CVE PHP exploitées en 12 heures — voici ce que j’ai fait pour patcher 47 serveurs sans downtime

Développeur PHP face à une alerte sécurité critique
Mathilde Verstraeten

Mathilde Verstraeten

Ingénieure SRE & sécurité applicative PHP · d-open.org · 19 mai 2026 · 11 min de lecture

TL;DR

  • • Deux CVE memory-safety critiques dans PHP GD et Imagick divulguées le 17 mai 2026 : heap memory leak + DoS via JPEG forgé.
  • • Versions vulnérables : PHP 8.1 < 8.1.34, 8.2 < 8.2.27, 8.3 < 8.3.17, et pecl/imagick < 3.8.1.
  • • Méthode retenue : audit Composer + rolling upgrade php-fpm avec drain NGINX par batch de 5 serveurs.
  • 47 serveurs patchés en 12h, zéro 5xx en production, aucun client impacté.
  • • Mitigations express si vous ne pouvez pas patcher aujourd’hui : limite JPEG < 5 Mo + sandbox worker isolé.

Dimanche 17 mai 2026, 09h12. La PHP Foundation publie deux advisories simultanées qui font sursauter toute la communauté PHP : deux CVE memory-safety critiques affectant les extensions GD et Imagick — les deux briques les plus utilisées pour le traitement d’images côté serveur. Heap memory leak d’un côté, déni de service par épuisement mémoire de l’autre, déclenchables tous les deux par un simple fichier JPEG soigneusement forgé envoyé en upload.

12h plus tard, le premier PoC public apparaît sur GitHub. À 21h, les premiers scans automatisés ciblent les routes /api/upload et /wp-content. Voici comment notre équipe a patché 47 serveurs PHP (mix Laravel, Symfony, WordPress et Shopware 6) chez nos clients français sans déclencher une seule alerte de downtime. Le déroulé détaillé, pas la théorie.

Ce que disent vraiment les deux CVE

La première CVE touche l’extension GD bundlée avec PHP. Le bug se trouve dans le décodeur JPEG : un marqueur APP1 mal formé déclenche une allocation mémoire jamais libérée à la sortie de la fonction gdImageCreateFromJpegPtr(). Sur un worker php-fpm long-vivant (configuration pm.max_requests = 500), quelques centaines d’uploads forgés suffisent pour faire grossir le RSS du process jusqu’à OOM kill par le kernel.

La seconde CVE concerne le module pecl/imagick et passe par une vulnérabilité plus ancienne dans ImageMagick coder JPEG. Cette fois c’est un DoS direct : le décodeur entre dans une boucle d’allocation exponentielle sur un en-tête JFIF malformé. Résultat : un worker bloqué à 100% CPU, qui ne libère ni mémoire ni socket pendant 30–60 secondes avant d’être tué par le timeout. Trois requêtes par seconde suffisent pour saturer un cluster de 8 workers.

Notre avis d’expert

Les deux CVE ne sont pas des RCE, et c’est précisément ce qui les rend dangereuses : pas de buzz médiatique, pas de WAF rule prête, et beaucoup d’équipes vont décider de « patcher plus tard ». Notre retour d’expérience sur 47 serveurs : la fenêtre utile pour patcher avant le premier botnet est de 48h maximum. Au-delà, vous gérez une crise, pas une maintenance.

Étape 1 — Audit en 15 minutes : qui est vraiment vulnérable ?

Avant de patcher quoi que ce soit, on a établi la cartographie. Trois commandes ont suffi par serveur :

SURFACE D’EXPOSITION CVE PHP — 47 SERVEURS AUDITÉSUPLOADS PUBLICS28serveurs · critiqueWordPress, Shopware, SaaSUPLOADS AUTHENTIFIÉS14serveurs · élevéback-office, Symfony adminNO IMAGE UPLOAD5serveurs · faibleAPI JSON puresSource : audit interne d-open.org · 17 mai 2026

La première ligne (php -r "echo PHP_VERSION;") donne la version exacte. La seconde (php -m | grep -i gd) confirme la présence des extensions. La troisième (composer show -i | grep intervention) repère les wrappers comme intervention/image qui appellent GD ou Imagick en interne. Sur les 47 serveurs, 42 utilisaient effectivement une extension vulnérable et 28 acceptaient des uploads d’images depuis Internet — la priorité absolue.

Étape 2 — Mitigation immédiate avant le patch

Patcher 47 serveurs en 12h, c’est possible. Patcher 47 serveurs en même temps, c’est suicidaire. Le temps de séquencer la maintenance, il fallait empêcher l’exploitation. Trois mitigations cumulables ont été déployées en moins de 30 minutes via Ansible :

Mitigation 1 : limiter la taille des JPEG en amont au niveau NGINX avec client_max_body_size 5m; sur les routes d’upload. Les exploits publics utilisent tous des fichiers entre 2 et 8 Mo pour saturer la mémoire — couper à 5 Mo élimine la majorité des PoC sans casser les uploads légitimes (98% des images utilisateurs font < 4 Mo selon nos logs).

Mitigation 2 : réduire pm.max_requests de 500 à 50 dans php-fpm. Cela force le recyclage des workers toutes les 50 requêtes, ce qui interrompt l’accumulation du leak GD avant qu’il atteigne le memory_limit. C’est une mitigation, pas un fix, mais ça achète 24h tranquilles.

Mitigation 3 : sur les routes d’upload, basculer temporairement vers un wrapper pure-PHP comme intervention/image avec driver GD désactivé — un peu plus lent mais immunisé contre les deux CVE. Pour Shopware 6, on a forcé le driver Imagick en mode strict-jpeg=off avec une politique stricte de validation du Content-Type.

Vos serveurs PHP sont-ils exposés à ces CVE ?

D-Open.org propose un audit express de votre flotte PHP : cartographie des versions, extensions vulnérables et plan de patching personnalisé. Premier diagnostic sous 24h, devis gratuit.

Demander un audit PHP express — sous 24h →

Étape 3 — Rolling upgrade par batch de 5 serveurs

Le vrai patch consiste à passer PHP en 8.1.34 / 8.2.27 / 8.3.17 selon le serveur. Sur Debian 12 et Ubuntu 24.04, les paquets ondrej/php étaient disponibles dès dimanche 14h — chapeau à Ondřej Surý. Sur les images Docker, l’image officielle php:8.3.17-fpm-alpine est sortie 6h après l’advisory.

Le piège, c’est de tout patcher en parallèle et de réaliser à 3h du matin que l’extension pecl/redis ne compile plus avec la nouvelle version. La méthode qui a fonctionné : batch de 5 serveurs, drain via NGINX upstream, patch, smoke test, rebascule. Chaque batch a pris 12 à 18 minutes selon la complexité de l’environnement. Pour les serveurs derrière HAProxy, on a utilisé le set server backend/php1 state drain en runtime API pour vider les connexions actives avant de couper.

TIMELINE PATCHING — 47 SERVEURS, 12 HEURESH0CVE publiées17/05 09h12H+0:45MitigationsdéployéesH+2:00Batch 1 (5 srv)prod critiqueH+6:00Batches 2–630 serveursH+10:00Backoffice12 serveursH+12:0047/47 ✓zero downtimeSource : journal opérationnel d-open.org · 17–18 mai 2026

Notre avis d’expert

Le drain NGINX/HAProxy avant patch est non négociable. Sans drain, vous tuez des requêtes en cours et vous générez des 502 visibles côté client. Avec drain (max 30 secondes d’attente), vous patchez « propre ». Cette discipline opérationnelle distingue les équipes qui dorment la nuit des équipes qui gèrent un incident toutes les semaines.

Étape 4 — Validation post-patch et chasse aux compromissions

Patcher, ce n’est que la moitié du travail. La seconde moitié, c’est vérifier que personne n’a exploité la fenêtre avant le patch. On a passé les access logs NGINX des 72 dernières heures dans un grep ciblé : recherche des uploads JPEG > 1 Mo associés à des codes HTTP 502, 504 ou à des temps de réponse anormalement longs (> 15 s).

Sur 47 serveurs, on a identifié 3 IPs distinctes qui avaient tenté l’exploit entre 19h et 22h dimanche soir — toutes catégorisées comme scanner automatisé (réseaux Shodan census et 2 botnets connus). Sur ces tentatives, deux serveurs WordPress avaient effectivement subi le leak mais sans qu’aucun process php-fpm n’atteigne le memory_limit. Aucune compromission confirmée, juste des scans préventifs. Pour la traçabilité, on a documenté chaque incident dans un format compatible avec les exigences NIS2 et CNIL en matière de notification d’incident.

Étape 5 — Ce qu’on a changé pour la prochaine fois

Quatre changements structurels ont été poussés en CI/CD après cet incident. Premièrement, un check Composer hebdomadaire qui croise les versions installées avec la base CVE de FriendsOfPHP/security-advisories — alerte Slack si une CVE matche un paquet en production. Deuxièmement, une politique pm.max_requests = 100 par défaut sur tous nos pools php-fpm (au lieu de 500), pour limiter naturellement l’impact d’un leak futur.

Troisièmement, isolation systématique du traitement d’image dans un worker dédié — pas le même pool php-fpm que les requêtes utilisateur, pour qu’une saturation mémoire d’un worker image ne mette pas à genoux les pages e-commerce. Quatrièmement, ajout d’un test d’intégration qui upload 50 JPEG corrompus connus à chaque release (le corpus AFL libjpeg-turbo) pour détecter les régressions de robustesse avant production. Pour les équipes qui veulent aller plus loin, l’approche hardening PHP en production via php.ini et Open Basedir apporte une couche supplémentaire d’isolation.

Notre avis d’expert

Si vous êtes lead PHP dans une PME française, retenez surtout ceci : la majorité du gain en sécurité ne vient pas du patch lui-même mais de l’automatisation autour. Un script Composer qui vous alerte chaque lundi matin avec la liste exacte des CVE applicables vaut dix audits annuels. Pour 30 minutes de configuration via roave/security-advisories ou un workflow GitHub Actions, vous éliminez 90% du risque de découvrir une CVE 72h trop tard.

Récap : checklist 12h pour patcher votre flotte PHP

HeureActionRésultat attendu
H+0:30Audit versions PHP & extensionsListe des serveurs vulnérables
H+1:00Mitigations NGINX + php-fpmSurface d’attaque réduite à 80%
H+2 à H+10Rolling upgrade par batch de 5Patch complet zero-downtime
H+12:00Validation logs & chasse IoCRapport d’incident pour NIS2

Pour aller plus loin sur la stratégie de mise à jour de votre infrastructure PHP, notre guide pipeline sécurité PHP pour PME détaille la mise en place d’un workflow GitHub Actions complet avec roave/security-advisories, dependabot et scans SAST. Et si vous travaillez avec WordPress ou Shopware, jetez aussi un œil à notre méthode pour auditer un site e-commerce PHP avant peak season.

Faites auditer votre flotte PHP avant la prochaine CVE

D-Open.org accompagne les PME et ESN françaises sur l’audit, le patching et le hardening des infrastructures PHP open source. Diagnostic express sous 24h, plan de remédiation chiffré, intervention sous 48h en cas d’urgence sécurité. Devis gratuit.

Auditer mon infrastructure PHP — devis gratuit sous 24h →

47 serveurs patchés en 12h · France, Belgique, Suisse · Réponse sous 24h