Skip to main content

Free 30-min security demo Book Now

Vulnerability Research

PHP2Shell (CVE-2026-109618, CVE-2026-109619)

PHP2Shell is a critical unauthenticated RCE in the PHP runtime (CVSS 9.2). Who is affected, fixed versions, interim hardening, detection and verification.

Offensive360 Security Research Team 10 min read
PHP2Shell CVE-2026-109618 CVE-2026-109619 PHP remote code execution PHP-FPM mod_php attack surface patch management security advisory

PHP2Shell is the public name for two critical vulnerabilities in the PHP runtime, CVE-2026-109618 and CVE-2026-109619, fixed by the PHP project on 21 October 2026. Both allow remote code execution without authentication, the PHP security team rates each of them CVSS v4.0 9.2, and the flaws sit in the engine itself rather than in any application’s code: a server is exposed as soon as it serves web requests through PHP. Technical details leaked a day before the planned disclosure, and early attack attempts were reported before most organisations had a chance to patch.

This article explains what the two bugs are, who is affected, which versions fix them, what to do while patching, how to check for compromise, and how to verify your estate afterwards. It is written for security teams and system administrators and is kept to what the PHP project and independent researchers have confirmed.

Key facts

ItemDetail
CVE identifiersCVE-2026-109618, CVE-2026-109619
Public namePHP2Shell (also written php2shell)
TypeMemory-safety flaws in the PHP engine’s request handling, leading to remote code execution
Authentication requiredNone
SeverityCritical, CVSS v4.0 9.2 for each (PHP security team rating)
AffectedEvery PHP installation that serves web requests: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed
Highest riskApache mod_php: a validated single-request, unauthenticated exploit exists
Fixed inPHP 8.5.12, 8.4.27, 8.3.36, 8.2.35; minimal source patches for 7.4, 8.0 and 8.1
DisclosureDetails leaked 20 October 2026; fixes released 21 October 2026, one day earlier than planned
ExploitationEarly attack attempts reported by large network operators around release day

Timeline

  • 20 October 2026. A post describing the vulnerabilities appeared online ahead of the embargo and was taken down, but screenshots circulated and independent researchers confirmed the leak. The PHP project published an advance notice the same day and moved the release forward.
  • 21 October 2026. PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 were released, one day before the originally planned date, together with minimal source patches for the end-of-life 7.4, 8.0 and 8.1 branches. Cloudflare reported that it had already observed early attacks against the two vulnerabilities before the patches were out.
  • Still open. The PHP project has not published a confirmed list of affected versions. Reports that PHP 5 through 8 are all affected remain unconfirmed. Until that changes, treat every unpatched PHP installation that serves web requests as affected.

The two vulnerabilities

CVE-2026-109618: out-of-memory handling during request setup

When PHP runs out of memory while it is still setting up the data for an incoming request, that request data is only partly initialised. PHP’s cleanup code nevertheless treats it as valid, which corrupts memory and opens a path to code execution. The PHP project validated full remote code execution over HTTP against Apache mod_php with default settings and an ordinary prefork configuration. No application code has to run: the fault is triggered before the first line of the application executes.

CVE-2026-109619: stale request state after free

PHP keeps some request-specific state after the memory backing it has been freed. A later request handled by the same worker process can reach that stale state. The result is a use-after-free on the heap that can disclose memory and, in the worst case, execute code. Because the two requests can come from different clients, the bug is also a cross-request information leak.

Why a “hello world” page is enough

Both flaws live in the engine’s request lifecycle, not in the application. A server that only serves a one-line index.php is exposed in the same way as a large framework application. That changes the shape of the response: the question is not “is my code vulnerable” but “which of my hosts run an unpatched PHP that accepts web requests”. Inventory, not code review, is the first job.

Who is affected

PHP’s advisory names every server API that serves web requests: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The PHP project regards Apache mod_php as the most exposed configuration, since the validated exploit targets it directly. PHP-FPM and the other SAPIs are affected and must be patched as well; nothing published so far justifies treating them as safe.

