PHP2Shell Vulnerability Fix: How to Patch and Verify the Fix in Production

PHP2Shell is the nickname for two critical flaws in the PHP engine, CVE-2026-109618 and CVE-2026-109619. To fix PHP2Shell, update every PHP runtime that serves web requests to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (or your vendor’s patched package), then restart or replace every PHP worker. An updated package on disk is not proof: the fix only counts once the running process has loaded the patched build.

PHP2Shell CVE Vulnerabilities at a glance

ItemCVE-2026-109618CVE-2026-109619
PHP advisory titleRCE via OOM corruptionRCE via stale global state
GitHub advisoryGHSA-w8hw-w9fx-j79wGHSA-6wmf-4rv5-p3rp
Severity (PHP, CVSS v4.0)9.2 Critical9.2 Critical
Fixed upstream releases8.5.12, 8.4.27, 8.3.36, 8.2.35 (October 21, 2026)Same releases
PHP 8.1 and olderNo official release; source patches for 7.4, 8.0, 8.1 to help vendors backportSame
CISA KEVAdded October 26, 2026; federal civilian deadline October 29, 2026Same
Complete fixUpdate. PHP’s security team calls updating the only complete mitigation.Update

What is the PHP2Shell vulnerability?

PHP2Shell is a researcher-coined name for a pair of remote code execution (RCE) flaws in the PHP runtime itself, not in WordPress, Drupal, Composer packages or any other application code. PHP’s own advisories do not use the name; they title the issues by mechanism.

  • CVE-2026-109618, “RCE via OOM corruption”: when PHP runs out of memory (OOM) at the wrong moment, request data can be left half-initialized, and request cleanup may treat that invalid data as valid.
  • CVE-2026-109619, “RCE via stale global state”: internal state owned by one request can outlive its memory, and a later request on the same worker may use it before it is reset.

Both were fixed in the same October 21, 2026 releases. Recorded Future attributes the name to Wiz Research, which found the issues alongside Calif and OpenAI.

What PHP2Shell is not. It is not a webshell, and it is not CVE-2026-115560. That third CVE, announced by PHP on October 23, is a separate, configuration-dependent session-handling issue (covered in the FAQ).

How PHP2Shell works

Both flaws live in how PHP aborts and cleans up a web request, so they can be reached before any application code runs.

PHP uses longjmp() to abandon a request when it hits an out-of-memory error. Per the PHP security team, an allocation failure can interrupt initialization while incomplete request state is already reachable, and request shutdown may then touch that invalid state (oss-security). The second flaw is the same family of problem across requests: state left pointing at freed memory survives into the next request handled by that worker.

This guide stops at the mechanism. You do not need exploit detail to patch, mitigate or verify.

PHP2Shell request lifecycle · two flaws, one worker

In both flaws, a request that was cut short leaves memory that PHP later trusts: during cleanup of the same request (CVE-2026-109618) or in the next request on that worker (CVE-2026-109619).

Which setups are at risk. PHP says all installations serving web requests are affected, naming PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed, and rates the risk highest for mod_php (LWN quoting php.net).

Execution modelWhat PHP’s advisories sayPractical reading
Apache mod_phpUnauthenticated RCE demonstrated over HTTP, before application code runsPatch first
PHP-FPM109618: susceptible by source analysis, no complete exploit shown. 109619: session path RCE validatedDo not defer
php-cgi, FrankenPHP, LiteSpeedNamed as affectedPatch on the same schedule
CLI only (cron, workers that never serve HTTP)Not a web request pathStill update, but lower urgency

Which PHP versions are affected?

Every upstream PHP release before the fixed version in its branch is affected, and older end-of-life branches are affected too. The trap is that a correctly patched distribution package often reports an older-looking version number.

