How to Patch PHP2Shell (CVE-2026-109618 and CVE-2026-109619) Today
Two critical PHP flaws let an unauthenticated attacker reach remote code execution. Here is the patch order, the stopgap settings, and the checks to run afterward.
On this page 8 sections
To patch php2shell, upgrade to PHP 8.5.12, 8.4.27, 8.3.36, or 8.2.35, restart every PHP worker, and confirm the running version. If you cannot patch yet, set memory_limit to -1 and disable session upload progress as stopgaps. Both flaws are rated CVSS 9.2 and can be exploited without logging in.
Backtrace covers the tools and tradeoffs engineers deal with in production, and this is one of those weeks. The PHP project shipped an out-of-cycle security release on October 21, 2026, and attackers moved before many teams had finished reading the notice. This guide is for engineers and on-call admins who run PHP anywhere, including inside appliances and control panels.
What Are CVE-2026-109618 and CVE-2026-109619?
They are two memory-safety bugs in PHP's request handling, nicknamed php2shell by researchers. PHP rates both 9.2 on CVSS v4.0, and an unauthenticated remote attacker can trigger either one. Together they open a path from a single web request to code execution on the server.
The first bug, CVE-2026-109618, is an out-of-memory flaw. When memory runs out while PHP's internal request data is only partly set up, later cleanup can treat that half-built data as valid. The second, CVE-2026-109619, is a use-after-free. Leftover state from one request points at freed memory, and a later request on the same worker can use it. PHP lists memory disclosure as a confirmed impact, according to Tenable's php2shell FAQ.
Exposure is wide. Every install that serves web requests is in scope, including PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, and LiteSpeed. PHP considers mod_php the highest risk because a demonstrated exploit can run before any application code. Researchers at Calif reported pre-authentication code execution against specific versions of WordPress, Drupal, Joomla, and Magento.
Which PHP Versions Are Affected and Fixed?
The earliest affected code path traces back to PHP 5.4.0, so almost every PHP server in the wild is affected. Only the four supported branches receive official fixes. Everything older either gets a source backport or nothing at all.
This table shows where each branch stands as of October 22, 2026.
| Branch | Fixed release | What to do |
|---|---|---|
| PHP 8.5 | 8.5.12 | Upgrade and restart workers |
| PHP 8.4 | 8.4.27 | Upgrade and restart workers |
| PHP 8.3 | 8.3.36 | Upgrade and restart workers |
| PHP 8.2 | 8.2.35 | Upgrade and restart workers |
| PHP 7.4 to 8.1 | No official release | Apply the source backport or upgrade |
| PHP 5.4 to 7.3 | None | Upgrade, isolate, or take offline |
The scale of the old-version problem is large. The Hacker News reported that Mallory counted about 884,000 internet-facing hosts with banners showing PHP 8.1 or older on October 20. That is roughly 59 percent of the 1.5 million hosts that reported any version. Those are banner counts, not confirmed vulnerable systems, but they show how many teams face an upgrade rather than a quick package bump.
How Do You Patch PHP2Shell Step by Step?
Patch internet-facing systems first, confirm the running version on each one, and restart every worker. Then work inward to internal tools. The order matters because exploit attempts started before disclosure, so public-facing hosts are the most likely targets.
Follow these steps in order.
- Inventory every PHP install. Include PHP bundled inside appliances, Windows software, and control panels such as cPanel and Plesk. A good software bill of materials makes this faster, and our SBOM generation how-to shows how to build one without slowing releases.
- Check your distro or host. Many providers backport the fix into their own package version, so a version string that looks old may already be patched. Read the changelog before you assume.
- Install the patched package on internet-facing hosts first, then everything else.
- Restart or reload PHP-FPM, Apache, and any other PHP worker. Old processes keep running vulnerable code until they restart.
- Verify. Run php -v for the CLI, and check the version the web server actually reports, since the two can differ.
Containers need one extra step. Rebuilding the image is not enough if the old tag is still running somewhere. Pull the new image, redeploy, and confirm no pod or task still uses the old digest. Teams that already follow a tight blue-green or canary rollout can push this out with little risk.
What If You Cannot Patch Today?
Use the documented stopgaps and shrink exposure. These settings reduce the attack surface but do not close the flaws. PHP is clear that updating is the only complete fix.
For CVE-2026-109618, set memory_limit to -1 in a way applications cannot override. For CVE-2026-109619, set session.upload_progress.enabled to 0, and on PHP 8.5 also set fatal_error_backtraces to 0. Restart all PHP workers after you change either setting. A container or cgroup memory limit can act as an availability boundary, but it is not a mitigation.
Then cut the blast radius. CERT-EU advises isolating internet-facing applications from public networks until a fix is applied and verified. For end-of-life systems, the realistic options are to upgrade, take the host offline, or put it behind a VPN or a web application firewall. Cloudflare has shipped WAF rules for known vectors, but they only cover traffic that passes through Cloudflare.
Limit what a compromised worker can reach. If the PHP process can read cloud credentials or deploy keys, an attacker gets them too. The principles in our least privilege guide for cloud teams apply directly: scope the instance role, remove unused keys, and keep secrets out of environment files the web user can read.
How Do You Check Whether You Were Already Hit?
Look for PHP processes doing things PHP should never do. Watch for php-fpm, php-cgi, httpd, or apache2 spawning shells, interpreters, or download tools. Those parent-child pairs are the clearest sign of a web shell or exploit in action.
Because attempts began on October 17, review logs back at least that far. Check for new files in the web root, new cron jobs or scheduled tasks, and new user accounts. Preserve web and PHP logs before you clean anything up.
If you suspect compromise, isolate the server first. Then rotate every secret that host could read, including database passwords, API tokens, and cloud keys. Our notes on API key rotation cover how to do that without breaking production.
Keep expectations realistic. As of this writing, PHP said it found no functional exploits when it shipped the release, and the public code circulating is unverified. Amazon says php2shell is now being broadly exploited, yet it is unclear whether those attempts would succeed against real systems. Assume the worst and patch anyway. A delay of even one business day leaves an exposed host open to a flaw that has a public exploit and a known attacker audience.
Why Did Attacks Start Before the Patch Shipped?
The flaws leaked before the fix did. On October 20, an anonymous poster on Hacker News claimed to know about two critical PHP bugs and named a disclosure date of October 22. The security firm watchTowr confirmed the leak was real and said the bugs were under embargo.
PHP responded within hours. It published an advance notice that evening and moved the release up to Wednesday, October 21. By then, Amazon's honeypot had already logged an attempt on October 17. That gap is the lesson. An embargo only works when nobody outside it is looking.
For comparison, Akamai saw exploit attempts within 24 hours of CVE-2024-4577 becoming public. The php2shell timeline is worse, because the first probe landed days earlier. Teams should plan for a patch window measured in hours, not in a sprint.
Special Cases: Shared Hosting, CMS Stacks, and Containers
Hosting and CMS setups need their own checks, because the PHP version often belongs to someone else. On shared hosting, you cannot restart workers yourself. Ask the provider to confirm the patched build and the restart time in writing.
For WordPress, Drupal, Joomla, and Magento, updating the CMS does nothing for this bug. The flaw lives in the PHP runtime underneath. Patch the interpreter, then keep the CMS and its plugins current as a separate task.
Bundled PHP is the sneakiest case. Some admin panels and appliances ship their own PHP build that your system package manager never touches. Search the filesystem for php binaries and compare each build against the fixed versions in the table above. When a vendor controls the build, open a support ticket and ask for their patch date.
Conclusion: Patch, Restart, Verify
The practical answer is simple. Upgrade to a fixed PHP release, restart every worker, and verify the running version on the web server itself. Do internet-facing hosts first and legacy systems right after.
A written record helps later, too. Note which hosts you patched, when you restarted them, and which ones you isolated instead. If a post-incident review ever asks what you knew and when, that short log answers it. Your next step today is the inventory. Find every place PHP runs, including the places nobody remembers owning. Backtrace's editors will keep tracking the follow-up disclosures as full technical details emerge.