Building the AI-native SOC for the 99% of companies who can't justify a $500K stack.
All security advisoriesSecurity advisory

PHP2Shell: Remote Code Execution in PHP

PHP2Shell is a pair of critical flaws in the PHP engine, CVE-2026-109618 and CVE-2026-109619, that let an unauthenticated attacker run code on a web server with crafted HTTP requests. No bug in your application is needed. Exploit details are public and attack traffic has been reported. Update PHP, restart every worker, then hunt for signs of compromise.

Status
Fixed by PHP on 21 October. Distribution packages are still rolling out, and Cloudflare reports attack traffic against its customers.
Affects
PHP serving web requests, before 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and older get no official fix.
Severity
Critical, CVSS 4.0 score 9.2
Primary record
PHP security advisory
Published

Reflects what was publicly known on the last updated date. Every fact links to a primary source at the end of the page.

On this page
  1. Are you affected?
  2. What to do now
  3. Fixed versions
  4. Find every PHP
  5. If you cannot update today
  6. Detect and hunt
  7. WAF and edge protections
  8. How PHP2Shell works
  9. Where sources differ
  10. Timeline
  11. Questions
  12. Sources

Are you affected by PHP2Shell?

Find the row that describes you. If PHP serves anything reachable from the internet, assume you are affected until you have checked.

  • You run PHP web apps or APIs on your own servers or containers

    PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP, LiteSpeed

    Act now

    Update today and restart every PHP process. PHP rates Apache with mod_php as the highest risk. Fixed versions

  • You run PHP 8.1 or older

    Including 7.x and 5.x

    Act now

    Affected, with no official release coming. Install a vendor backport or upgrade to PHP 8.2 or later. CISA advises taking these systems offline until they are fixed.

  • Your PHP runs on a managed host or platform

    Shared hosting, cPanel, Plesk, App Engine, Laravel Cloud

    Update needed

    Confirm with your provider that PHP is patched. Some platforms patched automatically, but custom images and containers are yours to rebuild. Platform status

  • You run products that bundle PHP

    Appliances, control panels, Windows software with php-cgi.exe

    Update needed

    Ask the vendor for a fixed build. The Dutch NCSC keeps a list of products that embed PHP.

  • Your site sits behind Cloudflare, Akamai or another WAF

    A CDN or web application firewall in front of PHP

    Update needed

    Edge rules block known attack shapes and buy time. They do not fix PHP, and they do nothing for traffic that reaches the origin directly. What each covers

  • You only run PHP on the command line

    Scripts, Composer, cron jobs that serve no web requests

    Low risk

    PHP describes the risk as installations that serve web requests. Update with your next routine patch.

What to do now

In order. Most teams can finish the first three today.

  1. Find every PHP that serves web traffic

    Servers, container images, control panels and products that bundle PHP. The PHP that serves requests is often a different install from the one on the command line. How to find them
  2. Update to a fixed version

    Install 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or your distribution’s patched package. Rebuild container images on a patched base image. Patch internet-facing systems first. Fixed versions
  3. Restart every PHP process

    Restart PHP-FPM, Apache, and long-running PHP workers such as queue workers or Laravel Octane. A process that started before the update keeps running the vulnerable code.
  4. If you cannot update today, reduce exposure

    Apply PHP’s temporary measures, or take the system off the internet. The measures block the known attack paths, not all of them.
  5. Hunt for compromise, then rotate secrets

    Servers exposed since 20 October may already have been tried, and one flaw can leak worker memory. Detect and hunt

Fixed versions

As of 21 October 2026, 16:30 UTC. Each row links to the vendor’s own advisory, tracker or changelog. Packages are still shipping, so check the source if your platform is listed as not yet fixed.

PHP releases

Affected and fixed PHP versions by branch
BranchAffectedFixed in
8.58.5.11 and earlier8.5.12
8.48.4.26 and earlier8.4.27
8.38.3.35 and earlier8.3.36
8.28.2.34 and earlier8.2.35
8.1 and olderAll versionsNo official release

For PHP 7.4, 8.0 and 8.1, the PHP security team published minimal source backports for people who build PHP themselves, but no official releases. PHP 8.2 reaches end of life on 31 December 2026.

Operating systems and images