Source of PHPFixed buildWhere to confirm
Upstream 8.58.5.12 or laterPHP 8.4.27 release notes (same advisory)
Upstream 8.48.4.27 or laterphp.net advisory, October 21, 2026
Upstream 8.38.3.36 or laterphp.net advisory
Upstream 8.28.2.35 or later (branch support ends December 31, 2026)php.net advisory
Upstream 8.1, 8.0, 7.4No official release; PHP published source patches to help backportersLWN
Ubuntu 24.04 LTSphp8.3 8.3.6-0ubuntu0.24.04.13USN-8948-1 (computingforgeeks walkthrough)
Ubuntu 22.04 LTSphp8.1 8.1.2-1ubuntu2.28USN-8948-1
Ubuntu 20.04php7.4 7.4.3-4ubuntu2.29+esm5 (Ubuntu Pro only)USN-8948-2
RHEL, AlmaLinux, Debian, cPanel, CloudLinux, PleskVendor builds that keep the upstream version stringEach vendor’s advisory or package changelog
Official Docker php imagesRebuilt October 21 for 8.5.12, 8.4.27, 8.3.36, 8.2.35; no fixed official tag for 8.1 or olderDocker Hub tag and digest
Appliances and vendor products (for example Palo Alto Networks PAN-OS and Panorama)Vendor hotfix, not a PHP update you can applyThe vendor’s own advisory

Why a fixed package can look vulnerable

Distributions backport the security patch into the PHP version they already ship and keep that version number. A fully patched Ubuntu 24.04 server still reports PHP 8.3.6, which is numerically far below 8.3.36. Judge a distribution build by its package release and changelog, never by comparing php -v against the upstream table. The reverse also holds: a scanner that only reads version strings will flag patched distro servers and can miss an unpatched appliance.

How to fix PHP2Shell

The fix is the patched PHP build, loaded by every process that serves web traffic. Work through these steps in order and keep evidence as you go.

  1. Inventory every PHP runtime. Hosts, container images, serverless layers, control panels, CI images that ship to production, and appliances or vendor products that embed PHP. Sophos’ Don Smith framed the real challenge as finding every instance where PHP is running, not installing the patch (Cyber Magazine).
  2. Rank by exposure. Internet-facing first, mod_php before PHP-FPM, management interfaces of appliances before internal tools.
  3. Identify the serving runtime and execution model. Record which SAPI serves HTTP (mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed) and which package or image provides it. The php CLI on the same host may be a different build.
  4. Choose the right fix for that source. Upstream builds: the fixed release in the same branch. Distribution packages: the vendor’s security update (Ubuntu recommends a full system update rather than cherry-picking packages). EOL branches: a vendor backport, or a move to 8.2 or later.
  5. Update packages or rebuild images. For containers, rebuild from the fixed base with a forced pull (docker build –pull), because Docker may otherwise reuse a cached base image.
  6. Restart or replace every worker. Reload PHP-FPM pools and restart Apache for mod_php. Redeploy containers so pods run the new image digest.
  7. Handle appliances through their vendor. You cannot patch PHP inside PAN-OS or a NAS yourself; apply the vendor hotfix and restrict management access until it lands.
  8. Record the evidence (see the verification section) before closing the ticket.

PHP2Shell remediation decision tree · five PHP sources

The right fix depends on where the PHP came from, but every path ends the same way: restart the workers and verify the running build.

PHP2Shell mitigation if you cannot patch immediately

Temporary mitigations reduce risk on known paths; none of them fixes PHP2Shell. PHP’s security team states that updating is the only complete mitigation (oss-security). Use these only to bridge a short gap, and patch anyway.

