Security advisory: Critical unauthenticated RCE in PHP (“php2shell”)

Published: October 21, 2026

CVE-2026-109618 | CVE-2026-109619

Severity: Critical (CVSS v4.0 9.2)

Status: Patch available — update immediately.

Fixed versions are available now. Updating is the only complete fix; patch internet-facing systems today.

Topics on this page:

Overview

An unpatched version of PHP can allow remote code execution, leading to remote shells, and no fully effective mitigations exist outside of immediate patching or taking a device offline. At present, only currently supported PHP versions will receive patches; everything else will remain vulnerable. SentinelOne and CrowdStrike Falcon should provide decent protection against the expected bulk brute-force attacks that will drop files and launch other services; however, for stealthy attacks that stay in PHP, this may not be the case. Monitoring PHP and web server error logs may help close gaps, and we will do what we can to assist with that monitoring. Tenable should be able to identify your running PHP instances, and we’ll expand Falcon access for those with accounts so they can view vulnerability information as well.

Summary

PHP has released 8.5.12, 8.4.27, 8.3.36, and 8.2.35 to fix two critical vulnerabilities that allow unauthenticated remote code execution as the web server’s PHP worker account. PHP’s security team describes every PHP installation that serves web request pages of any type as at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. It rates mod_php as highest risk, where an unauthenticated request can trigger a demonstrated exploit before any application code runs, so application-level hardening doesn’t help.

PHP says there is no complete mitigation short of updating; its interim settings only reduce exposure. PHP 8.1 and older get no official release, though PHP has published minimal source backports for 7.4, 8.0 and 8.1, and some distributions and vendors provide their own.

The planning point: Cloudflare has already reported early attacks earlier today, and now that the patches can be compared with the old code, mass exploitation is expected quickly. Patch internet-facing systems today, restart PHP so the fix actually loads, and treat any internet-facing system that was unpatched from October 20 onward as potentially compromised until checked.

Vulnerability details

Field Detail
CVE-2026-109618 RCE via out-of-memory (OOM) corruption (GHSA-w8hw-w9fx-j79w). When a request runs out of memory at the wrong moment, PHP leaves internal request data half-initialized and request cleanup then treats it as valid. Attackers can force this with crafted multipart requests that stay within PHP’s apparent limits.
CVE-2026-109619 RCE via stale global state (GHSA-6wmf-4rv5-p3rp). Internal state from one request survives after its memory is freed, and a later request handled by the same worker uses it (a use-after-free). Session upload progress, enabled by default, is one confirmed path.
Severity Critical, CVSS v4.0 9.2 for each (AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H). Exploit reliability depends on build, extensions and server layout, but PHP has validated full RCE.
Attack vector Network, no authentication, no user interaction. The mod_php path does not depend on any particular URL or application.
Exploit status Cloudflare reported early attacks before the release. Full technical details are now public in the GitHub advisories.

Apache mod_php is the highest risk, with full RCE validated for both CVEs on default settings. PHP-FPM RCE was validated for CVE-2026-109619, though that path needs a suitable application operation. FrankenPHP and LiteSpeed are rated likely susceptible. Patch all of them.

Impacted and fixed versions

PHP version Status Fixed in / Action
8.5, 8.4, 8.3 Vulnerable before 8.5.12, 8.4.27 and 8.3.36 Update to 8.5.12, 8.4.27 or 8.3.36
8.2 Vulnerable before 8.2.35. End of life December 31, 2026. Update to 8.2.35 and plan the move to a newer branch.
8.1 and older Vulnerable. End of life; no official release. 8.1, 8.0 and 7.4: distribution, vendor or PHP source backport. Older: upgrade or take offline.
Distro and vendor packages Version string may not change when a fix is backported. Distributions received the patches in advance. Check the package against your vendor’s advisory.

Recommendations

  • Find every PHP installation. Include departmental, faculty, lab, research-group, staging and archived sites; cPanel and Plesk; vendor appliances and Windows software bundling php.exe or php-cgi.exe; and PHP container images. Scan owned address space rather than relying on asset records alone.
  • Update internet-facing systems first. Install 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (Windows builds are on php.net), or your distribution’s fixed package, then move on to internal systems.
  • Restart PHP and confirm the fix is live. A patched package does nothing until running processes are replaced. Restart PHP-FPM, Apache and other PHP services, then confirm the version the running service reports.
  • Remi repository users: switch sources. The volunteer-run rpms.remirepo.net repository will not have updates today. PHP recommends switching to distribution packages or building from source. It is common on RHEL-family servers.
  • End-of-life PHP: patch, upgrade or take offline. For 8.1, 8.0 and 7.4, apply a distribution or vendor backport, or build from PHP’s source backports. Anything that cannot be fixed today should be taken offline or restricted to trusted networks until it is.
  • If you cannot update immediately, apply PHP’s interim settings. These reduce exposure but do not make a system safe:
    • Set session.upload_progress.enabled=0 in php.ini, the FPM pool or server configuration, then restart every worker. ini_set() and .user.ini apply too late to help. PHP suggests leaving this off even after patching if you do not use it.
    • Set memory_limit=-1 administratively (for example, php_admin_value) where applications cannot override it. Pair it with a per-worker container or cgroup memory limit, as removing PHP’s limit increases denial-of-service risk.
    • Lower post_max_size to 8M (no uploads) or 32M (uploads), and enforce request size, field, multipart part and header limits at the web server or proxy. If an application does not accept multipart form data, block it at the front end.
    • On PHP 8.5, set fatal_error_backtraces=0 and restart every worker.

Detection & verification

For any internet-facing system that was unpatched after October 20, check for compromise before declaring it remediated. Patching does not remove anything already installed.

  • Worker crashes and memory errors. Both flaws are triggered by forcing out-of-memory and fatal errors. Look for bursts of “Allowed memory size exhausted” errors, PHP-FPM children exiting abnormally, or Apache children crashing, especially repeated from one source.
  • Unusual multipart POSTs. Large multipart requests with no usable Content-Length, very high counts of parts, headers or empty file fields, or deeply nested field names. These can target any PHP URL, not one specific endpoint.
  • Unexpected child processes. PHP or web server processes (php-fpm, php-cgi, httpd, apache2) launching shells, interpreters or download tools, or command lines containing /dev/tcp/, fsockopen or mkfifo.
  • Persistence on the host. New or recently modified PHP files in web roots, unfamiliar plugins or themes, and new cron jobs, scheduled tasks or accounts. A PHP web shell can operate without spawning processes, so file review matters even where EDR is clean.

If you find something

Isolate the server and preserve web server and PHP logs. Report it immediately to security.response@utoronto.ca, and do not rebuild or wipe the system until we have been in touch.

Support

As always, please let us know if you have any questions or concerns or see unusual activity on your systems that you believe might be associated with this or any other vulnerability. Please send these communications to security.response@utoronto.ca.