PHP2Shell, cette semaine

Le 21 octobre 2026, le projet PHP a publié quatre versions d’un coup, 8.5.12, 8.4.27, 8.3.36 et 8.2.35, pour corriger deux failles critiques dans l’interpréteur lui-même1. Pas dans WordPress. Pas dans une extension. Dans PHP.

Les deux sont notées 9,2 en CVSS 4.0. Les deux permettent l’exécution de code à distance sans connexion. Les chercheurs qui les ont trouvées en donnent la portée sans détour : « Every PHP version released in the last decade is affected by at least one of these vulnerabilities, going back to version 5.4. »2

L’avis du projet PHP dit le reste :

Ce que dit l’avisCe que cela signifie pour vous
« unauthenticated remote code execution »personne n’a besoin d’un compte sur votre site
« risk highest for mod_php »la configuration Apache à l’ancienne la plus courante est la plus exposée
« before any application code runs »votre propre code, aussi soigné soit-il, n’a jamais son mot à dire
« There are no complete mitigations, updating is the only safe choice. »aucun changement de configuration ne vous sauve
« PHP 8.1 and older no longer receive updates »une bonne partie du web n’a aucun correctif

Et elle était utilisée avant que quiconque soit prévenu. Le réseau de pots de miel d’Amazon a enregistré une tentative le 17 octobre, quatre jours avant la divulgation3. watchTowr l’a vue dans la nature le 21, et des preuves de concept fonctionnelles étaient publiques quelques heures après le correctif4.

Les deux bugs sont des bugs de sûreté mémoire. L’un se trouve dans la façon dont l’interpréteur fait le ménage après avoir manqué de mémoire. L’autre est un use-after-free : la mémoire d’une requête est libérée puis relue, et la requête suivante sur le même worker peut la voir56. Retenez ce second-là. Il reviendra plus loin.

Rien de tout cela n’est nouveau. C’est tout l’objet de cet article. PHP2Shell n’est pas un accident arrivé à un langage prudent. C’est la dernière page d’un dossier long de presque trente ans, et chaque chiffre qu’il contient est public.

Un seul processus détient tout

De novembre 2014 à avril 2017, j’ai été ingénieur Linux de troisième niveau sur la plateforme cloud et hébergement de Pulsant. Une partie du travail consistait à configurer des environnements PHP-FPM pour des clients e-commerce et à les régler pour qu’ils aillent vite.

Les intrusions via PHP étaient courantes. Pas de temps en temps. Courantes. Et elles se ramenaient à deux causes : un mauvais déploiement, et aucune séparation entre le front end et le back end.

Le langage fait de la seconde le comportement par défaut. Un site PHP typique, c’est un seul processus. Le template de page, la logique métier et le SQL vivent tous dans le même gestionnaire de requête, souvent dans le même fichier. Ce processus tourne sous un seul utilisateur du système. Il peut lire le mot de passe de la base, parce que ce mot de passe est dans un fichier à côté du code. Et il peut généralement écrire dans sa propre racine web, parce que c’est ainsi que fonctionnent les téléversements et les mises à jour.

Un seul processus qui détient tout, face à des tiers avec leurs propres frontièresLe déploiement PHP habituelDes tiers avec leurs propres frontièresInternetun worker, un utilisateur systèmetemplates HTMLlogique métierSQL, construit dans le même fichierwp-config.php : mot de passe BDuploads/ : modifiablele code lui-même : modifiableun seul bug atteint toutbase, tous les droitsInternetfront endrend les pages, aucun identifiantservice back endson utilisateur, code non modifiablene répond qu'à une API étroitebase, moindre privilège
À gauche, le site PHP habituel : tout dans un seul worker, un seul utilisateur, à un bug de tout perdre. À droite, des tiers avec leurs propres frontières : le front end ne détient aucun identifiant et le back end ne peut pas se réécrire.

Ce n’est pas mon opinion sur la façon dont PHP est déployé. C’est ce que PHP et WordPress documentent.

SourceCe qu’elle dit
Manuel PHP, module Apachequand PHP tourne comme module Apache, « it inherits Apache’s user permissions », et « a malicious script could access and modify the database, even without a username and password »7
Manuel PHP, installation Apache« The mod_php approach embeds PHP directly into every Apache httpd worker process. »8
WordPress, wp-configle fichier « is located in the root of your WordPress file directory and contains … database connection information »9
WordPress, permissions des fichierswp-config.php « is initially created with 644 permissions, and it’s a hazard to leave it like that »10
WordPress, durcissementl’utilisateur de la base « only needs » SELECT, INSERT, UPDATE et DELETE, puis « it is NOT recommended to revoke these privileges »11

Relisez cette dernière ligne. L’éditeur vous dit à quoi ressemblerait le moindre privilège, puis vous dit de ne pas le faire, parce que les mises à jour modifient le schéma.

Comparez avec la version séparée. Le front end rend les pages et ne détient aucun secret. Le back end est un service distinct avec son propre utilisateur, une API étroite, et aucun droit d’écriture sur son propre code. Le compte de base de données peut faire ce dont le back end a besoin, et rien d’autre. Les recommandations de l’OWASP disent la même chose avec leurs mots : « The application’s backend database should be isolated from other servers », sur « a dedicated internal network segment »12. Le propre manuel de PHP dit que les applications « should never connect to the database as its owner or a superuser »13.

Rien de tout cela n’est exotique. C’est à cela que ressemble un processus correct. La raison pour laquelle cela compte ici est simple. Dans le modèle séparé, un bug dans le front end donne à l’attaquant un front end. Dans le modèle PHP habituel, un bug n’importe où lui donne les templates, le code, les identifiants et les données, d’un seul coup.

PHP-FPM aide, et le guide d’installation de PHP le présente désormais comme la manière recommandée de faire tourner PHP sous Apache8. Ses pools peuvent démarrer des workers « with different uid/gid/chroot/environment »14. Mais un pool par site, c’est toujours un site par processus, qui détient tout ce que ce site possède. C’est un meilleur mur entre clients. Ce n’est pas un mur à l’intérieur de l’application.

Gardez cette image en tête dans chaque section qui suit. Chaque bug du dossier atterrit sur ce processus.

Vingt-neuf ans de CVE

La National Vulnerability Database liste chaque CVE déposée contre l’interpréteur PHP sous un seul identifiant de produit, cpe:2.3:a:php:php. Posez-lui la question, elle répond 75715.

CVE de l'interpréteur PHP par année, avec la part de corruption mémoireCVE déposées contre l'interpréteur PHP, par année de publicationtoutes les CVE : 757corruption mémoire : au moins 28840801201141201997200220072012201620212026
Toutes les CVE contre l’interpréteur PHP par année de publication, avec la part de corruption mémoire superposée. Comptées via l’API NVD le 23 octobre 2026.

Ce total ne concerne que l’interpréteur. Pas de WordPress, pas de Drupal, pas d’extensions, pas de frameworks. Seulement le programme qui exécute votre PHP.

