Cybersecurity
PHP2Shell Fix for Old and EOL PHP Versions (7.4, 8.0, 8.1)
How to fix PHP2Shell (CVE-2026-109618, CVE-2026-109619) and the new CVE-2026-115560 on end-of-life PHP, what each workaround covers and what it breaks.
By Intelvue Engineering · Updated · 6 min read
Alert: patching is the fix. Update to a supported, official PHP release (8.2.35, 8.3.36, 8.4.27 or 8.5.12 or newer) from php.net or your operating system's packages. The workarounds below reduce risk on old and end-of-life (EOL) PHP while you upgrade. They are not a substitute for running supported PHP.
The short answer: if you are on PHP 7.4, 8.0 or 8.1, install your vendor's patched PHP package (the official backport), set session.upload_progress.enabled = Off, restart PHP, and plan an upgrade to PHP 8.2 or later. On PHP 7.3 or older there is no fix: restrict access to the server and block risky upload requests until you upgrade.
On 21 October 2026, PHP fixed two critical remote code execution flaws known as PHP2Shell (our overview). Two days later, PHP disclosed a related flaw, CVE-2026-115560, which has no fix yet but is blocked by the same setting. This guide is for the many teams that cannot jump to a supported PHP version overnight.
Why this matters for old PHP
A large part of the web still runs unsupported PHP. In August 2026, W3Techs reported about 37% of PHP websites on PHP 7 or older, all past end of life. Add sites on PHP 8.0 and 8.1, which are also EOL, and roughly 4 in 10 PHP sites get no official release for PHP2Shell.
What each measure covers (and breaks)
| Measure | CVE-2026-109618 | CVE-2026-109619 | CVE-2026-115560 | What it breaks |
|---|---|---|---|---|
| Supported PHP update (8.2+) | Fixed | Fixed | Not yet (next release) | Nothing expected |
| Vendor backport for 7.4, 8.0, 8.1 | Fixed | Fixed | Not covered | Upload progress bars; harsher out-of-memory exits |
session.upload_progress.enabled = Off |
No | Partial | Blocks the known path | Session-based upload progress bars |
Block multipart/form-data on routes that don't need uploads |
Blocks known triggers | Blocks known triggers | Reduces exposure | File uploads and file forms on blocked routes |
| WAF managed rules (e.g. Cloudflare) | Partial | Partial | Partial | Rare false positives |
| Restrict access or take offline | Full | Full | Full | Public access |
Every known PHP2Shell trigger so far is a multipart/form-data request (Sansec), which is why upload-related controls help while you patch.
Step-by-step fix for EOL PHP
1. Find every PHP version and how it runs
php -v # CLI version
ls /etc/php/ /opt/remi/ 2>/dev/null # multiple versions side by side
systemctl list-units '*php*fpm*' # FPM pools in use
Check each site's PHP-FPM pool or Apache mod_php module. The CLI version is often not the one serving traffic.
2. Install the patched package for your branch
PHP published "minimal mitigation for EOL version" patches for 7.4, 8.0 and 8.1, and vendors have packaged them (ComputingForGeeks, AlmaLinux).
| Platform | How to update |
|---|---|
| Ubuntu / Debian (incl. Ondřej Surý packages) | sudo apt update && sudo apt install --only-upgrade 'php8.1*' (match your version) |
| RHEL, Rocky, AlmaLinux | sudo dnf upgrade --refresh 'php*'; if your stream is retired, switch to the matching Remi stream |
| Remi software collections | sudo dnf upgrade -y 'php81-*' |
| cPanel / DirectAdmin | Update EasyApache 4 (ea-php81, ea-php80, ea-php74) or CustomBuild PHP |
Then restart every pool: sudo systemctl restart php8.1-fpm (and Apache if you use mod_php).
Verify by changelog, not version number. Patched builds keep the same version string (for example 8.1.34). Look for the CVE in the package changelog:
zgrep CVE-2026-109618 /usr/share/doc/php8.1-fpm/changelog.Debian.gz # Debian/Ubuntu
rpm -q --changelog php81-php-fpm | head -5 # Remi / RPM
3. Turn off session upload progress
Set it for every PHP version, in php.ini and in each FPM pool:
; php.ini
session.upload_progress.enabled = Off
; /etc/php/8.1/fpm/pool.d/www.conf (each pool)
php_admin_flag[session.upload_progress.enabled] = off
Restart PHP-FPM (or Apache with mod_php). The PHP Foundation recommends keeping it off until the next PHP release. To confirm what the web server sees, check phpinfo() from a temporary page, then delete that page.
4. Do not remove the memory limit
Some early advice suggested memory_limit = -1 to avoid the out-of-memory trigger. Don't: one request can then consume all server memory. Keep a sensible limit.
5. If there is no patched package (PHP 7.3 and older)
- Put the site behind a WAF with PHP2Shell rules enabled, in blocking mode.
- Block
multipart/form-dataon every route that does not need uploads (example below). - Restrict admin panels to a VPN or allow-listed IPs.
- If the server cannot be protected, take it offline until it is upgraded.
6. Plan the upgrade
Backports are a one-off rescue. The next PHP flaw may not get one. Schedule the move to PHP 8.2 or later now.
Samples: what breaks, and how to work around it
Upload progress bars stop updating
This classic pattern reads progress from the PHP session, so it stops working once session.upload_progress.enabled is off (and on patched EOL builds, which disable the feature in code):
<?php // progress.php: polled by the browser during an upload
session_start();
$key = ini_get('session.upload_progress.prefix') . 'avatar';
echo json_encode($_SESSION[$key] ?? null); // now always null
Workaround: measure progress in the browser instead. It needs no PHP session and works on every PHP version:
<input type="file" id="file"> <progress id="bar" max="100" value="0"></progress>
<script>
document.getElementById("file").addEventListener("change", (e) => {
const data = new FormData();
data.append("avatar", e.target.files[0]);
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = (p) => {
if (p.lengthComputable) document.getElementById("bar").value = (p.loaded / p.total) * 100;
};
xhr.open("POST", "/upload.php");
xhr.send(data);
});
</script>
Out-of-memory requests fail harder on patched EOL builds
With the backport, a request that exceeds memory_limit ends the PHP worker immediately: shutdown functions don't run and visitors see a 502 or 503 instead of a PHP error. If a heavy page (large import, report, image resize) starts failing:
; FPM pool: make the error visible in logs
catch_workers_output = yes
Watch the FPM log for exited with code 1 and raise memory_limit for that pool if needed.
Blocking multipart breaks uploads on blocked routes
An nginx example that blocks multipart requests everywhere except the endpoints that genuinely accept files:
# inside the server { } block
set $block_multipart 0;
if ($content_type ~* "^multipart/form-data") { set $block_multipart 1; }
if ($request_uri ~* "^/(wp-admin/async-upload\.php|account/avatar)") { set $block_multipart 0; }
if ($block_multipart) { return 403; }
Test your contact forms, checkouts and admin uploads after enabling it, and keep the allow-list short.
About CVE-2026-115560
As of 23 October 2026, PHP describes CVE-2026-115560 as an unlikely remote code execution path that needs an unusual setup: the server uses a non-default session.serialize_handler and the application switches it to php at runtime before starting the session, with upload progress enabled. No public exploit is known. The fix is planned for the next regular release, so keep session.upload_progress.enabled = Off and update again when it ships.
How Intelvue can help
Our team has patched and hardened PHP platforms for more than a decade, including WordPress, Magento and custom PHP on old versions. We can:
- Find every PHP install on your servers and confirm each one is patched.
- Apply the right backport or workaround for your stack without breaking checkout, uploads or admin.
- Replace session-based upload progress bars and test the site end to end.
- Plan and run the upgrade to supported PHP.
See our security audits and compliance service, or talk to an engineer today.
Frequently asked questions
- Can I fix PHP2Shell without upgrading to PHP 8.2 or later?
- Yes, for PHP 7.4, 8.0 and 8.1. PHP published minimal source patches for those branches and most distributions and control panels (Ubuntu, Remi, cPanel, DirectAdmin, Red Hat, AlmaLinux) ship them as package updates. PHP 7.3 and older have no official fix.
- Does session.upload_progress.enabled = Off fix PHP2Shell?
- No, not on its own. It blocks the new CVE-2026-115560 path and is recommended against CVE-2026-109619, but PHP developers say it is not enough by itself and it does nothing for CVE-2026-109618. Use it together with a patched PHP build.
- What breaks when I disable session upload progress?
- Only upload progress bars that read progress from the PHP session. File uploads themselves keep working. You can replace the progress bar with a browser-side one that needs no PHP session.
- Should I set memory_limit to -1 to avoid the out-of-memory trigger?
- No. With memory_limit = -1, a single request can use all server memory and take the whole server down. Keep a sensible limit and install the patched build.
- Is CVE-2026-115560 fixed in the 21 October releases?
- No. As of 23 October 2026, PHP says the fix will come in the next regular release. Until then, set session.upload_progress.enabled to Off and keep it off.