Security advisory · Published 23 October 2026 · By Prasad C G
PHP2Shell is the industry name for CVE-2026-109618 and CVE-2026-109619, two remote code execution bugs in PHP itself. They live in the code that sets up and tears down every web request, so they reach any PHP site, whatever framework or CMS it runs.
Do this today
- Upgrade to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or to your distribution's patched package.
- Restart PHP-FPM, Apache or your PHP server so the patched code is actually running.
- Assume compromise on any internet-facing server that ran an unpatched PHP after 20 October, and check it using the steps below.
Key facts
| CVEs | CVE-2026-109618 (GHSA-w8hw-w9fx-j79w) CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp) |
|---|---|
| Severity | Critical CVSS v4.0 9.2 for each, as rated by the PHP project |
| Access needed | None. A single crafted HTTP request is enough. |
| Exploitation | Seen in the wild on 21 October by watchTowr. A public proof-of-concept tool appeared on 20 October. |
| Discovered by | Calif, according to watchTowr |
| Fixed in | 8.5.12, 8.4.27, 8.3.36, 8.2.35 (and 8.6.0 RC4 for testers) |
| Server types at risk | PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed |
What happened
On 20 October 2026 the PHP project pre-announced security releases for two critical bugs. The same day, details leaked ahead of the planned disclosure and a proof-of-concept tool called "PHP2Shell" started circulating. PHP published the fixed releases on 21 October. By then, watchTowr's honeypots were already recording attacks using both bugs.
Linux distributions and long-term support vendors received the patches in advance, so a patched package may already be waiting for you. The gap that matters is between that release and the moment your own servers restarted on the new code.
The two bugs, in plain terms
CVE-2026-109618: corruption when memory runs out
While PHP is building the data for an incoming request, it can hit its memory limit and stop halfway. The partly built data is left in a broken state, and PHP's cleanup code later treats it as valid. An attacker who controls the request can shape that broken state into code execution. Large or complex form uploads (multipart requests) are the natural way to push PHP to that point.
CVE-2026-109619: state left over between requests
PHP workers handle one request after another. When a request ends in a fatal error, some request-owned state can survive after its memory has been freed, and the next request on the same worker can use it before it is reset. The PHP project confirmed two triggers: session upload progress tracking (on by default) and fatal-error backtraces in PHP 8.5.
Why your application code does not matter
Both bugs fire during request start-up and shutdown inside the PHP engine. Updating WordPress, Laravel, Symfony, Magento or your own code does not help, and neither does a code review. On Apache with mod_php, which the PHP project rates the highest risk, a demonstrated exploit runs before any application code is reached at all.
Affected versions
Every branch is affected below its fixed release. Note that this is per branch: 8.4.26 is vulnerable even though it is a newer release than 8.3.36.
| Branch | Status | What to do |
|---|---|---|
| 8.5 | Security support until 31 Dec 2029 | Upgrade to 8.5.12 |
| 8.4 | Security support until 31 Dec 2028 | Upgrade to 8.4.27 |
| 8.3 | Security support until 31 Dec 2027 | Upgrade to 8.3.36 |
| 8.2 | Security support until 31 Dec 2026 | Upgrade to 8.2.35 now, and plan a move to 8.4 or 8.5 before the end of the year |
| 8.1, 8.0, 7.4 | End of life. No official release. | Apply the PHP security team's source backport, use a patched package from your distribution or LTS vendor, or take the site offline until it is upgraded |
| 7.3 and older (incl. PHP 5) | End of life. No fix exists. | Isolate or take offline, and upgrade |
| 8.6.0 pre-releases | Affected before RC4 | Move to 8.6.0 RC4 or later |
For 7.4, 8.0 and 8.1 the PHP security team published minimal patches as branches in the php-src
repository (for example PHP-7.4-CVE-2026-109618-109619). They are a stop-gap for
teams that build PHP themselves, not a reason to stay on an unsupported version.
Distribution packages keep the old version number
Debian, Ubuntu, Red Hat and similar distributions usually backport security fixes without
changing the upstream version, so php -v may still show an older number on a
patched server. Check the package changelog for the CVE IDs instead:
# Debian / Ubuntu (package names vary, e.g. php8.3-fpm)
apt changelog php8.3-fpm | grep -E "CVE-2026-10961[89]"
# RHEL / AlmaLinux / Rocky
rpm -q --changelog php-fpm | grep -E "CVE-2026-10961[89]"
Find every PHP install
Attackers scan the whole internet, so the server you forgot about is the one at risk. Check:
- Web servers and VMs, including staging, admin panels and old marketing sites.
- Container images, including base images used by CI and by other teams.
- Shared or managed hosting, where your host has to install the update. Check their status page, or pick the patched version in your control panel once it is offered.
- Appliances and products that bundle PHP, such as control panels, intranet tools and vendor software. Ask the vendor for their advisory.
The command-line PHP and the PHP serving your website can be different builds. Check the one that serves requests:
# Command-line PHP
php -v
# PHP-FPM (the binary name varies by distribution)
php-fpm -v # or: php-fpm8.3 -v
# A container image
docker run --rm --entrypoint php your-image:tag -v
How to fix it
- Upgrade PHP to the fixed release for your branch, from php.net, your distribution, or your hosting control panel.
- Restart PHP. Running workers keep the old code in memory until they
restart. For example
sudo systemctl restart php8.3-fpmfor PHP-FPM, orsudo systemctl restart apache2for mod_php. - Rebuild container images without the build cache so the new base image is
pulled, for example
docker build --pull --no-cache ., then redeploy. - Confirm the running version. Compare the restart time of your PHP
processes with the time you installed the update, or check a temporary
phpinfo()page and delete it straight afterwards. - Deal with end-of-life servers: patch them with a backport, isolate them behind a VPN or access list, or take them offline until they are upgraded.
Stop-gaps while you patch
These reduce risk. They do not fix the bugs.
The PHP project says no setting fully closes either bug, and watchTowr considers setting-based mitigations ineffective against what it has seen. Use these only for the hours until the upgrade is done.
- Turn off session upload progress. This blocks the confirmed session path
for CVE-2026-109619. Set it in
php.ini, the FPM pool or the server configuration. Setting it from code withini_set()or in.user.iniis too late. - On PHP 8.5, turn off fatal-error backtraces
(
fatal_error_backtraces = 0). This blocks the other confirmed path. - Make memory exhaustion harder (CVE-2026-109618). Lower
post_max_size(the PHP project suggests 8M for sites without uploads and 32M with uploads) and limit request body size at your proxy or load balancer. - Move the memory limit out of PHP. The PHP project's guidance is to set
memory_limit = -1in a way applications cannot override, and to cap memory with cgroup or container limits instead. RLIMIT_AS and RLIMIT_DATA do not help. - Turn on your CDN or WAF provider's emergency rules for PHP2Shell, if they offer them.
; php.ini (or the equivalent in your FPM pool)
session.upload_progress.enabled = 0
post_max_size = 8M
fatal_error_backtraces = 0 ; PHP 8.5 only
; FPM pool: php_admin_value cannot be changed by the application
php_admin_value[memory_limit] = -1
If you set memory_limit = -1, make sure a container or cgroup memory limit is in
place first. Otherwise one heavy request can take down the whole server.
Have you already been hit?
If a server was reachable from the internet and ran unpatched PHP after 20 October, check it before you call the job done. Patching closes the door; it does not remove anyone who is already inside.
Signs to look for
- Crashing PHP workers. Memory-corruption attacks often crash workers
before they succeed. Look for
signal 11 (SIGSEGV)in PHP-FPM logs or segmentation faults in the Apache error log. - Unusual uploads. watchTowr advises looking for large or deeply nested multipart requests in your access logs.
- New or changed PHP files in the web root, upload folders and cache folders.
- Unexpected activity by the web server user: new processes, outbound connections, cron jobs or SSH keys.
# PHP-FPM worker crashes
grep -i "signal 11" /var/log/php*fpm*.log
# PHP files created or changed since 20 October
find /var/www -name "*.php" -newermt "2026-10-20" -ls
# Cron jobs for the web server user (www-data on Debian/Ubuntu)
sudo crontab -u www-data -l
If you find something
- Take the server out of service, but keep it running or snapshot it so the evidence survives.
- Rebuild from a known-good image on patched PHP. Cleaning a compromised server in place is rarely reliable.
- Rotate every secret the server could read: database passwords, API keys,
.envvalues, SMTP and payment credentials. - Check what the server could reach, such as databases and internal services, and review them too.
Common questions
Does updating WordPress or Laravel fix this?
No. The bugs are in PHP itself. Keep your application updated anyway, but only a patched PHP build fixes PHP2Shell.
Does a WAF protect me?
Partly, at best. A WAF in front of your site can block known attack patterns, but variants appear quickly, and on mod_php the exploit runs before any of your application's own defences. Treat a WAF as extra cover while you patch, not as the fix.
We are stuck on PHP 7.4. What now?
Patch with the official backport or a vendor build today, restrict who can reach the site, and plan the move to a supported version. An unsupported PHP version will keep producing incidents like this one.
Do we need to change our code?
Not for the fix. If you lower post_max_size as a stop-gap, test your upload
features afterwards.
How TechMaven can help
We build and run PHP systems in production, from Laravel platforms to WordPress estates. We can find every affected server and image, patch and restart them safely, check for signs of compromise, and plan the move off end-of-life PHP. Get in touch and a senior engineer will reply within one business day. For the Node.js and certificate issues from the same week, see the October 2026 security advisory.
Sources: php.net (opens in a new tab) (release announcements and supported versions (opens in a new tab)), watchTowr (opens in a new tab). Accurate as of 23 October 2026. Always confirm versions against your vendor's own advisory before you act.