// threat intel

PHP2Shell After the Patch: Why Old PHP Workers Stay Exploitable

PHP2Shell after patch: terminal restarting PHP-FPM workers to clear CVE-2026-109618 and CVE-2026-109619

PHP2Shell, two critical PHP runtime flaws disclosed on October 21, 2026, stays exploitable after the patch on any server whose PHP workers have not been restarted and on any container that has not been rebuilt. For Cyprus EMIs, brokers and iGaming operators running PHP, a green patch report can sit on top of a vulnerable process.

Key takeaways

  • PHP2Shell is CVE-2026-109618 and CVE-2026-109619: two CVSS 9.2 flaws in the PHP runtime enabling unauthenticated remote code execution and memory disclosure, disclosed October 21, 2026.
  • PHP 5.4 through 8.5.11 is affected. Fixes are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35; PHP 8.1 and older will not be patched.
  • Installing the package is not enough: restart php-fpm, Apache, FrankenPHP or LiteSpeed workers, and rebuild self-built containers on Cloud Run, GKE and App Engine flexible.
  • Until every worker is recycled, pm.max_requests = 1 and edge rules on oversized and multipart bodies reduce exposure; Cloud Armor rules are compensating controls only.
  • For NIS2, DORA and CySEC, keep evidence that the serving process changed: changelog CVE lines, process start times and container image digests.

What is PHP2Shell, and which builds actually close it?

PHP2Shell is the name for CVE-2026-109618 and CVE-2026-109619, two critical vulnerabilities in the PHP language runtime itself. The PHP project and Wiz Research disclosed them jointly on October 21, 2026, and CVE.org assigned both IDs the same day. Each carries a CVSS base score of 9.2.

Google Cloud has published the most detailed operator guidance so far. It says the flaws expose PHP applications to unauthenticated remote code execution and memory disclosure. An attacker needs no account and no credentials, only a PHP endpoint they can reach.

The research was AI-assisted. Google credits its Gemini 4 Argon model with contributions to finding the vulnerability, developing the exploit, detecting attacks and validating the patch. Wiz says it used a mix of models to identify and remediate the bugs.

Every release from PHP 5.4 through 8.5.11 is affected. PHP 5.4 shipped in 2012, so in practice this covers almost every PHP deployment still in production. The PHP project has shipped fixes for four supported branches:

Branch Fixed release Status
PHP 8.5 8.5.12 Patched
PHP 8.4 8.4.27 Patched
PHP 8.3 8.3.36 Patched
PHP 8.2 8.2.35 Patched
PHP 8.1 and earlier None End of life; remains vulnerable

Google’s guidance names PHP 5.5, 7.2, 7.3, 7.4 and 8.1 as staying vulnerable. The GitHub advisory identifiers are GHSA-w8hw-w9fx-j79w for CVE-2026-109618 and GHSA-6wmf-4rv5-p3rp for CVE-2026-109619, and PHP has published its own security advisory.

Settle one point with your development team early. This is an interpreter fix, not an application fix. Updating Composer dependencies, Laravel, Symfony, or WordPress core and plugins does not touch the vulnerable code. A software composition dashboard can show every library current while the php-fpm binary underneath is still affected.

That is also why WordPress and CMS penetration testing that stops at plugin versions misses this class of bug. The fix usually belongs to whoever owns base images, OS packages or the hosting platform, and in many Cyprus firms that is a different team, or a different company, from the developers.

How do the two flaws work?

Both bugs sit in how PHP manages memory for each request, which is why application-level scanning will not find them. Google describes each in two sentences, enough to explain the mitigations.

CVE-2026-109618 involves out-of-memory handling. If PHP runs out of memory while still building its internal request data, request cleanup can treat the half-initialized data as valid. An attacker who pushes a request into memory exhaustion at the right moment gets PHP’s own cleanup code working on broken structures. Hence the defensive focus on request size and upload parsing.

CVE-2026-109619 is a stale-state bug that crosses requests. State owned by one request can survive after its backing memory has been freed, and a later request on the same worker may use it before normal initialization resets it. It is a use-after-free pattern spread across two requests.