PériodeCVECorruption mémoireCe qui se passait
1997 à 2006933les débuts du web, peu de classification
200711419le Month of PHP Bugs
2008 à 201418754bruit de fond régulier
2015 à 2017208122les années unserialize et mémoire
2018 à 202310063moins nombreuses, toujours surtout mémoire
2024 à 20265527PHP2Shell tombe dans cette fenêtre
Total757288

Deux pics ressortent. Le premier est mars 2007, quand un ancien membre de l’équipe de sécurité de PHP a mené le Month of PHP Bugs, divulguant des failles dans le Zend Engine, le cœur de PHP et ses extensions « on a day by day basis »16. Il avait fondé la PHP Security Response Team, puis l’avait quittée, et avait dit pourquoi : « I dislike the ways bugs are handled »17. Quand le fondateur de l’équipe de sécurité d’un projet claque la porte et publie un bug par jour, cela vous dit comment les choses se passaient à l’intérieur.

Le second pic est 2016 : 120 CVE, dont 65 de corruption mémoire. Nous y reviendrons plus bas.

Le chiffre de la mémoire est un plancher, pas une estimation. NVD étiquette bon nombre d’anciens bugs « Other » plutôt qu’avec un type de faiblesse, y compris certains des use-after-free de la section suivante. Le vrai chiffre est plus élevé. J’utilise celui que je peux montrer.

Le moteur est écrit en C

C’est ici que l’argument de la sûreté mémoire doit être avancé avec soin, parce qu’un développeur PHP fera remarquer, à juste titre, que son code n’appelle jamais malloc. Les scripts PHP ne gèrent pas la mémoire à la main. Vous ne pouvez pas écrire un dépassement de tampon en PHP comme en C.

Vous n’en avez pas besoin. L’interpréteur qui exécute votre script est écrit en C, et ses extensions sont écrites en C. Chaque octet d’entrée non fiable que reçoit votre site, chaque en-tête, chaque téléversement, chaque champ de formulaire, chaque cookie, est analysé par ce C avant que votre code ne le voie. Quand ce C se trompe, votre PHP soigné ne compte pas. PHP2Shell l’a prouvé : l’avis dit que l’attaque peut se déclencher « before any application code runs »1.

Le dossier montre ce que ce C a raté :

Classe CWECe que c’estCVE de l’interpréteur PHP
CWE-119erreurs de tampon mémoire, en général93
CWE-125lecture hors limites50
CWE-190dépassement d’entier35
CWE-189erreurs numériques, ancienne étiquette33
CWE-416utilisation après libération27
CWE-787écriture hors limites26
CWE-476déréférencement de pointeur nul20

Ce sont les classes que les agences de sécurité ont en tête quand elles parlent de sûreté mémoire. En novembre 2022, la NSA a conseillé aux organisations « to consider making a strategic shift from programming languages that provide little or no inherent memory protection, such as C/C++, to a memory safe language when possible »18. En décembre 2023, la CISA, avec le National Cyber Security Centre britannique parmi les coauteurs, a mis un chiffre dessus : « two-thirds of reported vulnerabilities in memory unsafe programming languages still relate to memory issues »19.

Aucun des deux documents ne nomme PHP. Ils n’en ont pas besoin. Ils nomment le langage dans lequel PHP est construit.

Le pire exemple récurrent est unserialize(), la fonction qui retransforme une chaîne stockée en objets PHP. Elle a eu la même classe de bug, au même endroit, plus d’une fois :

CVEOùCe que NVD enregistre
CVE-2014-8142process_nested_datause-after-free dans unserialize20
CVE-2015-0231la même fonction« exists because of an incomplete fix for CVE-2014-8142 »21
CVE-2015-2787gestion de __wakeupuse-after-free dans unserialize
CVE-2016-5771SPL, avec le ramasse-miettesuse-after-free dans unserialize22
CVE-2016-5773ZipArchive, avec le ramasse-miettesuse-after-free dans unserialize

Le manuel PHP le sait. Sa page pour la fonction porte l’avertissement : « Do not pass untrusted user input to unserialize() regardless of the options value of allowed_classes. »23 C’est un langage qui vous dit qu’une de ses propres fonctions intégrées n’est pas sûre à utiliser sur la chose que la plupart du code web manipule toute la journée.

Puis il y a PHP-FPM, le gestionnaire de processus que le propre guide d’installation de PHP recommande plutôt que mod_php. En octobre 2019, CVE-2019-11043 a montré que « in certain configurations of FPM setup it is possible to cause FPM module to write past allocated buffers … opening the possibility of remote code execution »24. La configuration en question était une configuration nginx courante. Elle a été corrigée le 24 octobre 201925. La CISA l’a ensuite ajoutée à son catalogue des vulnérabilités connues comme exploitées, signalée comme utilisée dans des campagnes de rançongiciel26.

La PHP Foundation a bien commandé un véritable audit de sécurité du code source de l’interpréteur, et c’est à mettre à son crédit. Les résultats, publiés le 10 avril 2025, ont relevé 27 problèmes, dont 17 avec des implications de sécurité27. C’est une bonne pratique et cela devrait être normal. Ce sont aussi 17 de plus, dans l’audit d’une base de code qui avait déjà eu près de trois décennies de rapports de bugs publics.

Le langage a fait les mêmes erreurs un étage plus haut

Le C est une couche. Le langage au-dessus a fait le même genre d’erreur dans sa conception : faire confiance à des entrées auxquelles il n’avait aucune raison de faire confiance, et mettre des années à arrêter.

FonctionnalitéCe qu’elle faisaitDésactivée par défaut ou dépréciéeRetiréeDurée
register_globalstransformait les paramètres de requête en variables de scriptdésactivée en 4.2.0, 22 avril 2002285.4.0, 1er mars 201229dix ans
magic quoteséchappait les entrées automatiquement, et maldépréciées en 5.3.0, 30 juin 20095.4.0, 1er mars 201230trois ans
preg_replace /eévaluait le remplacement comme du code PHPdéprécié en 5.5.0, 20 juin 2013317.0.0, 3 décembre 201532deux ans et demi
allow_url_includelaissait include récupérer du code par le réseaudéprécié en 7.4.033
métadonnées phardésérialisées automatiquement à l’accès au fichiercorrigé en 8.034
0 == "foobar"renvoyait vraicorrigé en 8.035

register_globals mérite sa propre ligne. Pendant des années, n’importe quel paramètre de la requête, ?admin=1 par exemple, devenait une variable de votre script, et si votre code testait $admin avant de l’avoir défini, l’attaquant l’avait défini pour vous. Le manuel PHP lui-même a qualifié sa désactivation de « the most controversial change in PHP »29. Dix ans entre la désactivation par défaut et la disparition. Voilà combien de temps le projet a toléré une fonctionnalité qu’il savait dangereuse, parce que la retirer aurait cassé des sites.

Le cas phar suit le même schéma, une couche plus bas. En 2018, Sam Thomas a montré à Black Hat que de simples opérations sur un chemin phar:// désérialisaient des métadonnées fournies par l’attaquant, amenant le problème d’unserialize() jusque dans des fonctions que personne ne considérait comme dangereuses36. PHP 8.0, fin 2020, a cessé de le faire automatiquement, « to fix potential security vulnerabilities due to object instantiation, autoloading, etc. »34.

