All articles

php2shell: two critical PHP flaws are patched. Update your site's PHP today

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix CVE-2026-109618 and CVE-2026-109619, two unauthenticated remote code execution flaws. Who is affected, how to check your PHP version and what to do now.

Radek, ENSOMEDIAPublished 8 min readPo polskuAuf DeutschEn españolEn français中文بالعربية

On 21 October 2026 the PHP project released PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. They fix two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619, that can let an attacker run code on a web server without logging in. The PHP team says all PHP users should update immediately (php.net).

If your website runs on WordPress, WooCommerce, Joomla, Drupal or any other PHP software, this concerns you. The flaws are in PHP itself, not in WordPress or a plugin, so updating WordPress does not fix them. Your PHP has to be updated, usually by your hosting company.

What happened

  • 20 October 2026: the PHP security team announced a security release for 21 October 2026 at 14:00 UTC, fixing two critical vulnerabilities rated CVSS v4.0 9.2 (php.net).
  • 21 October 2026, 03:02 UTC: Cloudflare switched on firewall rules against the attack for its customers, including the free plan. Cloudflare says the details leaked before the official release and it saw attack traffic against its customers (Cloudflare blog).
  • 21 October 2026: PHP published the fixed releases and two security advisories, GHSA-w8hw-w9fx-j79w and GHSA-6wmf-4rv5-p3rp, both rated Critical, 9.2.

The two flaws are called "php2shell" (Cloudflare blog, BleepingComputer). The UK National Cyber Security Centre tells organisations to update, and to consider taking a system offline if it cannot be updated or mitigated quickly (NCSC).

Who is affected

According to PHP, every PHP installation that serves web requests is at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP rates the risk highest for mod_php, where a demonstrated exploit works with one unauthenticated request before any application code runs (php.net).

Both advisories list every version below 8.2.35, 8.3.36, 8.4.27 and 8.5.12 as affected (GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp). Older branches are affected too: the NCSC says PHP 5 onwards (NCSC) and Cloudflare says PHP 5.4 or later (Cloudflare blog).

If your site uses PHP and nobody has updated PHP since the afternoon of 21 October, assume it is affected.

How to check which PHP version your site uses

In WordPress: go to Tools > Site Health > Info and open the Server section. It shows the PHP version your site runs on (WordPress.org documentation). If Site Health also says your site is running an outdated version of PHP, treat it as urgent.

In your hosting panel: most panels (cPanel, Plesk, DirectAdmin and host-specific panels) have a page for viewing or choosing the PHP version, often called "PHP version", "PHP selector" or "PHP settings". If you cannot find it, ask your host.

Compare what you see with the fixed versions below. One caveat: Linux distributions and long-term support vendors received the patches in advance and ship their own packages (php.net). Their version number may not match the PHP project's numbers even when the fix is included. If your host uses distribution packages, the reliable answer comes from the host, not from the number alone.

What to do now

1. Get on a fixed version

Your PHP branch Fixed version Support status
8.5 8.5.12 Security fixes until 31 Dec 2029
8.4 8.4.27 Security fixes until 31 Dec 2028
8.3 8.3.36 Security fixes until 31 Dec 2027
8.2 8.2.35 Security fixes until 31 Dec 2026, then end of life
8.1 and older No official release End of life, see below

Fixed versions: php.net. Support dates: PHP supported versions.

If you are on PHP 8.2, update to 8.2.35 now and plan a move to 8.3 or newer. PHP 8.2 gets no security fixes after 31 December 2026 (php.net).

2. If you are on PHP 8.1, 8.0, 7.4 or older

The PHP project no longer releases updates for PHP 8.1 and older. Some distributions and LTS vendors provide backported fixes. Because of the severity, the PHP security team also published minimal source backports for PHP 7.4, 8.0 and 8.1, meant for people who build PHP from source or have no LTS vendor (php.net).

For a typical business website on shared or managed hosting the answer is simpler: switch to a supported version (8.3 or newer) in your hosting panel, or ask your host to do it. Test the site afterwards, because old plugins and themes sometimes break on newer PHP.

3. Ask your host

Send your host a short message:

Hi, is the PHP on my account (domain: example.com) already patched for CVE-2026-109618 and CVE-2026-109619? Which exact PHP version or package am I on, and when will the update be applied if it is not done yet?