Internet-wide measurements put the number of exposed PHP hosts in the millions; a VirusTotal estimate cited by BleepingComputer counts more than 5.1 million PHP hosts exposed online. PHP is also bundled inside appliances, management interfaces and vendor products that nobody thinks of as “PHP applications”, and those are the systems most often missed in a patch cycle.

Version status

BranchStatusAction
8.5SupportedUpdate to 8.5.12 or later
8.4SupportedUpdate to 8.4.27 or later
8.3Supported (security fixes)Update to 8.3.36 or later
8.2Supported (security fixes)Update to 8.2.35 or later
8.1End of lifeNo official release. The PHP project published a minimal source patch; apply your distribution’s backport or upgrade
8.0 and 7.4End of lifeMinimal source patch only; apply a vendor backport or upgrade
7.3 and olderEnd of lifeNo patch. Upgrade, or take the system off the internet until it is replaced

Linux distributions and LTS vendors received the fixes before publication, so packaged PHP on Debian, Ubuntu, RHEL and its derivatives, SUSE or Alpine should be updated from the vendor’s security repository rather than compiled by hand. Check your vendor’s advisory for the exact package version that carries the fix; some third-party repositories did not have updated packages on release day.

How to patch, and how to prove it

  1. Update the runtime. On packaged systems use the distribution tooling; for containers rebuild the image from an updated base tag and redeploy; on managed hosting confirm the PHP version in the control panel.
  2. Restart PHP-FPM and the web server. A package update alone does not replace the workers that are already running.
  3. Verify the version that actually serves traffic. php -v reports the command-line binary, which can differ from the FPM or Apache module version on the same host.
  4. Work in order of exposure. Internet-facing Apache mod_php first, then every other internet-facing PHP host, then internal systems.
  5. Record the version observed after restart for every host. You will need that list for the verification step at the end.
# Debian / Ubuntu
sudo apt update && sudo apt install --only-upgrade 'php*'
sudo systemctl restart php8.3-fpm apache2   # adjust the FPM unit to your branch

# RHEL / Rocky / Alma / Fedora
sudo dnf update 'php*'
sudo systemctl restart php-fpm httpd

# Verify what serves traffic, not only the CLI
php-fpm -v            # or php-fpm8.3 -v on Debian / Ubuntu
php -v                # CLI binary; can differ from the web SAPI

For Apache mod_php, confirm the module version through a temporary phpinfo() page served to a trusted network only, then remove the page. Containers should be rebuilt from an updated base image rather than patched in place, and the running digest compared with the rebuilt one.

Interim hardening while you patch

The PHP project published configuration measures for systems that cannot be patched immediately and states that they reduce but do not remove exposure. Apply them as a bridge, not as a destination:

  • Set post_max_size low: 8M where uploads are not needed, 32M where they are.
  • Set session.upload_progress.enabled = 0.
  • On PHP 8.5, set fatal_error_backtraces = 0.
  • Enforce memory limits at the container or cgroup level. PHP pairs this with memory_limit = -1 so that the engine’s own out-of-memory path is not the one that fires; do not raise memory_limit without an external limit in place.
  • Remove invalid per-request settings and fix fatal errors and timeouts that an attacker can trigger, since abnormal request termination is what both bugs build on.

At the network edge, use what your provider offers. Cloudflare deployed emergency WAF rules for these CVEs and describes them as temporary; request body size limits at the edge are consistent with the post_max_size guidance; and egress filtering from web servers makes a successful exploit far less useful, because most post-exploitation starts with an outbound connection. None of this replaces the update.

Detection and compromise checks

Exploitation of a runtime bug like this one tends to show up as a web server process doing something a web server never does. Indicators that incident responders are watching for:

  • PHP worker processes (php-fpm, php-cgi, httpd, apache2) spawning shells, interpreters or download tools.
  • Command lines containing /dev/tcp/, fsockopen or mkfifo, and reconnaissance commands such as whoami or id run by the web server user.
  • New files in web roots, web shells, new cron jobs, scheduled tasks or accounts created around the time of unusual requests.
  • Unexpected outbound connections from web servers.

If a host is suspected compromised: isolate it, preserve the web server and PHP logs, then rebuild from a known-good image and patch before it goes back online. Treat credentials and secrets that were reachable from that host as exposed.