Ensuite, le type juggling. Le == de PHP convertit les types avant de comparer, si bien que des chaînes qui ressemblent à des nombres sont comparées comme des nombres. La RFC qui en a corrigé une partie dans PHP 8.0 l’a dit sans détour : « This results in many surprising comparison results, the most notable of which is that 0 == “foobar” returns true. »35

Cette correction était réelle. Elle était aussi partielle. Voici la même vérification lancée dans les conteneurs officiels php:7.4-cli et php:8.5-cli, le second étant 8.5.12, la version corrigée pour PHP2Shell cette semaine, avec les deux sorties côte à côte :

$ php -r 'var_dump(0 == "foobar");'
bool(true)            # 7.4.33
bool(false)           # 8.5.12

$ php -r 'var_dump("0e462097431906509019562988736854" == "0e830400451993494058024219903391");'
bool(true)            # 7.4.33
bool(true)            # 8.5.12

Deux chaînes différentes, égales. Les deux commencent par 0e suivi de chiffres, donc PHP lit les deux comme zéro fois dix à la puissance de quelque chose, et zéro égale zéro. Les deux ont la forme d’un hachage MD5. Comparez un hachage de mot de passe stocké avec == au lieu de === ou de hash_equals(), et n’importe quelle entrée dont le hachage commence de cette façon correspond. C’est documenté depuis des années. Cela fonctionne toujours dans la version la plus récente.

Voilà le langage en un exemple. Une correction qui est entrée, la moitié du problème laissée derrière, et la version sûre qui exige de savoir qu’un autre opérateur existe.

Un shell, presque chaque année

La question qui vaut d’être posée à n’importe quelle plateforme n’est pas combien de bugs elle a eus. C’est à quelle fréquence quelqu’un aurait pu prendre tout le serveur sans mot de passe et sans que personne ne clique sur quoi que ce soit.

NVD note chaque CVE. Filtrez les 757 sur la note qui signifie exactement cela, attaque réseau, aucun privilège, aucune interaction utilisateur, impact élevé sur la confidentialité et l’intégrité, et vous obtenez 17215.

Notes de compromission totale sans authentification par année, et exploitation confirmée par annéeNoté compromission totale à distance, sans connexion ni actionCVE de l'interpréteur PHP, CVSS réseau, sans privilèges, sans interaction, impact élevé : 172204060651997200220072012201620212026Exploitation confirmée : PHP et applications PHP dans le KEV de la CISAentrées ajoutées par année, 81 au total ; le catalogue a démarré en novembre 202116202116202210202382024112025202026
En haut : CVE de l’interpréteur notées compromission totale à distance sans connexion et sans action de l’utilisateur. En bas : PHP et applications PHP ajoutés chaque année au catalogue de la CISA des vulnérabilités connues comme exploitées.

172 réparties sur 23 des 28 années qui comptent au moins une CVE PHP. Cinq seulement sont vides. 2016 à elle seule en compte 65.

Une note de gravité est une évaluation, pas une effraction. La seconde moitié du tableau est donc le catalogue Known Exploited Vulnerabilities de la CISA, qui ne liste que des failles dont l’exploitation dans la nature est confirmée26. Sur ses 1 754 entrées au 21 octobre 2026, 81 concernent PHP lui-même ou des applications écrites en PHP :

Année d’ajoutPHP et applications PHPCatalogue entier
202116311
202216555
202310187
20248186
202511245
2026, jusqu’au 21 octobre20270

2026 est déjà la pire année pour PHP dans le catalogue, et PHP2Shell n’y figure pas encore. Trois des entrées de cette année sont dans le cœur de WordPress lui-même : deux ajoutées le 21 juillet, et une inclusion de fichier distant le 25 septembre.

Entrées KEV connues comme utilisées par des rançongicielsQuoi
CVE-2019-11043dépassement de tampon dans PHP-FPM
CVE-2024-4577injection d’arguments dans PHP-CGI
CVE-2021-3129Laravel Ignition
CVE-2018-7600, CVE-2018-7602Drupal

Et le catalogue sous-compte PHP lourdement. Il est construit autour des systèmes fédéraux américains et exige une CVE plus une exploitation confirmée. Il contient 3 entrées pour des extensions WordPress. L’écosystème des extensions WordPress a enregistré 11 334 vulnérabilités sur la seule année 202537. Les 81, c’est la part que quelqu’un d’officiel a mise par écrit.

WordPress multiplie le tout

WordPress représente 39,6 % de tous les sites web, et 58,3 % des sites dont le système de gestion de contenu peut être identifié38. PHP est le langage côté serveur de 69,3 % des sites où on peut le voir39. Quel que soit donc le dossier de PHP, WordPress l’emmène sur une très grande partie du web, puis y ajoute le sien.

Le cœur n’est pas le problème principal. Les extensions, si.

20242025
Nouvelles vulnérabilités de l’écosystème WordPress, Patchstack7 9664011 33437
Dans les extensions96 %91 %
Dans le cœur76
Non corrigées à temps pour la divulgation publique33 %46 %
Délai médian avant exploitation de masse, bugs très exploités5 heures

Wordfence, avec sa propre base, en a compté 8 223 pour 2024, une hausse de 68 % sur 2023, et a constaté « Roughly 35% of the vulnerabilities disclosed in 2024 remain unpatched in 2025 »41. Bases différentes, totaux différents, même allure.

Prenez un moment avec les chiffres de 2025. Près de la moitié des vulnérabilités n’avaient aucun correctif du développeur au moment où elles ont été rendues publiques. Et pour celles que les attaquants visent vraiment, l’écart médian entre la divulgation et l’exploitation de masse est de cinq heures. La plupart des gens ne vérifient pas les mises à jour de leurs extensions toutes les cinq heures. La plupart ne le peuvent pas.

Le modèle des extensions est le multiplicateur. La sécurité d’un site dépend de l’auteur le moins soigneux de tout ce qui y est installé, et Wordfence a constaté que « over one third of developers are unreachable or unresponsive » quand on leur signale une faille41. Patchstack a compté 1 614 extensions et thèmes retirés du dépôt en 2024 pour des problèmes de sécurité que personne n’a corrigés40. Et à cause du modèle à processus unique, chaque extension tourne avec tous les droits du site.

Les incidents forment une longue liste. Voici ceux qui ont des sources primaires derrière eux :

AnnéeQuoiAmpleur
2011TimThumb, un script d’images intégré à de nombreux thèmes, permettait aux attaquants de « upload and execute arbitrary PHP code »42« many commercial and free themes »
2014RevSlider, à l’origine de la campagne SoakSoak43« compromising over 100,000 WordPress sites »
2016Mossack Fonseca, le cabinet des Panama Papers : son site « may have been breached via a vulnerable version of Revolution Slider »44le site faisait tourner une version exploitable ; la façon dont les données sont sorties n’a jamais été établie
2017Injection de contenu via l’API REST dans WordPress 4.7.0 et 4.7.1, activée par défaut4566 000 pages défigurées indexées par Google selon Sucuri46 ; 1 893 690 selon Wordfence quatre jours plus tard47
2020WP File Manager, exécution de code sans authentification, exploitée avant qu’un correctif existe48« over 700,000 active installations »
2025SureTriggers, création de compte administrateur sans authentification49« exploitation attempts observed within hours after disclosure »