The worker model makes the second flaw worse. PHP-FPM and Apache keep workers alive across many requests to avoid startup costs, so one worker can serve thousands of different customers. Leftover state passing from one request to the next is how memory disclosure happens. It also explains why the pre-patch hardening advice calls for forcing workers to recycle after every request.

Expect exploitation to be intermittent and to depend on which worker picks up a request. One clean test request, one negative memory scan or one log line without a suspicious cookie does not clear a worker pool.

Why is PHP2Shell still exploitable after the patch?

Because a running process loads PHP’s code into memory when it starts, and installing a new package does not replace what is already loaded. The Mandiant Consulting guidance Google added on October 23 is blunt: upgrading packages on disk leaves vulnerable libphp.so or php-fpm binaries resident in running worker processes. Restart the serving process explicitly:

  • php8.x-fpm for PHP-FPM pools behind Nginx or Apache
  • apache2 / httpd where PHP runs as mod_php
  • frankenphp for FrankenPHP deployments
  • lsws for LiteSpeed Web Server
  • Supervisor-managed PHP workers, such as queue consumers and schedulers

Package managers handle this inconsistently. Some distribution hooks restart services after an upgrade; others do not. Change freezes, blue-green pools and hosting panels often delay restarts on purpose. On engagements we regularly find servers with fully current packages whose PHP-FPM master started weeks before the update.

Do not trust php -v on its own. It reports the command-line binary, which can differ in version, package or configuration from the SAPI that actually serves web traffic. Check the serving path itself, for example by comparing process start times with the package install time.

Verify packages against the changelog, not just the version string. Google suggests apt-get changelog php-fpm on Debian and Ubuntu, or rpm -q --changelog php-fpm on RHEL-family systems, filtered for both CVE IDs.

Distributions often backport security fixes without moving to the new upstream release, so a package with an old-looking version string may contain the fix. A scanner that only compares versions will flag that package as vulnerable even though it contains the fix. Expect those false positives and close them with changelog evidence.

The reverse risk matters more. The PHP security team noted that volunteer-run third-party RPM mirrors may lag behind coordinated disclosure. Use official distribution security repositories or official source builds. A new version number from a repository you cannot vouch for proves nothing.

Who on Google Cloud has to rebuild, and who is patched for you?

Google states that Google Cloud’s own infrastructure is not vulnerable, but customers running PHP on it may be. Google is rolling out updated serverless base images for supported PHP versions. Whether they reach you automatically depends on the service:

  • App Engine standard: patched automatically for PHP 8.2 and later. No action required.
  • App Engine flexible: not updated automatically for any PHP version. Redeploy on PHP 8.2 or later.
  • Cloud Run and Cloud Run functions: updated automatically only where automatic base image updates are enabled. Otherwise rebuild and redeploy.
  • GKE: rebuild container images with a fixed PHP and redeploy your pods.
  • Cloud Marketplace: for CMS or LAMP solutions, apply the provider’s update or patch PHP directly.
  • Custom runtimes and self-built images on Cloud Run or App Engine flexible: your responsibility to rebuild and redeploy.

Google updated the post on October 21, 22 and 23, adding Mandiant remediation and detection guidance and revising its Security Command Center and Cloud Armor instructions. If your team read it on day one, read it again.

For exposure, Google points to the On-Demand Scanning API and Artifact Analysis for images, and to Security Command Center’s External Exposure service with the EXTERNALLY_EXPOSED_RCE_VULNERABILITY module. Vulnerability Assessment, Container Threat Detection for GKE and Cloud Run Threat Detection cover running workloads.

Google Security Operations added 23 curated detections to the Mandiant Frontline Threats rule pack. Enterprise Plus customers can search the Emerging Threat Center for GLOBAL.26.015 and, if they enabled the Threat Hunt Agent in public preview, run a hunt on it.

The same logic holds on AWS, Azure, on-premises Kubernetes and managed hosting: whatever image or host serves PHP must be rebuilt or restarted. A pipeline that pins a base image by digest keeps shipping the old runtime until someone moves the pin. Our container security assessment traces which images, tags and running workloads still carry an affected build.

What can you do before every worker is recycled?

Use the temporary controls Google and Mandiant named, and treat them as a bridge to the upgrade. Google is explicit that Cloud Armor mitigations are compensating controls only. Upgrading PHP and redeploying is the only full fix.