MitigationPath it targetsWhere it must be setLimitationsHow to verifySource
session.upload_progress.enabled=0, then restart every workerCVE-2026-109619 confirmed session paths; also CVE-2026-115560php.ini, FPM pool or server config applied before request parsing. Not ini_set() or FPM .user.iniBlocks confirmed session paths, not other variantsRead the effective value from the serving SAPI after restartPHP advisory text for GHSA-6wmf-4rv5-p3rp
fatal_error_backtraces=0 (PHP 8.5 only), then restartCVE-2026-109619 fatal backtrace pathSame administrative config layersCovers that one path onlyEffective value per SAPIGHSA-6wmf-4rv5-p3rp
memory_limit=-1, set so apps cannot override it (for example php_admin_value)CVE-2026-109618 controllable memory-limit failureFPM pool or Apache config; confirm no pool, directory or app restores a limitA real allocation failure can still reach the bug; unbounded memory is an availability riskEffective value per pool and vhostGHSA-w8hw-w9fx-j79w
Low post_max_size (8M without uploads, 32M with), upload_max_filesize below itCVE-2026-109618 multipart routes to OOMAdministrative configHardening onlyEffective values per SAPIGHSA-w8hw-w9fx-j79w
Container or cgroup memory limitsAvailability boundaryOrchestrator or cgroupNot a mitigation; do not use RLIMIT_AS or RLIMIT_DATA, which can trigger the same pathPod spec or cgroup settingsGHSA-w8hw-w9fx-j79w
WAF rules (for example Cloudflare, AWS WAF)Known exploit request patternsEdge or load balancerStopgap; vendors report evasive variantsRule in blocking mode, logs show matchesThe Hacker News
Remove from the internet or isolateAll pathsNetworkService impactExternal reachability testCERT-EU advice, via The Hacker News

Keep session.upload_progress.enabled=0 in place after patching unless an application needs the feature: PHP’s October 23 notice says it also protects against CVE-2026-115560 until the next regular release (oss-security).

How to verify the PHP2Shell fix in production

A PHP2Shell fix is verified when, for every asset, you can show that the process serving HTTP was started from a patched build after the patch landed. A version command alone does not show that.

The commands below are illustrative for Debian and Ubuntu with systemd. Package names, service names and paths differ on other platforms; follow your vendor’s documentation.

#CheckWhy it mattersEvidence to keepA failed check means
1Every PHP runtime is in the inventory, including images and appliancesUnlisted runtimes are where unpatched PHP survivesInventory export with owner per assetScope is incomplete; the ticket cannot close
2The version checked is the serving runtime, not the CLIThe php CLI can differ from the binary FPM or Apache loadsSAPI name plus build for each serving process (for example php-fpm8.3 -v, apache2ctl -M showing a php module)You verified the wrong binary
3Distro builds are judged by package release and changelogBackports keep old upstream version numbersPackage version (dpkg -l ‘php*’) and a changelog line naming both CVEsRe-check against the vendor advisory before calling it vulnerable or fixed
4Serving processes started after the updateRunning workers keep the old code in memoryService start time later than the package install time (systemctl show php8.3-fpm -p ActiveEnterTimestamp)Restart or reload, then re-check
5Containers run the rebuilt image digestA pulled image changes nothing until containers are recreatedImage digest in the registry matches the digest of running containersRedeploy
6Appliances and vendor products are on the vendor’s fixed releaseYou cannot verify embedded PHP with host toolsFirmware or hotfix version against the vendor advisoryApply the hotfix; restrict management access meanwhile
7Interim settings are still effective where you rely on themSettings in the wrong layer are silently ignoredEffective values read from the serving SAPIMove the setting to php.ini, the pool or server config
8Evidence is recorded per assetKEV reporting and audit need proof, not intentTicket with the items above, timestampedNot closed

PHP2Shell verification evidence chain · six checks

Work through the chain per asset; a gap at any link means the asset is not yet verified.

Two cautions. Vulnerability databases and scanners can lag new advisories, so a clean scan is not proof of a fix (ITNEXT). And do not run public exploit code against production to test a fix; the checks above prove the fix without attacking your own systems.

How to investigate possible PHP2Shell exploitation

Start your investigation window on October 17, 2026, not on the October 21 patch date. Amazon Threat Intelligence recorded a PHP2Shell exploitation attempt in its MadPot honeypots that day and advised defenders to look back at least that far (Security Affairs).

What is confirmed so far (as of October 29, 2026)

DateFindingSource
October 27Wiz saw no successful end-to-end exploitation in its own telemetry and no public proof of concept that works against arbitrary targetsWiz Research
October 26CISA added both CVEs to the Known Exploited Vulnerabilities catalogBleepingComputer
October 24Successful RCE confirmed against honeypot systems by Adel Karimi (Perplexity)The Hacker News
After October 23Unit 42 retracted its October 23 update linking a compromise to PHP2Shell (retraction date not stated)Unit 42
October 21Multiple proof-of-concept attempts from anonymized infrastructure, suggesting several actorsAmazon Threat Intelligence, via The Hacker News
October 17First recorded attempt, four days before disclosureAmazon Threat Intelligence