J’ai été prudent avec la ligne 2016. Wordfence a montré que le site du cabinet tournait sur une version du slider trivialement exploitable. Il n’a pas montré que c’est ainsi que les documents ont été pris, et je ne vais pas affirmer plus que ce que les preuves établissent.

Comment le malware reste

Entrer, c’est la moitié. Rester, c’est l’autre moitié, et PHP rend cela facile pour une raison qui ramène tout droit à l’image du processus unique.

L’interpréteur exécutera n’importe quel fichier .php qu’il peut atteindre. La racine web est généralement accessible en écriture au même utilisateur qui exécute le code. Donc dès qu’un attaquant a un moyen quelconque d’écrire un fichier, un formulaire de téléversement, un bug d’extension, un gestionnaire de fichiers, il peut écrire un script qui s’exécute chaque fois que quelqu’un le demande. C’est un web shell : un petit fichier, posé dans votre site, qui prend des ordres.

La CISA dit depuis des années dans quels langages ils sont surtout écrits : « The most commonly observed web shells are written in languages that are widely supported, such as PHP and ASP. »50 Les recommandations conjointes de la NSA et de l’Australian Signals Directorate les qualifient de « a long-standing, pervasive threat that continues to evade many security tools », et de difficiles à détecter parce qu’ils sont « easily modified by attackers and often employ encryption, encoding, and obfuscation »51.

Les chiffres du nettoyage montrent à quelle fréquence ils sont là :

SourceConstat
Sucuri, 2022, 43 374 sites nettoyés« 69.63% of compromised websites were found to have at least one backdoor » ; 1 188 864 portes dérobées retirées52
Sucuri, 2022« 90% of credit card skimmers were found in the form of malicious PHP code »52
Sucuri, 2023, 39 594 sites nettoyés« 49.21% of compromised websites were found with at least one website backdoor » ; WordPress 95,5 % des infections53
Wordfence, 2024« just under one million distinct sites infected with malware »41

Donc, sur l’année de nettoyage la plus récente, la moitié des sites piratés avaient encore un moyen de revenir, posé sur le disque. Restaurez la base, corrigez l’extension, et l’attaquant revient par le fichier qu’il a laissé.

Il n’y a pas de solution astucieuse à cela. Il y a la solution ennuyeuse et correcte, et la NSA l’a mise par écrit : « web applications should not have permission to write directly to a web accessible directory or modify web accessible code »51. Cette seule phrase, c’est le modèle à tiers séparés du début de cet article, dit par une agence de renseignement.

Où cela tourne malLe contrôle qui l’arrête
l’utilisateur d’exécution peut écrire le codecode appartenant à un utilisateur de déploiement distinct, en lecture seule pour l’utilisateur d’exécution
les téléversements atterrissent dans la racine webstocker les téléversements « outside of the webroot », ou sur un autre serveur54
PHP exécutera n’importe quoi dans les téléversementsaucune exécution de script pour les chemins de téléversement au niveau du serveur web, et « disable per directory configuration overrides on upload directories »54
personne ne remarque un nouveau fichiersurveillance d’intégrité des fichiers par rapport à une copie saine connue51
le compte de base de données peut tout fairemoindre privilège sur l’utilisateur de la base13

Le guide de durcissement de WordPress, pour ce qu’il vaut, ne mentionne jamais le fait d’empêcher PHP de s’exécuter dans le répertoire des téléversements11. C’est pourquoi le tableau cite l’OWASP et la NSA à la place.

Remarquez ce qui ne figure pas dans ce tableau. Les propres réglages de durcissement de PHP. Le manuel est honnête à leur sujet. disable_functions « can be circumvented and should not be considered a sufficient security measure for shared hosting environments », et open_basedir « is just an extra safety net, that is in no way comprehensive, and can therefore not be relied upon when security is needed »55. Quand la propre documentation d’un langage vous dit que ses boutons de sécurité ne sont pas des frontières de sécurité, croyez-la. La frontière doit donc venir de l’extérieur du processus.

Même php.net s’est fait cambrioler

Si l’infrastructure du projet lui-même était solide, on pourrait soutenir que le dossier s’explique par un problème difficile bien géré. Elle a été forcée deux fois.

QuandCe qui s’est passé
du 22 au 24 octobre 2013« JavaScript malware was served to a small percentage of php.net users » ; « two servers were compromised », méthode « unknown at this time »56
28 mars 2021« two malicious commits were pushed to the php-src repo » sous le nom de deux développeurs du cœur57

C’est celle de 2021 qui compte. Quelqu’un a poussé du code dans l’arbre source du langage lui-même, en se faisant passer pour les gens qui le maintiennent. Cela a été repéré. La réponse du projet mérite d’être citée parce que c’est la bonne, dite simplement : « maintaining our own git infrastructure is an unnecessary security risk », et les dépôts sont passés sur GitHub57.

Rendons à César : c’était une bonne décision, prise vite, et expliquée ouvertement. Mais regardez ce qu’elle reconnaît. Pendant des années, la source canonique d’un langage qui fait tourner l’essentiel du web a vécu sur une infrastructure auto-hébergée que le projet lui-même a jugée être un risque qu’il n’aurait pas dû porter.

La moitié du web tourne sur une version que personne ne corrige

Tout ce qui précède suppose que le site est à jour. Beaucoup ne le sont pas.

php.net prend actuellement en charge quatre branches. 8.2 ne reçoit plus que des correctifs de sécurité, jusqu’au 31 décembre 2026. 8.3, 8.4 et 8.5 sont les autres58. Tout ce qui est plus ancien est en fin de vie : 8.1 depuis le 31 décembre 2025, 8.0 depuis novembre 2023, 7.4 depuis novembre 202259.

Voici maintenant la part mesurée de ce qui tourne réellement :

Quelle part de PHP tourne sur des versions que php.net ne corrige plusVersion de PHP en service, par statut de support php.netSites PHP (W3Techs)48,3 %18,0 %33,7 %Installations WordPress34,7 %23,5 %41,8 %hors support8.2, hors support au 31 décembre 20268.3 et suivantes
Version de PHP en service, par statut de support. Sites PHP d’après les parts de version de W3Techs ; installations WordPress d’après les statistiques de wordpress.org. Les deux relevés le 23 octobre 2026.
Non supportées aujourd’huiNon supportées à partir du 1er janvier 2027
Sites PHP, W3Techs606148,3 %environ 66 %
Installations WordPress, wordpress.org6234,7 %environ 58 %

