Cybersecurity

PHP2Shell: Critical PHP RCE (CVE-2026-109618) Explained

PHP2Shell: Critical PHP RCE (CVE-2026-109618) Explained

PHP2Shell is the name given to two critical vulnerabilities in the PHP engine, CVE-2026-109618 and CVE-2026-109619, fixed on 21 October 2026 in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. They let an unauthenticated attacker execute code remotely (RCE) on the web server with the privileges of the PHP process, in many cases before any application code runs. WordPress, Drupal, Joomla, Magento, Nextcloud or a Laravel app cannot protect you, because the flaw sits below them, in the interpreter. Italy’s National Cybersecurity Agency issued alert AL07/261021/CSIRT-ITA rating the systemic impact as high.

What to do today, in short:

  • Update PHP to the fixed release of your branch (or your distribution’s patched package) and restart every PHP-FPM / Apache worker.
  • If you cannot update right away: apply the official temporary mitigations and consider, as several national CERTs recommend, taking exposed services offline until they are patched.
  • Review your logs for signs of exploitation: repeated out-of-memory errors, worker crashes, unexpected processes and files.

The full procedure for each distribution is in the companion tutorial: PHP2Shell Fix: Patch PHP on Linux, Docker and Windows.

What is PHP2Shell

Both flaws were reported to the PHP team in August 2026 by researchers from Calif, Wiz and OpenAI and fixed in the 21 October security release. The researchers’ technical write-up is on calif.io; the official details are in the two GitHub advisories of the PHP project.

Both are use-after-free bugs (CWE-416) scored CVSS v4.0 9.2, vector AV:N/AC:H/AT:P/PR:N/UI:N: exploitable over the network, with no credentials and no user interaction, according to advisories GHSA-w8hw-w9fx-j79w and GHSA-6wmf-4rv5-p3rp.

CVE Official name What happens
CVE-2026-109618 RCE via OOM corruption An out-of-memory error interrupts PHP while an internal structure is half-initialized; request cleanup treats it as valid and corrupts memory
CVE-2026-109619 RCE via stale global state Global state (errors, session, extensions) survives after its memory is freed; a later request on the same worker reuses it

CVE-2026-109618: running out of memory at the wrong moment

PHP handles memory_limit exhaustion by aborting the request with longjmp(). If the abort happens while an internal structure has been allocated but not yet initialized, the shutdown phase still processes it. The official advisory identifies several ways to trigger the out-of-memory condition on demand while parsing multipart requests (ordinary file uploads), staying within the configured limits: a missing or unusable content length, unlimited headers per part, and empty file fields combined with nested field names.

The key point: with default settings (memory_limit 128M, post_max_size 8M) the attack works, and Apache mod_php is confirmed exploitable. The fix removes the longjmp() path: memory exhaustion is now handled at the next safe point of the VM, with an immediate process exit above a higher threshold.

CVE-2026-109619: global state that outlives the request

A PHP worker serves many requests in sequence. If a fatal error, a timeout or an out-of-memory condition interrupts the end-of-request reset, some global pointers keep pointing at freed memory. The next request handled by the same worker can use them before normal initialization, for example through session upload progress tracking (session.upload_progress) or per-directory INI handling. On PHP 8.5, fatal error backtraces can also leave this stale state.

Vulnerable and fixed PHP versions

Branch Vulnerable Fixed Branch status
PHP 8.5 < 8.5.12 8.5.12 supported
PHP 8.4 < 8.4.27 8.4.27 supported
PHP 8.3 < 8.3.36 8.3.36 supported
PHP 8.2 < 8.2.35 8.2.35 security fixes only
PHP 8.1, 8.0, 7.4 all no official release end of life: source backports only
PHP 7.3 and older from 5.4 onward none end of life

According to the researchers, the oldest vulnerable path dates back to PHP 5.4.0 (Calif). For end-of-life branches the PHP project published only minimal source backports for 7.4, 8.0 and 8.1, with no binaries (php.net). If you run these branches, rely on your distribution’s packages (many patched old versions too) or move to a supported branch.

Mind the version number. Debian, Ubuntu, RHEL and AlmaLinux backport the fix into their own packages without changing the upstream version: a patched Ubuntu 24.04 still reports PHP 8.3.6 in php -v. Check the package, not the version string. The tutorial shows how.

Who is exposed

The PHP project lists every installation that serves web requests as at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed (php.net). The picture by deployment type, from the official advisories:

  • Apache + mod_php: highest risk. Exploitation demonstrated with a single unauthenticated request, before application code runs.
  • PHP-FPM (Nginx, Apache with proxy_fcgi): conditionally exposed. An FPM worker exits when startup fails, which blocks some paths, but it remains exploitable through session.upload_progress and PHP_VALUE parameters sent by the frontend.
  • php-cgi (e.g. IIS/FastCGI on Windows), FrankenPHP, LiteSpeed (LSAPI): considered likely susceptible, although the same path was not demonstrated in default configuration.
  • Command-line PHP (CLI): scripts and cron jobs do not serve web requests and are not the target, but the package must be updated anyway.

The researchers confirmed the issue, in some cases as pre-authentication RCE, on widely used applications: WordPress, Drupal, Joomla, MediaWiki, Roundcube, Magento, phpMyAdmin, Nextcloud, Laravel, Symfony and WHMCS (Calif). These applications are not at fault: the interpreter running them is. For the same reason, updating WordPress or its plugins does not fix PHP2Shell.

Is it exploited in the wild?

