Dev.to Security ๐Ÿ” Cybersecurity ๐Ÿ‘ 0 ๐Ÿ“– 5 min read

You patched PHP2Shell. How do you know it actually worked?

PHP2Shell, the pair of critical PHP flaws tracked as CVE-2026-109618 and CVE-2026-109619, was fixed on 21 October in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Both flaws are rated 9.2 on the CVSS v4 scale, and either one ca

You patched PHP2Shell. How do you know it actually worked?

PHP2Shell, the pair of critical PHP flaws tracked as CVE-2026-109618 and CVE-2026-109619, was fixed on 21 October in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Both flaws are rated 9.2 on the CVSS v4 scale, and either one can let an unauthenticated attacker run code on a server that handles PHP requests. If you have already updated, good. If you have only updated the package and moved on, you may not actually be fixed yet.

PHP2Shell patched? Check your server is fixed ยท NotVibesCoded

PHP2Shell was fixed on 21 October, but updating the package is only half the job. Workers must restart, containers must rebuild, and version numbers can lie.โ€ฆ

favicon notvibescoded.com

This is the follow-up to our PHP2Shell article. It covers the part most teams skip: proving the fix is live, on the server that is actually serving traffic.

The only complete fix is the update

Start here, because nothing else on this list is a substitute. Updating PHP to a fixed version, 8.5.12, 8.4.27, 8.3.36 or 8.2.35 depending on your branch, is the only complete fix. Application updates do not fix it. WordPress, plugin, theme and framework updates do not change PHP itself, and on Apache with mod_php a demonstrated exploit fires from a single unauthenticated request before any application code runs, so application-level defences never get a chance to help.

If you run PHP in containers, updating a running container is not enough. Rebuild the image from a patched base, then redeploy. A patched container running on an old image is exposed again the moment it restarts.

Step 1: restart every PHP worker

This is the step that silently undoes patches. PHP-FPM workers, Apache processes and long-running workers that were started before the update are still running the old code. The update only takes effect once every worker restarts.

After updating, restart PHP-FPM, restart Apache if you use mod_php, and restart any other PHP worker process you run. Then check that no old worker is still alive. If you use a process manager, confirm the old processes actually exited rather than assuming the restart command worked. On a busy server, a worker that refuses to die can keep serving requests with the old, vulnerable PHP for hours.

Step 2: check the version on the live server, not on your laptop

Run the version check on the server that serves production traffic, and in the same environment that serves requests. A staging server, a build machine and a developer laptop can all show a patched version while production still runs the old one. If you deploy through containers, check inside the running container, not just the image tag in your registry.

There is one trap here that catches people on Ubuntu and Debian. Those distributions backport security fixes into the version they already ship, so php -v can keep showing an old number, such as 8.3.6, even after the fix is installed. On Ubuntu 24.04, the fixed package is 8.3.6-0ubuntu0.24.04.13, and its changelog names both CVEs. Check the package version and changelog, not just the PHP version number, before declaring yourself safe or vulnerable.

Step 3: turn off session upload progress, and leave it off

PHP has asked users to switch off the session upload progress feature, and it is worth doing even after patching. The feature is enabled by default, it is rarely used by modern applications, and it is one confirmed attack path for CVE-2026-109619. Setting session.upload_progress.enabled=0 in php.ini, a PHP-FPM pool configuration, or a server configuration that applies before request parsing removes that path. Restart every worker after changing it, for the same reason as above: the setting only applies to workers started after the change.

Step 4: if you cannot update yet, say so honestly

Some servers cannot update this week. PHP 8.1 and older get no numbered release for this fix; the PHP project published source-only backports for 7.4, 8.0 and 8.1, and some distributions and long-term support vendors ship their own patched packages. If you are on one of those branches, your route is a vendor package, a source backport you build and test yourself, or a supported patched runtime from a vendor.

Interim measures can reduce exposure to specific attack paths, and they are worth doing while you arrange the update: raise the PHP memory limit, lower post_max_size, limit request sizes at the web server or proxy, and disable session upload progress. Be clear about what these are, though. They reduce exposure. They do not make an installation safe. Only the update fixes it, and anyone who tells you otherwise is selling you comfort.

Step 5: check for signs of compromise before you relax

PHP2Shell was not only a theoretical flaw. Security firms reported exploitation attempts before the fixes were public, and broad exploitation after release, so a server that was internet-facing during that window should not be assumed clean just because it is patched now. Patching stops new attacks through these flaws. It does not undo an attack that already succeeded.

Look for what does not belong: unexpected files in upload directories and web roots, new administrator accounts, scheduled tasks and cron entries you did not create, outbound connections to unfamiliar hosts, and changes to application files around the disclosure window. If you find anything you cannot explain, treat it as a compromise and rebuild from known-good sources rather than cleaning up files one by one.

The checklist, in order

  1. Update PHP to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or a vendor package that names both CVEs.
  2. Rebuild container images from a patched base and redeploy.
  3. Restart every PHP worker, and confirm the old ones actually exited.
  4. Verify the fix on the production server, checking package versions where distributions backport fixes.
  5. Set session.upload_progress.enabled=0 and restart workers again.
  6. If you cannot update, arrange a vendor package or backport now, and use the interim measures only as a bridge.
  7. Check for compromise before closing the incident.

Patching is not a single command. It is an update, a restart, a verification, and a check for damage, in that order. Do all four, and PHP2Shell is closed. Skip any one of them, and you are guessing.

Originally published on NotVibesCoded. Use AI. Just don't ship slop.

๐Ÿ“ฐ Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes โ€” full credit and traffic to the original publisher.