PHP 7.4 à lui seul, hors support depuis près de quatre ans, représente environ un cinquième de tous les sites PHP qui affichent leur version. La page des prérequis de WordPress demande PHP 8.3, puis dit que WordPress « also works with PHP 7.4+ », tout en notant que ces versions « have reached their official End Of Life »63. Un éditeur qui tourne encore sur une version morte est un éditeur qui a décidé de ne pas vous faire bouger.

Deux réserves honnêtes. W3Techs ne voit la version que sur les sites qui l’annoncent. Et certaines distributions Linux rétroportent des correctifs dans d’anciennes versions de PHP, si bien que « non supporté par php.net » ne veut pas toujours dire « non corrigé ». Mais PHP2Shell est le test de cela. Le projet a bien publié des correctifs source pour 7.4, 8.0 et 8.1 cette fois1, et quelqu’un doit encore les compiler, les livrer et les installer. Sur un hébergement mutualisé qui fait tourner une version dont personne n’est responsable, ce quelqu’un, c’est personne.

J’ai laissé tomber. Vous devriez envisager de partir aussi.

J’écrivais du PHP. Après Pulsant, j’ai laissé tomber le langage, à cause des problèmes qu’il causait et du travail que ces problèmes créaient. Pas un seul mauvais incident. Des années des deux mêmes causes, site après site, et le nettoyage qui retombait sur celui qui était de garde.

Je vais donc le dire clairement. Si le choix vous appartient, envisagez de le quitter. De meilleurs outils existent pour cela aujourd’hui, et Go est celui vers lequel je vous orienterais en premier.

Pas parce que c’est à la mode. Parce qu’il supprime, par défaut, l’essentiel de ce que cet article a compté :

Le site PHP habituelUn service Go
Sûreté mémoiremoteur écrit en C, 288 CVE de corruption mémoiresûr en mémoire par conception ; la NSA et la CISA le nomment toutes deux1819
Exécution du codeanalysé et recompilé à chaque requête sauf si OPcache est chargé, une extension à ajouter soi-même avant 8.5 ; puis exécuté par un interpréteur écrit en C ; un JIT depuis 8.0, désactivé par défaut6465compilé une fois, à l’avance, en code machine natif66
Servir une requêtele serveur web passe chaque requête à un interpréteurun binaire compilé répond lui-même en HTTP
Un fichier déposé dans la racine webun fichier .php s’exécute dès que quelqu’un le demanderien n’exécute un fichier du disque à cause de son chemin
Sortie HTMLecho écrit en brut ; l’échappement est une fonction dont il faut se souvenirhtml/template échappe par défaut, selon le contexte67
SQLles requêtes préparées existent dans PDO, si vous les utilisezla manière documentée passe les paramètres comme arguments68
Failles connues dans vos dépendancesvous l’apprenez par les infosgovulncheck ne signale que celles que votre code appelle vraiment69
Où vivent les élémentscode, configuration et téléversements dans une seule arborescence modifiableun binaire en lecture seule, avec la configuration et les téléversements ailleurs

Compilé compte deux fois. C’est plus rapide : les programmes Go « are compiled ahead of time to native machine code », sans machine virtuelle en dessous, et l’un des objectifs de conception affichés est « to approach the performance of C for comparable programs »66. Et c’est plus sûr, parce qu’il n’y a pas d’interpréteur sur le chemin de la requête qui analyse du code à l’exécution, ni de moteur en C aux 757 CVE entre le réseau et votre programme. PHP, laissé à lui-même, fait l’inverse. Sans OPcache, il charge, analyse et compile chaque script à chaque requête, inutilement, des milliers de fois par minute sur un site chargé. OPcache existe pour arrêter cela, « removing the need for PHP to load and parse scripts on each request »64. Mais il n’est pas actif d’emblée. Jusqu’à 8.4 incluse, c’est une extension partagée séparée que quelqu’un doit charger avec zend_extension et configurer. Seul PHP 8.5 l’intègre : « The Opcache extension is now always built into the PHP binary and is always loaded »70. La RFC du projet pour ce changement dit que « running PHP in production without OPcache is generally considered a mistake »71. W3Techs place 8.5 sur 4,5 % des sites PHP 860, donc pour presque tout ce qui tourne aujourd’hui, le remède à la compilation de chaque script à chaque requête reste un module complémentaire que quelqu’un a dû penser à ajouter. Et même chargé, ce qu’il met en cache, c’est du bytecode que l’interpréteur en C doit exécuter. Go fait la compilation une fois, avant que le programme ne voie la moindre requête.

Plus rapide et plus sûr, à condition d’être correctement codé. Cette dernière réserve, c’est tout l’objet des paragraphes qui suivent.

Le paquet de templates de Go résume sa conception en une ligne : il génère « HTML output safe against code injection », et « The escaping is contextual, so actions can appear within JavaScript, CSS, and URI contexts. »67 Son guide des bases de données est tout aussi clair : « You can avoid an SQL injection risk by providing SQL parameter values as sql package function arguments. »68 Ce sont les comportements par défaut. En PHP, ce sont des choses qu’il faut savoir aller chercher.

La ligne que je soulignerais est celle du fichier déposé. La moitié des sites piratés que Sucuri a nettoyés en 2023 avaient encore une porte dérobée sur le disque53, et cela ne marche que parce que l’interpréteur exécute n’importe quel script qu’il peut atteindre. Un service compilé ne va pas chercher de scripts. Un fichier déposé n’a rien sur quoi se brancher.

Maintenant la partie honnête, parce qu’un langage n’est pas un remède. Go est plus sûr en mémoire, pas parfaitement. Son propre modèle mémoire dit qu’une course de données sur une slice, une map ou une valeur d’interface « can in turn lead to arbitrary memory corruption »72, et Go fournit l’outil pour l’attraper. Compilez avec -race, ou lancez go test -race, et le binaire est compilé avec un détecteur qui signale une course au moment même où elle se produit. Il attrape les courses à l’exécution plutôt qu’à la compilation, et « can’t find races in code paths that are not executed », il a donc sa place dans chaque série de tests et sous une charge réaliste73. PHP n’a rien de tel. Tenir la mémoire d’une requête à l’écart de la suivante est laissé entièrement au moteur, et PHP2Shell, c’est ce moteur qui se trompe : de la mémoire libérée par une requête, lue par la suivante sur le même worker6. En dehors de cela, Go arrête la classe de corruption mémoire que cet article a comptée, et fait de la manière sûre la manière facile pour deux autres. Il n’arrête pas une vérification de connexion cassée, un test de permission manquant ou une requête construite en collant des chaînes si vous tenez à le faire. Go publie aussi ses propres avis de sécurité, via sa base de vulnérabilités69. Et un service Go lancé en root depuis un répertoire modifiable reste mal déployé.

Ce qu’il change, c’est le comportement par défaut. Le défaut de PHP, c’est un processus qui détient tout. Le défaut de Go, c’est un programme qui fait un seul travail, ce qui est la séparation du début de cet article avec l’essentiel du travail déjà fait. Si Go ne convient pas à votre équipe, Rust est l’autre porte de sortie. Les deux sont compilés à l’avance en code machine natif. Rust fonctionne « with no runtime or garbage collector »74, et le compilateur et le runtime de Go sont « implemented in Go and assembler, without C » depuis Go 1.575.