Patched operating system and image versions
SoftwareFixed inSource
Ubuntu 22.04, 24.04, 26.04, 26.10
Ubuntu Pro also has fixes for 14.04, 16.04, 18.04 and 20.04.
php8.1 8.1.2-1ubuntu2.28, php8.3 8.3.6-0ubuntu0.24.04.13, php8.5 8.5.4-0ubuntu1.5, php8.5 8.5.9-0ubuntu2.1Ubuntu CVE tracker
Debian 13 trixiephp8.4 8.4.27-1~deb13u1DSA-6574-1
Debian 12 bookwormphp8.2 8.2.35-1~deb12u1DLA-4848-1
Arch Linuxphp 8.5.12-1Arch package
Docker Official php image
Pull again and rebuild. The RC1 tags do not contain the fix.
8.5.12, 8.4.27, 8.3.36, 8.2.35 tagsdocker-library/php #1694
Windows builds (windows.php.net)8.5.12, 8.4.27, 8.3.36, 8.2.35PHP advisory

Distributions often backport the fix without changing the PHP version number. Ubuntu 24.04’s fixed package is still PHP 8.3.6, for example. Check the package version, not only php -v.

Hosting platforms

Patched hosting platforms
PlatformFixed inSource
cPanel EasyApache 4
EA4 v25.91 also backports the fix to ea-php74, ea-php80 and ea-php81.
ea-php85 8.5.12, ea-php84 8.4.27, ea-php83 8.3.36, ea-php82 8.2.35EasyApache 4 changelog
Plesk on Linux
Fixes for PHP 7.4 to 8.1, and for Plesk on Windows, are in development.
8.5.12, 8.4.27, 8.3.36, 8.2.35Plesk support article
Google App Engine and Cloud Run
Standard environment, and Cloud Run with automatic base image updates. Flexible environment and custom images must be redeployed. PHP 8.1 and older stay vulnerable.
PHP 8.2 and later, patched automaticallyGoogle Cloud blog
Laravel Vapor
Custom and Docker runtimes must be rebuilt.
Native runtimes for PHP 8.3 and laterLaravel blog

Not yet fixed

Platforms without a released fix
SoftwareStatusSource
Red Hat Enterprise LinuxRated Important. No fixed package listed yet.Red Hat CVE page
Amazon Linux 2 and 2023Pending fix. No fix planned for the php8.1 package on Amazon Linux 2023.Amazon Linux security center
SUSE Linux EnterprisePending. Updated packages are in testing.SUSE CVE page
FedoraUpdates submitted and in testing.Red Hat Bugzilla
Debian unstableStill on php8.4 8.4.26.Debian security tracker
Remi’s repositoryNo update on 21 October. PHP suggests distribution packages or building from source.PHP advisory
HomebrewFormulae still on 8.5.11, 8.4.26, 8.3.35 and 8.2.34.Homebrew php formula
Laravel Forge, Ondřej Surý PPAPHP 8.5 is patched. 8.2 to 8.4 are waiting on the PPA.Laravel blog

Until a package arrives for these, apply the temporary measures. If your platform is not listed, check its own security tracker.

Find every PHP

PHP hides in places nobody lists as a PHP server: vendor appliances, control panels, Windows software that ships php-cgi.exe, and container images built months ago. Inventory first, then patch.

On each server

Shell
php -v                        # the command-line PHP
php-fpm -v                    # may be named php-fpm8.3, php-fpm84 and so on
apachectl -M | grep -i php    # any output means Apache loads mod_php

Look for PHP binaries and modules that the package manager does not know about, such as copies bundled with vendor software:

Shell
sudo find / -xdev -type f \
  \( -name 'php' -o -name 'php[0-9]*' -o -name 'php-fpm*' -o -name 'php-cgi*' \
     -o -name 'libphp*.so' -o -name 'frankenphp' -o -name 'lsphp*' \) \
  2>/dev/null

If PHP came from your distribution, check the package changelog for the CVE numbers. A match means the fix is installed.

Debian and Ubuntu
zgrep -E "CVE-2026-10961[89]" /usr/share/doc/php*-common/changelog.Debian.gz
RHEL, Fedora and derivatives
rpm -q --changelog php-common | grep -E "CVE-2026-10961[89]"

In running containers

Shell
for c in $(docker ps -q); do
  printf '%s %s\n' "$c" \
    "$(docker exec "$c" php -r 'echo PHP_SAPI, " ", PHP_VERSION;' 2>/dev/null || echo 'no php')"
done

