November 2, 2026
PHP2Shell: Two Critical Runtime Vulnerabilities, One Follow-On Warning
An offensive-security analysis of CVE-2026–109618 and CVE-2026–109619, public exploit research, safe validation, and the additional PHP…

By Muhammad Raheem
14 min read
An offensive-security analysis of CVE-2026–109618 and CVE-2026–109619, public exploit research, safe validation, and the additional PHP session-upload issue.
Introduction
When assessing a web application, it is natural to focus on its exposed routes, authentication logic, plugins, API endpoints and framework-specific weaknesses.
But the application is only one layer of the attack surface.
Beneath WordPress, Magento, Laravel, Drupal and other PHP applications sits the PHP runtime. It parses requests, manages memory, handles sessions and controls the lifecycle of each request. A vulnerability in that layer can affect applications that have completely different codebases.
That is what makes PHP2Shell interesting.
On 21 October 2026, the PHP project published two critical remote-code-execution advisories:
- CVE-2026–109618 — RCE via out-of-memory corruption.
- CVE-2026–109619 — RCE via stale global state.
Both received a CVSS v4.0 score of 9.2 from the PHP Group.
The vulnerabilities are particularly relevant to penetration testers because the attack surface is not limited to a specific CMS or framework. The PHP runtime and its serving configuration matter.
There is also an important distinction between the two vulnerabilities, the exploitability of different SAPIs, and what public proof-of-concept repositories actually demonstrate.
This article examines those distinctions rather than treating every PHP installation as equally exploitable.
1. Vulnerability overview
CVE-2026–109618 — Out-of-memory corruption
PHP uses longjmp() as part of its out-of-memory handling. In certain request-processing paths, an allocation failure can interrupt execution before internal request structures have been completely initialized.
The problem is what happens next.
Request cleanup may continue and interpret partially initialized state as valid. That can lead to memory corruption and, under suitable conditions, remote code execution.
The issue is particularly relevant to request parsing and multipart upload handling.
CVE-2026–109619 — Stale global state
The second vulnerability concerns internal state that survives beyond the lifetime of the memory it references.
PHP maintains global state that can temporarily point into request-owned memory. If that state is not reset correctly, or is repopulated after being reset, a later operation can reference memory that has already been freed.
A subsequent request handled by the same worker may consume that stale state before normal initialization has completed.
The important concept is worker reuse.
A web worker is a long-running process. Request-owned memory should not remain accessible through global references after that request has ended. When the lifecycle is interrupted, the next request can encounter state that should no longer exist.
Why the distinction matters
These are related PHP runtime vulnerabilities, but they should not be collapsed into one generic exploit description.
CVE-2026–109618 concerns unsafe state after an out-of-memory failure.
CVE-2026–109619 concerns stale internal state surviving a request boundary.
They share an emergency patch release, but their exploitation paths and prerequisites are not identical.
2. Severity, affected versions and exploitation status
PHP published the advisories on 21 October 2026.
The PHP Group's CVSS v4.0 score is 9.2 Critical for both vulnerabilities.
The vector is:
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
A few metrics deserve attention:
- AV:N — the attack vector is network-based.
- PR:N — no privileges are required.
- UI:N — no victim interaction is required.
- AC:H — successful exploitation has high attack complexity.
- AT:P — successful exploitation depends on attack requirements being present.
The high attack complexity is important. A critical score does not mean every vulnerable PHP deployment can be exploited using the same public script.
Fixed upstream versions
Upgrade to the following fixed PHP releases or a downstream package with a documented security backport:
- PHP 8.2: 8.2.35
- PHP 8.3: 8.3.36
- PHP 8.4: 8.4.27
- PHP 8.5: 8.5.12
PHP 8.1 and older no longer receive normal security releases from the PHP project. PHP provided minimal source backports for 7.4, 8.0 and 8.1, while distributions and LTS vendors may provide their own updates.
Do not assume that a version banner tells the complete story. A vendor may backport a fix while retaining an older upstream version string.
For legacy deployments, verify the package changelog or vendor security notice.
Exploitation status
CISA added both vulnerabilities to its Known Exploited Vulnerabilities catalog on 26 October 2026.
That is a meaningful change in prioritization. This is no longer a vulnerability that should be assessed solely on the basis of theoretical exploitability.
VulnCheck also documented early scanning and attempted exploitation activity. Its canary observations included multipart probes and an attempted session-file webshell chain. In one observed attempt, the follow-up file retrieval returned 404.
The distinction matters:
- CISA KEV inclusion is evidence of exploitation.
- Honeypot and canary observations provide useful information about attacker behavior.
- A failed webshell retrieval is not proof of a successful compromise.
- Public exploit availability does not establish that every vulnerable build is exploitable with that particular PoC.
For an incident investigation, preserve the distinction between scanning, attempted exploitation, successful execution and confirmed persistence.
3. Attack-surface discovery: look beneath the framework
A common inventory mistake is to identify the application but not the runtime serving it.
A WordPress installation, for example, may be running PHP through Apache mod_php, PHP-FPM behind Nginx, a container image or a hosting-panel-managed runtime.
Those deployments should not be treated as identical.
Start by identifying the PHP installations and their configurations.
Local inventory
On Linux systems, useful initial checks include:
php -v
php --ini
php -i | grep -E \
'Server API|memory_limit|session.upload_progress.enabled|fatal_error_backtraces'
apachectl -M 2>/dev/null | grep -i php
ps -eo pid,ppid,user,args | \
grep -E '[p]hp-fpm|[a]pache2|[h]ttpd'php -v
php --ini
php -i | grep -E \
'Server API|memory_limit|session.upload_progress.enabled|fatal_error_backtraces'
apachectl -M 2>/dev/null | grep -i php
ps -eo pid,ppid,user,args | \
grep -E '[p]hp-fpm|[a]pache2|[h]ttpd'For containerized deployments:
docker ps --format '{{.Names}} {{.Image}}'docker ps --format '{{.Names}} {{.Image}}'These are inventory checks, not vulnerability proofs.
One particularly important limitation: php -v and php -i normally describe the CLI runtime. The CLI binary may not be the same build or configuration used by the web server.
Check the actual Apache module, PHP-FPM binary, FPM pool configuration and container image.
Search beyond obvious PHP applications
Include:
- WordPress and WooCommerce installations.
- Magento and Adobe Commerce.
- Laravel and Symfony applications.
- Drupal and Joomla.
- cPanel and Plesk hosting environments.
- Internal administration panels.
- Containers containing bundled PHP runtimes.
- Legacy applications using separate PHP-FPM pools.
- Appliances and third-party products that bundle PHP internally.
An application may not disclose PHP through an X-Powered-By header. The absence of a visible PHP version is not proof that PHP is absent or patched.
For an authorized external assessment, a passive fingerprinting tool can provide useful initial evidence. It cannot establish whether a vendor backport is installed or whether the vulnerable SAPI and configuration are present.
4. Exploitability and the role of the SAPI
PHP's advisory identifies all PHP installations serving web requests as potentially at risk. This includes:
- Apache with mod_php.
- PHP-FPM.
- php-cgi.
- FrankenPHP.
- LiteSpeed.
However, PHP explicitly considers the risk highest for mod_php, where an unauthenticated request can reach the demonstrated vulnerable path before application code runs.
This distinction is important when evaluating research claims.
Apache mod_php
The vendor demonstrated an exploit against mod_php.
A vulnerable request-processing path can be reached before application-level routing or authentication logic has an opportunity to protect the request.
This means that the security of the PHP runtime itself matters, not simply the security of the CMS or framework.
PHP-FPM
PHP-FPM needs a more careful assessment.
A failure during request startup can result in the FPM child being terminated. That changes whether a particular memory-corruption path survives long enough to be consumed.
It does not mean FPM should be considered universally safe.
Other application-stage and worker-reuse paths have been documented. The PHP advisories and research writeups distinguish those paths from the demonstrated mod_php case.
For an assessment, record the actual SAPI and the conditions of the tested path rather than transferring a mod_php result directly to FPM.
5. Public PoC and research review
The number of public PHP2Shell repositories increased rapidly after disclosure.
Repository popularity is not a substitute for exploit validation. A repository can contain a crash trigger, a memory-corruption primitive, an application-dependent chain or a genuine command-execution demonstration.
Those are different levels of evidence.
The following review is based on public repository material and research writeups. I did not execute any exploit code.
Repository: eness/php2shell-CVE-2026–109618-CVE-2026–109619-PoC
Repository:
https://github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC
The repository contains a Python PoC for CVE-2026–109618 and claims remote arbitrary command execution.
Its README describes a multi-stage memory-corruption chain and provides a build-specific exploit profile.
The documented default target profile requires:
- Apache prefork with mod_php.
- A particular PHP build profile.
- Specific session and upload-progress configuration.
- A constrained memory configuration.
- Specific binary-layout information and offsets.
One notable detail is that the README's default profile specifies display_errors=1. That is not a safe assumption to make about production deployments.
The README also identifies a PHP 8.4.26 Apache Docker image as its default profile. It is therefore not reasonable to interpret the repository as a universal exploit for every PHP version, architecture or SAPI.
What does it demonstrate?
The repository claims an RCE implementation, not merely a crash trigger. Its stated proof is command execution in the intended target configuration.
Limitations:
- Build-specific assumptions.
- Narrower default configuration than a generic PHP version check suggests.
- Binary offsets and allocator behavior matter.
- The repository's claims have not been independently reproduced in this review.
A tester should not mark a target exploitable simply because its PHP version is below the upstream fix threshold.
Repository: zake1god/php2shell
Repository:
https://github.com/zake1god/php2shell
This repository takes a more explicitly lab-oriented approach.
Its README describes a loopback-only Docker environment containing:
- A vulnerable PHP 8.4.26 Apache mod_php instance.
- A patched PHP 8.4.27 instance.
- A mitigated PHP 8.4.26 instance.
The author reports a positive RCE control in the vulnerable instance and negative results in the patched and mitigated controls.
It also describes a persistent proof artifact intended to distinguish command execution from an HTTP 500, timeout, memory exhaustion message or worker crash.
That is a useful design choice.
A crash is not proof of RCE. A timeout is not proof of RCE. A 500 response is not proof of RCE.
What does it demonstrate?
The repository claims a positive command-execution result in its pinned local lab and includes negative controls.
Limitations:
- The demonstration is calibrated to a specific PHP and Apache build.
- Its README explicitly warns against assuming portability to arbitrary PHP binaries.
- The result is an author-reported lab demonstration, not an independently reproduced result here.
For controlled research, its loopback-only design is preferable to pointing an exploit at a production endpoint.
Repository: ikow/php2shell-poc
Repository:
https://github.com/ikow/php2shell-poc
This repository is useful because it separates multiple proposed exploitation chains instead of presenting one path as the only way to reach impact.
Its README describes five chains, including paths involving:
- Application-level local file inclusion.
- Application deserialization and destructor behavior.
- Session serialization-handler differences.
- Runtime OOM and stale-state behavior.
The prerequisites differ between those chains.
For example, a chain that needs an application LFI sink is not equivalent to a standalone PHP runtime exploit. Similarly, a path requiring an application to call unserialize() and expose a suitable gadget should not be presented as a generic pre-authentication primitive.
What does it demonstrate?
The repository contains exploit research, lab material and detection content. Its README describes the individual chains and their stated prerequisites.
Limitations:
The repository's claims about five independent chains should not be treated as five independently verified, universally applicable exploits. Each chain needs its own review of the implementation, runtime, application requirements and test evidence.
Non-exploit scanner: Evil0ctal/php2shell-scanner
Repository:
https://github.com/Evil0ctal/php2shell-scanner
This is a different category of tool.
Its README describes a remote non-destructive scanner and read-only host forensics. The remote scan does not execute the vulnerability chain. The forensic functionality is intended to inspect server-side artifacts without executing discovered files.
That makes it potentially useful for authorized exposure assessment and incident triage.
But a version-based or fingerprint-based scanner is not a substitute for verifying the actual package and serving runtime.
Independent exploit research: VulnCheck
Research:
https://www.vulncheck.com/blog/php2shell-vulnerabilities
VulnCheck independently reported reproducing both vulnerabilities and developing a working exploit for CVE-2026–109618.
Its published research describes support for several specific PHP versions on AMD64 and ARM64 with default settings and display_errors=off under mod_php.
It also reported that one public PoC it tested successfully bypassed ASLR on PHP 8.4.26, but did not work outside that specific setup in its testing.
This is a useful reminder that exploit reliability is a property of the runtime build and environment, not just the CVE identifier.
6. Safe authorized lab validation
Memory-corruption testing can crash workers and interrupt service availability.
Do not test an OOM or worker-reuse exploit path against a production system simply because the test is described as a PoC.
A safer validation process is:
- Create an isolated, disposable lab.
- Bind the lab services to loopback rather than exposing them to a network.
- Record the PHP build, architecture, SAPI, configuration and container image digest.
- Establish a vulnerable positive-control instance.
- Establish a patched negative-control instance.
- Establish a mitigated negative-control instance.
- Capture PHP error logs, web-server logs, worker lifecycle events and process telemetry.
- Confirm that any claimed execution is distinguishable from a crash or HTTP error.
- Destroy the lab and its generated artifacts when finished.
The zake1god/php2shell repository provides an example of a loopback-only lab design.
For an assessment that does not require exploit execution, start with local package verification and a passive remote check. Do not send memory-exhaustion traffic to a customer production environment.
7. Detection and evidence collection
For defenders, a useful detection strategy should combine request telemetry, process telemetry and host-level evidence.
No single indicator is sufficient.
HTTP and WAF telemetry
Look for:
- Unusual multipart POST requests to PHP endpoints.
- Abnormally large or malformed multipart bodies.
- Unusual numbers of multipart fields or parts.
- Unexpected use of the configured session upload-progress field.
- Repeated 5xx responses following suspicious PHP requests.
- Requests that correlate with worker restarts or crashes.
A custom User-Agent is useful for correlation but weak as a primary detection. An attacker can change it.
Request-body inspection belongs at a WAF, reverse proxy or IDS layer when ordinary access logs do not capture request bodies.
PHP and web-server logs
Investigate:
- Memory exhaustion errors.
- Fatal errors during request startup or cleanup.
- Repeated PHP worker crashes.
- Apache segmentation faults.
- PHP-FPM child exits and unexpected worker replacement.
- Sudden changes in HTTP 500 and 502 rates.
An error such as memory exhaustion is a reason to investigate, not proof that the vulnerability was exploited.
Endpoint and process telemetry
One of the most useful behavioral signals is an unexpected child process spawned by a PHP or web-server worker.
Monitor process ancestry involving:
apache2httpdphp-fpmphp-cgi
Unexpected child processes such as shells, interpreters and download utilities deserve investigation, especially when their parent is running under the web application account.
Correlate process creation with:
- The originating HTTP request.
- The web-server service account.
- Outbound network connections.
- File modifications.
- New or modified scheduled tasks.
- Changes to application configuration.
Host-level evidence
Review:
- PHP session storage directories.
- Web roots and upload directories.
- Temporary directories.
- Newly created PHP files.
- Changes to
.htaccessand application configuration. - Unexpected application accounts.
- Database and API credentials accessible to the web worker.
If suspicious execution is found, preserve evidence before cleaning the host.
Detection rules
CISA published a PHP2Shell Sigma rule in its public repository:
The rule is marked test, so it should be reviewed and tuned for the organization's actual log sources and field mappings before production deployment.
A useful additional defensive reference is the public scanner and forensics project:
https://github.com/Evil0ctal/php2shell-scanner
8. Impact and post-exploitation boundaries
A successful PHP2Shell exploitation path can result in code execution in the context of the PHP or web-server worker.
That is serious, but it is important to describe the boundary accurately.
Remote code execution as www-data, for example, does not automatically mean root access.
The practical impact depends on:
- Filesystem permissions.
- Database access.
- Application secrets.
- Cloud credentials available to the process.
- Container privileges and mounted volumes.
- Network access from the compromised workload.
- Whether other services trust the web application account.
A penetration tester should establish what the web worker can actually access.
Potentially exposed assets include database credentials, application configuration, API tokens, source code, uploaded files and cloud metadata or service credentials where network and identity controls permit access.
Do not assume a container escape or host-level privilege escalation. Those are separate findings that require separate evidence.
9. MITRE ATT&CK mapping
The primary mapping is:
- T1190 — Exploit Public-Facing Application
This is justified when an exposed PHP service is exploited through a network-facing request.
A follow-on mapping may be appropriate if telemetry confirms it:
- T1059.004 — Unix Shell
This applies when exploitation is followed by shell execution on a Linux system.
Do not automatically assign post-exploitation techniques merely because a vulnerability is capable of RCE. Map observed behavior, not hypothetical behavior.
10. Remediation and verification
Primary remediation
Upgrade to a fixed PHP release or a downstream vendor package with a documented backport.
Then restart every relevant PHP worker and web-server process.
Updating files on disk is not enough if old worker processes continue running the vulnerable binary in memory.
Verify:
- The package version and security changelog.
- The actual web-serving SAPI.
- Every PHP-FPM pool.
- Apache mod_php modules.
- Container image versions.
- Long-running PHP processes.
- Any separately bundled PHP runtime.
Temporary mitigation for CVE-2026–109618
PHP recommends removing the controllable PHP memory-limit failure path with an administratively enforced:
memory_limit=-1
It also recommends conservative request-size limits, including lower post_max_size values and limits on decoded request size, input fields, multipart parts, headers and nesting depth.
This must be approached carefully. An unlimited PHP memory limit should not mean unlimited host memory consumption. Use container or cgroup limits as an availability boundary.
PHP specifically warns against substituting RLIMIT_AS or RLIMIT_DATA, because those can cause the allocation failure involved in the vulnerable path.
These are temporary exposure reductions, not complete fixes.
Temporary mitigation for CVE-2026–109619
PHP recommends disabling session upload progress:
session.upload_progress.enabled=0session.upload_progress.enabled=0Apply it through startup-level configuration such as php.ini, the FPM pool or the web-server configuration, and restart every worker.
Do not rely on application-level ini_set() or FPM .user.ini for this mitigation.
For PHP 8.5, PHP also recommends:
fatal_error_backtraces=0fatal_error_backtraces=0This blocks a confirmed fatal-backtrace path, not every possible exploitation path.
Important follow-on issue: CVE-2026–115560
There is a separate issue that should not be confused with the two PHP2Shell CVEs.
On 23 October 2026, PHP published an informational advisory for CVE-2026–115560.
PHP describes this as an unlikely RCE vector requiring a specific combination:
- The application configures
session.serialize_handlerasphp_binaryorphp_serialize. - The application switches the handler to
phpat runtime usingini_set()before callingsession_start(). - Session upload progress remains enabled.
PHP says applications that do not change the serialization handler at runtime are not exposed to this particular path.
The 21 October PHP2Shell releases do not fix CVE-2026–115560.
PHP recommends keeping session.upload_progress.enabled=0 until the next regular bugfix release. The PHP archive still describes the issue as awaiting that release and a full advisory.
This is an important operational nuance: patching the original two CVEs does not mean every related session-upload-progress risk has disappeared.
Official reference:
https://www.php.net/archive/2026.php
11. Lessons for penetration testers and red teamers
There are several practical lessons from this disclosure.
First, inventory the runtime, not just the application.
A CMS fingerprint does not tell you which PHP binary or SAPI is actually serving requests.
Second, separate a crash from code execution.
A memory-corruption PoC may produce a worker crash, a 500 response or a denial-of-service condition. That does not establish arbitrary command execution.
Third, review PoCs as engineering artifacts.
Check the tested version, architecture, SAPI, configuration, offsets, worker model, proof mechanism and negative controls. A repository with many stars is not automatically reliable.
Fourth, understand worker lifecycle.
The stale-state issue demonstrates why request boundaries and worker reuse are security-relevant. The next request can matter just as much as the request that triggered the original failure.
Fifth, establish impact using the actual service account.
If execution is confirmed, document the permissions and resources accessible to that account. Do not overstate the result as root compromise or container escape without evidence.
Finally, verify the remediation in the running environment.
Check vendor backports, restart every worker and confirm that the actual web-serving runtime is patched.
Conclusion
PHP2Shell is a strong example of why application security cannot stop at application code.
CVE-2026–109618 and CVE-2026–109619 demonstrate how failures in memory handling and request lifecycle management can create a remote execution risk beneath otherwise unrelated applications.
The CISA KEV additions make prioritization clear. Public exploit research makes it equally clear that exploitability is configuration- and build-dependent.
For penetration testers, the most valuable approach is to combine runtime discovery, careful PoC triage, controlled lab validation and evidence-based impact assessment.
The question is not simply whether a server runs PHP.
The question is which PHP runtime is actually serving requests, what state it carries between requests, and whether that runtime has been patched and restarted.
Sources and further reading
Primary PHP advisories and records
- PHP News Archive, 2026 — https://www.php.net/archive/2026.php
- CVE-2026–109618 — https://www.cve.org/CVERecord?id=CVE-2026-109618
- CVE-2026–109619 — https://www.cve.org/CVERecord?id=CVE-2026-109619
- GHSA-w8hw-w9fx-j79w — https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
- GHSA-6wmf-4rv5-p3rp — https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
Exploitation and technical research
- VulnCheck — https://www.vulncheck.com/blog/php2shell-vulnerabilities
- Canadian Centre for Cyber Security — https://www.cyber.gc.ca/en/alerts-advisories/al26-026-critical-vulnerabilities-impacting-php-cve-2026-109618-cve-2026-109619
Public PoC and lab repositories
- https://github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC
- https://github.com/zake1god/php2shell
- https://github.com/ikow/php2shell-poc
- https://github.com/Evil0ctal/php2shell-scanner
Detection