PHP2Shell: The Critical PHP Flaw Hitting Servers Right Now, and What to Do About It

If you run anything on PHP (WordPress, Laravel, Drupal, Magento, or a custom app), stop and check your PHP version. This week’s disclosure isn’t a bug in some plugin. It’s a flaw in PHP itself, it’s already being exploited, and the fix is a patch you need to apply today.
This situation is moving fast. I wrote this on October 22, 2026, so check the vendor advisories linked at the end for the latest.
What happened
The timeline was messy. On October 20, details leaked ahead of the planned disclosure, and the PHP security team published an advance notice. On October 21, independent researchers confirmed the flaws were real, and PHP shipped patched releases ahead of schedule. The problems were nicknamed PHP2Shell. (Aikido)
It’s two vulnerabilities, not one. They’re tracked as CVE-2026-109618 and CVE-2026-109619, and the PHP security team rates both Critical (CVSS v4.0 9.2). (Patchstack)
- CVE-2026-109618 (out-of-memory corruption): When an out-of-memory error interrupts a vulnerable operation, PHP leaves request data partially initialized. An attacker can steer that broken state toward code execution. (Qualys)
- CVE-2026-109619 (stale global state): PHP keeps references to request data after the memory behind it has been freed. This is a classic use-after-free. (Qualys)
Why this one is serious
Most PHP security stories are about application bugs: SQL injection in one plugin, a bad file upload in one CMS. Fixing those means updating that app. Here the interpreter itself is the problem, so your app code can be perfect and you’re still exposed.
Three things make it worse:
- It’s broad. Every PHP installation serving web requests is at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP, and LiteSpeed. The researchers who found it, Wiz, say every version back to 5.4 is affected by at least one of the issues. (Patchstack)
- It can happen before your code runs. PHP considers mod_php the highest risk, because an unauthenticated request can trigger the attack before any application code runs. Your authentication, input validation, and framework middleware never get a chance to help. (Patchstack)
- It’s already being used. Cloudflare reported that exploitation has started. watchTowr’s honeypot network also saw exploitation in the wild on October 21. Rapid7 noted a working exploit was developed during the research, and the work is being independently reproduced, so a public exploit is expected soon. (Aikido)
One caveat on sources: Cisco’s advisory, published earlier on October 21, said it wasn’t aware of malicious use. Reports of attacks came in later that day, so treat the situation as active.
Step 1: Find out what you’re running
Don’t assume. Check every place PHP lives:
php -v # CLI version
php-fpm -v # FPM version, which may differ
apache2ctl -M | grep php # Check whether mod_php is loaded
The CLI and the web-serving binary are often different installs. The one that matters is whatever answers web requests. Also check:
- Docker images and base layers (look at the
FROM php:...line). - Staging and “forgotten” servers.
- Shared hosting, where you’ll have to ask your provider.
- Managed platforms and appliances. Vendors like Cisco have published their own advisories for affected products.
If you want an automated check, Help Net Security reports that Searchlight Cyber released an open-source tool, php2shell-scanner, that tests whether a host is exposed. Only scan systems you own or have permission to test. (Help Net Security)
Step 2: Patch
The fixes are in PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35. Move to the newest patch release of your branch. (Help Net Security)
Practical notes:
- Restart after upgrading. Installing the package isn’t enough. Restart PHP-FPM or Apache so the running process picks up the new binary.
- Rebuild containers properly. Pull a fresh base image (
docker build --pull) instead of relying on a cached layer. - Watch your package source. Rapid7 relays PHP’s warning that
rpms.remirepo.netwould not have updates on October 21, and users should switch to distribution packages or build from source. (Rapid7) - Old PHP versions are the hard case. Branches like 7.x and 5.x are end-of-life, and the upstream patches listed above are for supported branches. Your options are to upgrade to a supported version, use a vendor that backports fixes, or use patched images. Aikido, for instance, said it was adding patched images, including 7.* variants. Upgrading is the real fix. Anything else buys time. (Aikido)
Step 3: If you can’t patch right now
PHP published temporary mitigations. These reduce exposure but are not a substitute for the patch. Per Qualys’ summary:
- For CVE-2026-109618, set a per-worker cgroup memory limit, which works as an availability boundary.
- For CVE-2026-109619, set
session.upload_progress.enabled = Off. - For CVE-2026-109619 on PHP 8.5, set
fatal_error_backtraces = Off.
See Qualys’ mitigation summary.
Also put a WAF or edge filter in front of the app. Cloudflare reported attempts to evade its protections, so treat that as one layer of defense, not a guarantee. Cisco’s advisory, notably, listed no workarounds for its own affected products, so check your vendor’s guidance. (Cisco)
Step 4: Assume you might have been hit, and look
If your server was internet-facing and unpatched after the leak, check for compromise instead of just patching and moving on.
- Look for new or modified files in web roots, upload directories, and temporary folders, especially
.phpfiles you don’t recognize (web shells). - Check process behavior. Your web server user spawning shells,
curl, orwgetis a red flag. - Review outbound connections from web servers. Most web apps shouldn’t be calling unfamiliar hosts.
- Check logs for odd bursts of requests around October 20 to 22, and for requests that caused memory errors or worker crashes.
- Rotate secrets (database passwords, API keys,
.envvalues) if you find any sign of compromise, because code execution means those were readable.
If you do find something, rebuild from a clean image instead of cleaning the box by hand.
Step 5: Long-term lessons
This won’t be the last interpreter-level bug. A few habits make the next one less painful:
- Know your inventory. The hardest part of this week for many teams is simply answering “where do we run PHP?” Keep an inventory.
- Make patching fast. If upgrading PHP takes you weeks, fix the process now. Containers and automated rebuilds help.
- Run on supported versions. End-of-life PHP gets no upstream fix when something like this hits.
- Limit the blast radius. Run the web process as a low-privilege user, keep it in a container with a read-only filesystem where possible, restrict outbound network access, and keep secrets out of reach. Be realistic, though: with memory-corruption bugs like these, settings like
disable_functionsare not a reliable barrier, so isolation matters more. - Layer your defenses. A WAF, runtime monitoring, and file-integrity checks won’t replace patching, but they can buy you time or catch what slipped through.
The short version
- Find every PHP install that serves web traffic.
- Update to 8.5.12, 8.4.27, 8.3.36, or 8.2.35 (or your branch’s equivalent), then restart.
- If you can’t patch yet, apply PHP’s temporary mitigations and filter at the edge.
- Hunt for signs of compromise, and rotate secrets if you find any.
- Move off end-of-life PHP versions.
Treat this as an emergency, not a ticket for next sprint.
#php #security #ai #software