This shows the command-line PHP inside each container, which is usually the same build that serves requests in official images. Your registry’s image scanner covers images that are not running.

Through the web server

To see the version and settings that live requests actually use, save this as a PHP file with a hard-to-guess name in your web root, request it once, then delete it.

PHP
<?php
echo PHP_SAPI, " ", PHP_VERSION, "\n";
echo "session.upload_progress.enabled=", var_export(ini_get("session.upload_progress.enabled"), true), "\n";
echo "memory_limit=", ini_get("memory_limit"), "\n";
echo "post_max_size=", ini_get("post_max_size"), "\n";

The first line shows the server interface, for example fpm-fcgi or apache2handler for mod_php, and the version. The other lines show whether the temporary measures below are in effect. Do not leave the file in place or use a public phpinfo() page instead.

If you cannot update today

PHP is explicit: there is no complete workaround. These measures break the attack paths that are known, not every variant. Use them only until the update is installed, or take the system offline as CISA and the UK NCSC advise.

Change three PHP settings

From PHP’s advisory. Turning off session upload progress blocks the confirmed session paths for CVE-2026-109619. Removing PHP’s own memory limit and capping request size reduces exposure to CVE-2026-109618. Set them in server configuration so applications cannot change them, then restart every PHP process.

PHP-FPMAdd to each pool file, for example /etc/php/8.3/fpm/pool.d/www.conf
FPM pool
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
Apache with mod_phpAdd to the server or virtual host configuration
Apache
php_admin_flag session.upload_progress.enabled off
php_admin_value memory_limit -1
php_admin_value post_max_size 8M
php.iniFor other setups. Check that no pool or virtual host overrides it
php.ini
session.upload_progress.enabled = 0
memory_limit = -1
post_max_size = 8M
  • Use post_max_size = 32M if your application accepts uploads, and keep upload_max_filesize below it.
  • On PHP 8.5, also set fatal_error_backtraces to off the same way. It removes the producer behind the confirmed mod_php exploit.
  • With no PHP memory limit, one request can use all the memory on the host. Cap memory with a container or cgroup limit instead, ideally one that kills only the affected worker. Do not use RLIMIT_AS or RLIMIT_DATA: PHP says these trigger the vulnerable allocation failure.
  • Setting these with ini_set() or a .user.ini file does not work.
  • PHP suggests keeping session upload progress off even after patching if you do not use it, since attackers are now studying this rarely used feature.

Remove per-request PHP settings that warn

The technical advisory for CVE-2026-109619 shows that an invalid or deprecated PHP setting applied per request can be enough to consume stale state, even when the warning is never displayed or logged. Under mod_php that means php_value and php_flag in Apache configuration or .htaccess. Under PHP-FPM it means PHP_VALUE or PHP_ADMIN_VALUE sent by nginx or another frontend. Find them, then remove any that PHP reports as deprecated or invalid.

Shell
# Apache: per-directory PHP settings, applied before request startup under mod_php
sudo grep -rnE "php_(admin_)?(value|flag)" /etc/apache2 /etc/httpd 2>/dev/null
sudo find /var/www -name .htaccess -exec grep -HnE "php_(value|flag)" {} + 2>/dev/null

# nginx and other FastCGI frontends: settings passed to PHP-FPM per request
sudo grep -rnE "PHP_(ADMIN_)?VALUE" /etc/nginx /etc/apache2 /etc/httpd 2>/dev/null

Silencing diagnostics with error_reporting, display_errors or @ does not help: the stale state is touched before PHP decides whether to report the warning.

Bound requests at the frontend

Both PHP advisories recommend limiting decoded request size, input field count, multipart part count, headers per part and nesting depth at the web server or proxy, including for requests without a usable Content-Length. If an application does not accept multipart form data at all, the technical advisory for CVE-2026-109618 says to block it before it reaches PHP. Sansec gives the same advice. This breaks every upload form and some checkout forms.

nginxInside the server block
nginx
if ($http_content_type ~* "multipart/form-data") { return 403; }
ApacheInside the <Directory> block for your web root. Requires mod_rewrite
Apache
RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart/form-data [NC]
RewriteRule ^ - [F]

The Apache rule must sit inside the <Directory> block that applies to your web root: rewrite rules in the global server configuration are not inherited by virtual hosts unless you enable that. Send a test multipart request to confirm it returns 403.

Detect and hunt