C# et Java figurent aussi sur la liste des langages sûrs en mémoire des agences18, mais ils ne sont pas une sortie du problème par lequel cet article a commencé. Chacun tourne sur une machine virtuelle écrite en C++. HotSpot, chez OpenJDK, représente « around 3000 C/C++ header and source files, comprising more than 1.2 million lines of code »76, et le ramasse-miettes et le compilateur JIT de .NET sont du code source C++ dans l’arborescence CoreCLR77. C’est la même forme que PHP : un gros moteur natif entre le réseau et votre code. Et Java charge du code dans une application en cours d’exécution, par conception. Son chargeur de classes standard existe « to load classes and resources from a search path of URLs referring to both JAR files and directories »78, et Log4Shell en a fait une exécution de code à distance : quiconque contrôlait un message de journal « can execute arbitrary code loaded from LDAP servers »79. La faille est entrée tout droit dans le catalogue de la CISA26. C’est la même porte que celle de PHP, avec plus de cérémonie devant.

Alors prenez Go ou Rust. Migrez d’abord le back end, un endpoint à la fois, et laissez le front end PHP ne détenir rien qui vaille d’être volé jusqu’à ce qu’il puisse partir lui aussi.

Si vous le déployez encore ainsi, pouvez-vous vous dire professionnel ?

Il y a assez de preuves ci-dessus pour que ce ne soit plus une opinion. Voici donc la question, posée directement. Si vous déployez encore PHP comme un seul processus qui détient le code, les identifiants et une racine web modifiable, pouvez-vous vous dire professionnel ?

Cela dépend de laquelle de trois personnes vous êtes. Et savoir laquelle n’est pas quelque chose qui vous arrive. S’assurer de savoir, c’est le métier.

Vous avez une vraie contrainte, et vous l’avez mise par écrit. Un produit dont l’activité dépend n’existe qu’en PHP. Une migration est chiffrée et dans le budget de l’an prochain. Très bien. C’est professionnel, à condition que la raison soit sur papier avec une date à côté, que l’utilisateur d’exécution ne puisse pas écrire le code, que les téléversements ne puissent pas s’exécuter, que le compte de base de données soit réduit, et que vous ayez corrigé PHP2Shell cette semaine. Vous courez un risque connu en connaissance de cause, avec les murs que vous pouvez mettre autour.

On ne vous l’a jamais dit. Personne ne vous a montré le dossier, et le tutoriel avec lequel vous avez appris mettait tout dans un seul répertoire. C’est une lacune, et tout le monde a des lacunes. Cela cesse d’être une lacune au moment où vous avez lu jusqu’ici.

Vous savez, et vous le construisez quand même. Vous avez vu les chiffres, ou assez d’entre eux. Vous savez que le mot de passe de la base est dans la racine web et que la racine web est modifiable. Vous déployez comme ça parce que c’est plus rapide, parce que le client ne paiera pas pour mieux, et parce que personne ne vous a obligé à le justifier. C’est le cas que vise cette question. La faute n’est pas la lacune dans vos connaissances. C’est de construire par-dessus une lacune que vous avez déjà vue et que vous n’êtes jamais revenu combler.

Tout le monde est passé par là. Y rester par choix, c’est la partie qui n’est pas défendable.

La porte a toujours été ouverte

Ce qui me frappe à la lecture de ce dossier, ce n’est pas que PHP ait des bugs. Tous les langages en ont. C’est à quel point peu de choses ont jamais été une surprise.

Le projet savait que register_globals était dangereux en 2002 et l’a retiré en 2012. Son manuel vous dit de ne pas faire confiance à unserialize(), ni à disable_functions, ni à open_basedir. Sa propre documentation dit qu’un script sous mod_php peut atteindre la base sans mot de passe. Les agences répètent depuis des années que le langage dans lequel il est construit est la source des deux tiers des bugs mémoire. Chaque avertissement est là, par écrit, venant des gens qui devraient savoir.

Et il a continué de gagner malgré tout, parce qu’il était bon marché. Bon marché à héberger, bon marché à apprendre, bon marché à vendre à un client qui voulait un site pour vendredi. Un répertoire, un processus, un mot de passe dans un fichier, et un site qui marchait. Son prix affiché, c’était une offre d’hébergement mutualisé. Ce qu’il coûtait n’a jamais figuré sur la facture : les nettoyages, les portes dérobées laissées sur le disque, les numéros de carte des clients siphonnés par du PHP malveillant, la fenêtre de cinq heures entre la divulgation et l’attaque.

C’est cela qui m’exaspère. Pas les bugs. La décision, prise encore et encore par des gens qui savaient, que la manière bon marché suffisait parce que personne ne vérifiait. Une norme, c’est ce que l’on tient quand personne ne vérifie. La séparation entre front end et back end, le code en lecture seule, le compte de base de données réduit : rien de tout cela n’est nouveau, rien n’est cher, et tout cela aurait fait d’un bon nombre des incidents ci-dessus rien qui vaille d’être raconté.

