{
  "slug": "php2shell-incident-response",
  "date": "2026-10-25",
  "image": "blog10.webp",
  "tags": [
    "security",
    "threat-detection",
    "ops"
  ],
  "author": {
    "en": "ManageLM Team",
    "fr": "L'équipe ManageLM",
    "de": "ManageLM-Team"
  },
  "title": {
    "en": "PHP2Shell: Patching Hundreds of Servers Before the Botnet Gets There",
    "fr": "PHP2Shell : corriger des centaines de serveurs avant que le botnet n'arrive",
    "de": "PHP2Shell: Hunderte Server patchen, bevor das Botnetz da ist"
  },
  "summary": {
    "en": "Two unauthenticated remote code execution bugs in PHP itself, the exploit in the wild the day the fix shipped, and most of the web on versions that will never get a package. Here is what the response looks like when the agent is already on every server: find the exposed hosts without touching one, check the ones that were hit, update PHP across hundreds of machines in one request, and apply the PHP project's own mitigations where no update exists. And why this is what every vulnerability looks like from now on.",
    "fr": "Deux failles d'exécution de code à distance sans authentification dans PHP lui-même, l'exploit observé dans la nature le jour de la sortie du correctif, et une bonne partie du web sur des versions qui n'auront jamais de paquet. Voici à quoi ressemble la réponse quand l'agent est déjà sur chaque serveur : trouver les hôtes exposés sans en toucher un seul, vérifier ceux qui ont été touchés, mettre à jour PHP sur des centaines de machines en une requête, et appliquer les mesures d'atténuation du projet PHP là où aucune mise à jour n'existe. Et pourquoi toutes les vulnérabilités ressembleront désormais à celle-là.",
    "de": "Zwei Lücken für unauthentifizierte Remote-Code-Ausführung in PHP selbst, der Exploit am Tag des Fixes bereits in freier Wildbahn, und ein großer Teil des Webs auf Versionen, für die nie ein Paket kommen wird. So sieht die Reaktion aus, wenn auf jedem Server schon ein Agent läuft: die exponierten Hosts finden, ohne einen einzigen anzufassen, die getroffenen prüfen, PHP auf Hunderten Maschinen mit einer Anweisung aktualisieren und dort, wo kein Update existiert, die Gegenmaßnahmen des PHP-Projekts ausrollen. Und warum ab jetzt jede Schwachstelle so aussieht."
  },
  "content": {
    "en": "<p>On Tuesday 20 October somebody posted the details of two PHP bugs on social media, two days ahead of the coordinated disclosure date. The PHP project pulled its emergency release forward to Wednesday afternoon. The same day, honeypots were logging exploitation attempts, and within a day or two there were proof-of-concept scripts on GitHub that anyone could run. The pair got a name, PHP2Shell, and a CVSS score of 9.2.</p><p>If you run PHP anywhere that answers HTTP, you have had a bad week. This post is about what the week looked like for people with an agent on every one of their servers, and why we think that difference is about to matter for every vulnerability, not just this one.</p><h3>What actually broke</h3><p>Two bugs in PHP itself, not in a framework or a plugin. Both are reachable by anyone who can send a POST request. Neither needs an account.</p><ul><li><strong>CVE-2026-109618</strong> is a memory corruption that happens when PHP runs out of memory part way through setting up a request. The bailout leaves request data half-initialised and the shutdown code treats it as if it were valid. An attacker gets there with a large upload or a flood of form fields that pushes the worker past <code>memory_limit</code>.</li><li><strong>CVE-2026-109619</strong> is a use-after-free in the session upload-progress feature, the one that has been on by default since PHP 5. Internal state outlives the request memory it points to, and a second request on the same worker gets to use it.</li></ul><p>Every SAPI that serves web requests is in scope: mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed. Fixed releases are 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and older got no release, only limited source backports that distributions are turning into packages at their own pace. PHP 7.3 and earlier get nothing. The researchers who confirmed that PHP 5 is affected too did not surprise anyone, they just reminded us how much of the web still runs on it.</p><p>Qualys published numbers from its own telemetry: 167 million PHP installations in sight, 71 percent of them on branches that reached end of life years ago, and 199,000 patched in the first twelve hours. We would not bet on the exact figures, but the shape is right.</p><div class=\"tw\"><table><thead><tr><th></th><th>CVE-2026-109618</th><th>CVE-2026-109619</th></tr></thead><tbody><tr><td>What it is</td><td>Memory corruption when PHP runs out of memory mid-request</td><td>Use-after-free in session upload progress</td></tr><tr><td>How it is reached</td><td>One oversized or field-heavy POST, mod_php being the worst case</td><td>Two requests on the same worker, multipart with <code>PHP_SESSION_UPLOAD_PROGRESS</code></td></tr><tr><td>Fixed in</td><td>8.2.35, 8.3.36, 8.4.27, 8.5.12</td><td>The same releases</td></tr><tr><td>If you cannot update</td><td><code>memory_limit = -1</code> as an admin value, tight size caps, a cgroup bound</td><td><code>session.upload_progress.enabled = 0</code>, <code>pm.max_requests = 1</code> on FPM</td></tr></tbody></table></div><h3>The timeline is the whole story</h3><p>Here is the part that should change how you plan. Leak on Tuesday. Patch on Wednesday at 14:00 UTC. Exploitation seen in the wild on Wednesday. Public exploit code shortly after. CISA's alert on Wednesday, revised on Friday with a detection rule, because by then the question was no longer who is vulnerable but who has already been hit.</p><p>That is not an unusually fast attacker. That is the normal speed now. The scanners that map the internet for PHP endpoints were running before the advisory existed. The proof of concept takes a competent person an afternoon, and it takes an agent sitting on a coding model rather less than that. Once it exists it gets handed to infrastructure that was already built to sweep address space and try one more request against every host that answers. Nobody is sitting at a keyboard on the attacking side either.</p><p>So the clock a defender is racing has moved. It used to be the quarterly patch cycle, then it was patch Tuesday, then it was \"this week\". For a bug like this one it is the same afternoon, and whatever you have not patched by the time the botnets are tuned is a host you should assume has been visited.</p><h3>What the old playbook does with that afternoon</h3><p>Be honest about how incident response for a bug like this runs in most organisations, because we have all lived it.</p><p>First, find the hosts. The CMDB says 212 servers run PHP. The real number is somewhere between 300 and 500, depending on how you count the container images, the vendor appliance with a web UI, and the box in the branch office that was supposed to be decommissioned in 2023. Second, raise the ticket, because the change process is not suspended just because it is urgent. Third, start opening SSH sessions. Debian here, Alma there, an Ubuntu 20.04 that will need a PPA, a SUSE that someone set up before they left. Every one slightly different, every one needing a human to type the command, read the result, restart the right service and check the version. A careful person does maybe ten an hour. Four hundred servers is forty hours of somebody's time, and you do not have forty somebodies at three in the afternoon on a Wednesday.</p><p>Fourth, the ones you cannot update at all. The 8.1 hosts, the application that was validated against 7.4 and nobody dares touch, the appliance. For those you need configuration changes by hand, in the right file, in the right pool, and a restart of every worker. More SSH sessions, more typing, more hours.</p><p>Meanwhile the honeypots are already logging the exploit.</p><p>None of that is incompetence. It is what happens when the unit of work is a human at a keyboard on one server at a time, and the attacker's unit of work is a request against a million servers at once.</p><h3>Hour zero: find every exposed host without opening a shell</h3><p>A ManageLM agent runs on each server and the portal already knows what is on it, because the <a href=\"features/inventory.html\">inventory scan</a> collects installed packages, running services and listening ports as a matter of routine. So the first question of the incident, which hosts run PHP behind a web server and which version, is a search, not a scan. Ask it in the portal, or ask Claude through MCP: \"which servers run php-fpm or mod_php, and which package version\". You get the list in seconds, grouped by site, and it includes the box in the branch office because the agent on it does not know it was supposed to be decommissioned.</p><p>Then the <a href=\"features/secaudit.html\">security audit</a>'s CVE check takes over. It compares what each host has installed against the advisory data on OSV.dev, using your distribution's own package versions rather than PHP's. That matters this week, because a backported fix keeps the old upstream version number and a naive <code>php -v</code> will tell you a patched Debian host is still vulnerable. Once the advisory is in the feed, every affected host carries a failing finding with the advisory id, the installed version and the fixed one, and the CISA KEV flag when it lands there. Severity follows exposure, so the internet-facing hosts sort to the top. Anything the check could not reach is reported as a gap, never as clean. Run it on \"all\" and you have the real scope of the problem in the time it takes to make coffee.</p><h3>Was anyone already inside?</h3><p>CISA's guidance for this one is blunt: look for PHP worker processes launching shells or downloading tools. That is a specific thing to look for, and it is exactly what <a href=\"features/threats.html\">Threat Detection</a> watches for on every Linux host where it is on. The rule is literally called \"Shell spawned by web server\", and php-fpm, php, apache2 and httpd are on its list. A worker that forks <code>/bin/sh</code> raises an alert within seconds, narrated by the model with a severity, delivered by email with a Kill Service button on it. Container workloads are excluded on purpose, so a legitimate build job in a container does not drown the signal.</p><p>The second indicator is a dropped file. The public exploit scripts write attacker-supplied data into a real session file on the server, and the payloads in circulation are PHP code. Virus and Malware Detection scans every file written to local disk as it lands, against the YARA Forge rule set, so a webshell dropped into the session directory or the document root is an alert with a Quarantine action next to it, with no model in the loop at all.</p><p>For the hosts that did alert, the investigation runs over the agent too. The log skill greps the access logs for the multipart POSTs carrying <code>PHP_SESSION_UPLOAD_PROGRESS</code> and the burst of <code>t[]</code> fields the exploit uses. The services skill lists what the worker spawned and what is still running. The files skill walks the session save path for anything that contains PHP code. When you would rather drive it yourself, the browser console opens a root shell on the host with no SSH key and no VPN, the assistant under it explains what the log line means, and the whole session is recorded, because this is the one you will have to show someone later.</p><p>One more thing the advisories mention and the news coverage mostly skipped: both bugs also hand an unauthenticated attacker a read of PHP worker memory, which means database passwords, API keys and tokens that happened to be in a request. If a host was hit, the credentials it held are burnt. <a href=\"features/credentials.html\">Credential Rotation</a> exists for this exact moment: rotate the database login, the application secret and the service account, deliver the new values everywhere they are used, and do it from the same portal rather than from a spreadsheet of places to go.</p><h3>Hour one: update hundreds of servers in one request</h3><p>Now the part that takes forty hours in the old playbook.</p><p>The instruction is one sentence: \"Update PHP to the fixed release on all web servers and restart PHP-FPM or Apache afterwards\". Target a group, a site, or \"all\". The portal turns that into one task per host and sends them out together, so a fleet of four hundred is four hundred tasks running in parallel, not four hundred sessions in a row. On each host the agent reads the distribution, picks apt, dnf, zypper or apk accordingly, upgrades the PHP packages, restarts the worker pool and reads the version back. The whole wave is done in about the time one of those hosts would have taken by hand.</p><p>What keeps that safe at that speed is that the agent is not a shell with a model in front of it. The package skill allows the package managers and the read-only basics, nothing else, in code, and the kernel sandbox enforces it under the process. The model can propose <code>rm -rf</code> all it likes; the command never runs. A policy ruleset on the production group can add \"never restart services between 09:00 and 18:00 without saying so\", and it applies to every task in the wave. Every host comes back with a report of what it ran and what changed, and the ones that failed are listed separately with the reason.</p><p>Then run the audit again on the same scope. The CVE finding clears host by host as the fixed package version is seen, and the ones still failing are your remaining work, which is a shorter list than it was an hour ago. If you would rather not be the one typing, the same wave can be a scheduled task, or sent from Slack, from ChatGPT, from VS Code or from Claude, because the portal is an MCP server and they all reach the same dispatch.</p><h3>The hosts you cannot update</h3><p>There will be some. PHP 8.1 and older where the distribution has not shipped a backport yet or never will, the application pinned to a version for reasons nobody wrote down, the appliance whose vendor will send a firmware update in due course.</p><p>The PHP project's position is that no configuration change is a complete fix, and it is right. But it also published the settings that close the known paths, and applying them across the fleet is the same kind of task as the update was. For the upload-progress bug, <code>session.upload_progress.enabled = 0</code>, set in php.ini or as a <code>php_admin_value</code> in the FPM pool or the Apache configuration, not with <code>ini_set()</code>, because it has to be in force before the request is parsed. For the out-of-memory bug, <code>memory_limit = -1</code> enforced administratively, with <code>post_max_size</code>, <code>upload_max_filesize</code>, <code>max_input_nesting_level</code> and <code>max_file_uploads</code> pulled down tight so size caps do the limiting instead, and a cgroup memory bound on the service as the availability backstop. On FPM, <code>pm.max_requests = 1</code> stops state surviving from one request to the next. Then restart every worker, because a setting only new workers see is not a mitigation.</p><p>The web server skill does this the way you would want a careful colleague to: read the config first, back it up, make the change, run the config test, reload only if the test passes. Every file it touches is recorded and can be reverted from the task. One instruction, one scope, every host tagged as not updatable, and a report per host saying which setting was applied where. For the ones that should not be reachable from the internet at all until a package arrives, the firewall skill closes ports 80 and 443 to everything but the proxy, in the same wave.</p><p>Those hosts stay failing in the audit, deliberately. A mitigation is not a fix and the report should not pretend otherwise. What it gives you is a list that gets shorter as packages arrive, instead of a list you have to rebuild from memory in two weeks.</p><h3>Why agents, and not simply more people</h3><p>The arithmetic is not subtle. The attacker's cost per additional target is a request. The defender's cost per additional target, in the traditional model, is a person's attention for several minutes. Any response built on that asymmetry loses as soon as the exploit is automated, and this week the exploit was automated within a day.</p><p>What an agent on every server changes is that the defender's cost per target also becomes a request. One operator with a view of the fleet does the deciding: what to look for, what to update, which hosts get mitigation instead, when to run it. The hundreds of pairs of hands the old playbook needed are the agents, already installed, already authorised locally, already inside the allowlist and the audit trail. The sysops are not replaced in the sense of being made redundant. They are replaced in the sense that the scenario stops needing hundreds of them at once, which is the only number that would have mattered on Wednesday afternoon, and the one nobody has.</p><p>It also changes who gets to be careful. In the manual version, careful means slow, and slow loses. In this version, careful is what the allowlist, the sandbox, the config test before the reload and the revert do on your behalf, at the same speed on host four hundred as on host one.</p><h3>This is what every vulnerability looks like now</h3><p>PHP2Shell is not special. It is a widely deployed component, an unauthenticated bug, a leaked advisory and automated exploitation on the same day, and that combination is going to keep happening. The agents writing exploits are only going to get better at it, and the infrastructure that sweeps the internet with them is already in place and does not sleep.</p><p>The question to ask of your own incident response is not whether you would have patched. Everyone would have patched. It is how many hours into the week the last exposed host would have been patched or fenced off, and what was running on it by then. If the honest answer involves a change board meeting on Thursday, that is the thing to fix before the next one.</p><p>ManageLM is free for up to ten agents, with everything in this post included. Put one on a web server today and run the audit. You will know in a few minutes whether PHP2Shell is still your problem. <a href=\"https://app.managelm.com/register\" target=\"_blank\">Start here</a>.</p>",
    "fr": "<p>Le mardi 20 octobre, quelqu'un a publié sur les réseaux sociaux le détail de deux failles PHP, deux jours avant la date de divulgation coordonnée. Le projet PHP a avancé sa version d'urgence au mercredi après-midi. Le jour même, des honeypots enregistraient déjà des tentatives d'exploitation, et en un jour ou deux des scripts de démonstration que n'importe qui pouvait lancer circulaient sur GitHub. Le duo a reçu un nom, PHP2Shell, et un score CVSS de 9,2.</p><p>Si vous faites tourner PHP quelque part qui répond en HTTP, vous avez passé une mauvaise semaine. Ce billet raconte à quoi cette semaine a ressemblé pour ceux qui avaient un agent sur chacun de leurs serveurs, et pourquoi nous pensons que cette différence va compter pour toutes les vulnérabilités à venir, pas seulement celle-là.</p><h3>Ce qui a vraiment cassé</h3><p>Deux failles dans PHP lui-même, pas dans un framework ni dans un plugin. Toutes deux atteignables par quiconque peut envoyer une requête POST. Aucune ne demande de compte.</p><ul><li><strong>CVE-2026-109618</strong> est une corruption mémoire qui survient quand PHP manque de mémoire en plein milieu de la préparation d'une requête. L'abandon laisse les données de la requête à moitié initialisées et le code d'arrêt les traite comme si elles étaient valides. Un attaquant y parvient avec un gros upload ou un déluge de champs de formulaire qui pousse le worker au-delà de <code>memory_limit</code>.</li><li><strong>CVE-2026-109619</strong> est un use-after-free dans la fonction de suivi de progression des uploads en session, celle qui est activée par défaut depuis PHP 5. Un état interne survit à la mémoire de requête vers laquelle il pointe, et une seconde requête sur le même worker peut s'en servir.</li></ul><p>Toutes les SAPI qui servent des requêtes web sont concernées : mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed. Les versions corrigées sont 8.5.12, 8.4.27, 8.3.36 et 8.2.35. PHP 8.1 et antérieurs n'ont pas eu de version, seulement des rétroportages partiels du code source que les distributions transforment en paquets à leur rythme. PHP 7.3 et antérieurs n'ont rien. Les chercheurs qui ont confirmé que PHP 5 était touché aussi n'ont surpris personne, ils nous ont juste rappelé quelle part du web tourne encore dessus.</p><p>Qualys a publié des chiffres tirés de sa propre télémétrie : 167 millions d'installations PHP en vue, 71 % d'entre elles sur des branches en fin de vie depuis des années, et 199 000 corrigées dans les douze premières heures. Nous ne parierions pas sur les chiffres exacts, mais la forme est la bonne.</p><div class=\"tw\"><table><thead><tr><th></th><th>CVE-2026-109618</th><th>CVE-2026-109619</th></tr></thead><tbody><tr><td>De quoi il s'agit</td><td>Corruption mémoire quand PHP manque de mémoire en cours de requête</td><td>Use-after-free dans le suivi de progression des uploads</td></tr><tr><td>Comment on y arrive</td><td>Un seul POST surdimensionné ou bourré de champs, mod_php étant le pire cas</td><td>Deux requêtes sur le même worker, en multipart avec <code>PHP_SESSION_UPLOAD_PROGRESS</code></td></tr><tr><td>Corrigé dans</td><td>8.2.35, 8.3.36, 8.4.27, 8.5.12</td><td>Les mêmes versions</td></tr><tr><td>Si la mise à jour est impossible</td><td><code>memory_limit = -1</code> en valeur administrative, plafonds de taille serrés, limite cgroup</td><td><code>session.upload_progress.enabled = 0</code>, <code>pm.max_requests = 1</code> sous FPM</td></tr></tbody></table></div><h3>La chronologie, c'est toute l'histoire</h3><p>Voici ce qui devrait changer votre façon de planifier. Fuite le mardi. Correctif le mercredi à 14 h UTC. Exploitation observée dans la nature le mercredi. Code d'exploitation public peu après. Alerte de la CISA le mercredi, révisée le vendredi avec une règle de détection, parce qu'à ce stade la question n'était plus de savoir qui était vulnérable mais qui avait déjà été touché.</p><p>Ce n'est pas un attaquant anormalement rapide. C'est la vitesse normale, désormais. Les scanners qui cartographient Internet à la recherche de points d'entrée PHP tournaient avant que l'avis n'existe. La preuve de concept prend un après-midi à une personne compétente, et sensiblement moins à un agent posé sur un modèle de code. Une fois qu'elle existe, elle est confiée à une infrastructure construite précisément pour balayer des plages d'adresses et tenter une requête de plus contre chaque hôte qui répond. Côté attaque non plus, personne n'est assis devant un clavier.</p><p>L'horloge contre laquelle court un défenseur a donc bougé. C'était le cycle de correctifs trimestriel, puis le patch Tuesday, puis « cette semaine ». Pour une faille comme celle-là, c'est le même après-midi, et tout ce que vous n'avez pas corrigé au moment où les botnets sont réglés est un hôte dont vous devez supposer qu'il a reçu de la visite.</p><h3>Ce que l'ancien manuel fait de cet après-midi</h3><p>Soyons honnêtes sur la façon dont la réponse à incident se déroule dans la plupart des organisations pour une faille de ce genre, parce que nous l'avons tous vécue.</p><p>D'abord, trouver les hôtes. La CMDB dit que 212 serveurs font tourner PHP. Le vrai chiffre se situe entre 300 et 500, selon la façon dont on compte les images de conteneurs, le boîtier du fournisseur avec son interface web, et la machine de l'agence qui devait être décommissionnée en 2023. Ensuite, ouvrir le ticket, parce que le processus de changement n'est pas suspendu sous prétexte que c'est urgent. Puis commencer à ouvrir des sessions SSH. Une Debian ici, une Alma là, une Ubuntu 20.04 qui aura besoin d'un PPA, une SUSE installée par quelqu'un parti depuis. Chacune un peu différente, chacune réclamant un humain pour taper la commande, lire le résultat, redémarrer le bon service et vérifier la version. Une personne soigneuse en fait peut-être dix par heure. Quatre cents serveurs, c'est quarante heures du temps de quelqu'un, et vous n'avez pas quarante quelqu'un à quinze heures un mercredi.</p><p>Enfin, ceux qu'on ne peut pas mettre à jour du tout. Les hôtes en 8.1, l'application validée sur 7.4 que personne n'ose toucher, le boîtier. Pour ceux-là, il faut des changements de configuration à la main, dans le bon fichier, dans le bon pool, et un redémarrage de chaque worker. Encore des sessions SSH, encore de la saisie, encore des heures.</p><p>Pendant ce temps, les honeypots enregistrent déjà l'exploit.</p><p>Rien de tout cela n'est de l'incompétence. C'est ce qui arrive quand l'unité de travail est un humain devant un clavier sur un serveur à la fois, et que l'unité de travail de l'attaquant est une requête contre un million de serveurs d'un coup.</p><h3>Heure zéro : trouver chaque hôte exposé sans ouvrir un shell</h3><p>Un agent ManageLM tourne sur chaque serveur et le portail sait déjà ce qu'il y a dessus, parce que l'<a href=\"features/inventory.html\">inventaire</a> collecte en routine les paquets installés, les services actifs et les ports en écoute. La première question de l'incident, quels hôtes font tourner PHP derrière un serveur web et dans quelle version, est donc une recherche, pas un scan. Posez-la dans le portail, ou posez-la à Claude via MCP : « quels serveurs font tourner php-fpm ou mod_php, et dans quelle version de paquet ». Vous avez la liste en quelques secondes, groupée par site, et elle inclut la machine de l'agence parce que l'agent qui est dessus ne sait pas qu'elle devait être décommissionnée.</p><p>Ensuite, le contrôle CVE de l'<a href=\"features/secaudit.html\">audit de sécurité</a> prend le relais. Il compare ce que chaque hôte a d'installé avec les données d'avis d'OSV.dev, en utilisant les versions de paquets de votre distribution plutôt que celles de PHP. Ça compte cette semaine, parce qu'un correctif rétroporté garde l'ancien numéro de version amont et qu'un <code>php -v</code> naïf vous dira qu'un hôte Debian corrigé est toujours vulnérable. Une fois l'avis dans le flux, chaque hôte touché porte un constat en échec avec l'identifiant de l'avis, la version installée et la version corrigée, plus le marqueur KEV de la CISA quand il y arrive. La sévérité suit l'exposition, donc les hôtes ouverts sur Internet remontent en tête. Tout ce que le contrôle n'a pas pu joindre est signalé comme une lacune, jamais comme sain. Lancez-le sur « all » et vous avez l'étendue réelle du problème le temps de faire un café.</p><h3>Quelqu'un était-il déjà entré ?</h3><p>La consigne de la CISA pour celle-ci est sans détour : cherchez des processus worker PHP qui lancent des shells ou téléchargent des outils. C'est une chose précise à chercher, et c'est exactement ce que la <a href=\"features/threats.html\">détection des menaces</a> surveille sur chaque hôte Linux où elle est activée. La règle s'appelle littéralement « Shell spawned by web server », et php-fpm, php, apache2 et httpd figurent sur sa liste. Un worker qui lance <code>/bin/sh</code> déclenche une alerte en quelques secondes, racontée par le modèle avec une sévérité, livrée par e-mail avec un bouton Kill Service dessus. Les charges en conteneur sont exclues volontairement, pour qu'un job de build légitime dans un conteneur ne noie pas le signal.</p><p>Le second indicateur est un fichier déposé. Les scripts d'exploitation publics écrivent des données fournies par l'attaquant dans un vrai fichier de session sur le serveur, et les charges qui circulent sont du code PHP. La détection de virus et de malwares analyse chaque fichier écrit sur le disque local au moment où il arrive, avec le jeu de règles YARA Forge, si bien qu'un webshell déposé dans le répertoire de sessions ou dans la racine web est une alerte avec une action Quarantaine à côté, sans aucun modèle dans la boucle.</p><p>Pour les hôtes qui ont bel et bien alerté, l'enquête passe elle aussi par l'agent. La compétence journaux fouille les logs d'accès à la recherche des POST multipart portant <code>PHP_SESSION_UPLOAD_PROGRESS</code> et de la rafale de champs <code>t[]</code> que l'exploit utilise. La compétence services liste ce que le worker a lancé et ce qui tourne encore. La compétence fichiers parcourt le répertoire de sauvegarde des sessions à la recherche de tout ce qui contient du code PHP. Quand vous préférez conduire vous-même, la console navigateur ouvre un shell root sur l'hôte sans clé SSH ni VPN, l'assistant en dessous explique ce que signifie la ligne de log, et toute la session est enregistrée, parce que c'est celle que vous devrez montrer à quelqu'un plus tard.</p><p>Une chose de plus que les avis mentionnent et que la presse a largement sautée : les deux failles donnent aussi à un attaquant non authentifié une lecture de la mémoire du worker PHP, c'est-à-dire des mots de passe de base de données, des clés d'API et des jetons qui se trouvaient dans une requête. Si un hôte a été touché, les identifiants qu'il détenait sont grillés. La <a href=\"features/credentials.html\">rotation des identifiants</a> existe pour ce moment précis : changer le login de la base, le secret applicatif et le compte de service, livrer les nouvelles valeurs partout où elles servent, et le faire depuis le même portail plutôt que depuis un tableur d'endroits à visiter.</p><h3>Heure un : mettre à jour des centaines de serveurs en une requête</h3><p>Voici la partie qui prend quarante heures dans l'ancien manuel.</p><p>L'instruction tient en une phrase : « Mets à jour PHP vers la version corrigée sur tous les serveurs web et redémarre PHP-FPM ou Apache ensuite ». Visez un groupe, un site, ou « all ». Le portail en fait une tâche par hôte et les envoie ensemble, si bien qu'un parc de quatre cents machines, ce sont quatre cents tâches en parallèle, pas quatre cents sessions à la file. Sur chaque hôte, l'agent lit la distribution, choisit apt, dnf, zypper ou apk en conséquence, met à niveau les paquets PHP, redémarre le pool de workers et relit la version. Toute la vague est terminée à peu près dans le temps qu'aurait pris un seul de ces hôtes à la main.</p><p>Ce qui rend ça sûr à cette vitesse, c'est que l'agent n'est pas un shell avec un modèle devant. La compétence paquets autorise les gestionnaires de paquets et les commandes de lecture de base, rien d'autre, dans le code, et le bac à sable noyau l'impose sous le processus. Le modèle peut proposer <code>rm -rf</code> tant qu'il veut ; la commande ne s'exécute jamais. Une règle de politique sur le groupe de production peut ajouter « ne jamais redémarrer de services entre 9 h et 18 h sans le dire », et elle s'applique à chaque tâche de la vague. Chaque hôte revient avec un rapport de ce qu'il a exécuté et de ce qui a changé, et ceux qui ont échoué sont listés à part avec la raison.</p><p>Puis relancez l'audit sur le même périmètre. Le constat CVE s'efface hôte par hôte à mesure que la version de paquet corrigée est vue, et ceux qui échouent encore sont ce qu'il vous reste à faire, une liste plus courte qu'une heure plus tôt. Si vous préférez ne pas être celui qui tape, la même vague peut être une tâche planifiée, ou partir de Slack, de ChatGPT, de VS Code ou de Claude, parce que le portail est un serveur MCP et que tous aboutissent au même envoi.</p><h3>Les hôtes que vous ne pouvez pas mettre à jour</h3><p>Il y en aura. PHP 8.1 et antérieurs là où la distribution n'a pas encore livré de rétroportage ou ne le fera jamais, l'application figée sur une version pour des raisons que personne n'a notées, le boîtier dont le fournisseur enverra une mise à jour de firmware en temps utile.</p><p>La position du projet PHP est qu'aucun changement de configuration n'est un correctif complet, et elle est juste. Mais il a aussi publié les réglages qui ferment les chemins connus, et les appliquer sur tout le parc est le même genre de tâche que la mise à jour. Pour la faille du suivi d'upload, <code>session.upload_progress.enabled = 0</code>, posé dans php.ini ou en <code>php_admin_value</code> dans le pool FPM ou la configuration Apache, pas avec <code>ini_set()</code>, parce qu'il doit être en vigueur avant l'analyse de la requête. Pour la faille de mémoire épuisée, <code>memory_limit = -1</code> imposé administrativement, avec <code>post_max_size</code>, <code>upload_max_filesize</code>, <code>max_input_nesting_level</code> et <code>max_file_uploads</code> resserrés pour que ce soient les plafonds de taille qui limitent, et une borne mémoire cgroup sur le service comme filet de disponibilité. Sous FPM, <code>pm.max_requests = 1</code> empêche un état de survivre d'une requête à la suivante. Puis redémarrer chaque worker, parce qu'un réglage que seuls les nouveaux workers voient n'est pas une atténuation.</p><p>La compétence serveur web fait ça comme vous l'attendriez d'un collègue soigneux : lire la configuration d'abord, la sauvegarder, faire le changement, lancer le test de configuration, recharger seulement si le test passe. Chaque fichier touché est enregistré et peut être rétabli depuis la tâche. Une instruction, un périmètre, chaque hôte marqué comme non mettable à jour, et un rapport par hôte disant quel réglage a été appliqué où. Pour ceux qui ne devraient pas du tout être joignables depuis Internet tant qu'un paquet n'arrive pas, la compétence pare-feu ferme les ports 80 et 443 à tout sauf au proxy, dans la même vague.</p><p>Ces hôtes restent en échec dans l'audit, délibérément. Une atténuation n'est pas un correctif et le rapport ne doit pas prétendre le contraire. Ce qu'il vous donne, c'est une liste qui raccourcit à mesure que les paquets arrivent, au lieu d'une liste à reconstruire de mémoire dans deux semaines.</p><h3>Pourquoi des agents, et pas simplement plus de monde</h3><p>L'arithmétique n'a rien de subtil. Le coût de l'attaquant par cible supplémentaire est une requête. Le coût du défenseur par cible supplémentaire, dans le modèle traditionnel, c'est l'attention d'une personne pendant plusieurs minutes. Toute réponse bâtie sur cette asymétrie perd dès que l'exploit est automatisé, et cette semaine l'exploit a été automatisé en un jour.</p><p>Ce qu'un agent sur chaque serveur change, c'est que le coût du défenseur par cible devient lui aussi une requête. Un opérateur avec une vue du parc prend les décisions : quoi chercher, quoi mettre à jour, quels hôtes reçoivent une atténuation à la place, quand lancer. Les centaines de paires de mains dont l'ancien manuel avait besoin, ce sont les agents, déjà installés, déjà autorisés localement, déjà dans la liste blanche et dans la piste d'audit. Les administrateurs ne sont pas remplacés au sens où ils deviendraient superflus. Ils sont remplacés au sens où le scénario cesse d'en exiger des centaines en même temps, le seul chiffre qui aurait compté ce mercredi après-midi, et celui que personne n'a.</p><p>Ça change aussi qui a le droit d'être prudent. Dans la version manuelle, prudent veut dire lent, et lent perd. Dans celle-ci, la prudence, ce sont la liste blanche, le bac à sable, le test de configuration avant rechargement et le retour arrière qui l'exercent pour vous, à la même vitesse sur le quatre-centième hôte que sur le premier.</p><h3>Voilà à quoi ressemblent toutes les vulnérabilités désormais</h3><p>PHP2Shell n'a rien d'exceptionnel. C'est un composant massivement déployé, une faille sans authentification, un avis qui fuit et une exploitation automatisée le jour même, et cette combinaison va continuer à se produire. Les agents qui écrivent des exploits ne vont que s'améliorer, et l'infrastructure qui balaie Internet avec eux est déjà en place et ne dort pas.</p><p>La question à poser à votre propre réponse à incident n'est pas de savoir si vous auriez corrigé. Tout le monde aurait corrigé. C'est à combien d'heures dans la semaine le dernier hôte exposé aurait été corrigé ou isolé, et ce qui tournait dessus à ce moment-là. Si la réponse honnête passe par une réunion du comité des changements jeudi, c'est ça qu'il faut régler avant la prochaine.</p><p>ManageLM est gratuit jusqu'à dix agents, avec tout ce qui est décrit dans ce billet. Posez-en un sur un serveur web aujourd'hui et lancez l'audit. Vous saurez en quelques minutes si PHP2Shell est encore votre problème. <a href=\"https://app.managelm.com/register\" target=\"_blank\">Commencez ici</a>.</p>",
    "de": "<p>Am Dienstag, dem 20. Oktober, hat jemand die Details zweier PHP-Lücken in sozialen Netzwerken veröffentlicht, zwei Tage vor dem abgestimmten Offenlegungstermin. Das PHP-Projekt zog sein Notfall-Release auf Mittwochnachmittag vor. Noch am selben Tag verzeichneten Honeypots Angriffsversuche, und innerhalb von ein, zwei Tagen lagen auf GitHub Proof-of-Concept-Skripte, die jeder starten konnte. Das Paar bekam einen Namen, PHP2Shell, und einen CVSS-Wert von 9,2.</p><p>Wer irgendwo PHP betreibt, das auf HTTP antwortet, hatte eine schlechte Woche. Dieser Beitrag handelt davon, wie diese Woche für Leute aussah, die auf jedem ihrer Server einen Agenten hatten, und warum wir glauben, dass dieser Unterschied künftig bei jeder Schwachstelle zählen wird, nicht nur bei dieser.</p><h3>Was tatsächlich kaputt ist</h3><p>Zwei Fehler in PHP selbst, nicht in einem Framework oder Plugin. Beide erreicht jeder, der einen POST-Request schicken kann. Keiner braucht ein Konto.</p><ul><li><strong>CVE-2026-109618</strong> ist eine Speicherkorruption, die auftritt, wenn PHP mitten im Aufbau eines Requests der Speicher ausgeht. Der Abbruch lässt die Request-Daten halb initialisiert zurück, und der Shutdown-Code behandelt sie, als wären sie gültig. Ein Angreifer kommt dorthin mit einem großen Upload oder einer Flut von Formularfeldern, die den Worker über <code>memory_limit</code> hinaustreibt.</li><li><strong>CVE-2026-109619</strong> ist ein Use-after-free in der Fortschrittsanzeige für Session-Uploads, die seit PHP 5 standardmäßig eingeschaltet ist. Interner Zustand überlebt den Request-Speicher, auf den er zeigt, und ein zweiter Request auf demselben Worker darf ihn benutzen.</li></ul><p>Betroffen ist jede SAPI, die Web-Requests bedient: mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed. Die korrigierten Versionen sind 8.5.12, 8.4.27, 8.3.36 und 8.2.35. PHP 8.1 und älter bekamen kein Release, nur begrenzte Quellcode-Backports, die die Distributionen in ihrem eigenen Tempo zu Paketen machen. PHP 7.3 und älter bekommen nichts. Dass Forscher auch PHP 5 als betroffen bestätigt haben, hat niemanden überrascht; es hat nur daran erinnert, wie viel vom Web noch darauf läuft.</p><p>Qualys hat Zahlen aus der eigenen Telemetrie veröffentlicht: 167 Millionen sichtbare PHP-Installationen, 71 Prozent davon auf Zweigen, die seit Jahren das Ende ihres Lebenszyklus erreicht haben, und 199.000 in den ersten zwölf Stunden gepatcht. Auf die genauen Zahlen würden wir nicht wetten, aber die Größenordnung stimmt.</p><div class=\"tw\"><table><thead><tr><th></th><th>CVE-2026-109618</th><th>CVE-2026-109619</th></tr></thead><tbody><tr><td>Was es ist</td><td>Speicherkorruption, wenn PHP mitten im Request der Speicher ausgeht</td><td>Use-after-free in der Upload-Fortschrittsanzeige der Session</td></tr><tr><td>Wie man hinkommt</td><td>Ein übergroßer oder feldreicher POST, mod_php als schlimmster Fall</td><td>Zwei Requests auf demselben Worker, multipart mit <code>PHP_SESSION_UPLOAD_PROGRESS</code></td></tr><tr><td>Behoben in</td><td>8.2.35, 8.3.36, 8.4.27, 8.5.12</td><td>Dieselben Releases</td></tr><tr><td>Wenn kein Update geht</td><td><code>memory_limit = -1</code> als Admin-Wert, enge Größenlimits, eine cgroup-Grenze</td><td><code>session.upload_progress.enabled = 0</code>, <code>pm.max_requests = 1</code> unter FPM</td></tr></tbody></table></div><h3>Der Zeitablauf ist die ganze Geschichte</h3><p>Hier kommt der Teil, der Ihre Planung ändern sollte. Leak am Dienstag. Patch am Mittwoch um 14:00 UTC. Ausnutzung in freier Wildbahn am Mittwoch beobachtet. Öffentlicher Exploit-Code kurz darauf. CISA-Warnung am Mittwoch, am Freitag um eine Erkennungsregel ergänzt, weil die Frage da längst nicht mehr lautete, wer verwundbar ist, sondern wer schon getroffen wurde.</p><p>Das ist kein ungewöhnlich schneller Angreifer. Das ist inzwischen das normale Tempo. Die Scanner, die das Internet nach PHP-Endpunkten kartieren, liefen, bevor es das Advisory gab. Der Proof of Concept kostet eine fähige Person einen Nachmittag, und einen Agenten auf einem Coding-Modell deutlich weniger. Sobald er existiert, wird er einer Infrastruktur übergeben, die ohnehin dafür gebaut ist, Adressräume abzugrasen und bei jedem Host, der antwortet, einen Request mehr zu versuchen. Auch auf der Angreiferseite sitzt niemand an einer Tastatur.</p><p>Die Uhr, gegen die ein Verteidiger läuft, hat sich also verschoben. Früher war es der vierteljährliche Patch-Zyklus, dann der Patch Tuesday, dann „diese Woche“. Bei einer Lücke wie dieser ist es derselbe Nachmittag, und alles, was Sie nicht gepatcht haben, bis die Botnetze eingestellt sind, ist ein Host, bei dem Sie von Besuch ausgehen sollten.</p><h3>Was das alte Drehbuch mit diesem Nachmittag anfängt</h3><p>Seien wir ehrlich, wie Incident Response bei so einer Lücke in den meisten Organisationen abläuft, denn wir haben es alle erlebt.</p><p>Erstens, die Hosts finden. Die CMDB sagt, 212 Server laufen mit PHP. Die echte Zahl liegt irgendwo zwischen 300 und 500, je nachdem, wie man Container-Images zählt, die Hersteller-Appliance mit Web-Oberfläche und die Kiste in der Zweigstelle, die 2023 abgeschaltet werden sollte. Zweitens, das Ticket aufmachen, denn der Change-Prozess ist nicht ausgesetzt, nur weil es eilt. Drittens, SSH-Sitzungen öffnen. Hier ein Debian, dort ein Alma, ein Ubuntu 20.04, das ein PPA brauchen wird, ein SUSE, das jemand vor seinem Weggang aufgesetzt hat. Jeder ein bisschen anders, jeder braucht einen Menschen, der den Befehl tippt, das Ergebnis liest, den richtigen Dienst neu startet und die Version prüft. Eine sorgfältige Person schafft vielleicht zehn pro Stunde. Vierhundert Server sind vierzig Stunden von jemandes Zeit, und vierzig Jemande haben Sie an einem Mittwoch um drei Uhr nachmittags nicht.</p><p>Viertens die, die sich gar nicht aktualisieren lassen. Die 8.1-Hosts, die Anwendung, die gegen 7.4 abgenommen wurde und die niemand anfassen will, die Appliance. Dort braucht es Konfigurationsänderungen von Hand, in der richtigen Datei, im richtigen Pool, und einen Neustart jedes Workers. Mehr SSH-Sitzungen, mehr Tipperei, mehr Stunden.</p><p>Währenddessen protokollieren die Honeypots den Exploit bereits.</p><p>Nichts davon ist Unfähigkeit. Es ist das, was passiert, wenn die Arbeitseinheit ein Mensch an einer Tastatur auf einem Server nach dem anderen ist, und die Arbeitseinheit des Angreifers ein Request gegen eine Million Server auf einmal.</p><h3>Stunde null: jeden exponierten Host finden, ohne eine Shell zu öffnen</h3><p>Auf jedem Server läuft ein ManageLM-Agent, und das Portal weiß bereits, was darauf ist, weil die <a href=\"features/inventory.html\">Inventur</a> installierte Pakete, laufende Dienste und lauschende Ports routinemäßig einsammelt. Die erste Frage des Vorfalls, welche Hosts PHP hinter einem Webserver betreiben und in welcher Version, ist also eine Suche, kein Scan. Stellen Sie sie im Portal, oder stellen Sie sie Claude über MCP: „Welche Server laufen mit php-fpm oder mod_php, und in welcher Paketversion“. Sie haben die Liste in Sekunden, nach Standort gruppiert, und die Kiste in der Zweigstelle ist dabei, weil der Agent darauf nicht weiß, dass sie abgeschaltet werden sollte.</p><p>Dann übernimmt die CVE-Prüfung des <a href=\"features/secaudit.html\">Sicherheitsaudits</a>. Sie vergleicht, was auf jedem Host installiert ist, mit den Advisory-Daten von OSV.dev, und zwar anhand der Paketversionen Ihrer Distribution, nicht anhand der PHP-Versionen. Das zählt diese Woche, weil ein zurückportierter Fix die alte Upstream-Versionsnummer behält und ein naives <code>php -v</code> Ihnen erzählt, ein gepatchter Debian-Host sei noch verwundbar. Sobald das Advisory im Feed ist, trägt jeder betroffene Host einen fehlgeschlagenen Befund mit der Advisory-Kennung, der installierten und der korrigierten Version, dazu die KEV-Markierung der CISA, sobald sie dort landet. Der Schweregrad folgt der Exposition, also sortieren sich die Hosts am Internet nach oben. Alles, was die Prüfung nicht erreichen konnte, wird als Lücke gemeldet, nie als sauber. Starten Sie sie auf „all“, und Sie kennen den tatsächlichen Umfang des Problems, bevor der Kaffee durchgelaufen ist.</p><h3>War schon jemand drin?</h3><p>Die Anleitung der CISA ist hier unverblümt: Achten Sie auf PHP-Worker-Prozesse, die Shells starten oder Werkzeuge herunterladen. Das ist etwas Konkretes, und genau darauf achtet die <a href=\"features/threats.html\">Bedrohungserkennung</a> auf jedem Linux-Host, auf dem sie eingeschaltet ist. Die Regel heißt wörtlich „Shell spawned by web server“, und php-fpm, php, apache2 und httpd stehen auf ihrer Liste. Ein Worker, der <code>/bin/sh</code> startet, löst binnen Sekunden einen Alarm aus, vom Modell mit Schweregrad eingeordnet, per E-Mail zugestellt, mit einem Kill-Service-Knopf darauf. Container-Workloads sind absichtlich ausgenommen, damit ein legitimer Build-Job im Container das Signal nicht ertränkt.</p><p>Der zweite Indikator ist eine abgelegte Datei. Die öffentlichen Exploit-Skripte schreiben vom Angreifer gelieferte Daten in eine echte Session-Datei auf dem Server, und die kursierenden Payloads sind PHP-Code. Die Viren- und Malware-Erkennung prüft jede auf eine lokale Platte geschriebene Datei beim Eintreffen gegen das YARA-Forge-Regelwerk, sodass eine Webshell im Session-Verzeichnis oder im Document Root ein Alarm mit einer Quarantäne-Aktion daneben ist, ganz ohne Modell in der Schleife.</p><p>Bei den Hosts, die tatsächlich Alarm geschlagen haben, läuft auch die Untersuchung über den Agenten. Der Log-Skill durchsucht die Access-Logs nach den multipart-POSTs mit <code>PHP_SESSION_UPLOAD_PROGRESS</code> und der Salve von <code>t[]</code>-Feldern, die der Exploit benutzt. Der Dienste-Skill listet, was der Worker gestartet hat und was noch läuft. Der Datei-Skill geht den Session-Speicherpfad nach allem durch, was PHP-Code enthält. Wenn Sie lieber selbst fahren, öffnet die Browser-Konsole eine Root-Shell auf dem Host ohne SSH-Schlüssel und ohne VPN, der Assistent darunter erklärt, was die Log-Zeile bedeutet, und die ganze Sitzung wird aufgezeichnet, denn das ist die, die Sie später jemandem zeigen müssen.</p><p>Noch etwas, das in den Advisories steht und in der Berichterstattung meist unterging: Beide Lücken geben einem unauthentifizierten Angreifer auch Lesezugriff auf den Speicher des PHP-Workers, also auf Datenbankpasswörter, API-Schlüssel und Tokens, die gerade in einem Request lagen. Wurde ein Host getroffen, sind die Zugangsdaten darauf verbrannt. Die <a href=\"features/credentials.html\">Rotation von Zugangsdaten</a> ist genau für diesen Moment da: Datenbank-Login, Anwendungsgeheimnis und Dienstkonto wechseln, die neuen Werte überallhin ausliefern, wo sie gebraucht werden, und das aus demselben Portal statt aus einer Tabelle mit abzuklappernden Stellen.</p><h3>Stunde eins: Hunderte Server mit einer Anweisung aktualisieren</h3><p>Jetzt der Teil, der im alten Drehbuch vierzig Stunden dauert.</p><p>Die Anweisung ist ein Satz: „Aktualisiere PHP auf allen Webservern auf das korrigierte Release und starte danach PHP-FPM oder Apache neu“. Ziel ist eine Gruppe, ein Standort oder „all“. Das Portal macht daraus eine Aufgabe pro Host und schickt sie zusammen los, sodass eine Flotte von vierhundert Maschinen vierhundert parallel laufende Aufgaben sind, nicht vierhundert Sitzungen hintereinander. Auf jedem Host liest der Agent die Distribution, wählt entsprechend apt, dnf, zypper oder apk, aktualisiert die PHP-Pakete, startet den Worker-Pool neu und liest die Version zurück. Die ganze Welle ist in etwa der Zeit durch, die einer dieser Hosts von Hand gebraucht hätte.</p><p>Was das bei diesem Tempo sicher hält, ist, dass der Agent keine Shell mit einem Modell davor ist. Der Paket-Skill erlaubt die Paketmanager und die lesenden Grundbefehle, sonst nichts, im Code, und die Kernel-Sandbox setzt es unter dem Prozess durch. Das Modell kann <code>rm -rf</code> vorschlagen, so oft es will; der Befehl läuft nie. Ein Richtlinien-Regelwerk auf der Produktionsgruppe kann „Dienste zwischen 9 und 18 Uhr nie ohne Ankündigung neu starten“ ergänzen, und es gilt für jede Aufgabe der Welle. Jeder Host kommt mit einem Bericht zurück, was er ausgeführt hat und was sich geändert hat, und die fehlgeschlagenen stehen gesondert mit Grund in der Liste.</p><p>Dann lassen Sie das Audit auf demselben Umfang noch einmal laufen. Der CVE-Befund erlischt Host für Host, sobald die korrigierte Paketversion gesehen wird, und die noch fehlschlagenden sind Ihre Restarbeit, eine kürzere Liste als vor einer Stunde. Wenn Sie lieber nicht selbst tippen, kann dieselbe Welle eine geplante Aufgabe sein oder aus Slack, ChatGPT, VS Code oder Claude kommen, denn das Portal ist ein MCP-Server und alle landen beim selben Versand.</p><h3>Die Hosts, die Sie nicht aktualisieren können</h3><p>Es wird welche geben. PHP 8.1 und älter, wo die Distribution noch keinen Backport geliefert hat oder nie liefern wird, die Anwendung, die aus nirgends notierten Gründen auf einer Version festgenagelt ist, die Appliance, deren Hersteller zu gegebener Zeit ein Firmware-Update schickt.</p><p>Die Position des PHP-Projekts lautet, dass keine Konfigurationsänderung ein vollständiger Fix ist, und sie stimmt. Aber es hat auch die Einstellungen veröffentlicht, die die bekannten Pfade schließen, und sie über die Flotte auszurollen ist dieselbe Art Aufgabe wie das Update. Für die Upload-Fortschritts-Lücke <code>session.upload_progress.enabled = 0</code>, gesetzt in der php.ini oder als <code>php_admin_value</code> im FPM-Pool oder in der Apache-Konfiguration, nicht per <code>ini_set()</code>, weil es gelten muss, bevor der Request geparst wird. Für die Speicherlücke <code>memory_limit = -1</code> administrativ erzwungen, mit <code>post_max_size</code>, <code>upload_max_filesize</code>, <code>max_input_nesting_level</code> und <code>max_file_uploads</code> eng gezogen, damit stattdessen Größenlimits begrenzen, und einer cgroup-Speichergrenze auf dem Dienst als Netz für die Verfügbarkeit. Unter FPM verhindert <code>pm.max_requests = 1</code>, dass Zustand von einem Request zum nächsten überlebt. Dann jeden Worker neu starten, denn eine Einstellung, die nur neue Worker sehen, ist keine Gegenmaßnahme.</p><p>Der Webserver-Skill macht das so, wie man es sich von einem sorgfältigen Kollegen wünscht: zuerst die Konfiguration lesen, sichern, ändern, den Konfigurationstest laufen lassen, nur bei bestandenem Test neu laden. Jede berührte Datei wird festgehalten und lässt sich aus der Aufgabe heraus zurücksetzen. Eine Anweisung, ein Umfang, jeder als nicht aktualisierbar markierte Host, und pro Host ein Bericht, welche Einstellung wo gesetzt wurde. Für die, die bis zum Eintreffen eines Pakets gar nicht aus dem Internet erreichbar sein sollten, schließt der Firewall-Skill in derselben Welle die Ports 80 und 443 für alles außer dem Proxy.</p><p>Diese Hosts bleiben im Audit absichtlich auf Rot. Eine Gegenmaßnahme ist kein Fix, und der Bericht sollte nichts anderes vorgeben. Was Sie bekommen, ist eine Liste, die mit jedem eintreffenden Paket kürzer wird, statt einer Liste, die Sie in zwei Wochen aus dem Gedächtnis rekonstruieren müssen.</p><h3>Warum Agenten und nicht einfach mehr Leute</h3><p>Die Rechnung ist nicht subtil. Die Kosten des Angreifers pro zusätzlichem Ziel sind ein Request. Die Kosten des Verteidigers pro zusätzlichem Ziel sind im herkömmlichen Modell die Aufmerksamkeit eines Menschen über mehrere Minuten. Jede Reaktion, die auf dieser Asymmetrie aufbaut, verliert, sobald der Exploit automatisiert ist, und diese Woche war der Exploit innerhalb eines Tages automatisiert.</p><p>Was ein Agent auf jedem Server ändert, ist, dass auch die Kosten des Verteidigers pro Ziel zu einem Request werden. Ein Operator mit Blick auf die Flotte entscheidet: wonach suchen, was aktualisieren, welche Hosts stattdessen eine Gegenmaßnahme bekommen, wann es losgeht. Die Hunderte Paar Hände, die das alte Drehbuch brauchte, sind die Agenten, schon installiert, schon lokal berechtigt, schon innerhalb von Allowlist und Audit-Trail. Die Sysops werden nicht ersetzt in dem Sinne, dass sie überflüssig würden. Sie werden ersetzt in dem Sinne, dass das Szenario nicht mehr Hunderte von ihnen auf einmal braucht, die einzige Zahl, die an diesem Mittwochnachmittag gezählt hätte, und die, die niemand hat.</p><p>Es ändert auch, wer sorgfältig sein darf. In der manuellen Fassung heißt sorgfältig langsam, und langsam verliert. In dieser Fassung erledigen Allowlist, Sandbox, Konfigurationstest vor dem Neuladen und Rücksetzung die Sorgfalt für Sie, auf Host vierhundert genauso schnell wie auf Host eins.</p><h3>So sieht jetzt jede Schwachstelle aus</h3><p>PHP2Shell ist nichts Besonderes. Es ist eine weit verbreitete Komponente, eine Lücke ohne Authentifizierung, ein geleaktes Advisory und automatisierte Ausnutzung am selben Tag, und diese Kombination wird sich wiederholen. Die Agenten, die Exploits schreiben, werden darin nur besser, und die Infrastruktur, die das Internet mit ihnen abgrast, steht bereits und schläft nicht.</p><p>Die Frage an Ihre eigene Incident Response ist nicht, ob Sie gepatcht hätten. Jeder hätte gepatcht. Sie lautet, in welcher Stunde der Woche der letzte exponierte Host gepatcht oder abgeriegelt gewesen wäre, und was bis dahin darauf lief. Wenn die ehrliche Antwort eine Change-Board-Sitzung am Donnerstag enthält, dann ist das, was vor der nächsten Lücke zu ändern ist.</p><p>ManageLM ist für bis zu zehn Agenten kostenlos, mit allem, was in diesem Beitrag steht. Setzen Sie heute einen auf einen Webserver und starten Sie das Audit. In ein paar Minuten wissen Sie, ob PHP2Shell noch Ihr Problem ist. <a href=\"https://app.managelm.com/register\" target=\"_blank\">Hier geht es los</a>.</p>"
  }
}