How Offensive360 helps

A point worth stating plainly: PHP2Shell is a bug in the PHP engine, not in your application. No static code scanner, ours included, finds it by reading your source. What application security tooling contributes to this incident is inventory, exposure and verification, and that is where Offensive360 fits:

  • Exposure inventory from the outside. Offensive360 DAST and Attack Surface Management identify which internet-facing applications are served by PHP and flag version disclosure, so the patch list is based on what is actually running, including forgotten subdomains and partner-hosted endpoints that ASM keeps surfacing after the first pass.
  • Inventory from the code. Offensive360 SAST and dependency analysis map the PHP applications, frameworks and libraries across your repositories, so internal and legacy applications are not missed in the patch cycle, and application-layer weaknesses that would help an attacker after a foothold get fixed on the way.
  • Verification after patching. Re-scans with Offensive360 DAST and the O360 AI Pentester confirm from an attacker’s perspective which PHP services remain reachable and which still disclose a vulnerable version after the roll-out.
  • Exposure assessment as a service. The Offensive360 team runs a focused PHP2Shell exposure assessment for customers and partners: external inventory, patch verification and a review of compromise indicators, with a short written result your management can act on.

Offensive360’s own platform does not serve web requests through PHP; no action is required on Offensive360 appliances or cloud services for this issue. Customers and partners who want help prioritising their PHP estate can contact the team.

References

This article will be updated as the PHP project publishes further details, in particular the confirmed range of affected versions.

Frequently asked questions

What is PHP2Shell?

PHP2Shell is the public name for two critical vulnerabilities in the PHP runtime, CVE-2026-109618 and CVE-2026-109619, fixed by the PHP project on 21 October 2026. Both allow remote code execution without authentication and both are rated CVSS v4.0 9.2 by the PHP security team. They affect the engine itself, so any PHP installation that serves web requests is exposed regardless of the application running on it.

Which PHP versions fix PHP2Shell?

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 contain the fix. For the end-of-life branches 8.1, 8.0 and 7.4 the PHP project published minimal source-level patches that distributions and vendors can apply; there is no official release for them. PHP 7.3 and older have no patch and should be upgraded or isolated.

Is PHP2Shell being exploited in the wild?

Technical details leaked publicly on 20 October 2026, one day before the planned disclosure, and Cloudflare reported observing early attacks against the two vulnerabilities before the patches were released. A working exploit against Apache mod_php was validated by the PHP project. Broad opportunistic exploitation should be expected.

Am I affected if I run PHP-FPM instead of Apache mod_php?

Yes. The PHP advisory covers every server API that serves web requests: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed. Apache mod_php is the most exposed configuration because the validated single-request exploit targets it, but PHP-FPM and the other SAPIs must be patched as well.

Does a web application firewall protect against PHP2Shell?

A WAF reduces exposure and buys time; it does not remove the vulnerability. Cloudflare deployed emergency rules and describes them as temporary, and the PHP project states that its own interim configuration measures reduce but do not fully prevent exploitation. Only updating PHP removes the flaw.

Can SAST or DAST tools detect PHP2Shell?

Not by reading application code: PHP2Shell is a bug in the PHP engine, not in your application, so no static code scanner finds it in your source. What application security tooling does for this incident is inventory and verification: DAST and attack surface management identify internet-facing applications served by PHP and flag version disclosure, SAST and dependency analysis map the PHP applications and libraries across repositories, and re-scans after patching confirm which services still disclose a vulnerable version.

How do I verify that a server is actually patched?

Check the version of the component that serves web traffic, not only the command-line binary: run php-fpm -v for PHP-FPM, check the loaded module version for Apache mod_php, or render a temporary phpinfo() page from a trusted network and remove it afterwards. Do this after restarting PHP-FPM and the web server, because updated packages do not replace running workers until they are restarted.

Offensive security

See your attack surface the way an attacker does

Explore external asset discovery with ASM and scoped application testing with Autonomous Red Teaming. Review evidence, coverage limits and deployment requirements during an evaluation.

Also see: Autonomous Red Teaming · AI Pentester

See your attack surface the way an attacker does

Book a demo