Runtime hardening

  • Set pm.max_requests = 1 in the PHP-FPM pool configuration so each worker is replaced after every request. This targets the cross-request stale-state flaw directly. The cost is real: process overhead rises and capacity falls under load. On busy payment, betting or trading APIs, watch latency, queue depth and gateway errors.
  • Put the settings in the main startup php.ini or a static FPM pool configuration (php_admin_value / php_admin_flag), not per-directory overrides, and restart all workers afterwards.
  • Do not rely on display_errors = Off. Google warns that hiding errors does not fully block memory leaks, which can surface through oversized session cookies or specific error pages.

Edge and WAF controls

  • If Cloud Armor managed rules are already active, protection applies automatically. Otherwise, enable the stable ruleset in enforce mode, including the File Upload and RFI categories.
  • Add a rule so uninspected or oversized request bodies never reach backends. Large payloads are the obvious way to force out-of-memory conditions.
  • Block multipart/form-data on routes that do not accept uploads, and reject chunked transfer encoding where the application does not need it.
  • Cap body size and multipart header counts, refuse deeply nested bracketed field names, and enforce a strict format for PHPSESSID cookies.

Take exact thresholds from Google’s latest guidance and size them to your own upload routes rather than copying numbers from secondary write-ups. Then test through the full production path. CDNs, load balancers, WAFs and Nginx parse chunked bodies, multipart boundaries and long cookies differently, so a rule that catches a tidy test request may never see what your origin receives.

Wiz is offering patched WizOS PHP base images, standard Alpine-hardened and FIPS-compliant, at zero billable units for 60 days. That helps if you want a clean base quickly, but rebuilding on your distribution’s fixed packages closes the same hole.

If you are stuck on PHP 8.1 or older

No upstream patch is coming, so every control above becomes permanent risk management. You have three realistic options. Upgrade to PHP 8.2.35 or later. Isolate the application behind strict edge rules, restricted network access and per-request worker recycling, with a dated migration plan. Or rely on an OS vendor that still supports its PHP package and whose changelog lists both CVEs.

An internet-facing PHP 7.4 or 8.1 application carrying a public CVSS 9.2 flaw is hard to defend in an audit. If the business accepts the risk, document it, approve it at the right level and attach the compensating controls with their test results. A CySEC or DORA reviewer will ask for exactly that.

What if a worker has already leaked memory?

Treat it as a data exposure, not a patching delay. A long-lived PHP worker at a payment or trading platform holds database credentials, payment service provider API keys, tokens for KYC and sanctions-screening vendors, session cookies and personal data from every request it served.

This bites harder in Cyprus than in most other jurisdictions. EMIs, CIF-licensed forex brokers, iGaming back offices and corporate service provider portals run heavily on PHP: Laravel, Symfony, custom frameworks, WordPress front ends and commercial back-office software. Many were built five or more years ago, and that is where we still find PHP 7.4 and 8.1 in production.

If you find credible evidence of exploitation, upgrading PHP is only the start. Rotate the secrets the worker could reach, invalidate sessions, review access logs on downstream APIs and decide whether a personal-data breach has occurred. If an attacker reached code execution, treat the whole application host as compromised.

Capture memory before you restart

Mandiant advises capturing worker memory before patching or rebooting any server showing active probing or anomalous PHPSESSID cookies. Restarting workers permanently destroys the volatile heap evidence that would show what a leak exposed.

From incident work, our caveat is to move quickly. Isolate the host, collect web server, PHP-FPM, reverse proxy, authentication and outbound-connection logs plus the relevant process memory, then restart. Do not keep an actively compromised production service online for a perfect forensic image. Patch and restart hosts with no indicators straight away.

In the logs, correlate signals rather than hunting for a single smoking gun: repeated requests landing on the same worker PIDs, worker crashes or out-of-memory events, unusual child processes spawned by PHP, and outbound connections from web hosts that normally talk only to the database.

What is reported, and what is still unknown

Google’s guidance does not confirm in-the-wild exploitation, although Mandiant Threat Defense says it is hunting for intrusion activity related to the campaign. Outlets including The Hacker News and Security Affairs have reported large volumes of exploitation attempts. Treat those reports as reasons to hunt, not as established facts about your estate.

