Book a call

WRITINGS / ANALYSIS

PHP2Shell: Least Effort, Biggest Gain. WAF First, Patch Without Delay

Analysis · Security

On October 21, 2026, two critical vulnerabilities in the PHP runtime were disclosed: CVE-2026-109618 and CVE-2026-109619. Known together as PHP2Shell, both carry a CVSS v4.0 score of 9.2 and can lead to remote code execution without authentication.

Before discussing the mitigations, there is an important distinction: running a vulnerable PHP version does not automatically mean a system can be compromised.

Both vulnerabilities have a High attack complexity rating and require additional conditions for exploitation. Those conditions vary depending on the PHP build, server configuration, memory layout, and request lifecycle. Successfully triggering the underlying memory corruption is not necessarily the same as achieving reliable remote code execution.

But the complexity should not be mistaken for safety. Researchers have demonstrated remote code execution against Apache mod_php under ordinary deployment conditions, and confirmed exploit paths also exist for PHP-FPM.

The practical risk is not identical across every installation. Neither is it theoretical.

Muvrans does not use PHP, so these vulnerabilities do not directly affect our systems. Still, the disclosure illustrates a broader engineering problem: some vulnerabilities live inside the runtime rather than in application code. Updating a WordPress installation or its plugins, for example, will not fix a vulnerability in the PHP runtime underneath it.

And when a critical runtime patch must be deployed across multiple servers, containers, or environments, protections at the edge can reduce exposure while that work is underway.

WAF first: reducing risk while patching

Cloudflare reported that it deployed PHP2Shell WAF protections approximately nine hours before the public disclosure on October 21. According to Cloudflare, the vulnerability details had leaked ahead of the coordinated release, and its network had already observed attack traffic targeting customers.

The protections were automatically deployed to customers with Cloudflare WAF enabled, including Free users.

On the Free plan, rules were released under the Cloudflare Managed Free Ruleset. Paid plans received protections through the Cloudflare Managed Ruleset, with Cloudflare advising customers to verify that the rules are deployed in block mode.

The advantage of this approach is speed. A WAF can reduce exposure without rebuilding containers or changing application code.

But where the protection acts matters.

Request-side rules inspect incoming HTTP traffic and can block a malicious request before it reaches the origin.

Cloudflare also introduced full transaction detection for PHP2Shell, using signals from both the incoming request and the origin response to identify attacks that cannot be reliably distinguished from legitimate traffic using request data alone.

Cloudflare dashboard showing default protection applied to responses from the origin.

Cloudflare response rules dashboard. Screenshot from Cloudflare’s PHP2Shell WAF protection article.

This creates an important limitation.

A response-side rule can prevent a suspicious origin response from reaching the attacker, but it cannot undo code that has already executed on the server. Blocking the response may reduce information disclosure or feedback available to the attacker. It does not provide the same preventive guarantee as blocking the request.

That is why understanding a rule’s detection point and action matters as much as knowing that the rule exists.

Protecting the origin

There is another relatively simple configuration issue worth checking: direct access to the origin.

If attackers can bypass Cloudflare and send requests directly to the web server, Cloudflare WAF protections will not inspect those requests.

Restricting inbound connections to Cloudflare IP ranges is a useful starting point, but those IP ranges are shared across Cloudflare customers. Allowlisting them does not prove that a request passed through your own Cloudflare zone.

Authenticated Origin Pulls can provide stronger origin authentication. Using a zone-specific or hostname-specific client certificate allows the origin to authenticate connections associated with your Cloudflare configuration.

Cloudflare Tunnel is another option where the architecture supports it, using outbound connections rather than exposing an inbound origin service. It is an alternative to, not a combination with, Authenticated Origin Pulls.

Neither mechanism replaces the PHP security updates.

Then patch: the real fix

On October 21, the PHP team released the following security updates:

PHP branchPatched version
PHP 8.58.5.12
PHP 8.48.4.27
PHP 8.38.3.36
PHP 8.28.2.35

These releases address the two PHP2Shell vulnerabilities. The PHP security team explicitly recommends updating immediately.

Publishing a new container image is not sufficient by itself. The image must be deployed, existing PHP workers must be replaced, and the running build must be verified.

A command such as php -v can be useful, but it may show the CLI version rather than the PHP runtime handling HTTP requests. PHP-FPM, Apache modules, and CLI installations do not necessarily use the same binaries or configuration.

The relevant question is whether production requests are being served by the corrected build.

October 23 update: an additional session upload progress advisory

On October 23, the PHP team published an additional informational advisory concerning an unlikely remote code execution scenario involving session upload progress.

The mitigation was not entirely new. Disabling session upload progress had already been included in the October 21 advisory for CVE-2026-109619.

The newer announcement clarifies a specific remaining scenario that requires an unusual combination of configuration and application behavior.

For this scenario to occur, all of the following conditions must be present:

  1. The application initially configures session.serialize_handler as php_binary or php_serialize.
  2. Application code changes the handler to php at runtime using ini_set(), before calling session_start().
  3. PHP session upload progress remains enabled.

Applications that never change the session serialization handler at runtime do not meet these specific conditions.