If you run your own server and use the volunteer-maintained rpms.remirepo.net repository, PHP says it will not have updates on 21 October and urges switching to distribution packages or building from source (php.net).

4. A firewall buys a few days, it is not the fix

Cloudflare deployed rules for the known attack methods on all plans with the WAF, including Free (Cloudflare blog). Cloudflare's CTO called them a stopgap and told admins to patch (Tenable). PHP itself says there are no complete mitigations and updating is the only safe choice (php.net).

Two limits. Rules cover known attack patterns, and attackers were already changing their payloads to get around them (Cloudflare blog). And the rules protect nothing if attackers can reach your server directly by its IP address, so the origin server should only accept web traffic from Cloudflare (Sansec).

5. If you cannot update today

PHP lists configuration changes that reduce exposure to the known attack paths but do not make a server safe (php.net). They are server settings, so on shared hosting your host has to apply them. Hand this list to your developer or host:

  • For CVE-2026-109618: set memory_limit=-1 in a way applications cannot override (for example php_admin_value in the FPM pool or Apache configuration), set a low post_max_size (8M without uploads, 32M with uploads) with upload_max_filesize below it, and limit request size, field count, multipart parts and headers at the web server or proxy. Do not use RLIMIT_AS or RLIMIT_DATA.
  • For CVE-2026-109619: set session.upload_progress.enabled=0 in php.ini, the FPM pool or server configuration and restart every worker (ini_set() and .user.ini do not work for this). On PHP 8.5, also set fatal_error_backtraces=0 and restart every worker. Remove invalid or deprecated per-request settings that produce warnings.

Technical details

Both flaws come from the same kind of problem: when a request ends abnormally, PHP can leave memory in a broken state that a later step trusts (BleepingComputer, Cloudflare blog).

CVE-2026-109618, RCE via OOM corruption (GHSA-w8hw-w9fx-j79w). PHP uses longjmp() to abort a request when it runs out of memory. In some places request memory is reachable before it is fully initialized. If any allocation fails at that moment, the request shutdown can read the half-built data. Attackers can force the out-of-memory condition with multipart requests: a body without a usable content length, a part with a huge number of headers, or many empty file fields with nested names. With Apache mod_php this happens during automatic body parsing, before any application code runs. Remote code execution as the web worker account was confirmed against mod_php with default input and memory limits. FPM is assessed as susceptible from source analysis, though no complete FPM exploit was demonstrated. The patch replaces longjmp() on out-of-memory with a delayed soft stop at a safe point and a hard _exit() at a higher threshold.

CVE-2026-109619, RCE via stale global state (GHSA-6wmf-4rv5-p3rp). A PHP worker keeps some global state (error, session, object and extension state) that points into memory owned by one request. A fatal error, including running out of memory or Maximum execution time exceeded, can skip the reset of that state. The next request handled by the same worker can then use the freed memory before normal initialization, which is a use after free. Two early consumers are confirmed: warnings from per-request INI settings applied before initialization, and session upload progress, which is on by default and does not need the application to call session_start(). The PHP 8.5 fatal_error_backtraces path is the basis of the confirmed mod_php exploit. The session path was validated against both mod_php and FPM. Hiding errors with error_reporting, display_errors or @ does not protect.

Both advisories score 9.2 with the vector CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N: network attack, no privileges, no user interaction, high attack complexity, and full impact on confidentiality, integrity and availability of the server.

What ShieldWave checks

From outside, nobody can tell whether a server has the patch. What a scan can see is the PHP version the server announces about itself.

  • The free scan at shieldwave.io reads the X-Powered-By response header. If the server reports a PHP version older than the fixed release of its branch, or a branch that gets no fix at all, the report lists a php2shell finding with both CVE numbers and the release you need. Many hosts hide this header, and distributions patch without changing the number, so a finding means "ask your host", and no finding does not prove the server is patched.
  • The Ensomedia Security plugin for WordPress shows the PHP version the site runs on and whether that branch is still supported (plugin page). That catches the worst case in this incident: a site on PHP 8.1, 8.0, 7.4 or older, which gets no official fix. The plugin is free, needs no account, and is in the WordPress.org directory. In your dashboard, go to Plugins > Add New and search for "Ensomedia Security".

For the exact patch level, use Site Health and the table above, and confirm with your host.

Sources

Official:

Other: