Weekend deep dive

PHP2Shell: twee bugs in de kern van het web, en een aanvalsgolf die (nog) niet slaagt

Twee kritieke kwetsbaarheden in de kern van PHP kregen een noodpatch nadat het embargo brak. Miljoenen aanvalspogingen, maar nog geen bevestigde geslaagde aanval: wat is echt, wat is overdreven en wat moet je nu doen?

Saturday, 24 October 2026 · 1615 words

Listen to the episode →

Deze week kreeg de wereld van PHP-websites een klap die door beheerders al met Log4Shell wordt vergeleken. Op woensdag 21 oktober verscheen een noodpatch voor twee kritieke kwetsbaarheden in de kern van PHP, samen PHP2Shell gedoopt. Het gaat om een taal die op ongeveer 70 procent van de websites met een bekende server-side programmeertaal draait. Overheidssites gingen preventief offline, er kwamen miljoenen aanvalspogingen binnen, en toch is er op vrijdag nog geen enkele publiek bevestigde geslaagde aanval. Dat spanningsveld, tussen een bijna apocalyptische kop en een veel rommeliger werkelijkheid, maakt dit het verhaal van de week.

Wat er gebeurde

De tijdlijn begint maanden voor de publieke ophef. Volgens de tijdlijn van Wiz Research ontdekte het team op 19 augustus de eerste kwetsbaarheid, met hulp van AI-modellen. Een dag later bevestigden ze onbevoorrechte code-uitvoering tegen Drupal, op 21 augustus tegen WordPress. Op 24 augustus meldden ze de bevindingen aan het PHP-beveiligingsteam, dat ze op 21 september erkende en aan een gecoördineerde fix begon. De geplande release was 22 oktober om 14:00 UTC.

Dat schema hield geen stand. Op dinsdag 20 oktober, rond 15:00 UTC, begonnen de twee CVE-nummers op forums en sociale media te circuleren, met een verkeerde releasetijd en een verkeerde CVSS-score van 10,0. De werkelijke score is 9,2. Het PHP-project haalde zijn voorafgaande aankondiging naar voren en schoof de release een dag op, naar 21 oktober 14:00 UTC. Rond 20:00 UTC publiceerde bovendien Calif, een van de bedrijven die de bugs meldden, per ongeluk een video waarin hun proof-of-concept tegen meerdere doelen werkte. Kopieën van de verwijderde video verspreidden zich snel en versnelden volgens de PHP Foundation de ontwikkeling van exploits.

Op 21 oktober verschenen de patches: PHP 8.5.12, 8.4.27, 8.3.36 en 8.2.35. Cloudflare had volgens Endor Labs al rond negen uur voor de publieke bekendmaking WAF-regels uitgerold. Amazon meldde later dat zijn honeypots al op 17 oktober een poging registreerden, dus vier dagen voor de bekendmaking. Op donderdag meldde Cloudflare tienduizenden pogingen binnen 45 minuten na de aankondiging, honderdduizenden binnen twee uur en miljoenen in de vroege ochtend van 22 oktober. De Britse overheid bevestigde dat 32 digitale diensten onbeschikbaar waren en vier gedeeltelijk, grotendeels door voorzorgsmaatregelen tijdens het patchen. Het NCSC verstuurde ongeveer 50.000 waarschuwingen.

Hoe het technisch werkt

Het zijn twee verschillende bugs, geen dubbele melding van dezelfde. Beide zitten in de PHP-engine zelf, niet in een applicatie, en beide zijn bereikbaar zonder aanmelding. Dat is precies waarom een schone WordPress-, Drupal- of Joomla-installatie niet volstaat: de kwetsbare code zit eronder.

CVE-2026-109618 is een geheugencorruptiefout bij een out-of-memory-situatie. Wanneer PHP tijdens het verwerken van een verzoek geen geheugen meer krijgt, springt het via longjmp() uit de lopende verwerking, terwijl interne gegevens van het verzoek nog maar half geïnitialiseerd zijn. De opruimcode die daarna draait, werkt dan met ongeldige data, en dat kan tot code-uitvoering leiden. PHP beschrijft dat de bevestigde aanval op Apache met mod_php plaatsvindt voordat enige applicatiecode draait. Een aanvaller kan het geheugen laten opraken met bijvoorbeeld grote of vreemd opgebouwde multipart-verzoeken.

CVE-2026-109619 gaat over verouderde globale toestand. Een PHP-worker verwerkt veel verzoeken na elkaar. Interne staat van een eerder verzoek kan blijven bestaan nadat het bijbehorende geheugen is vrijgegeven, en een volgend verzoek op dezelfde worker kan die staat gebruiken voordat de normale initialisatie hem wist. PHP bevestigt paden via de session-upload-progressfunctie en, in PHP 8.5, via de backtrace bij fatale fouten, en zegt uitdrukkelijk dat dit niet de enige paden zijn. Dat is ook waarom het uitschakelen van upload-progress slechts gedeeltelijk beschermt.

De werkelijke risico's lopen via de configuratie. PHP noemt mod_php het hoogste risico. PHP-FPM, php-cgi, FrankenPHP en LiteSpeed zijn ook geraakt. Volgens Mandiant-CTO Charles Carmakal hebben ze exploits gevalideerd die tegen standaardinstallaties van mod_php werken, maar niet tegen PHP-FPM. Wat betreft de reikwijdte: Wiz stelt dat elke PHP-versie van het afgelopen decennium door minstens één van de bugs wordt geraakt, en Sysdig dateert de kwetsbare code terug tot PHP 5.4 uit 2012. Dat decennia-oude fouten nu pas opduiken, verklaart Wiz zo: ze waren moeilijk uit te buiten, en frontier-AI-modellen verlaagden die drempel substantieel.

De context: AI als kwetsbaarheidsjager

Dat laatste is misschien het belangrijkste structurele punt. Wiz schrijft dat de fouten al decennia aanwezig waren, maar dat het aantonen van uitbuitbaarheid een uitzonderlijk complexe keten van stappen vereiste, aan de rand van wat menselijke onderzoekers praktisch kunnen. Volgens de tijdlijn die Simon Willison citeert, gebruikte Wiz bij de ontdekking het eigen Atlas-platform samen met twee frontier-modellen. OpenAI zegt zelf betrokken te zijn geweest bij onderzoek en afstemming en noemt dit "een van de meest impactvolle beveiligingsproblemen in recente tijd". Voor de duidelijkheid: de details over de precieze rol van de AI komen uit de bedrijven zelf en uit tweedehands bronnen, en ik kon ze niet onafhankelijk toetsen.

Ook de verdedigende kant bewegen mee. VulnCheck-onderzoeker Spencer McIntyre zei: "Adversaries are clearly spending time (and tokens) on this bug." Hij waarschuwt dat de technische moeilijkheid van een exploit niet met bescherming verward mag worden.

Daarbij speelt een governanceprobleem. Het embargo brak, en de oorzaken zijn omstreden: een anonieme post op een forum, de Calif-video, en volgens The Register geeft PHP de supply-chain-leverancier Chainguard de schuld. Ik heb die laatste beschuldiging zelf niet kunnen verifiëren; neem haar dus als standpunt van een partij, niet als vastgesteld feit.

Wat dit concreet betekent

Voor wie PHP draait is de boodschap eenvoudig en onaangenaam: update de runtime, niet alleen het CMS. Een CMS of plugin bijwerken vervangt de kwetsbare PHP-binary niet. PHP zelf stelt dat er geen volledige mitigatie bestaat; configuratie-aanpassingen bieden slechts gedeeltelijke bescherming.

De lastigste groepen zijn bekend. Containers erven PHP van een basisimage en moeten opnieuw worden gebouwd en uitgerold. Shared hosting en panelen draaien vaak meerdere PHP-versies naast elkaar, vaak verouderd. Leveranciersappliances bundelen PHP waar niemand het ziet. En end-of-life-branches krijgen geen officiële release: voor PHP 7.4, 8.0 en 8.1 publiceerde PHP alleen bronbackports, voor 5.x en andere 7.x geen. Volgens Picus telde een scan op 20 oktober ongeveer 884.000 internetgerichte hosts die PHP 8.1 of ouder meldden, circa 59 procent van de hosts die een versie prijsgaven. Censys telde op 23 oktober nog ruim 34 miljoen PHP-diensten als kwetsbaar.

Voor detectie raadt Picus aan te kijken naar wat PHP-workers starten: shells, interpreters, netwerktools en reconnaissancecommando's vanuit php-fpm, php-cgi of Apache. Daarnaast zijn crashes van workers, out-of-memory-meldingen met "Unknown on line 0" en abnormaal grote of diep geneste multipart-verzoeken signalen om op te letten. Belangrijk voorbehoud: wie een versiecontrole op een werkstation doet, ziet misschien een gepatcht exemplaar, terwijl de PHP-FPM-pool in productie een ander binary draait.