The sources do not fully agree yet, so read them carefully:

  • Amazon recorded an exploitation attempt on 17 October, four days before disclosure, on its MadPot honeypots (Help Net Security).
  • On 20 October details leaked before the coordinated disclosure (Armis); watchTowr reports active exploitation seen across its honeypot network (watchTowr).
  • Italy’s ACN, as of 21 October, lists no public PoC and no known exploitation, and the flaws are not in CISA’s KEV catalog (ACN).

The operational conclusion is the same either way: a pre-authentication flaw in such a widespread component, with details already out and at least one attempt observed, means the patch window is measured in hours, not weeks.

What to do now: the checklist

  1. Inventory. List every server with exposed PHP, including containers, managed hosting and appliances that bundle PHP (control panels, webmail, business software). For each, note branch, SAPI (mod_php or FPM) and distribution.
  2. Prioritize. Internet-facing mod_php servers first, then FPM; applications with no authentication in front (public sites, upload forms, webmail) first.
  3. Update to the fixed package and restart the workers: an update without a restart leaves vulnerable code in memory.
  4. Verify the installed package (not just php -v).
  5. If you cannot update: temporary mitigations and, if the service is not critical, shut it down or put it behind authentication.
  6. Hunt for signs of compromise on servers that stayed exposed in recent days.

Every step, with commands for Debian, Ubuntu, RHEL/AlmaLinux/Rocky, Docker and Windows, is in the tutorial: PHP2Shell Fix: Patch PHP on Linux, Docker and Windows.

Temporary mitigations (not enough on their own)

The PHP project is explicit: the only complete mitigation is updating. The following measures reduce some attack paths, not all of them (GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp):

  • session.upload_progress.enabled = 0, set administratively (php.ini, FPM pool, Apache config) followed by a restart of every worker. It does not work through ini_set() or .user.ini. The PHP developers recommend keeping it off even after patching if your application does not use the feature.
  • memory_limit = -1 via php_admin_value, together with a service or container (cgroup) memory limit: it removes the simplest trigger of CVE-2026-109618 but exposes the server to running out of RAM. Avoid RLIMIT_AS and RLIMIT_DATA, which cause exactly the vulnerable allocation failure.
  • A conservative post_max_size (8M without uploads, 32M with uploads) and limits on request size, multipart parts and headers at the reverse proxy or WAF.
  • PHP 8.5 only: fatal_error_backtraces = 0.
  • Risk reduction: pm.max_requests = 1 on FPM pools if performance allows, since a worker that serves a single request cannot reuse stale state.

Turning off display_errors, using the @ operator or changing error_reporting does not protect you.

The major WAF vendors have shipped dedicated rules (Cloudflare made them available on the free plan too, according to Help Net Security): useful as a safety net, not as a substitute for the patch.

Read also: Nginx Reverse Proxy: Secure HTTPS, Headers, and Rate Limiting

How to spot an attack attempt

Italy’s ACN recommends reviewing logs regardless of patch status, looking for (ACN):

  • anomalous HTTP requests, especially very large multipart POSTs or ones with an unusual number of fields;
  • recurring Allowed memory size of ... bytes exhausted errors;
  • PHP process crashes (segmentation faults in FPM workers or Apache children);
  • unexpected processes spawned by the web server user (www-data, apache, nginx);
  • unauthorized changes to application files and abnormal outbound network connections.

Ready-made commands to search for these signals are in the tutorial. If anything turns up, treat the server as compromised: isolate it, investigate, rotate credentials.

Read also: ACN Incident: 24-Hour Notification Checklist

Why PHP2Shell is different from the usual web flaws

Most vulnerabilities hitting PHP sites live in a plugin, a theme or a framework, and are closed by updating that component. PHP2Shell lives in the interpreter: any application is a possible entry point, and application-level defenses (security plugins, WordPress scanners) cannot see it. It is also a telling example of the role of AI tools in vulnerability research: the researchers say they used language models to find and generalize the bug, which was rooted in a problem known for years but never turned into an exploit (Calif).

For anyone running servers, the practical lesson is simple: keep an up-to-date inventory of runtime versions (PHP, but also Java, Node.js, Python) and a patch process that measures reaction time in hours.

Read also: Linux Hardening: 15-Point Checklist for Production (2026)

PHP2Shell FAQ

Is my WordPress site vulnerable to PHP2Shell?

It depends on the server’s PHP version, not on the WordPress version. If the site runs on unpatched PHP (any branch from 5.4 to 8.5 without the 21 October 2026 fix), it is exposed. On shared or managed hosting, updating is the provider’s job: ask for written confirmation that your PHP includes the fixes for CVE-2026-109618 and CVE-2026-109619.

php -v shows an old version: am I vulnerable?

Not necessarily. Linux distributions backport the fix without changing the upstream version number. Check the package version (dpkg -l or rpm -q) and look for the two CVEs in the changelog.

I run PHP 7.4 or 8.1: is there a patch?

The PHP project does not ship binaries for end-of-life branches, but it published source backports for 7.4, 8.0 and 8.1. Ubuntu, Debian, AlmaLinux and other distributions shipped patched packages for old versions too, some only through extended support (Ubuntu Pro). The lasting fix is moving to a supported branch.

Is a WAF enough?

No. WAF rules lower the risk while you patch, but there are several attack paths and new variants will appear. The only complete fix is updating PHP and restarting the workers.

Do I need to restart anything after updating?

Yes: PHP-FPM and/or Apache. Until the workers restart, vulnerable code stays in memory.

Sources

Share this article:

Written by

Rosario Giordano

Rosario Giordano is a system administrator and IT consultant specializing in cybersecurity and cloud, with over 20 years of experience managing enterprise Linux infrastructures. His areas of expertise include SSH hardening, Kubernetes platforms, PostgreSQL databases, VMware/ Proxmox virtualization, and compliance with NIS2 and ISO 27001 security frameworks