PHP2Shell n’est pas la fin de ce dossier. C’est seulement l’entrée de cette semaine. Le langage le corrigera, les hébergeurs déploieront la mise à jour tôt ou tard, et la part des versions remontera comme elle le fait toujours, lentement. Ce qui décide si le prochain vous coûtera, ce n’est pas PHP. C’est de savoir si vous avez construit les murs qu’il ne vous a jamais donnés, ou si vous êtes passé à quelque chose qui les fournit d’origine.


  1. PHP — News archive 2026, 21st October — « PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix two critical vulnerabilities that can allow unauthenticated remote code execution » ; « We consider the risk highest for mod_php, with a demonstrated exploit where an unauthenticated request can trigger the attack before any application code runs » ; « There are no complete mitigations, updating is the only safe choice. » ↩︎ ↩︎ ↩︎

  2. Wiz Research — PHP2Shell — 21 octobre 2026 ; « Every PHP version released in the last decade is affected by at least one of these vulnerabilities, going back to version 5.4 » ; « All of the disclosed vulnerabilities are memory-safety issues ». ↩︎

  3. AWS Security Blog — PHP2Shell exploitation prior to public disclosure in MadPot — une tentative d’exploitation enregistrée le 17 octobre 2026. ↩︎

  4. watchTowr — PHP2Shell FAQ — exploitation observée dans la nature le 21 octobre 2026. ↩︎

  5. NVD — CVE-2026-109618 — la gestion d’une erreur de manque de mémoire laisse des données de requête partiellement initialisées que le nettoyage traite comme valides ; exécution de code à distance. ↩︎

  6. NVD — CVE-2026-109619 — mémoire de requête utilisée après avoir été libérée ; exécution de code à distance ; concerne les versions depuis 5.4.0. ↩︎ ↩︎

  7. PHP manual — Installed as an Apache module — « When PHP is used as an Apache module it inherits Apache’s user permissions » ; « a malicious script could access and modify the database, even without a username and password ». ↩︎

  8. PHP manual — Apache 2.x on Unix systems — « The mod_php approach embeds PHP directly into every Apache httpd worker process. » ↩︎ ↩︎

  9. WordPress — wp-config.php — situé à la racine du répertoire WordPress, il contient les informations de connexion à la base de données. ↩︎

  10. WordPress — Changing file permissions — wp-config.php « is initially created with 644 permissions, and it’s a hazard to leave it like that ». ↩︎

  11. WordPress — Hardening WordPress — privilèges de la base de données, permissions des fichiers ; aucune consigne pour bloquer l’exécution de PHP dans les téléversements. ↩︎ ↩︎

  12. OWASP — Database Security Cheat Sheet — « The application’s backend database should be isolated from other servers » ; un segment de réseau interne dédié. ↩︎

  13. PHP manual — Database design — « Applications should never connect to the database as its owner or a superuser. » ↩︎ ↩︎

  14. PHP manual — FastCGI Process Manager — des pools qui démarrent des workers « with different uid/gid/chroot/environment ». ↩︎

  15. NVD CVE API, virtualMatchString=cpe:2.3:a:php:php — interrogée le 23 octobre 2026 : 757 CVE. Corruption mémoire comptée comme CWE-119, 120, 121, 122, 125, 129, 131, 189, 190, 191, 415, 416, 476, 680, 787, 824, 843 ou 908 : 288. Compromission totale à distance comptée comme CVSS 3.x AV:N/PR:N/UI:N/C:H/I:H, ou CVSS 2 réseau, sans authentification, impact complet sur la confidentialité et l’intégrité quand aucune note 3.x n’existe : 172. ↩︎ ↩︎

  16. Month of PHP Bugs, php-security.org, Wayback Machine — « During March 2007 old and new security vulnerabilities in the Zend Engine, the PHP core and the PHP extensions will be disclosed on a day by day basis. » ↩︎

  17. The Register — Stefan Esser interview, 7th February 2007 — fondateur du Hardened-PHP Project, venant de quitter la PHP Security Response Team : « I dislike the ways bugs are handled ». ↩︎

  18. NSA — Software Memory Safety, November 2022, Wayback Machine — « a strategic shift from programming languages that provide little or no inherent memory protection, such as C/C++, to a memory safe language when possible. » Également : « Examples of memory safe language include C#, Go, Java®, Ruby™, Rust®, and Swift®. » ↩︎ ↩︎ ↩︎

  19. CISA and partners — The Case for Memory Safe Roadmaps, December 2023 — coécrit notamment avec le NCSC britannique ; « two-thirds of reported vulnerabilities in memory unsafe programming languages still relate to memory issues. » ↩︎ ↩︎

  20. NVD — CVE-2014-8142 — use-after-free dans process_nested_data pendant unserialize. ↩︎

  21. NVD — CVE-2015-0231 — use-after-free dans unserialize qui « exists because of an incomplete fix for CVE-2014-8142 ». ↩︎

  22. NVD — CVE-2016-5771 — use-after-free dans SPL déclenché via unserialize et le ramasse-miettes. ↩︎

  23. PHP manual — unserialize — « Do not pass untrusted user input to unserialize() regardless of the options value of allowed_classes. » ↩︎

  24. NVD — CVE-2019-11043 — « in certain configurations of FPM setup it is possible to cause FPM module to write past allocated buffers … opening the possibility of remote code execution. » ↩︎

  25. PHP 7 ChangeLog — corrigé le 24 octobre 2019 dans 7.3.11, 7.2.24 et 7.1.33, bug #78599. ↩︎

  26. CISA — Known Exploited Vulnerabilities catalogue — flux JSON version 2026.10.21, 1 754 entrées ; 81 pour PHP ou des applications écrites en PHP, par éditeur et produit ; usage par des rançongiciels tel qu’enregistré dans le flux. ↩︎ ↩︎ ↩︎

  27. The PHP Foundation — PHP core security audit results, 10th April 2025 — « The audit identified 27 issues, with 17 having security implications ». ↩︎

  28. PHP 4 ChangeLog — 4.2.0, 22 avril 2002 : « register_globals defaults to ‘off’ now ». ↩︎

  29. PHP manual — Using Register Globals, Wayback Machine — « DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0 » ; « the most controversial change in PHP ». ↩︎ ↩︎

  30. PHP manual — Magic Quotes, Wayback Machine — « DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0 ». ↩︎

  31. PHP manual — Deprecated features in PHP 5.5.x, Wayback Machine — « The preg_replace() /e modifier is now deprecated. » ↩︎

  32. PHP manual — Pattern Modifiers, Wayback Machine — e « DEPRECATED in PHP 5.5.0, and REMOVED as of PHP 7.0.0. » ↩︎

  33. PHP manual — Deprecated features in PHP 7.4 — « The allow_url_include ini directive is deprecated. » ↩︎

  34. PHP manual — Backward incompatible changes in PHP 8.0 — les métadonnées phar « will no longer be automatically unserialized, to fix potential security vulnerabilities due to object instantiation, autoloading, etc. » ↩︎ ↩︎

  35. PHP RFC — Saner string to number comparisons — mise en œuvre dans PHP 8.0 ; « the most notable of which is that 0 == “foobar” returns true. » ↩︎ ↩︎

  36. Sam Thomas, Black Hat USA 2018 — It’s A PHP Unserialization Vulnerability Jim, But Not As We Know It — les opérations sur des chemins phar:// désérialisent les métadonnées. ↩︎

  37. Patchstack — State of WordPress Security in 2026 — données 2025 : 11 334 nouvelles vulnérabilités, 91 % dans les extensions, 6 dans le cœur, 46 % non corrigées à temps pour la divulgation, médiane de 5 heures avant l’exploitation de masse. ↩︎ ↩︎

  38. W3Techs — WordPress — « 58.3% of all the websites whose content management system we know. This is 39.6% of all websites. » ↩︎

  39. W3Techs — PHP — « PHP is used by 69.3% of all the websites whose server-side programming language we know. » Consulté le 23 octobre 2026. Versions majeures parmi les sites PHP : 8 à 65,3 %, 7 à 26,9 %, 5 à 7,7 %. ↩︎

  40. Patchstack — State of WordPress Security in 2025 — données 2024 : 7 966 nouvelles vulnérabilités, 96 % dans les extensions, 7 dans le cœur, 33 % non corrigées à temps pour la divulgation. ↩︎ ↩︎

  41. Wordfence — 2024 Annual WordPress Security Report — 8 223 vulnérabilités, une hausse de 68 % ; « Roughly 35% of the vulnerabilities disclosed in 2024 remain unpatched in 2025 » ; « just under one million distinct sites infected with malware ». ↩︎ ↩︎ ↩︎

  42. Mark Maunder — Zero day vulnerability in many WordPress themes, 1st August 2011 — timthumb.php intégré à « many commercial and free themes » ; les attaquants pouvaient « upload and execute arbitrary PHP code ». ↩︎

  43. Sucuri — RevSlider vulnerability leads to massive WordPress SoakSoak compromise, 15th December 2014 — « compromising over 100,000 WordPress sites ». ↩︎

  44. Wordfence — Mossack Fonseca breach, Revolution Slider possible cause, 7th April 2016, Wayback Machine — « may have been breached via a vulnerable version of Revolution Slider ». ↩︎

  45. Sucuri — Content injection vulnerability in WordPress REST API, 1st February 2017 — « allows an unauthenticated user to modify the content of any post or page » ; activée par défaut sur 4.7.0 et 4.7.1. ↩︎

  46. Sucuri — WordPress REST API vulnerability abused in defacement campaigns, 6th February 2017 — « Google alone shows 66,000+ pages compromised », pour une seule campagne. ↩︎

  47. Wordfence — Rapid growth in REST API defacements, 10th February 2017, Wayback Machine — les pages défigurées indexées par Google sont passées « from 1,496,020 to 1,893,690 » ; le décompte antérieur de Sucuri était de 66 000. ↩︎

  48. Wordfence — 700,000 WordPress users affected by zero-day in File Manager plugin, 1st September 2020, Wayback Machine — « a WordPress plugin with over 700,000 active installations ». ↩︎

  49. Patchstack — SureTriggers vulnerability exploited within 4 hours, 10th April 2025 — création d’administrateur sans authentification ; « exploitation attempts observed within hours after disclosure ». ↩︎

  50. CISA — Compromised Web Servers and Web Shells, TA15-314A — « The most commonly observed web shells are written in languages that are widely supported, such as PHP and ASP. » ↩︎

  51. NSA and ASD — Detect and Prevent Web Shell Malware, April 2020, Wayback Machine — « web applications should not have permission to write directly to a web accessible directory or modify web accessible code » ; la surveillance d’intégrité des fichiers en solution de repli. ↩︎ ↩︎ ↩︎

  52. Sucuri — 2022 Website Threat Research Report — 43 374 sites nettoyés ; 69,63 % avec au moins une porte dérobée ; 1 188 864 portes dérobées retirées ; 90 % des skimmers de cartes en PHP malveillant. ↩︎ ↩︎

  53. Sucuri — 2023 Hacked Website and Malware Threat Report — 39 594 sites nettoyés ; 49,21 % avec au moins une porte dérobée ; WordPress 95,5 % des infections. ↩︎ ↩︎

  54. OWASP — File Upload Cheat Sheet — stocker les téléversements « outside of the webroot » ; « disable per directory configuration overrides on upload directories ». ↩︎ ↩︎

  55. PHP manual — Description of core php.ini directives — disable_functions « can be circumvented » ; open_basedir « can therefore not be relied upon when security is needed ». ↩︎

  56. PHP — News archive 2013, 24th October — malware servi du 22 au 24 octobre 2013 ; deux serveurs compromis. ↩︎

  57. PHP internals — Changes to Git commit workflow, 28th March 2021 — deux commits malveillants poussés dans php-src ; le serveur git.php.net abandonné et GitHub rendu canonique. ↩︎ ↩︎

  58. PHP — Supported versions — 8.2 en correctifs de sécurité jusqu’au 31 décembre 2026 ; 8.3, 8.4 et 8.5 supportées. Consulté le 23 octobre 2026. ↩︎

  59. PHP — Unsupported branches — fin de vie de 8.1 le 31 décembre 2025, de 8.0 le 26 novembre 2023, de 7.4 le 28 novembre 2022. ↩︎

  60. W3Techs — PHP version 8 — parts des sous-versions au sein de PHP 8 ; combinées aux parts des versions majeures pour donner 48,3 % des sites PHP sur des versions non supportées. ↩︎ ↩︎

  61. W3Techs — PHP version 7 — 7.4 représente 73,4 % des sites PHP 7. ↩︎

  62. WordPress — Statistics — versions de PHP des sites WordPress qui remontent leurs données à wordpress.org ; 34,7 % en dessous de 8.2. Consulté le 23 octobre 2026. ↩︎

  63. WordPress — Requirements — « PHP version 8.3 or greater » ; fonctionne avec 7.4+, qui a « reached their official End Of Life ». ↩︎

  64. PHP manual — OPcache introduction — « OPcache improves PHP performance by storing precompiled script bytecode in shared memory, thereby removing the need for PHP to load and parse scripts on each request. » Jusqu’à PHP 8.4, une extension partagée chargée via zend_extension. ↩︎ ↩︎

  65. PHP manual — OPcache runtime configuration — opcache.jit disponible depuis PHP 8.0.0, valeur par défaut « disable ». ↩︎

  66. Go — Frequently Asked Questions — « Go programs are compiled ahead of time to native machine code » ; le runtime « does not include a virtual machine » ; « One of Go’s design goals is to approach the performance of C for comparable programs ». ↩︎ ↩︎

  67. Go — package html/template — « implements data-driven templates for generating HTML output safe against code injection » ; « The escaping is contextual, so actions can appear within JavaScript, CSS, and URI contexts. » ↩︎ ↩︎

  68. Go — Avoiding SQL injection risk — « You can avoid an SQL injection risk by providing SQL parameter values as sql package function arguments. » ↩︎ ↩︎

  69. Go — Vulnerability management — une base de vulnérabilités tenue à jour ; govulncheck « only surfaces vulnerabilities that actually affect you, based on which functions in your code are transitively calling vulnerable functions ». ↩︎ ↩︎

  70. PHP manual — Backward incompatible changes in PHP 8.5 — « The Opcache extension is now always built into the PHP binary and is always loaded. The INI directives opcache.enable and opcache.enable_cli are still honored. » ↩︎

  71. PHP RFC — Make OPcache a non-optional part of PHP — mise en œuvre dans PHP 8.5 ; « running PHP in production without OPcache is generally considered a mistake ». ↩︎

  72. Go — The Go Memory Model — les courses sur des valeurs multi-mots « can in turn lead to arbitrary memory corruption » ; ThreadSanitizer via go build -race signale les courses. ↩︎

  73. Go — Data Race Detector — lancer les tests avec go test -race ; « The race detector only finds races that happen at runtime, so it can’t find races in code paths that are not executed. » ↩︎

  74. Rust — rust-lang.org — « Rust is blazingly fast and memory-efficient: with no runtime or garbage collector ». ↩︎

  75. Go 1.5 Release Notes — « The compiler and runtime are now implemented in Go and assembler, without C. ». ↩︎

  76. OpenJDK — The HotSpot Group — « around 3000 C/C++ header and source files, comprising more than 1.2 million lines of code ». ↩︎

  77. dotnet/runtime — src/coreclr — le ramasse-miettes (gc/gc.cpp) et le JIT (jit/compiler.cpp) sont en C++. ↩︎

  78. Java SE 21 — URLClassLoader — « to load classes and resources from a search path of URLs referring to both JAR files and directories ». ↩︎

  79. NVD — CVE-2021-44228 — « An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers » ; ajoutée au KEV de la CISA le 10 décembre 2021. ↩︎