The attack runs inside PHP before your application starts, so application logs usually show nothing. CrowdStrike reports that a successful exploit can return a normal HTTP 200 without crashing the worker. Hunt on what PHP does next, not on what the application saw.

1. The log line an attempt leaves

According to CrowdStrike, the one server-side trace of an out-of-memory attempt is a fatal error reported in Unknown on line 0, meaning no PHP file was running when memory ran out. Ordinary memory errors name a script and a line. Adjust the paths to your layout.

Shell
sudo grep -hE "Allowed memory size of [0-9]+ bytes exhausted .* in Unknown on line 0" \
  /var/log/apache2/error.log* /var/log/httpd/error_log* \
  /var/log/php*-fpm.log* /var/log/nginx/error.log* 2>/dev/null

On systemd hosts the same lines, plus workers dying, may be in the journal. PHP-FPM ends a child whose request startup fails, so a burst of child exits is also worth a look.

Shell
sudo journalctl --since "2026-10-20" -u 'php*-fpm*' -u apache2 -u httpd \
  | grep -E "in Unknown on line 0|exited on signal|exited with code"

A match is a reason to investigate the requests around it, not proof of compromise. Large legitimate uploads can produce similar errors.

2. Request and response shapes

Wiz lists the signals it saw while developing exploits:

  • Unusual multipart requests, often to paths that never accept uploads, followed by memory errors or repeated HTTP 500 responses.
  • Large or garbled PHPSESSID cookies in responses, especially from applications that do not use sessions. This is how the memory disclosure variant returns leaked memory.
  • PHP workers exiting or being replaced with no clear cause.

Default access logs do not record the content type or request size, so these requests look like any other POST. If you front PHP with nginx, a temporary log format makes them visible:

nginx
log_format php2shell '$remote_addr [$time_iso8601] "$request" $status '
                     'ct="$content_type" len=$request_length '
                     'up_status=$upstream_status up_time=$upstream_response_time';
access_log /var/log/nginx/php2shell.log php2shell;

Look for multipart/form-data POSTs with a large len to routes that take no uploads, and for runs of 500 or 502 upstream statuses from one source. WAF and CDN logs that capture response headers are the best place to look for oversized session cookies.

3. What PHP starts

The highest-signal detection after a successful attack is process lineage. Huntress and CISA both point to PHP or web server processes such as php-fpm, php-cgi, httpd or apache2 starting:

  • Shells: sh, bash, cmd.exe, powershell.exe.
  • Interpreters and tools: python, perl, curl, wget, nc, certutil.exe.
  • Reconnaissance: whoami, id, uname -a, ipconfig.
  • Command lines with reverse shell patterns such as /dev/tcp/, fsockopen or mkfifo.

If you collect Linux process creation events in a SIEM, this Sigma rule is a starting point. Tune the child list against what your applications legitimately run before you page anyone on it.

Sigma
title: Shell or download tool started by a PHP web worker
id: 4a741ee5-edbc-4637-acec-65adb7263448
status: experimental
description: >
  A PHP web worker starting a shell, interpreter or network tool. Common after
  remote code execution such as PHP2Shell (CVE-2026-109618, CVE-2026-109619).
references:
  - https://www.huntress.com/blog/php2shell-leaked-critical-php-vulnerabilities
logsource:
  product: linux
  category: process_creation
detection:
  parent:
    ParentImage|contains:
      - '/php-fpm'
      - '/php-cgi'
      - '/apache2'
      - '/httpd'
      - '/lsphp'
      - '/frankenphp'
  child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/python'
      - '/python3'
      - '/perl'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
      - '/whoami'
      - '/id'
      - '/uname'
  condition: parent and child
falsepositives:
  - Applications that legitimately shell out, such as image or PDF tooling
level: high
tags:
  - attack.initial-access
  - attack.t1190
  - attack.execution
  - attack.t1059

On hosts with no endpoint agent, an audit rule on the web server account gives you the same visibility from the kernel:

auditd
# Log every program started by the web server account (www-data is uid 33 on Debian
# and Ubuntu; use the apache or nginx uid on RHEL). Review the volume before keeping it.
sudo auditctl -a always,exit -F arch=b64 -S execve -F euid=33 -k php-worker-exec
sudo ausearch -k php-worker-exec -i | grep -E "proctitle=|exe="

Florian Roth’s free process-watcher does the same with eBPF and ships a PHP configuration kit. It needs root and Linux 5.15 or newer with BTF, and it detects processes only: code that runs inside PHP without starting a program is invisible to it.