The public material does not describe the full exploit chain. That is the right call for defenders, but it makes real-world reliability hard to judge. Nobody has yet said how consistently the memory disclosure works against hardened configurations, and commercial PHP platforms and hosting panels will patch on their own schedules.

Management needs two decisions this week: who owns PHP runtime patching for each estate, including outsourced platforms, and which exploitation indicators trigger secret rotation and the incident process rather than a routine change ticket.

How do you prove the runtime changed for NIS2, DORA or CySEC?

Build an evidence record that links each production service to a fixed binary that is actually running. A change ticket alone does not prove that. For each PHP estate, keep:

  • Package changelog lines showing CVE-2026-109618 and CVE-2026-109619, or the upstream version (8.5.12, 8.4.27, 8.3.36 or 8.2.35) and where it came from.
  • Start times of PHP-FPM masters and Apache, FrankenPHP or LiteSpeed processes, later than the package install time.
  • Container image digests before and after the rebuild, plus deployment records showing the new digest runs in Cloud Run, GKE or App Engine flexible.
  • A check of the serving SAPI through the real web path, not just the command line.
  • Detection coverage: which rules were enabled and when, such as the Google SecOps pack or EDR policies, and which log searches covered the window before the patch.
  • For PHP 8.1 and older, the signed risk acceptance and compensating-control test results.

Reporting clocks

Keep reporting in proportion. A vulnerability or a log full of scanning is not automatically a reportable incident. Under GDPR, an actual personal-data breach goes to the supervisory authority without undue delay and, where feasible, within 72 hours of becoming aware, unless it is unlikely to put individuals at risk.

Under NIS2, a significant incident needs an early warning within 24 hours, an incident notification within 72 hours and normally a final report within a month. DORA has applied to in-scope financial entities since January 17, 2025, and its classification depends on real service impact. Waiting for forensic certainty can push you past those deadlines.

If you find genuine indicators, start the evidence and escalation trail on day one. Our NIS2 and DORA compliance readiness work maps those clocks to your incident process, and our piece on whether your SOC can actually see an intrusion covers the detection side.

From our engagements: retests regularly turn up a PHP runtime nobody listed — a forgotten admin subdomain, a reporting server, a marketing WordPress site on shared hosting or a PSP callback handler in its own container. An independent retest that maps every PHP-serving endpoint and checks each one from the outside turns ‘we patched’ into evidence an auditor accepts.

FAQ

What is PHP2Shell (CVE-2026-109618)?

PHP2Shell is the nickname for CVE-2026-109618 and CVE-2026-109619, two CVSS 9.2 flaws in the core PHP runtime disclosed by the PHP project and Wiz Research on October 21, 2026. They can expose PHP applications to unauthenticated remote code execution and memory disclosure.

Which PHP versions are affected, and is PHP 8.1 patched?

All versions from PHP 5.4 through 8.5.11 are affected. Fixes ship in 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and earlier are end of life and the PHP project will not release fixes, so those installations stay vulnerable until upgraded.

Do I need to restart PHP-FPM after installing the security update?

Yes. Mandiant's guidance says upgrading packages on disk leaves vulnerable libphp.so or php-fpm binaries resident in running workers. Explicitly restart php8.x-fpm, apache2/httpd, frankenphp or lsws, plus any supervisor-managed PHP workers.

Does display_errors Off stop PHP memory disclosure?

No. Google warns that hiding errors does not fully block memory leaks. Use per-request worker recycling and edge controls as temporary measures, and treat upgrading PHP as the only full fix.

How do I check if my php-fpm package includes the fix?

Read the package changelog with apt-get changelog php-fpm or rpm -q –changelog php-fpm and look for both CVE IDs. Distributions often backport fixes without changing the upstream version, so a version-only scanner can report a false positive.

If you need independent evidence that every PHP endpoint now runs a fixed runtime, our CySEC ICT risk penetration testing includes a targeted PHP2Shell retest built for CySEC, NIS2 and DORA files.


// get started

Work with CyprusPentest

Tell us about your target and goals. We’ll reply with scope and a fixed-price quote — usually within one business day.

./request_engagement