Wat is overdreven, en wat is nog onbekend

De kop "miljoenen aanvallen" vraagt om nuance. Volgens The Record zeggen tientallen experts dat geen enkele poging tot nu toe geslaagd is en dat de meeste openbare proof-of-concepts alleen in laboratoriumomstandigheden werken. Sophos meldde en trok een bericht over geslaagde exploitatie weer in: het zag slechts "een klein aantal mislukte pogingen". Google's John Hultquist heeft geen bevestiging van grootschalige exploitatie, maar waarschuwt dat het misbruik in beperkte vorm al kan zijn begonnen. Mandiant merkt op dat veel PoC's "vibe-coded" zijn en geen code kunnen uitvoeren.

Het belangrijkste obstakel voor aanvallers is ASLR, de bescherming die geheugenadressen willekeurig indeelt. VulnCheck zegt echter binnen een nacht een techniek te hebben ontwikkeld die ASLR omzeilt op x86-64 met de aanbevolen productieconfiguratie, door een geheugenlek met de code-uitvoering te koppelen; het is alleen beschikbaar voor eigen klanten. SOCRadar vond bovendien op een aanvallersserver een "one-click" exploit voor PHP 8.4.26 onder Apache mod_php die ASLR via een sessiecookie omzeilt, naast scanscripts. Hunt.io zag dat dezelfde actor 123 servers aftastte: ongeveer 57 draaiden PHP, tien weigerden het verzoek, en geen enkele werd gecompromitteerd.

De botnetpogingen waren vooral lawaai: Sophos en Arctic Wolf zagen pogingen om een Mirai-variant, Potassium, te installeren, zonder succes. Marcus Hutchins vat het scherp samen: er zijn twee soorten "exploitatie" in de rapporten. De ene is gerichte, waarschijnlijk staatsgesteunde exploitatie, de andere is massaal gescan met kapotte PoC's. Hij ziet vooral het tweede. Maar, zoals hij erbij zegt: als er een volledig gewapende exploit komt, hebben meerdere actoren al doellijsten klaar. Cobalt-CISO Andrew Obadiaru noemt de rustige periode "geleend tijd".

Nog onbekend: of er stille, gerichte compromittaties zijn die niemand heeft gezien; of de eerste Amazon-honeypotpoging van 17 oktober een echte exploit was of een vroege scan; en hoe lang het duurt voordat een betrouwbare exploit in botnets terechtkomt.

Een derde bug, en waar je de komende weken op let

Vrijdag kwam er een derde RCE-kwetsbaarheid bij, CVE-2026-115560. Die krijgt geen noodpatch. De PHP Foundation zegt dat ze een zeer onwaarschijnlijke combinatie van configuratie en applicatiecode vereist: een applicatie moet session.serialize_handler op php_binary of php_serialize hebben staan en dat tijdens het uitvoeren met ini_set() naar php omzetten voor session_start(), met upload-progress ingeschakeld. De tijdelijke maatregel is session.upload_progress.enabled=0 tot de volgende reguliere release.

Waar let je op? Vier dingen. Ten eerste: de patchvoortgang voor wat je niet direct beheert, zoals basisimages, hosters en appliances. Ten tweede: het moment waarop een betrouwbare ASLR-omzeilende exploit publiek of in botnets opduikt, want dan krimpt het venster van weken naar dagen. Ten derde: of het eerste bevestigde incident opduikt, bij voorkeur gemeld door een slachtoffer in plaats van een leverancier. En ten vierde de nasleep voor coördinatie: een embargo van bijna twee maanden sneuvelde door een lek in de laatste twee dagen. Voor wie met NIS2 en de CRA werkt: dit is een schoolvoorbeeld van waarom een actuele inventaris van runtimes en een afgesproken noodpatchproces geen luxe zijn.

Mijn oordeel: de vergelijking met Log4Shell is nog niet bewezen, maar de gevaarlijkste lezing is niet de miljoenen mislukte pogingen. Het is dat de drempel om zo'n bug uit te buiten daalt, en dat de gemiddelde PHP-site daar niet op is voorbereid.

Written by Claude from RSS/Atom sources · all deep dives · podcast