4. Files and persistence

After code execution, attackers usually drop a web shell and make sure they can come back. Huntress recommends looking for new files in the web root and writable folders, and for new cron jobs, scheduled tasks and accounts.

Shell
# PHP files written since the leak in web, upload and temporary folders
sudo find /var/www /tmp /var/tmp /dev/shm /var/lib/php \
  -type f \( -name '*.php' -o -name '*.phtml' -o -name '*.phar' \) \
  -newermt "2026-10-20" -ls 2>/dev/null

# Persistence: web user crontabs, new accounts, SSH keys
sudo crontab -u www-data -l 2>/dev/null
sudo find /etc/cron* /var/spool/cron -newermt "2026-10-20" -ls 2>/dev/null
sudo find / -xdev -name authorized_keys -newermt "2026-10-20" -ls 2>/dev/null

Deployments also write new files, so compare against your release history. A PHP file in /tmp, /dev/shm or an upload folder is suspicious on its own.

5. Outbound connections

Web servers talk to a short, stable list of hosts: databases, caches, a few APIs. A PHP worker connecting anywhere else is worth explaining. On the host:

Shell
# Live outbound connections held by PHP or web server processes
sudo ss -tnpH state established | grep -E '"(php-fpm[^"]*|php-cgi|apache2|httpd|lsphp)"'

A snapshot only catches live connections. For history, use VPC flow logs, firewall logs or DNS logs, and look for web tier hosts reaching new destinations since 20 October. Default-deny egress for the web tier is the control that turns this from a hunt into a block.

6. If you find something

  • Isolate the host and preserve web server, PHP and system logs before you rebuild anything.
  • Rebuild from a known-good image on a fixed PHP rather than cleaning in place.
  • Rotate every secret the host could read: database passwords, API keys, cloud credentials, session signing keys. The memory disclosure variant means this applies even without signs of code execution.
  • Check what those credentials touched after 20 October in your cloud and database audit logs.

If you think you have found a compromise and want a second pair of eyes, talk to our team.

WAF and edge protections

Several providers have shipped rules that block the known attacks, some on by default. They are worth having while you patch. Do not depend on them.

Why an edge rule is not enough

  • The rules recognise attack shapes known so far. Cloudflare reports attackers already mutating payloads to get past its rules, and Wiz says more variants exist than the published ones.
  • They only see traffic that passes through the provider. If your origin is reachable directly, the rules do nothing. Allow inbound connections only from the provider’s IP ranges.
  • Some are off until you turn them on, or only log matches instead of blocking them.
  • Cloudflare calls its rules defence in depth, Fastly calls its virtual patch partial protection, and the PHP2Shell researchers say not to treat a rule as a substitute for updating PHP.

What each provider has announced

Protections announced by security providers
ProviderWhat it doesWhat you need to doSource
Cloudflare WAFManaged rules on by default for every plan, including Free, since 03:02 UTC on 21 October. A new response-side rule inspects what the origin sends back and can block it.Free: nothing. Pro, Business and Enterprise: confirm the Cloudflare Managed Ruleset is set to block, not log.Cloudflare blog
Akamai App & API ProtectorAdaptive Security Engine rule 3000991, plus existing command injection rules that Akamai says stop weaponised payloads.Akamai does not say whether the rule is on by default. Check that it is active and blocking.Akamai blog
Fastly Next-Gen WAFA virtual patch for both CVEs that looks for the request shapes these attacks use.Apply the virtual patch to each service yourself. Fastly then updates it automatically.Fastly blog
Cisco SnortIntrusion prevention signatures 67359 and 67360, also in the free Community Ruleset.Update your ruleset and make sure the signatures block rather than alert.Cisco Talos
WordPress VIPAutomattic says every site on its platform was protected before the release.Nothing.WordPress VIP notice
CrowdStrike FalconDetects what attackers do after getting in, such as web shells and shells started by PHP. It does not block the attack itself.Make sure someone acts on the alerts.CrowdStrike blog
Wiz SensorA response policy that terminates processes behaving like a PHP2Shell exploit.Turn the policy on. It needs sensor version 1.0.12768 or later.Wiz blog

Wiz also credits AWS, Microsoft, Imperva and Vercel with preparing mitigations, but none had published anything specific on their own sites at the time of writing. The general PHP rule groups in AWS WAF and Google Cloud Armor are not specific to these flaws. If your provider is not listed, ask it directly.

