PHP2Shell (CVE-2026-109618, CVE-2026-109619): what to patch, what to check and how a WAF helps
Two critical PHP flaws allow unauthenticated remote code execution. Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, turn off session upload progress, and check your logs for the signs we list here.
By the OpenWAF security team
In short. PHP2Shell is the name the researchers gave to two critical flaws in the PHP engine, CVE-2026-109618 and CVE-2026-109619 (CVSS 4.0 score 9.2), disclosed on 21 October 2026. Both can lead to unauthenticated remote code execution (PHP RCE) as the web server’s PHP user. They are fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35.
- Update PHP now and restart every PHP worker. No configuration change is a complete fix.
- Until you can, set
session.upload_progress.enabled=0inphp.inior the pool configuration, and lowerpost_max_size. - A third issue, CVE-2026-115560, is not fixed by those releases. The same setting covers it until the next PHP bugfix release.
- OpenWAF blocks requests that carry the session upload progress field at the edge (rule 10075). It is a stopgap and does not replace the update.
What PHP2Shell is
PHP2Shell is a family of memory-safety bugs in how PHP sets up and tears down each web request. It was found by researchers from Wiz, Calif and OpenAI’s Codex Security, who report that affected code goes back to PHP 5.4. The PHP project published two advisories on 21 October 2026 and new releases for every supported branch at the same time.
| CVE | Advisory | What goes wrong | Impact |
|---|---|---|---|
| CVE-2026-109618 | GHSA-w8hw-w9fx-j79w “RCE via OOM corruption” | An out-of-memory error can interrupt PHP while request data is only partly initialised. Request cleanup then treats that invalid data as valid. | Unauthenticated RCE. Validated over HTTP against mod_php with default memory and input limits. |
| CVE-2026-109619 | GHSA-6wmf-4rv5-p3rp “RCE via stale global state” | Request-owned state can outlive the memory behind it. The next request handled by the same worker may use it before it is reset (a use-after-free). | Unauthenticated RCE and disclosure of memory from other requests. |
Both advisories carry the same CVSS 4.0 vector, AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H: network reachable, no login, no user interaction, full impact on the server. The attack complexity is rated high, but the researchers demonstrated working exploits, so treat that rating with caution.
How an attacker reaches the bugs
For CVE-2026-109618, the attacker pushes PHP into an out-of-memory error at the wrong moment. The advisory describes several ways to do it through the multipart parser:
- a body without a usable
Content-Lengthskips thepost_max_sizecheck; - each multipart part can carry any number of headers;
- empty file fields do not count towards
max_file_uploads, but they still create metadata, and nested field names multiply the work.
For CVE-2026-109619, one request leaves stale state behind and a later request on the same worker consumes it. The confirmed paths are:
- session upload progress, which is enabled by default and works without the application ever calling
session_start(); - diagnostics raised by per-request INI settings (
php_valuein.htaccess, orPHP_VALUEin FPM); - the PHP 8.5
fatal_error_backtracessetting.
Who is affected
According to the PHP project, every PHP installation that serves web requests is at risk. The server API (SAPI) that runs PHP changes how easy the attack is:
| SAPI | Risk | Why |
|---|---|---|
| Apache mod_php | Highest | mod_php always runs request shutdown, even when request startup failed. The demonstrated exploit fires before any application code runs, so the application on top does not matter. |
| PHP-FPM (Nginx, Apache proxy_fcgi, Caddy) | High | FPM ends the child process when startup fails, and no complete FPM exploit of CVE-2026-109618 has been shown. RCE through CVE-2026-109619 was validated on FPM with a suitable application operation. |
| php-cgi | Affected | Listed by the PHP project among the affected web SAPIs. |
| FrankenPHP | High | Long-lived workers. The advisory calls it likely susceptible to attacks that do not depend on the application. |
| LiteSpeed (LSAPI) | Affected | Exploits that depend on the application are considered likely but have not been validated. |
WordPress, Drupal and Joomla sites run on these same SAPIs. The researchers report pre-authentication RCE against all three, and the memory disclosure of CVE-2026-109619 works whatever the application.
Fixed versions
| Branch | Fixed in | Notes |
|---|---|---|
| PHP 8.5 | 8.5.12 | Also set fatal_error_backtraces=0 if you cannot update yet. |
| PHP 8.4 | 8.4.27 | |
| PHP 8.3 | 8.3.36 | |
| PHP 8.2 | 8.2.35 | Security support ends on 31 December 2026. |
| PHP 8.1, 8.0, 7.4 | No release | End of life. The PHP security team published minimal source backports as branches: 8.1, 8.0 and 7.4. |
The PHP 8.6.0 release candidate published the same day (RC4) also contains the fixes.
Distribution packages. Linux distributions and LTS vendors received the patches in advance. A distribution package can carry the fix under an old-looking version number, so check the package changelog for the CVE IDs instead of comparing versions. For example:
apt changelog php8.2-fpm | grep -E 'CVE-2026-10961[89]' # Debian, Ubuntu
rpm -q --changelog php-fpm | grep -E 'CVE-2026-10961[89]' # RHEL, Alma, Rocky
php -v # upstream builds only
After updating, restart every PHP process: Apache for mod_php, each FPM pool, FrankenPHP and LiteSpeed workers. A worker that is still running keeps the vulnerable code in memory.
Exploitation status
The disclosure was rushed. A proof-of-concept video was posted by mistake the evening before the planned release, and The Hacker News reported early attacks and “active exploitation attempts” on 21 October, the day of the patches. Later reporting mentions honeypot hits as early as 17 October and Mirai-variant botnets trying the flaws. No source has publicly confirmed a successful compromise so far. With this much scanning, assume every unpatched PHP server will be probed.
Partial mitigations and their limits
The PHP project is explicit: only updating is a complete solution. The measures below reduce exposure to specific attack paths while you schedule the update. They do not make an installation safe.
For CVE-2026-109618 (out-of-memory corruption)
- memory_limit=-1, set where applications cannot override it (
php_admin_valuein the FPM pool or Apache configuration). This removes the PHP memory limit failure an attacker can control. An allocation failure in the operating system can still reach the vulnerable code. - A low post_max_size:
8Mfor sites without uploads,32Mif you need them, withupload_max_filesizebelow it. - Request limits at the web server or proxy for decoded body size, number of fields, multipart parts, headers and nesting depth. They must also cover requests without a usable
Content-Length. - A container or cgroup memory limit as an availability boundary, ideally one that kills only the affected worker. Do not use
RLIMIT_ASorRLIMIT_DATA: they can cause the very allocation failure the attack needs.
For CVE-2026-109619 (stale global state)
- session.upload_progress.enabled=0 in
php.ini, the FPM pool or the server configuration, then restart every worker.ini_set()and FPM’s.user.iniapply too late and do not help. This closes the confirmed session paths, not every variant. - On PHP 8.5, fatal_error_backtraces=0, which closes the confirmed backtrace path only.
- Remove invalid or deprecated per-request settings that emit diagnostics before the request starts. Hiding them with
error_reporting,display_errorsor@does not help. - Fix fatal errors and execution timeouts that an attacker can trigger, including in callbacks, uploads, imports and cleanup code.
; php.ini or FPM pool (php_admin_value[...] = ...), then restart every worker
session.upload_progress.enabled = 0
post_max_size = 8M ; 32M if the site accepts uploads
upload_max_filesize = 4M ; always below post_max_size
fatal_error_backtraces = 0 ; PHP 8.5 only
Note a behaviour change after the update. Running out of memory no longer stops PHP on the spot: the error is raised at the next safe point, and a second, hard limit above memory_limit ends the process outright. Shutdown functions do not run in that case, so review code that relies on register_shutdown_function() to log or clean up after a memory error.
Signs of an attack
The researchers quoted by The Hacker News point to these signs. Look for them in web server, PHP and FPM logs from 17 October onwards:
- unusual
multipart/form-datarequests, often to URLs that never accept uploads, followed by “Allowed memory size exhausted” errors or repeated HTTP 500 responses; - oddly large
PHPSESSIDcookies in responses; - PHP workers restarting or crashing for no clear reason (
child exited on signalin FPM, segmentation faults in the Apache error log); - bursts of warnings before any script runs, cleanup diagnostics, or “Maximum execution time exceeded” on odd URLs, which the GHSA advisories list as signs worth reviewing.
Turn on log_errors with error_reporting=E_ALL while you investigate. Clean logs are not proof of safety: a successful exploit can leave no PHP error at all. If you find these signs on an unpatched server, treat it as possibly compromised. Look for new files in writable directories, new cron jobs and unexpected outbound connections from the PHP user, and rotate the secrets the application can read.
The follow-up: CVE-2026-115560
On 23 October 2026, two days after the patches, the PHP project published an informational advisory about a separate, “unlikely” RCE vector in session upload progress, CVE-2026-115560. The 21 October releases do not fix it.
It needs an unusual combination of configuration and code:
- the configuration sets
session.serialize_handlertophp_binaryorphp_serialize; - the application switches it to
phpat runtime withini_set()before callingsession_start(); - session upload progress is still enabled.
Applications that never change the serialize handler at runtime are not exposed. The PHP project will ship the fix and a full advisory with the next regular bugfix release; no date or version has been announced. Its advice is to set session.upload_progress.enabled=0 until then. If you already did that for CVE-2026-109619, keep it.
To check whether your code switches the handler:
grep -rnE "ini_set\(\s*['\"]session\.serialize_handler" --include='*.php' .
How OpenWAF protects your sites
Rule 10075 is enabled on the OpenWAF edge. It blocks every request in which a request argument is named PHP_SESSION_UPLOAD_PROGRESS (case-insensitive), whether it sits in a multipart body, a URL-encoded body or the query string. This is the field PHP reads to start session upload progress. Dropping it at the edge keeps those requests away from the PHP worker, which covers the confirmed session paths of CVE-2026-109619 and the CVE-2026-115560 vector.
A WAF rule is a stopgap, and this one has clear limits:
- It does not cover CVE-2026-109618 in general. The out-of-memory paths go through the multipart parser itself, and a request built for them does not need that field. Per-site request size and time-out limits make memory exhaustion harder, but they are not a fix.
- It does not cover the paths of CVE-2026-109619 that depend on server configuration, such as per-request INI diagnostics or
fatal_error_backtraces. - It only matches the default field name. If an application changed
session.upload_progress.name, requests with the new name are not blocked by this rule. - It only protects hostnames proxied through OpenWAF. Traffic that reaches your origin directly bypasses it, so restrict the origin to OpenWAF where you can.
Legitimate upload progress bars use the same field, so they stop working behind the rule. If you need one, add a per-site exception for rule 10075 on that path, and only after the server runs a fixed PHP release. Sites that run the WAF in log-only mode record matching requests instead of blocking them.
The fix is still to update PHP. The rule buys time while you do.
Checklist
- List every server, container image and hosting account that runs PHP, and note the SAPI (mod_php, FPM, CGI, FrankenPHP, LiteSpeed).
- Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or install your distribution’s package whose changelog lists CVE-2026-109618 and CVE-2026-109619.
- On 7.4, 8.0 or 8.1, apply the source backport or your LTS vendor’s package, and plan the move to a supported branch.
- Restart Apache, every FPM pool and every long-running PHP worker. Rebuild and redeploy container images.
- Set
session.upload_progress.enabled=0inphp.inior the pool configuration until the CVE-2026-115560 fix ships, or permanently if you do not use upload progress. - Until every host is patched, lower
post_max_size, enforce request limits at the proxy and setfatal_error_backtraces=0on PHP 8.5. - Search logs from 17 October for the signs above, and treat unpatched servers that show them as possibly compromised.
- Put public PHP sites behind a WAF that blocks
PHP_SESSION_UPLOAD_PROGRESSwhile you patch, and restrict origins to the WAF.
Frequently asked questions
Is PHP2Shell being exploited?
Exploitation attempts started within hours of the 21 October 2026 disclosure, according to reporting by The Hacker News that cites Cloudflare, watchTowr and others. At the time of writing no source has publicly confirmed a successful compromise, but mass scanning means every unpatched PHP server should be treated as a target.
I run Nginx with PHP-FPM, not mod_php. Am I affected?
Yes. The PHP project lists every PHP installation that serves web requests, including PHP-FPM, php-cgi, FrankenPHP and LiteSpeed. mod_php carries the highest risk because a demonstrated exploit fires before any application code runs; on FPM, remote code execution through CVE-2026-109619 was validated with a suitable application operation. Patch either way.
My distribution still reports an older PHP version. Am I vulnerable?
Not necessarily. Linux distributions and LTS vendors received the patches in advance and often backport them without changing the upstream version string. Check your package changelog for CVE-2026-109618 and CVE-2026-109619 instead of comparing version numbers.
Is session.upload_progress.enabled=0 enough?
No. It blocks the confirmed session upload progress paths of CVE-2026-109619 and the CVE-2026-115560 vector, but not the out-of-memory corruption of CVE-2026-109618 or other variants. Only updating PHP fixes PHP2Shell. Keep the setting off after patching if you do not use upload progress bars.
Does a WAF protect me from PHP2Shell?
Partly. A WAF can drop requests that carry the PHP_SESSION_UPLOAD_PROGRESS field, as OpenWAF rule 10075 does, and request size limits make memory exhaustion harder. It cannot see every path to CVE-2026-109618 or the configuration-based paths of CVE-2026-109619. Treat it as a stopgap while you patch.
What is CVE-2026-115560 and is there a fix?
It is a separate, unlikely remote code execution vector in session upload progress, announced by the PHP project on 23 October 2026. It needs an unusual setup: session.serialize_handler set to php_binary or php_serialize in the configuration and switched to php with ini_set() before session_start(). The 21 October releases do not fix it; the fix and full advisory come with the next regular bugfix release. Until then, set session.upload_progress.enabled=0.
What should I do on PHP 7.4, 8.0 or 8.1?
These branches no longer receive releases. The PHP security team published minimal source backports for 7.4, 8.0 and 8.1 for people who build from source; otherwise ask your LTS vendor or distribution, or move to a supported branch.
Sources
- GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618) PHP, Oct 21, 2026
- GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619) PHP, Oct 21, 2026
- Security advisory: Critical remote code execution vulnerabilities, update now php.net, Oct 21, 2026
- Informational advisory: Session upload progress (CVE-2026-115560) php.net, Oct 23, 2026
- PHP Issues Emergency Patches for Two Critical PHP2Shell RCE Flaws as Exploit Attempts Emerge The Hacker News, Oct 21, 2026
- PHP Warns of Another Unpatched RCE Risk Two Days After Emergency PHP2Shell Patches The Hacker News
- CVE-2026-109618 record CVE Program, Oct 21, 2026
- PHP2Shell (researchers’ site: Wiz, Calif, OpenAI Codex Security) PHP2Shell researchers
Topics
- PHP2Shell
- CVE-2026-109618
- CVE-2026-109619
- CVE-2026-115560
- PHP RCE
- session upload progress
- mod_php
- PHP-FPM
Author
OpenWAF