At 21:33 CEST on Tuesday, 20 October, PHP pre-announced two critical vulnerabilities, with a fix due the next afternoon. A hosting provider running cPanel servers read that notice and saw the problem straight away. The fix would cover PHP 8.2 to 8.5 only. The sites hosted on their servers run every PHP version from 5.2 up, because each site stays on the version its application was built for.
PHP’s release would fix four branches. Those servers run 16.
The standard PHP security advice is to run a supported version and wait for your vendor. By the time TechCrunch called the week the “PHP-ocalypse“, that advice had a visible gap: somebody has to own the branches upstream has dropped. During PHP2Shell (CVE-2026-109618 and CVE-2026-109619), CloudLinux did.
CloudLinux shipped fixed ea-php (cPanel’s EasyApache PHP builds) and alt-php (CloudLinux’s PHP builds behind PHP Selector) for all 16 branches from 5.2 to 8.5, plus native PHP packages for every affected version.
The Imunify360 web application firewall (WAF) had been blocking the public exploit since the morning of 21 October, hours before PHP’s fix.
PHP2Shell is two remote code execution flaws in PHP itself, both scored 9.2 on CVSS v4.0 and neither needing a login.
In CVE-2026-109618, PHP runs out of memory mid-request, and cleanup treats the half-built data as valid. In CVE-2026-109619, one request’s state survives after its memory is freed, and the next request on the same worker can use it.
PHP2Shell sits below the application. PHP reads the request before the site’s code runs, so any PHP script on the server will do, whether or not it handles forms. The site’s own PHP application security never gets a say because the flaw triggers before that code starts.
PHP lists every web-facing setup as affected (PHP-FPM, mod_php, php-cgi, FrankenPHP, and LiteSpeed) and rates the risk highest on Apache with mod_php.
The exploit toolkit came first.
Details leaked on 20 October, and a public tool, also called PHP2Shell, went live before the fix. It abuses session upload progress, which is on by default. Some requests carry a User-Agent starting php2shell-, but about two-thirds of those carrying the tool’s multipart boundary used a different one.
The nine guides that ranked for PHP security on 26 October all end on the same instruction: run a supported version. On a shared hosting server, that advice reaches the wrong person.
A shared server holds hundreds of accounts, each pinned to the PHP version its application was written for. A shop module that breaks on PHP 8 doesn’t care about php.net’s calendar.
That is why PHP Selector, which lets each account pick its PHP version, supports PHP 5.2 to 8.5.
The provider can’t force everyone onto PHP 8.4. Forced upgrades break sites, and broken sites come back as tickets and churn. Providers already pay for it: 53% name outdated or vulnerable software as their top security challenge, and security incidents take 35% of their support time.
So when PHP says “upgrade,” a hosting provider hears a different question. Who patches the version my customer is stuck on, and how fast?
Imunify360 telemetry recorded the first request from the public exploit tool at 01:33 CEST on 21 October, four hours after PHP’s notice and 14 hours before its fix. From about 10:20, scanning scaled up sharply, and by 13:00 requests naming the PHP2Shell exploit tool had reached more than 3,600 servers in the Imunify360 network.
The WAF got there first. At 11:10, Imunify360 ruleset 8.83 reached stable and blocked the known exploit request on ModSecurity and Coraza, about 4.5 hours before PHP’s fix. The rule matches how the request is built, not the tool’s name, so requests that hid the name were blocked too.
Around noon, an IP reputation rule began sending exploiting addresses to a CAPTCHA on every protected server. Over three days, five ruleset releases extended blocking to LiteSpeed, caught renamed variants of the tool, added a logging rule for malformed session cookies, and blocked a serialized object in the upload progress field. The Imunify360 coverage table by web server shows what each setup had, and when.
From 21 to 26 October, the dedicated PHP2Shell rules matched about 9 million times. Blocking rules accounted for about 6.25 million of those matches, and 99% of them were on requests the WAF denied. The public tool’s fingerprint appeared in 62% of all matches.
PHP released 8.2.35, 8.3.36, 8.4.27, and 8.5.12 at 15:45. That left four released fixes to package, source backports for 7.4, 8.0, and 8.1, and nothing for the nine branches from 5.2 to 7.3. The build team paused other builds and wrote the missing fixes itself.
The result covered every branch a hosting server runs. Fixed ea-php shipped for all 16 branches, ea-php52 to ea-php85, on CloudLinux 7 to 10. Fixed alt-php shipped for all 16 branches on CloudLinux 7, 8, and 9. Native PHP packages followed for every affected version, and TuxCare Endless Lifecycle Support (ELS) released packages for alt-php, distribution PHP, and PHP for Windows. Each arrived as a normal package update.
What shipped for PHP2Shell
Source: the CloudLinux advisory, which lists every fixed package and version.
Timeline: PHP2Shell response, 20 to 23 October 2026 (CEST)
Everything in the WAF lane before 15:45 on 21 October was in place before PHP released its fix.
Not all of it went well. The first fixed alt-php and ea-php packages kept their old version numbers, so scanners flagged patched servers as vulnerable. On 21 October, we announced fixed alt-php for CloudLinux while it sat only in the TuxCare ELS repository; the correction took about three hours (customers hit the gap before the correction went out).
Servers with the WAF off, in log-only mode, or running ImunifyAV, Imunify’s malware scanner, had no WAF protection. As of 26 October, the blocking rules still target the upload progress path that the public exploit uses. The out-of-memory path of CVE-2026-109618 is covered by logging rules that measure its likely request shapes, but not yet by a blocking rule.
A change is already in place. alt-php and ea-php for 8.2 to 8.5 were rebuilt with php.net version numbers on 23 October.
The status page incident keeps the full record.
Three layers patch PHP, and each stops somewhere different.
The OWASP PHP Configuration Cheat Sheet makes a fair point: extended support from a distribution or vendor does not make a branch “supported.” We agree. A backported fix leaves PHP 7.4 outside php.net’s policy. It closes the CVE on the exact version the site runs, so the upgrade can happen on the customer’s schedule instead of the CVE’s.
HardenedPHP, the backported patch set included in CloudLinux and Imunify360, carries security fixes to end-of-life PHP 5.x, 7.x, and 8.x as drop-in packages that work with PHP Selector. If you already run CloudLinux or Imunify360, it covers your end-of-life PHP today.
ELS for PHP is the same technology sold standalone for the rest of the fleet, on 20 platforms: EL6 to EL10, Ubuntu 16.04 to 26.04, Debian 10 to 13, Alpine 3.23 and 3.24, and Windows Server 2019, 2022, and 2025.
PHP’s release fixed four branches; we shipped fixes for 16.
PHP 8.2 reaches end of life on 31 December 2026, nine weeks after this post.
After that, the next PHP CVE gets no php.net release for 8.2, whatever its score. Since PHP 8.1, each branch gets about two years of active support and two more years of security-only fixes, ending on 31 December.
Sources: php.net supported versions and end-of-life branches, read 26 October 2026.
Most PHP security best practices still apply on a shared server.
What changes is who owns each one. The provider sets some fleet-wide in php.ini, while others live in the customer’s code.
PHP2Shell is a useful test: almost none of them stopped it.
session.upload_progress.enabled = 0ini_set() or .user.inimemory_limit, post_max_size, max_file_uploads)disable_functions (exec, system, shell_exec, passthru)open_basedirallow_url_include = Off, allow_url_fopenexpose_php = Offdisplay_errors = Off, log_errors = Onsession.cookie_httponly, session.cookie_secure, session.use_strict_modeFull directive reference: the OWASP PHP Configuration Cheat Sheet. Vulnerability classes: TuxCare’s guide to common PHP vulnerabilities.
Run this PHP security test for every PHP version the server serves.
Step 1. Check each build’s changelog for the CVE IDs (commands below; repeat for each installed alt-php and ea-php version, and use dpkg -l for ea-php on Ubuntu). Rebased native packages name no CVE, so check for 8.2.35, 8.3.36, or later instead. If fixed packages don’t appear, confirm cloudlinux-release is current.
rpm -q --changelog alt-php85-common | grep -E 'CVE-2026-(109618|109619)'
rpm -q --changelog ea-php84-php-cli | grep -E 'CVE-2026-(109618|109619)'
dpkg -l ea-php84-php-cli # CloudLinux for Ubuntu: compare the version with the fixed list
rpm -q --changelog php-cli | grep -E 'CVE-2026-(109618|109619)'
rpm -q php-cli # rebased native builds: 8.2.35 or later on 8.2, 8.3.36 or later on 8.3
rpm -q cloudlinux-release # if the update fails or finds nothing to installStep 2. Restart PHP-FPM or the web server after updating. A patched package doesn’t fix workers that are already running. For ea-php on cPanel:
/scripts/restartsrv_httpd
/scripts/restartsrv_apache_php_fpmStep 3. Keep session upload progress off. Set session.upload_progress.enabled = 0 in php.ini or the PHP-FPM pool (php_admin_value), where accounts can’t override it; a .user.ini can switch it back on. PHP first gave this as an interim measure for PHP2Shell. On 23 October, it extended the advice to patched servers: a third session flaw, CVE-2026-115560, will be fixed only in PHP’s next regular release. It needs an unusual setup, an application that switches session.serialize_handler to php at runtime, so applications that never do that can keep the feature on. Restart PHP, confirm the effective value on a phpinfo() page for each version, and remove the page afterwards; php -i shows command-line settings, which can differ. PHP’s advisory gives separate memory and request-size settings for the out-of-memory flaw.
Step 4. Confirm the Imunify360 WAF is on, in blocking mode, and on ruleset 8.88 or later. The path below is for cPanel with Apache; other panels and LiteSpeed use different paths. Run as root:
cat /etc/apache2/conf.d/modsec_vendor_configs/imunify360-full-apache/VERSION
imunify360-agent update --force modsec-rules # if older than 8.88, then check againStep 5. Check whether exploit requests reached PHP before the server was patched. Default access logs record the User-Agent but not the multipart boundary or form fields, so they catch only requests that name the tool. On Imunify360, the Incidents list shows WAF matches by rule (77830995, 77318849, 77866818, 77236259, and later PHP2Shell rules), and the ModSecurity audit log, where enabled, may include the request headers of flagged requests. A request the WAF blocked never reached PHP. Others did: anything before the rules arrived (11:10 CEST on 21 October, or 15:18 on LiteSpeed), anything on servers with the WAF off or in log-only mode, and variants the rules don’t match. Those leave no trace in the Incidents list, so don’t wait for a hit. For every account that ran unpatched PHP, keep the logs first, run a malware scan for web shells, look for PHP files written to website folders on or after 20 October, and check for unexpected processes running as the account’s user (the web server user with mod_php). Confirm what a file is before you delete it.
General hygiene, beyond PHP2Shell: run composer audit on Composer-based applications, because a PHP security audit of the interpreter says nothing about the libraries above it.
php2shell- (for example php2shell-109618, php2shell-scan/109618); some security checkers use it tooB7kQpoc618, B7kQpoc619; renamed boundaries containing php2shell or nphp618; boundaries starting p2s, or lfi plus 16 hex charactersPHP_SESSION_UPLOAD_PROGRESS field, a session ID, a file, and text fields holding binary data, usually with no Referer
Back to the ops lead at the hosting provider reading PHP’s notice on Tuesday night.
By Friday, every branch on those servers had a fixed package, and the four php.net still-supported versions carried version numbers a scanner could read.
The next deadline is 31 December, when 8.2 leaves the supported list.
Check your accounts’ branches against the lifecycle table. For anything past end of life, the patched build is HardenedPHP on CloudLinux and Imunify360, or ELS for PHP everywhere else.
Not on a stock build. PHP 7.4 reached end of life in November 2022, and for PHP2Shell, php.net shipped only a source backport. Run it on a patched build, such as HardenedPHP or ELS for PHP, while the upgrade is planned.
Distributions patch the PHP versions they ship, and vendors that own a branch patch the rest. CloudLinux covers 16 branches, 5.2 to 8.5: HardenedPHP on CloudLinux and Imunify360, ELS for PHP elsewhere.
No. Both act on running scripts, and PHP2Shell triggers while PHP is still reading the request. Turning off session upload progress narrows one path; only a patched build closes both CVEs.
For PHP2Shell: check each PHP version’s changelog or version number against the fixed list, restart PHP, confirm the WAF ruleset is 8.88 or later, and check WAF incidents and access logs for the tool’s indicators. For applications, run composer audit on their dependencies.
Same technology, different packaging. HardenedPHP comes included with CloudLinux and Imunify360. ELS for PHP is the standalone product for other distributions and servers without Imunify360, on 20 platforms including Ubuntu, Debian, Alpine, and Windows Server.
Comments