How PHP2Shell works

PHP2Shell is two flaws in Zend, the engine inside every PHP build. When PHP hits a fatal condition, such as exhausting memory_limit or exceeding the execution time, it jumps straight out of whatever it was doing with longjmp(). Nothing in between runs cleanup, and CrowdStrike describes how PHP then proceeds into a normal shutdown that assumes every structure is consistent. Because PHP parses the request body before any application code is compiled, exploitation does not depend on what the server hosts. Wiz notes that even a one-line Hello World page on an affected version can be attacked.

CVE-2026-109618: out-of-memory corruption

A crafted request makes PHP run out of memory while a data structure is half built, for example while it is adding a form field to $_POST. The cleanup of that same request then reads the half-built entry as if it were valid. The technical advisory lists several ways to reach out-of-memory while staying within PHP’s apparent limits, including multipart bodies with no usable length, parts with unbounded headers, and empty file fields that do not count towards max_file_uploads.

Exposure depends on the server interface. Apache with mod_php always runs request shutdown, even when startup failed, so the whole attack completes before any application code runs. PHP confirmed full code execution there with default settings. PHP-FPM ends the child when startup fails, which blocks that exact path. PHP still considers FPM susceptible through other paths, but had not demonstrated a complete FPM exploit for this CVE. FrankenPHP behaves like mod_php on source analysis.

CVE-2026-109619: stale state across requests

A worker keeps some state between requests: session, error, decoder and extension state. If a request is aborted before that state is reset, it keeps pointing into memory that has been freed. The next request handled by the same worker can use it before normal initialisation replaces it, a use-after-free that a prepared heap layout turns into code execution or memory disclosure.

The technical advisory confirms two early consumers of that stale state: session upload progress, which is on by default and needs no session_start(), and warnings raised by per-request PHP settings. On PHP 8.5, the new fatal error backtraces feature provides the producer behind the strongest confirmed mod_php exploit. A validated PHP-FPM path also exists, though it depends on a suitable operation in the application.

Memory disclosure

Separately from code execution, Wiz showed that the session upload progress path can return a region of freed worker memory to the attacker inside a PHPSESSID response cookie. That memory can hold passwords, tokens, API keys and data from other users’ requests. This is why patching alone does not close the incident for exposed servers: rotate what they held.

Why it took so long

The PHP Foundation calls the time it took to ship a fix a structural failure. First signs of the memory problem surfaced in a 2024 audit, and work on a fix stalled until the reports in August 2026. Wiz attributes the speed of the eventual exploit work to frontier AI models, which made it practical to adapt a complex memory exploit to each target’s layout. Expect attackers to have the same advantage. The fix itself removes longjmp() from out-of-memory handling and resets the wider request state, which closes the known variants.

Where sources differ

Early reporting disagrees in places. What each source says, and how we read it.

Points where sources disagree
QuestionWhat the sources sayOur reading
Which versions are affectedPHP’s CVE records list only 8.2 to 8.5. Wiz, Cloudflare and Talos say every version since PHP 5.4 is affected, and PHP itself published source backports for 7.4, 8.0 and 8.1.Treat every version before the fixed releases as affected.
Which bug belongs to which CVEPHP’s advisory places the session upload progress bug under CVE-2026-109619. The table in Wiz’s post places it under CVE-2026-109618.We follow PHP. The same release fixes both, so it does not change what you do.
How severe it isPHP scores both CVEs 9.2 under CVSS 4.0. Red Hat rates them Important, 8.1 under CVSS 3.1. The 10.0 score that leaked on 20 October was wrong.Different scoring systems. Treat it as critical for anything serving web traffic.
What an attack looks likeWiz points to memory errors, repeated HTTP 500 responses and worker churn. CrowdStrike says its successful exploit left the worker running and returned a normal HTTP 200, with nothing in application logs.Both can be true for different variants. Hunt for the failures, but do not treat their absence as proof of safety.
Whether it is being exploitedCloudflare reports attack traffic and attackers adapting payloads to evade its rules. CISA, Talos and Huntress had not observed exploitation on 21 October.Probing is confirmed. Assume internet-facing servers are being tried.

Several posts written before PHP’s advisory describe only the upload progress path and present turning that setting off as a complete fix. PHP’s own advisory says it is not. The Swiss NCSC also notes that a firewall alone is not sufficient.