Reading these together: exploitation attempts are widespread and successful RCE has been shown in controlled conditions, but reliable exploitation at scale against real systems has not been publicly established. Attribution claims to specific threat actors come from single vendors and are not repeated here.

Triage levels

LevelWhat you seeWhat to do
Internet scanningRequests probing for PHP endpoints or versionsNote it; confirm the host is patched
Exploitation attemptRequests matching published detection logic, such as CISA’s SIGMA rule or WAF matchesConfirm the host was patched at that time; review worker crashes and errors around the timestamps
Successful exploitationEvidence that attacker code ran: unexpected child processes of the web worker, new files in web roots, outbound connections from PHP workersIsolate the host and start incident response
Confirmed compromisePersistence, data access or lateral movementFull incident response; rebuild rather than clean

One caution from the research: application logs may show little, because exploitation happens below the application layer (Recorded Future). Look at web server logs, process telemetry and network flows too. Wiz also reported that the bugs can expose worker memory, including credentials and API keys, without full code execution; if an exposed host was unpatched in the window, rotating secrets that lived in PHP memory is a sensible precaution.

PHP2Shell remediation checklist

  • ☐ Inventory complete: hosts, images, appliances, vendor products, with an owner each
  • ☐ Serving SAPI and PHP source recorded per asset
  • ☐ Correct fix chosen: upstream release, distro security update, vendor backport or vendor hotfix
  • ☐ Packages updated or images rebuilt with a forced base pull
  • ☐ Workers restarted; containers redeployed on the new digest
  • ☐ Appliance hotfixes applied; management access restricted until then
  • ☐ Runtime verified per asset (serving build, start time, digest, changelog)
  • ☐ session.upload_progress.enabled=0 kept unless the feature is needed
  • ☐ Logs and telemetry reviewed from October 17, 2026
  • ☐ Secrets rotated on hosts that were exposed and unpatched
  • ☐ Evidence attached; ticket closed

Frequently asked questions

What is PHP2Shell? PHP2Shell is the nickname for CVE-2026-109618 and CVE-2026-109619, two critical remote code execution flaws in the PHP engine fixed on October 21, 2026.

Which PHP versions contain the fix? PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, or later releases in the same branch. Distribution packages carry the fix under their own version numbers.

Are end-of-life PHP versions affected? Yes. The PHP project ships no release for 8.1 or older; it published source patches for 7.4, 8.0 and 8.1 to help vendors backport. Use a vendor backport or move to a supported branch.

Do distribution backports count as fixes? Yes, when the vendor’s advisory or package changelog lists both CVEs. A patched Ubuntu 24.04 server still reports PHP 8.3.6.

How can I check that production is patched? Check the build loaded by the process serving HTTP, confirm it started after the update, and for containers confirm the running image digest is the rebuilt one. php -v on the host is not enough.

Does disabling session.upload_progress fix PHP2Shell? No. It blocks the confirmed session paths of CVE-2026-109619 only; CVE-2026-109618 is untouched. Only updating is a complete fix.

Does a WAF replace patching? No. WAF vendors describe their rules as a stopgap, and evasive request variants have been reported.

Is PHP2Shell exploited in the wild? CISA lists both CVEs as known exploited (added October 26, 2026), and successful RCE was confirmed on honeypots. Reliable exploitation at scale has not been publicly shown.

Is CVE-2026-115560 part of PHP2Shell? No. It is a separate, unlikely session-handling issue that needs an application to switch session.serialize_handler to php at runtime. PHP will fix it in the next regular release; session.upload_progress.enabled=0 mitigates it meanwhile.

Does updating WordPress, Drupal or Joomla fix it? No. The flaw is in PHP itself, so the PHP runtime must be updated by you or your host.

Conclusion

Patch every PHP runtime that serves web traffic, then prove it: the serving process, its start time, its image digest and its vendor changelog. Teams that already keep a software inventory, such as an SBOM for each container image, can answer “where is PHP running?” in minutes rather than days. Start with that inventory, then work the checklist above.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top