Skip to content

php2shell: What Happened to PHP and What to Do Right Now โ€‹

Two critical flaws in the PHP core, nicknamed php2shell, allow unauthenticated remote code execution. They were exploited before the patches were out, and they're now on CISA's Known Exploited Vulnerabilities list.

This post has no exploit details, just the checklist I'd hand to any PHP team this week.


๐Ÿงจ What Happened โ€‹

Both flaws are in PHP itself, so your code doesn't need to be doing anything wrong:

  • CVE-2026-109618, RCE via OOM corruption. Out-of-memory handling can interrupt PHP while request data is only partly set up, and cleanup then treats that data as valid.
  • CVE-2026-109619, RCE via stale global state. Internal state from one request can outlive its memory and be reused by a later request on the same worker.

Both are rated CVSS v4.0 9.2. According to the official advisory, every PHP installation serving web requests is affected: PHP-FPM, Apache mod_php (the highest risk), php-cgi, FrankenPHP and LiteSpeed.

The timeline:

  • 17 October: Amazon's honeypots recorded an exploitation attempt, which Amazon disclosed on 22 October.
  • 20 October: php.net gave advance notice of a critical release. The CVE IDs leaked onto public forums the same day, and the release was brought forward a day.
  • 21 October: PHP released fixes and the advisory, and CISA issued its alert.
  • 23 October: PHP published an informational advisory for a related issue, CVE-2026-115560.
  • 26 October: CISA added both CVEs to the KEV catalog.

๐Ÿ” Step 1: Check Your Version โ€‹

BranchFixed in
8.58.5.12
8.48.4.27
8.38.3.36
8.28.2.35

Check the PHP that serves web traffic, not just the CLI. They're often different binaries:

bash
php -v
php-fpm -v    # may be php-fpm8.4 etc. on Debian/Ubuntu

Distro packages often backport fixes without changing the upstream version number, so on Debian, Ubuntu or RHEL, check your vendor's security tracker rather than trusting php -v alone.


๐Ÿฉน Step 2: Patch, Starting With Internet-Facing Systems โ€‹

Update to a fixed release and restart every worker. A PHP-FPM pool still running the old binary isn't patched.

If you genuinely can't patch today, the advisory lists partial mitigations. They reduce exposure but don't make you safe:

ini
; php.ini or FPM pool config, applied before request parsing
memory_limit = -1
post_max_size = 8M            ; 32M if you need uploads
upload_max_filesize = 8M      ; keep below post_max_size
session.upload_progress.enabled = 0
fatal_error_backtraces = 0    ; PHP 8.5 only

Set these where applications can't override them, such as php_admin_value in the FPM pool, not via ini_set() or .user.ini. Enforce request-size limits at your proxy, and keep a container memory limit, since memory_limit = -1 removes PHP's own. A WAF can buy time, but it's not a fix.


๐Ÿณ Step 3: Containers and Base Images โ€‹

Expect blind spots here:

  • Floating tags like php:8.4-fpm get rebuilt upstream, but your image doesn't change until you rebuild and redeploy.
  • Pinned tags like php:8.4.26-fpm never change. Bump them.
  • Images built on top of yours, CI runners and one-off worker images need rebuilding too.
  • Check what's inside the running image, not what the Dockerfile says:
bash
docker run --rm --entrypoint php your-image:tag -v

Don't forget software that bundles its own PHP, such as appliances and vendor products. CISA explicitly calls these out.


โ˜๏ธ Step 4: Managed Hosting and PaaS โ€‹

If someone else manages the runtime, don't assume they've patched it. Check their security bulletin and confirm the PHP version your app actually reports.


โšฐ๏ธ Step 5: End-of-Life Versions โ€‹

PHP 8.1 and older get no official releases. The PHP team published minimal source-only backports for 7.4, 8.0 and 8.1, which only help if you build from source. Otherwise, you need an LTS vendor or an upgrade.

CISA's advice is blunt: if you can't patch, or you're on 8.1 or older, take those systems offline until they're fixed. I agree.

PHP 8.2 also reaches end of life on 31 December 2026, so if this is your wake-up call, aim for 8.4 or 8.5.


๐Ÿ•ต๏ธ Step 6: Assume Exploitation and Look For It โ€‹

Exploitation started before the patches were public, so look back through your logs:

  • A web worker spawning a shell is the strongest signal. PHP-FPM or Apache children running sh, curl or wget deserve a look.
  • Bursts of memory-exhausted fatal errors during request start-up, and segfaults in Apache or FPM logs.
  • Multipart requests with session-related field names your app doesn't use.

CISA has published a SIGMA detection rule, and Datadog's write-up has more detection guidance. If you find something, treat the host as compromised: rotate its secrets and rebuild it.


โž• The Follow-Up: CVE-2026-115560 โ€‹

On 23 October, PHP published an informational advisory for CVE-2026-115560 in session upload progress. It only applies to an unusual setup:

  • session.serialize_handler is set to php_binary or php_serialize in config.
  • The app switches it to php at runtime with ini_set() before session_start().
  • Session upload progress is still enabled.

It isn't fixed in the 21 October releases; the fix is due in the next regular release. The mitigation is session.upload_progress.enabled = 0. If you already set it for CVE-2026-109619, leave it in place.


๐ŸŽฏ Conclusion โ€‹

This is about as serious as it gets for PHP: core bugs, no authentication, and exploitation already under way. Patch to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, restart your workers, rebuild your images, deal with your EOL boxes, and check your logs for signs you were hit first.

Once the dust settles, make sure you can answer "which PHP version is running where?" in minutes rather than days.