PHP2Shell zijn twee kritieke kwetsbaarheden in PHP zelf, CVE-2026-109618 en CVE-2026-109619, waarmee een niet-geauthenticeerd webverzoek code kan uitvoeren op elke PHP-installatie die webverzoeken afhandelt: PHP-FPM, Apache met mod_php, php-cgi, FrankenPHP en LiteSpeed. Beide worden in het wild uitgebuit en staan in de KEV-catalogus van CISA. De fix is PHP 8.5.12, 8.4.27, 8.3.36 of 8.2.35; PHP 8.1 en ouder krijgen geen upstream-release. Upgrade, en bouw en deploy daarna elk container-image met PHP opnieuw, inclusief oude tags die nog draaien en images die u aan klanten hebt geleverd.
De server patchen die u kent, is het makkelijke deel. Wat blootgesteld blijft, is de PHP die u vergeten bent: een runtime die in een base image is gecompileerd, een image-tag van vorig jaar die nog in productie draait, een CI-image of een product dat met een end-of-life PHP aan klanten is geleverd. Deze pagina helpt u eerst te patchen en laat dan zien hoe u de rest vindt.
Wat er gebeurde
| Datum (2026) | Gebeurtenis | Bron |
|---|---|---|
| 11 en 21 augustus | Calif meldt de twee fouten aan het PHP-project | Calif |
| 17 oktober | De eerste uitbuitingspoging die Amazon in zijn honeypots zag, vóór de bekendmaking | Amazon Threat Intelligence |
| 20 oktober | PHP kondigt een beveiligingsrelease aan voor 21 oktober, 14:00 UTC, die twee kwetsbaarheden met CVSS 4.0 9,2 verhelpt | php.net |
| 21 oktober | PHP brengt 8.5.12, 8.4.27, 8.3.36 en 8.2.35 uit en publiceert zijn advies; de CVE-records worden openbaar; NCSC-NL opent zijn repository php2shell | PHP-advies, NCSC-NL |
| 21 oktober | De officiële Docker-images php worden bijgewerkt naar de opgeloste versies | docker-library/php |
| 21 oktober | watchTowr meldt uitbuiting van beide CVE's in het wild; CISA publiceert een waarschuwing | watchTowr, CISA |
| 22 oktober | Searchlight Cyber publiceert php2shell-scanner | GitHub |
| 23 oktober | PHP adviseert session.upload_progress.enabled=0 in te stellen vanwege een afzonderlijke, onwaarschijnlijke RCE-vector, CVE-2026-115560 | php.net |
| 26 oktober | CISA voegt beide CVE's toe aan de KEV-catalogus, met 29 oktober als deadline voor Amerikaanse federale instanties | CISA KEV |
De naam PHP2Shell komt uit de analyse van Calif en wordt in de hele sector gebruikt; de adviezen van PHP zelf gebruiken hem niet. De CVE-records noemen Calif, Wiz en OpenAI als ontdekkers.
Wie getroffen is
Elke PHP die webverzoeken afhandelt. Het advies van PHP noemt PHP-FPM, Apache met mod_php, php-cgi, FrankenPHP en LiteSpeed, en noemt het risico het hoogst voor mod_php, "met een aangetoonde exploit waarbij een niet-geauthenticeerd verzoek de aanval kan starten voordat er applicatiecode draait." Omdat de fouten in PHP zelf zitten, zijn applicaties op basis van Laravel, Symfony of WordPress blootgesteld zodra de PHP eronder dat is.
| Branch | Getroffen | Opgelost in | Upstream-ondersteuning |
|---|---|---|---|
| 8.5 | vóór 8.5.12 | 8.5.12 | Actief |
| 8.4 | vóór 8.4.27 | 8.4.27 | Actief |
| 8.3 | vóór 8.3.36 | 8.3.36 | Alleen beveiligingsfixes, tot 31 december 2027 |
| 8.2 | vóór 8.2.35 | 8.2.35 | Alleen beveiligingsfixes, tot 31 december 2026 |
| 8.1, 8.0, 7.4 | alle versies, volgens Calif en watchTowr | geen release; minimale backports van de broncode in php-src | End-of-life |
| 7.3 en ouder, inclusief PHP 5 | alle versies, volgens Calif en watchTowr | geen upstream-fix | End-of-life |
De adviezen van PHP noemen alleen de ondersteunde branches. Voor oudere meldt Calif dat "het vroegste getroffen pad dat we vonden teruggaat tot PHP 5.4.0", en watchTowr noemt PHP 7 en PHP 5 getroffen zonder fix. PHP zegt dat branches 8.1 en ouder "geen updates meer krijgen van het PHP-project", maar publiceerde minimale backports van de broncode voor 7.4, 8.0 en 8.1 voor wie vanuit de broncode bouwt. Sommige distributies en commerciële leveranciers van langetermijnondersteuning leveren teruggezette fixes voor end-of-life branches; vraag het de uwe. Als u de volgende hoofdversie test: PHP 8.6.0 RC4, op dezelfde dag uitgebracht, bevat de fixes ook.
Hoe het werkt
Beide CVE's zijn geheugenveiligheidsfouten in de manier waarop PHP een verzoek opzet en weer afbreekt, onder alle applicatiecode. De CVE-records classificeren beide als use after free (CWE-416), samen met onjuiste afhandeling van uitzonderlijke omstandigheden, toegang tot een niet-geïnitialiseerde pointer, ongecontroleerde geheugentoewijzing en onjuiste initialisatie (CWE-755, CWE-824, CWE-1325, CWE-1419). In de woorden van PHP:
- CVE-2026-109618, RCE via OOM-corruptie: "de afhandeling van geheugentekort kan PHP onderbreken terwijl interne verzoekgegevens pas gedeeltelijk zijn geïnitialiseerd. Het opruimen van het verzoek kan de ongeldige gegevens dan als geldig behandelen." Een request body die zo is opgebouwd dat het geheugen opraakt terwijl PHP hem parst, kan die afbreking veroorzaken. Apache met mod_php voert het opruimen ook uit als het starten van het verzoek mislukt is; daarom werkt de aanval daar voordat er applicatiecode draait. Voor PHP-FPM zegt het advies van PHP dat analyse van de broncode erop wijst dat het vatbaar is, al is er nog geen volledige FPM-exploit aangetoond.
- CVE-2026-109619, RCE via verouderde globale toestand: "interne toestand die bij een verzoek hoort, kan blijven bestaan nadat het onderliggende geheugen is vrijgegeven. Een later verzoek dat door dezelfde worker wordt afgehandeld, kan die verouderde toestand gebruiken voordat de normale initialisatie hem reset." Er zijn twee verzoeken nodig die dezelfde worker bereiken: een dat de toestand achterlaat, bijvoorbeeld via een fatale fout, en een dat hem gebruikt. Het advies van PHP bevestigt het pad via de voortgang van sessie-uploads tegen mod_php en FPM, en het pad via backtraces van fatale fouten in PHP 8.5 tegen mod_php.
Daarom richten de tijdelijke instellingen van PHP zich op geheugenlimieten, de grootte van de request body, de voortgang van sessie-uploads en backtraces van fatale fouten: elke instelling sluit één pad naar de fouten af, niet de fouten zelf. PHP, als CNA, geeft beide een 9,2 volgens CVSS 4.0. De eigen CVSS 3.1-beoordelingen van NVD zijn 9,8 voor CVE-2026-109618 en 8,1 voor CVE-2026-109619.
Hoe u controleert of u getroffen bent
Begin met de hosts die u kent en zoek daarna naar PHP in alles wat u bouwt en levert.
Op een host of VM controleert u de versie die PHP meldt. Controleer ook de web-SAPI, want php-fpm of de Apache-module kan uit een ander pakket komen dan de opdrachtregel:
php -v
php-fpm -v
Distributiepakketten (Debian, Ubuntu, Alpine, RHEL) krijgen de fix vaak als backport zonder nieuwe upstream-versie: Ubuntu 24.04 levert de fix bijvoorbeeld als 8.3.6-0ubuntu0.24.04.13. Alleen de versie controleren is hier misleidend. Toon het geïnstalleerde pakket en vergelijk het met de opgeloste pakketversie in de security tracker van uw distributie:
dpkg -l 'php*' | grep '^ii' # Debian, Ubuntu
apk info -v | grep '^php' # Alpine
rpm -qa 'php*' # RHEL, Fedora, Rocky, Alma
In container-images. Officiële php:-images compileren PHP vanuit de broncode, dus de versie zit in het image zelf, niet in een pakketlijst van de distributie. Vraag het image direct:
docker run --rm --entrypoint php php:8.3-fpm -v
Om elk image te controleren dat u echt draait, maakt u een lijst en vraagt u elk image afzonderlijk. Voor Kubernetes:
kubectl get pods -A \
-o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' \
| sort -u \
| while read -r image; do
version=$(docker run --rm --entrypoint php "$image" -r 'echo PHP_VERSION;' 2>/dev/null)
printf '%s\t%s\n' "${version:-no php}" "$image"
done
Images die FROM debian of FROM alpine zijn gebouwd met PHP via de pakketbeheerder hebben de pakketcontrole hierboven nodig, uitgevoerd in het image.
In uw repositories zoekt u elke plek waar PHP wordt gekozen:
git grep -nE '^FROM[[:space:]]+(.*/)?php:' -- '*Dockerfile*' '*.dockerfile'
git grep -nE 'php-version|image:.*php' -- .github/workflows '*.yml' '*.yaml'
Vastgepinde tags zoals php:8.3.30-fpm blijven kwetsbaar tot iemand ze wijzigt. Zwevende tags zoals php:8.3-fpm zijn vanaf 21 oktober opnieuw gebouwd met de opgeloste versies, maar een image dat daarvoor is gebouwd, houdt de oude PHP tot u het opnieuw bouwt. De php-constraint in composer.json zegt welke versies uw code accepteert, niet welke er draait.
In CI. Build- en testjobs gebruiken vaak hun eigen PHP: een php:-servicecontainer, een setup-action met een php-version-input of een runner-image. Ze verwerken geen productieverkeer, maar ze laten zien welke images en versies uw pipeline produceert.
Blootgestelde hosts. De php2shell-scanner van Searchlight Cyber test een URL met grote multipart-verzoeken, ongeveer 29 MiB per pad. Gebruik hem alleen tegen hosts die u mag testen. De README waarschuwt voor fout-positieven bij gepatchte PHP met een lage memory_limit, en als PHP zijn versie niet prijsgeeft, kan de scanner een gepatchte server niet van een kwetsbare onderscheiden. Zie hem als aanwijzing, niet als bewijs. De repository van NCSC-NL verzamelt detectieregels en een lijst van producten die PHP meeleveren, met hun status.
Wat de scan van vandaag u niet kan vertellen. De images in uw registry vandaag scannen dekt wat u vandaag zou deployen. Het dekt niet een eerdere release die u aan een klant leverde, de oude tag die een klant nog draait, of welke van uw builds images met een kwetsbare PHP hebben geproduceerd. Daarvoor hebt u een record nodig van wat elke build erin heeft gestopt, per release. Zie zijn we getroffen? Zo beoordeelt u een nieuwe CVE over al uw builds.
Hoe u het oplost, en wat u doet als u nog niet kunt patchen
- Upgrade naar 8.5.12, 8.4.27, 8.3.36 of 8.2.35, of naar het opgeloste pakket van uw distributie. Op 8.1 of ouder stapt u over op een ondersteunde branch; de backports van PHP en builds van leveranciers zijn noodoplossingen.
- Bouw elk image opnieuw vanaf een opgeloste basis (haal het base image opnieuw op, of bouw zonder cache) en deploy opnieuw. Images die al draaien, houden hun oude PHP tot ze worden vervangen, dus herstart ook de workloads.
- Verifieer met de checklist hieronder, op de draaiende containers, niet alleen op het nieuwe image.
Als u nog niet kunt upgraden, noemt het advies van PHP maatregelen die "de blootstelling aan specifieke aanvalspaden verkleinen, maar een installatie niet veilig maken." Voor CVE-2026-109618:
- "Stel
memory_limit=-1in, bij voorkeur op een manier die applicaties niet kunnen overschrijven, zoalsphp_admin_valuein de FPM-pool of de Apache-configuratie, en controleer dat geen pool-, map- of applicatie-instelling weer een eindige limiet instelt." - "Stel voor applicaties die geen bestandsuploads nodig hebben
post_max_size = 8Min. Zijn bestandsuploads nodig, stel danpost_max_size = 32Min. Houdupload_max_filesizeonderpost_max_size." - Gebruik een geheugenlimiet van de container of cgroup als grens voor de beschikbaarheid, en vervang die niet door
RLIMIT_ASofRLIMIT_DATA, "omdat die de kwetsbare mislukte geheugentoewijzing kunnen veroorzaken."
Voor CVE-2026-109619:
- "Stel
session.upload_progress.enabled=0in en herstart elke worker. Gebruikphp.ini, een FPM-pool of serverconfiguratie die vóór het parsen van het verzoek geldt. Vertrouw niet opini_set()of FPM-.user.ini." - "Stel op PHP 8.5
fatal_error_backtraces=0in en herstart elke worker."
Controleer met welke instellingen elke worker werkelijk draait:
php-fpm -i | grep -E 'memory_limit|post_max_size|session.upload_progress.enabled'
De waarschuwing van CISA gaat verder: organisaties die niet direct kunnen updaten, of die nog PHP 8.1 of ouder draaien, "moeten op PHP gebaseerde systemen offline halen totdat ze gepatcht of geüpdatet kunnen worden." CISA adviseert ook te letten op PHP-workerprocessen die shells starten of tools downloaden.
De fix verifiëren
- Vraag de draaiende PHP, niet het image dat u wilde deployen. Voer
php-fpm -v(ofphp -v) uit in elke draaiende container en op elke host, en bevestig 8.5.12, 8.4.27, 8.3.36, 8.2.35 of nieuwer. - Vertrouw bij distributiepakketten niet alleen op de versiestring. Debian, Ubuntu, RHEL en andere distributies zetten de fix terug in de versie die ze al leveren, dus een gepatchte PHP kan nog steeds 8.3.6 melden: de fix van Ubuntu 24.04 is
8.3.6-0ubuntu0.24.04.13. Vergelijk de volledige pakketversie met de security tracker van uw distributie, of zoek de CVE in de changelog van het pakket, die hem meestal noemt. De valkuil werkt ook andersom: een scanner die alleen upstream-versienummers vergelijkt, kan een teruggezet pakket als kwetsbaar markeren. - Controleer of elke workload het opnieuw gebouwde image draait. Een tag die nu naar een opgelost image wijst, verandert niets aan een pod die het oude heeft opgehaald. Vergelijk de image-digest die elke container draait met de digest die u hebt gebouwd:
kubectl get pods -A \
-o jsonpath='{range .items[*]}{range .status.containerStatuses[*]}{.image}{"\t"}{.imageID}{"\n"}{end}{end}'
- Controleer of elke worker is herstart. PHP-FPM en Apache houden de oude code geladen tot ze herstarten; de procescontrole onder "Controleren op compromittering" toont welke hem nog draaien.
- Als u nog op de tijdelijke instellingen vertrouwt, controleer dan elke pool met het commando
php-fpm -ihierboven, en houd ze aan tot de upgrade overal is uitgevoerd. - Voer de inventarisatie opnieuw uit uit het controlegedeelte, over uw registry, CI-images en de releases die klanten draaien, niet alleen productie.
Controleren op compromittering
PHP2Shell wordt in het wild uitgebuit, en Amazon zag de eerste poging op 17 oktober 2026, vier dagen vóór de fix. Als een vanaf internet bereikbare PHP sindsdien op enig moment een getroffen versie draaide zonder de tijdelijke instellingen, controleer hem dan.
Hoe groot de blootstelling is. Shodan-bannertellingen die Mallory op 20 oktober publiceerde, gerapporteerd door CybelAngel, vonden 2,24 miljoen vanaf internet bereikbare hosts die PHP aangeven; van de ongeveer 1,5 miljoen die een versie tonen, draaien er 883.717 (59%) een branch zonder officiële fix. Dit zijn tellingen van hosts, geen bevestigd kwetsbare systemen: teruggezette pakketten kunnen oud lijken en toch gepatcht zijn, en ongeveer 740.000 hosts verbergen hun versie.
Appliances en producten die PHP meeleveren. PHP draait ook in appliances, netwerkapparatuur, beheerinterfaces en leveranciersproducten waarin u het misschien niet zelf kunt bijwerken. De inventaris van NCSC-NL volgde op 9 november 2026 968 van zulke producten: 205 opgelost, 215 kwetsbaar, 93 in onderzoek, 240 afhankelijk van de runtime en 214 niet getroffen. Controleer die producten afzonderlijk en installeer updates van leveranciers zodra ze beschikbaar zijn.
Zorg dat de fix echt draait. Op hosts en VM's draait een PHP-FPM-, php-cgi- of Apache-proces dat vóór de upgrade is gestart nog steeds de oude code. De memory map ervan toont dan het vervangen binary of libphp als verwijderd. Vergelijk ook de starttijden van processen met het tijdstip van de upgrade:
for pid in $(pgrep -f 'php-fpm|php-cgi|apache2|httpd|frankenphp'); do
grep -qE '(php|libphp)[^/]*\(deleted\)' "/proc/$pid/maps" 2>/dev/null \
&& echo "PID $pid still runs a replaced PHP"
done
ps -o pid,lstart,args -p "$(pgrep -d, -f 'php-fpm|php-cgi|apache2|httpd|frankenphp')"
Indicatoren uit primaire bronnen:
- Verzoeken: POST-verzoeken met formulier-uploads die de string
PHP_SESSION_UPLOAD_PROGRESSbevatten, die Amazon Threat Intelligence in uitbuitingspogingen zag. Amazon noemt ook bronadressen (103.216.220.92,31.223.184.166,37.19.200.5,134.209.159.64,103.114.163.188,95.217.98.37), maar merkt op dat die bij gedeelde anonimiseringsinfrastructuur horen: onderzoek een treffer, maar behandel hem niet als bewijs. - Processen en bestanden: PHP-workerprocessen die shells starten of tools downloaden (CISA, dat op 23 oktober een Sigma-detectieregel toevoegde), en onverwachte procesuitvoering of bestandswijzigingen op webservers (Amazon).
- Logs: in logs van Apache, PHP-FPM, reverse proxy's en services: waarschuwingen of core-fouten die zich herhalen voordat scripts draaien, fatale fouten en parse-fouten, en
Maximum execution time exceeded. Het advies van PHP voegt toe dat "het ontbreken van een fout in de logs geen bewijs van veiligheid is."
Wanneer u van compromittering moet uitgaan. Als u een van deze indicatoren vindt, of als een blootgestelde server een getroffen PHP zonder mitigaties draaide en uw logs uitbuiting niet kunnen uitsluiten, behandel hem dan als gecompromitteerd. PHP beschrijft de impact als remote code execution onder het account van de webworker, en dat account kan meestal de configuratie en geheimen van de applicatie lezen.
Roteer wat de worker kon lezen. Databasewachtwoorden, API-sleutels en tokens in omgevingsvariabelen en configuratiebestanden, sleutels die sessies of cookies ondertekenen (en de sessies die ermee zijn ondertekend), en alle cloudreferenties die voor de host beschikbaar zijn. Roteer nadat de host opnieuw is opgebouwd, zodat de nieuwe geheimen nooit op een gecompromitteerde machine staan.
Opnieuw opbouwen in plaats van opschonen. Vervang een gecompromitteerde host of container vanuit een bekend goed image, en neem geen bestanden over die de worker kon schrijven, zoals uploadmappen, caches of gegenereerde code. Hergebruik geen images, build-caches of artefacten die op een gecompromitteerde host zijn gemaakt.
Wat u uw klanten vertelt
Als u software levert die op PHP draait, zullen uw klanten ernaar vragen. Antwoord met versies en acties, ook voordat u elk antwoord hebt. Een antwoord dat u kunt aanpassen:
PHP2Shell (CVE-2026-109618, CVE-2026-109619) treft PHP-versies vóór 8.5.12, 8.4.27, 8.3.36 en 8.2.35, en alle oudere PHP-branches. [Product] versies [x tot y] leveren PHP [versie] mee en zijn getroffen; versie [z], uitgebracht op [datum], levert PHP [opgeloste versie] mee. Upgrade naar [z]. Als u niet direct kunt upgraden, pas dan de PHP-instellingen uit ons advies [link] toe en beperk de netwerktoegang tot de applicatie. [Product] versies [a tot b] zijn niet getroffen. We werken deze melding uiterlijk [datum] bij.
Als u nog aan het controleren bent, zeg dat dan, en zeg wanneer u antwoordt. Een eerste verklaring en sjablonen voor elke uitkomst vindt u in hoe u klanten antwoordt na een aanval op de softwareketen.
Hoe CRACI helpt
CRACI draait uw GitHub Actions-jobs en legt tijdens het bouwen vast wat elke job binnenhaalt, inclusief container-images, apt- en apk-pakketten en Composer-pakketten, en bewaart elke eerdere build met zijn SBOM. Wanneer een CVE wordt gepubliceerd, markeert de continue herbeoordeling de eerdere builds die het getroffen pakket bevatten, zodat u ziet welke releases blootgesteld waren en hoe lang, niet alleen wat de scan van vandaag vindt. Policy gates kunnen builds blokkeren die een specifieke CVE bevatten.
Eén beperking bij dit incident: PHP die in een officieel php:-image is gecompileerd, komt binnen in het image, niet als pakketdownload. CRACI legt de image-referentie vast die elke build heeft opgehaald, dus doorzoek uw builds op de php:-tags en op PHP-pakketten.
Vind elke build die een kwetsbare PHP heeft geleverd
Meer over build-records: SBOM's tijdens de build, SBOM's van Docker-images, wat containerscanning mist, de CISA KEV-catalogus en trends in CVE-publicaties. Andere incidenten: alle kwetsbaarheden.
Voor PHP-beveiliging buiten dit incident, zie onze gids over PHP-beveiliging.
Bronnen en updates
Primaire bronnen:
- PHP: beveiligingsadvies van 21 oktober 2026, informatief advies van 23 oktober 2026, GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp, ondersteunde versies
- CVE-records: CVE-2026-109618, CVE-2026-109619
- CISA: waarschuwing van 21 oktober 2026, KEV-catalogus
- NCSC-NL: repository php2shell
- NVD: CVE-2026-109618, CVE-2026-109619
- FIRST: EPSS-scores
Onderzoek en analyse:
- Calif: PHP2Shell, a tale of two PHP remote vulnerabilities
- Amazon Threat Intelligence
- watchTowr
- Akamai
- CybelAngel
- php2shell-scanner van Searchlight Cyber
Updates:
- 2026-11-11: De scores van NVD, EPSS, CWE-klassen, credits, nieuwste veilige versies en end-of-life-datums toegevoegd aan het overzichtsblok, plus PHP 8.6.0 RC4 en secties over hoe de fouten werken, het verifiëren van de fix en het controleren op compromittering.
- 2026-11-11: Eerste publicatie.