To fully protect against this remaining scenario until the next regular bugfix release, PHP recommends:

session.upload_progress.enabled=0

The setting must take effect before PHP processes the request. The October 21 advisory specifies applying it administratively through php.ini, an FPM pool, or appropriate server configuration, followed by restarting PHP workers. Setting it through application-level ini_set() or relying on FPM .user.ini is not sufficient for the confirmed early session paths.

Disabling the feature may affect applications that depend on PHP’s built-in session upload progress functionality. Administrators should review their application requirements and effective configuration before making the change.

PHP states that applications which never change the serialization handler at runtime can keep session upload progress enabled for this specific scenario.

A full advisory for CVE-2026-115560 is expected with the next regular PHP release.

This does not invalidate the October 21 patches for CVE-2026-109618 and CVE-2026-109619. It identifies a narrowly conditioned residual risk requiring separate attention.

It is also a good example of why a security update and a configuration review serve different purposes.

Patches are available, but what about systems that haven’t been updated?

A critical CVE does not mean every server running the affected software can be compromised with the same request.

PHP2Shell illustrates that distinction particularly well.

CVE-2026-109618 involves corruption during out-of-memory handling. Its exploitability depends partly on how PHP initializes and shuts down requests. Remote code execution has been demonstrated against Apache mod_php, including ordinary prefork configurations.

For PHP-FPM, source analysis establishes susceptibility to the underlying flaw, but the original advisory does not report a complete FPM exploit for that specific vulnerability.

CVE-2026-109619 involves stale global state surviving between requests. Successful exploitation requires a sequence of operations that produces the stale state and subsequently consumes it, potentially in another request handled by the same PHP worker.

Confirmed exploitation paths exist, including session-related paths affecting both mod_php and PHP-FPM.

These differences matter when evaluating real-world exposure.

A vulnerability rating describes severity and exploit conditions. It does not tell us how many systems have actually been compromised, nor whether every possible deployment is equally exploitable.

At the same time, high attack complexity does not justify delaying a security update when working exploits have already been demonstrated.

Older PHP installations

PHP 8.1 and earlier no longer receive upstream security updates from the PHP project.

Some Linux distributions and long-term support vendors maintain backported fixes for older releases. The PHP security team also provided minimal source backports for PHP 7.4, 8.0, and 8.1.

This is why checking a version string alone can be misleading. An older vendor-maintained package may contain the relevant fix, while an unpatched upstream installation remains exposed.

For systems that cannot be updated immediately, priority should be given to:

  • Restricting unnecessary public access and unused endpoints.
  • Verifying applicable WAF protections, their enforcement actions, and origin access restrictions.
  • Reviewing access, error, WAF, and server logs from before the October 21 public disclosure, because attack traffic had already been observed.
  • Investigating indicators of exploitation, including unusual PHP worker failures, unexpected processes, and suspicious application behavior.
  • Treating the PHP update as an emergency change rather than waiting for routine maintenance.

The absence of suspicious log entries does not prove that a system was never exploited. Not every failure or exploitation step leaves a reliable log entry.

1. Reduce exposure immediately

Verify that relevant Cloudflare WAF protections are active and enforcing the expected actions. Restrict direct access to the origin.

2. Patch in parallel

Identify all PHP runtimes serving production traffic. Apply the corrected release or verify the relevant vendor-supported backport.

Restart affected workers and verify the actual runtime version or package build.

3. Review the October 23 advisory

Check whether the application uses the unusual session serialization handler transition described by PHP. Apply the recommended temporary mitigation where appropriate, ensuring the setting takes effect before request processing.

4. Verify and investigate

Confirm that production is running the corrected build, perform regression checks, and examine available evidence of potential exploitation before declaring remediation complete.

A WAF rule being active is not sufficient evidence that the system is safe. Neither is the existence of a patched container image in a registry.

For teams new to Cloudflare

For a standard full-zone setup, onboarding usually starts by changing the domain’s authoritative nameservers to Cloudflare. Partial setup alternatives exist for certain paid configurations.

Before making that change:

  • Back up the existing DNS records and verify that the imported records are complete.
  • Set supported web-facing A, AAAA, and CNAME records to Proxied.
  • Preserve mail-related DNS records. MX and TXT records are not proxied, while CNAME records used for email and domain verification generally need to remain DNS-only.
  • Configure SSL/TLS as Full (strict), using a valid origin certificate.
  • Once the zone becomes Active, verify WAF coverage and origin access restrictions.

Moving DNS to Cloudflare alone does not secure the origin or patch a vulnerable PHP installation.

Final thought

PHP2Shell is a reminder that identifying a vulnerability is not the same as demonstrating reliable exploitation against every installation.

Some exploitation paths require specific configurations, worker behavior, and carefully coordinated memory states. Others have already been demonstrated under relatively ordinary server conditions.

The engineering response should reflect both realities: avoid treating every affected server as already compromised, but do not use exploit complexity as an excuse to leave it unpatched.

Edge protection can reduce exposure while teams deploy and verify the fix.

That is its value. Not replacing the patch, but buying time to apply it properly.


Sources