Security / Web Development
PHP2Shell: Two Critical PHP Flaws and How to Patch Them
Your PHP server may be exposed before your application code runs. PHP2Shell is the community name for two critical PHP runtime vulnerabilities that can enable unauthenticated remote code execution through specially crafted web requests. Updating the runtime is the complete fix.
PHP2Shell at a glance
PHP2Shell refers to CVE-2026-109618 and CVE-2026-109619, two critical vulnerabilities in PHP's request handling and cleanup paths. Both are rated CVSS v4.0 9.2. The PHP project says the issues can affect PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed.
The risk is below WordPress, Laravel, Magento or custom application code. A well-written application can still be exposed if the PHP runtime underneath it is vulnerable. PHP's own advisory describes the highest risk for Apache with mod_php, where a demonstrated exploit can reach the runtime before application code runs.
Which PHP versions are fixed?
The fixed upstream releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.2 reaches end of life on 31 December 2026, so teams using it should patch now and schedule a move to PHP 8.3 or later.
PHP 8.1 and older are end-of-life in the upstream project. Some Linux distributions and long-term-support vendors may provide backported fixes, and PHP has published minimal source backports for some legacy branches. Verify the exact package or vendor build rather than assuming that an unchanged major or minor version means you are unpatched.
How the two PHP2Shell flaws work
CVE-2026-109618 is an out-of-memory corruption flaw. In some request-handling paths, an allocation failure can interrupt PHP while internal request data is only partially initialized. Request cleanup may then process that invalid state. Crafted multipart requests, including upload and form parsing paths, are relevant to the documented attack surface.
CVE-2026-109619 involves stale request-owned state. Internal state can continue pointing to memory that has already been freed. A later request handled by the same worker may touch that stale state before normal initialization resets it, creating a use-after-free condition.
The practical takeaway is more important than the memory-management terminology: both flaws can turn an unauthenticated HTTP request into code execution or sensitive memory access on an affected server. Do not wait for an application-level patch to arrive.
Who should patch first?
Start with every internet-facing PHP installation, then prioritize Apache deployments using mod_php because the PHP advisory documents the strongest demonstrated attack path there. PHP-FPM behind Nginx or Apache is not automatically safe; it is listed as affected and should be patched on the same schedule.
Also inventory shared hosting, cPanel or other panels, containers, appliances and managed products that bundle PHP. The PHP binary used by a web server can differ from the command-line binary, and an operating-system vendor may backport a fix without changing the visible PHP version in the way you expect.
How to check your real PHP exposure
First check the command-line runtime with `php -v`, but do not stop there. Confirm the version and SAPI used by the web server. A temporary diagnostic endpoint can print `PHP_VERSION` and `PHP_SAPI`; remove it immediately after checking and never leave a version endpoint publicly accessible.
For containers, inspect the base image tag in the Dockerfile and rebuild from a fixed image. For Ubuntu or another Linux distribution, inspect installed PHP packages and read the vendor security notice for the exact package revision. For cPanel or shared hosting, ask the provider which PHP build serves your domain and whether it includes the PHP2Shell fixes.
Record the result per host: PHP version, SAPI, operating system or vendor package, internet exposure, application owner and last restart. This inventory makes it possible to prove that every worker has actually loaded the patched runtime.
What to do this week: a patch checklist
1. Inventory all PHP installations, including servers, containers, hosting panels and bundled appliances. Prioritize internet-facing systems.
2. Upgrade to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or apply a verified vendor backport. Restart Apache, PHP-FPM, LiteSpeed or the relevant worker pool.
3. Confirm the version and SAPI from the web-serving environment, not only from an administrator's shell. Check that old workers are gone.
4. Review access logs, error logs, process trees, new files, scheduled tasks and outbound connections for signs of compromise. Patching does not prove that a host was never accessed.
5. If immediate patching is impossible, apply PHP's documented interim controls and proxy-level request limits while you plan the update. Treat these as a bridge, not a complete fix.
6. Make PHP 8.2's 31 December 2026 end-of-life date part of the upgrade plan instead of waiting for another emergency.
Interim mitigations are not a replacement for patching
PHP's advisory lists measures that can reduce exposure to specific attack paths when an update cannot be applied immediately. Examples include setting a low `post_max_size`, disabling `session.upload_progress.enabled` before request parsing, setting `fatal_error_backtraces=0` on PHP 8.5 for the documented path, and enforcing request-size, multipart, header and nesting limits at the web server or proxy.
Configuration placement matters. A per-request `ini_set()` or `.user.ini` may be too late for an issue that occurs during request initialization. Restart every worker after changing server-level configuration. Do not assume that hiding errors with `display_errors`, `error_reporting` or `@` makes the runtime safe.
The PHP project is explicit that updating is the only complete solution. If an exposed system cannot be patched or temporarily controlled, assess whether it should be isolated or taken offline until remediation is possible.
Frequently asked questions
Is WordPress affected by PHP2Shell? If the WordPress site serves requests through a vulnerable PHP runtime, yes. Updating WordPress core or plugins alone does not patch PHP.
Is Laravel affected? The flaws are in the PHP runtime, not in Laravel. A Laravel application inherits the exposure of the PHP version and SAPI that run it.
Can Nginx with PHP-FPM wait? No. The complete FPM exploit path may differ from mod_php, but PHP-FPM is listed among affected configurations. Patch it on the same timeline.
Do I need to take the site offline? Not by default. Patch first where possible. If patching and interim controls cannot be applied quickly, follow a documented risk decision about isolation or temporary shutdown.
Does PHP 8.1 have an upstream fix? PHP 8.1 and older are end-of-life upstream. Check for a trusted vendor backport or migrate to a supported branch; do not rely on an unverified version label.
The broader lesson for web teams
Runtime security is part of application security. A dependency inventory that lists only Composer packages, CMS plugins and JavaScript libraries is incomplete if it cannot answer which PHP build and SAPI serve production traffic.
For PHP, Laravel and WordPress teams, the durable response is a repeatable patch process: inventory the runtime, pin and rebuild images, monitor vendor advisories, test upgrades, restart workers deliberately, review logs after critical disclosures and document ownership. That turns PHP2Shell from an emergency search into an operational capability.
Apptheka Solutions builds and maintains PHP, Laravel and WordPress applications. If you need help identifying PHP runtimes, reviewing exposure or upgrading an end-of-life PHP deployment, our backend and cloud engineering team can help with a focused audit and patch plan.
Sources
- PHP.net - Security advisory: Critical remote code execution vulnerabilities
- PHP.net - PHP 8 ChangeLog
- PHP GitHub advisory - CVE-2026-109618
- PHP GitHub advisory - CVE-2026-109619
- UK NCSC - Critical security issue affecting PHP
- Ubuntu - PHP2Shell vulnerability fixes
- NHS England Digital - Critical Vulnerabilities in PHP