Timeline

Times are UTC. Discovery dates come from the PHP Foundation’s and Wiz’s accounts.

  1. 2026-07-30

    2026-07-30

    Security firm Calif begins an audit of PHP under the Patch the Planet program.

    PHP Foundation

  2. 2026-08-11

    2026-08-11

    Calif reports an unauthenticated remote code execution flaw. OpenAI independently reports the same root cause on the same day.

    PHP Foundation

  3. 2026-08-19

    2026-08-19

    Wiz Research finds its first variant and confirms unauthenticated code execution against Drupal the next day.

    Wiz Research

  4. 2026-08-24

    2026-08-24

    Wiz Research reports further ways to attack the same flaws.

    PHP Foundation

  5. 2026-09-18

    2026-09-18

    OpenAI reports further attack paths.

    PHP Foundation

  6. 2026-10-20

    2026-10-20about 15:00 UTC

    The CVE numbers leak on forums and social media, with an incorrect score of 10.0. No technical details leak.

    PHP Foundation

  7. 2026-10-2019:30 UTC

    PHP pre-announces the release for 14:00 UTC on 21 October, a day ahead of the original embargo.

    PHP advisory

  8. 2026-10-20about 20:00 UTC

    Calif mistakenly publishes a video of a working exploit. It is deleted, but copies circulate.

    PHP Foundation

  9. 2026-10-21

    2026-10-2103:02 UTC

    Cloudflare turns on WAF rules for all plans, including Free, and later reports attack traffic against its customers.

    Cloudflare blog

  10. 2026-10-2113:30 UTC

    PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35 and publishes its advisory. Ubuntu, Debian, Arch, cPanel and Plesk ship fixes the same day.

    CERT-EU advisory 2026-018

  11. 2026-10-21

    CISA urges immediate patching and says it has not observed exploitation. Cisco Talos ships Snort signatures 67359 and 67360.

    CISA alert

The exploitation status was checked against the CISA Known Exploited Vulnerabilities catalog, which did not list either CVE on 21 October.

PHP2Shell questions

Short answers. The sections above have the detail and sources.

What is PHP2Shell?

PHP2Shell is the name for two critical flaws in the PHP engine, CVE-2026-109618 and CVE-2026-109619. Both come from how PHP cleans up after a request is aborted by a fatal error such as running out of memory. A crafted request can turn that cleanup into remote code execution or a leak of server memory, with no login and no bug in the application.

Which PHP versions fix PHP2Shell?

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released on 21 October 2026. PHP 8.1 and older are affected but get no official release, so install a vendor backport or upgrade to PHP 8.2 or later. Distribution packages often keep the old version number, so check the package changelog for the CVE numbers.

Is PHP2Shell being exploited?

Cloudflare reports attack traffic against its customers and attackers changing payloads to get past its rules. CISA, Cisco Talos and Huntress had not observed exploitation on 21 October 2026, and the flaws were not in the CISA Known Exploited Vulnerabilities catalog. Treat internet-facing PHP as being probed.

How do I tell if my server was attacked?

Look for out-of-memory errors reported in Unknown on line 0 in the web server or PHP error log, PHP worker processes starting shells or download tools, new PHP files in web, upload or temporary folders, and outbound connections from web servers. A successful attack can return a normal HTTP 200 and leave nothing in application logs, so a clean log does not prove a server is safe.

Does Cloudflare or another firewall protect me from PHP2Shell?

Only partly. Cloudflare blocks known attacks by default on every plan, Akamai has a dedicated rule, and Fastly offers a virtual patch you must apply. These rules cover known attack shapes and only traffic that passes through the provider. They buy time. Update PHP anyway.

Is there a workaround if I cannot update PHP yet?

Not a complete one. PHP recommends turning off session.upload_progress.enabled, setting memory_limit to -1 with a container or cgroup memory limit instead, and lowering post_max_size, all in server configuration, then restarting every PHP process. On PHP 8.5 also turn off fatal_error_backtraces. These block the known attack paths only.

Do I need to restart PHP after updating?

Yes. Restart PHP-FPM, Apache and any long-running PHP workers such as queue workers. A process that started before the update keeps running the vulnerable code.

Should I rotate secrets after patching?

Yes, for internet-facing PHP servers. One of the flaws can leak worker memory, which can contain passwords, tokens, API keys and data from other requests. Rotate the secrets those servers hold once they are patched.

Sources