Published 21 October 2026. This page is updated as the facts change; the change log is at the end.
What You Need to Know
On 21 October 2026 the PHP project released PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619, known together as PHP2Shell. Both allow unauthenticated remote code execution: an attacker who can send one HTTP request to a PHP web server can run commands on it as the web server user, before any application code runs. The flaws are in the PHP engine itself, not in WordPress, Joomla, Magento or any plugin, so updating the application does nothing; the PHP runtime has to be updated. PHP rates both CVSS 9.2 and says all installations serving web requests are at risk, with Apache’s mod_php at the highest risk because a working exploit has been demonstrated against it in a default configuration. Details leaked a day before the scheduled fix, and Cloudflare and watchTowr both reported attack traffic on 21 October.
The Bottom Line: If you run PHP anywhere that the internet can reach, update it today. If someone else runs it for you, which is the position of most South African businesses on shared or managed hosting, ask your host in writing, today, which PHP version your site is on and when it will be patched. The configuration changes circulating online, including the widely shared
session.upload_progress.enabled=0, reduce exposure but do not make a server safe; PHP says so in its own advisory. The only fix is the update.
Key Facts
- CVSS 9.2 (v4.0), both CVEs — rated Critical by the PHP security team. Network attack, no privileges, no user interaction.
- Fixed versions: 8.5.12, 8.4.27, 8.3.36, 8.2.35 — released 21 October 2026, ahead of the 14:00 UTC schedule.
- Every release of 8.2, 8.3, 8.4 and 8.5 before those versions is affected, per PHP’s advisories. PHP 8.1, 8.0 and 7.4 are end of life, but PHP published source patches for them “given the severity”.
- Researchers say PHP 5.4 (2012) onward is affected — Wiz and Sansec both make this claim; PHP has not confirmed a lower bound. Rated PROBABLE.
- Exploitation in the wild: CONFIRMED — Cloudflare observed attack traffic against its customers before the public release, and watchTowr observed exploitation in its honeypots on 21 October. Not yet in CISA’s KEV catalogue at the time of writing.
- Pre-authentication RCE demonstrated against WordPress, Drupal and Joomla (Wiz) and Magento 2.4.9 (Calif, via Sansec).
- Over 9,800 South African internet-facing servers running PHP — MyBroadband’s Shodan figure, naming Afrihost, Xneelo, Amazon Data Services South Africa and Microsoft among the hosts. That is an exposure count, not a count of unpatched servers.
- Discovered 19 August, reported to PHP 24 August, leaked 20 October — the leak, on Hacker News, forced the release forward.
- Found with AI assistance — Wiz says frontier models did much of the work of turning a long-standing flaw into an exploit. That is the company’s own account.
The Two Vulnerabilities
CVE-2026-109618 — Remote Code Execution via Out-of-Memory Corruption
PHP exits a request with longjmp() when it runs out of memory. In some contexts that
happens while the request’s internal data is only partly initialised, and request shutdown then
treats the invalid data as valid. An attacker can push a request to the memory limit on purpose:
PHP’s advisory names multipart requests with missing content-length checks, unlimited headers
per part, and empty file controls and nested field names that generate large array structures.
PHP validated full remote code execution over HTTP against Apache mod_php with default input
and memory limits and normal prefork configurations. More workers and more traffic raise the
number of attempts needed; they do not remove the condition. Rated CONFIRMED.
CVE-2026-109619 — Remote Code Execution via Stale Global State
PHP can leave request-owned state (error, session, object and extension state) pointing at memory
after the request’s heap has been freed. A later request handled by the same worker can use
that stale state before normal initialisation resets it: a use-after-free across requests, which
PHP says yields memory disclosure and, with a crafted heap layout, full remote code execution. Two
features are the confirmed paths. Session upload progress, which is enabled by
default and needs no session_start(), can act as both the producer and the consumer of
the stale state. On PHP 8.5, fatal error backtraces store state that is not reset
after a fatal error. Any attacker-reachable fatal error, including a parse failure, an uncaught
error, an execution timeout or an out-of-memory condition, can abandon an operation before its reset
runs. Rated CONFIRMED. Wiz describes the disclosure side as application-agnostic: worker memory,
which can hold other requests’ passwords, tokens and keys, leaks without any application code
being involved.
Which Servers Are Exposed
PHP’s position is that every installation serving web requests is at risk. Its advisories differ on how much has been demonstrated per environment, and that difference matters for prioritising:
- Apache with mod_php — exploitation of both CVEs confirmed. mod_php always runs request shutdown, even after a failed startup, and Apache
php_valueand.htaccesssettings are applied before request startup, which gives CVE-2026-109619 an early consumer. Patch first. - PHP-FPM (nginx, Apache with mod_proxy_fcgi) — susceptible by source analysis for CVE-2026-109618, with no complete FPM exploit demonstrated at the time of writing. For CVE-2026-109619 the session upload progress path was validated on FPM, and the early-consumer path needs the frontend to pass
PHP_VALUEorPHP_ADMIN_VALUEparameters that trigger a diagnostic. Treat as exposed. - LiteSpeed (LSAPI, lsphp) — “likely susceptible” and a “conditional candidate”, unvalidated, per PHP. We could not find a statement from LiteSpeed by 21 October. LiteSpeed is the most common web server on South African shared hosting; do not read the absence of a demonstrated exploit as safety.
- FrankenPHP — likely susceptible to CVE-2026-109618; no early consumer established for CVE-2026-109619 in the default configuration, which PHP says does not make it immune.
- php-cgi — listed by PHP among the at-risk SAPIs.
- Command-line PHP only (cron jobs, build tools), with nothing serving HTTP — not in the scope PHP describes.
What Has Been Observed
Three independent observers have reported attack traffic. Cloudflare turned on managed WAF protections at 03:02 UTC on 21 October, about nine hours before disclosure, and says it “observed attack traffic targeting our customers” and saw attackers changing payloads to get past the rules; its CTO called the firewall changes “a stopgap only”. watchTowr reports exploitation observed through its honeypot network as of 21 October, with no attribution made public. Sansec places Cloudflare’s first report of early attacks at 07:43 UTC, before the patch existed. Against that, Huntress had not seen exploitation in its own customer base as of 10:00 ET on 21 October, Australia’s ACSC said it was not aware of active exploitation, and CISA had not added either CVE to the KEV catalogue at the time of writing. Read that as early, targeted activity rather than the mass exploitation that Sansec and others expect to follow now that the patches and write-ups are public: patch diffs are the usual starting point for mass exploitation tooling. No confirmed indicators of compromise had been published; Huntress lists them as pending.
A GitHub repository claims a proof-of-concept exploit. At the time of writing its own README says the
exploit code is “being developed and tested” and will be published “very
soon”, while a file named poc_109618.py sits in the file list, and most of the
repository is mitigation tooling including a script that asks to be run with sudo.
Do not run “quick fix” scripts from unverified repositories on production
servers. Leaked-vulnerability weeks reliably produce lures of exactly this shape. Wiz and
Calif hold working exploits and have not released them.
What to Do Now
- Find every PHP install you own. Web servers, but also appliances and vendor products that bundle PHP: hosting control panels, monitoring dashboards, intranet tools, ticketing systems, the brochure site an agency built in 2019. Huntress’s advice is the right one: inventory first, including the ones nobody manages. A PHP server with nothing but a “Hello World” page is exploitable.
- Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, and restart every worker. On Debian 13 (trixie) the fix is in
php8.4 8.4.27-1~deb13u1(DSA-6574-1). On Ubuntu, USN-8948-1 fixesphp8.1 8.1.2-1ubuntu2.28on 22.04,php8.3 8.3.6-0ubuntu0.24.04.13on 24.04, and php8.5 on 26.04 and 26.10. Debian 12 (bookworm) had no fixed php8.2 package at the time of writing; check the Debian security tracker before assumingapt upgradehas covered you. The volunteer-run Remi repository (rpms.remirepo.net), widely used on RHEL-family servers, did not have packages on 21 October: switch to distribution packages or build from source. - On PHP 8.1, 8.0 or 7.4, you have three choices. Take the LTS vendor’s backport (Ubuntu 22.04’s php8.1 above is one); build from PHP’s minimal source-backport branches for 7.4, 8.0 and 8.1 published on GitHub; or move the site to a supported version. On DirectAdmin CustomBuild and similar panels that compile PHP from source, older branches do not get distribution backports, so the third option is usually the realistic one. PHP 5 and PHP 7.0 to 7.3 have no fix from anyone.
- If someone else hosts your site, send them one email today asking: which PHP version and SAPI (mod_php, PHP-FPM or LiteSpeed) serves our site; has the PHP2Shell update been applied, and if not, when; and will you confirm in writing when it is done. DirectAdmin’s only statement by 21 October was that it would “release an update with new PHP versions as soon as they are published by the PHP developers”; we could locate no statement from cPanel or LiteSpeed. The duty to protect your customers’ data under POPIA stays with you regardless of who runs the server.
- Put the site behind a WAF while you patch. Cloudflare’s managed rules for PHP2Shell are on by default on every plan including Free; Professional and above should confirm the managed ruleset is in block mode. Restrict the origin to Cloudflare’s IP ranges, otherwise an attacker who knows the origin address bypasses the WAF entirely. Cloudflare, Sansec and PHP all describe the WAF as a stopgap, not a fix.
- Afterwards, keep
session.upload_progress.enabled=0if you do not use the feature; PHP recommends this even on patched servers.
If You Cannot Patch Today
PHP’s own words: these measures “reduce exposure to specific attack paths but do not make
an installation safe”. Several South African administrators spent 20 October rolling out
session.upload_progress.enabled=0 fleet-wide as a fix; a PHP developer’s response,
relayed in the DirectAdmin community thread, was that it “doesn’t do much”. It
blocks the confirmed session paths of CVE-2026-109619 and nothing else. Taken together, and applied
in configuration that loads before request parsing (php.ini, an FPM pool
php_admin_value, or the Apache configuration, never ini_set() or
.user.ini), with every worker restarted afterwards, the mitigations are:
- Against CVE-2026-109618: set
memory_limit=-1administratively, and check that no pool, directory or application setting puts a finite limit back; this removes the controllable memory-limit failure, but an underlying allocation failure can still reach the vulnerable path, and one request can now consume the whole server’s memory. Set a lowpost_max_size(8M if the application takes no uploads, 32M if it does) withupload_max_filesizebelow it, and enforce decoded request size, field count, multipart part count, header count and nesting depth at the web server or proxy, including for requests without a usableContent-Length. Use a container or cgroup memory limit as the availability boundary; do not useRLIMIT_ASorRLIMIT_DATA, which can themselves trigger the vulnerable path. - Against CVE-2026-109619: set
session.upload_progress.enabled=0; on PHP 8.5 also setfatal_error_backtraces=0; remove invalid or deprecated per-request settings that emit diagnostics before initialisation (hiding them witherror_reporting,display_errorsor@does not help); fix attacker-reachable fatal errors and execution timeouts; and, where performance allows, setpm.max_requests=1so a worker never handles a second request. - At the web server: if the application does not need file uploads, block
multipart/form-datarequests outright. Sansec’s rules are, for nginx,if ($http_content_type ~* "multipart/form-data") { return 403; }in every PHP server block, and for Apache,RewriteCond %{HTTP:Content-Type} multipart/form-data [NC]followed byRewriteRule ^ - [F]in every virtual host. This breaks uploads, including admin image uploads and some checkout forms; test an order after applying it. - If none of that is possible: take the site offline or make it read-only. Application maintenance modes do not help, because PHP still parses every request; stop PHP-FPM and serve a static maintenance page, or at minimum return 503 to anything other than GET and HEAD. CERT-EU’s advice for organisations that cannot patch is the same: isolate internet-facing PHP applications.
How to Tell Whether You Have Already Been Hit
There are no confirmed indicators of compromise yet, so hunt on behaviour. Successful exploitation
gives the attacker a shell as the web server user, which means the first thing to look for is
a PHP worker process spawning something it never should: php-fpm,
php-cgi, httpd, apache2 or lsphp starting
sh, bash, python, perl, curl,
wget or nc, command lines containing /dev/tcp/,
fsockopen or mkfifo, and reconnaissance such as whoami,
id or uname -a run from a web server. On Linux servers without EDR, Florian
Roth’s process-watcher in observe mode gives exactly this view. Wiz adds the request-side
signals: unusual multipart requests followed by memory-limit errors, repeated HTTP 500 responses,
unexpectedly large or malformed PHPSESSID cookies, and PHP worker churn. PHP recommends
log_errors=On, a working error_log and error_reporting=E_ALL,
and adds that a clean log does not prove safety. Preserve web server and PHP logs now, before they
rotate. If you find any of this, isolate the server, and remember that a shell as the web server
user also means the database credentials in the application’s configuration files are
compromised: rotate them.
A confirmed compromise of a server holding personal information starts the clocks this site covers every week: notification to the Information Regulator and affected data subjects under POPIA section 22, 72 hours to the SAPS under section 54 of the Cybercrimes Act for electronic communications service providers and financial institutions, and 24 hours to the Prudential Authority under Joint Standard 2 for supervised financial institutions. Decide now, in writing, what finding would count as reasonable grounds.
Timeline
- 19 August 2026 — Wiz Research finds the first bug; unauthenticated RCE confirmed against Drupal on 20 August and WordPress on 21 August.
- 24 August — reported to the PHP security team. PHP acknowledges and begins a coordinated fix on 21 September.
- 20 October, morning — a Hacker News post announces two critical PHP flaws headed for disclosure; it is removed, but screenshots circulate. watchTowr confirms the flaws are real and reproduces CVE-2026-109618. PHP posts an advance notice of a security release for 21 October, 14:00 UTC.
- 21 October, 03:02 UTC — Cloudflare’s managed WAF rules go live on all plans. Attack traffic observed against Cloudflare customers before disclosure.
- 21 October, about 13:30 UTC — PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35, ahead of schedule, and publishes the advisories. Debian publishes DSA-6574-1 for trixie; Ubuntu publishes USN-8948-1.
- 21 October — watchTowr reports exploitation observed in its honeypots. The Remi repository has no packages. This advisory published.
Sources
- PHP, Security advisory: critical remote code execution vulnerabilities (21 October 2026)
- PHP, GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618)
- PHP, GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619)
- Wiz Research, PHP2Shell: AI uncovers critical RCE vulnerabilities
- Cloudflare, Cloudflare deploys protections against php2shell vulnerability
- watchTowr, PHP RCE FAQ
- Huntress, Rapid Response: php2shell
- Sansec, PHP2Shell: Critical PHP RCE
- Debian, security tracker for CVE-2026-109618; Ubuntu, CVE-2026-109618 (USN-8948-1)
- MyBroadband, Thousands of Internet servers in South Africa at risk of being taken over (21 October 2026)
- TechCentral, Critical PHP vulnerabilities put a large part of the web at risk (21 October 2026)
- DirectAdmin community, Critical PHP updates thread
Updates
- 21 October 2026 — first published, on the day the fixed releases shipped.