PHP2Shell refers to two PHP memory-safety vulnerabilities, CVE-2026-109618 and CVE-2026-109619, that can allow unauthenticated remote code execution. CISA added both to its Known Exploited Vulnerabilities catalog on October 26, 2026. Check the PHP runtime handling web requests, apply the appropriate security update, and investigate the exposure period using the logs you already collected. CISA catalog
Patch verification and incident investigation answer different questions. A fixed runtime closes the affected path; it does not establish what happened before the update. An empty log search does not establish that an exposed server was untouched.
Technical information checked October 31, 2026.
Start with the PHP runtime serving requests
PHP’s advisory covers web deployments including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP, and LiteSpeed. PHP identifies mod_php as the highest-risk configuration. Include every application entry point in the assessment rather than checking only the host’s default PHP command. PHP security advisory
This read-only command identifies the CLI binary selected by your shell:
php -r 'printf("PHP=%s SAPI=%s\n", PHP_VERSION, PHP_SAPI);'
Example output:
PHP=8.5.12 SAPI=cli
Your version will depend on the installed binary. SAPI=cli is the critical limitation: this result does not identify an FPM worker, an Apache module, another container, or a different PHP installation selected by the web server.
For each public application, record:
- the host, container, or pod serving it;
- the PHP package or image actually running;
- the web SAPI and worker pool;
- the package vendor and security-update evidence;
- when the fixed workers replaced the previous processes.
Use an existing protected diagnostic or administrative mechanism to verify the serving runtime. Avoid adding a public phpinfo() page. A deployment image tag and a new CLI process are useful inventory details, but neither proves that every existing web worker has been replaced.
Check the fix for your PHP release
The upstream advisories identify these initial fixed releases for the original PHP2Shell pair:
| PHP branch | Initial release fixing the pair |
|---|---|
| 8.2 | 8.2.35 |
| 8.3 | 8.3.36 |
| 8.4 | 8.4.27 |
| 8.5 | 8.5.12 |
These are historical fix floors, not instructions to stop at those versions indefinitely. Use the current supported security release or the fixed package documented by your vendor. PHP request-state advisory
Distribution packages may carry backported fixes without adopting the corresponding upstream version string. Match the complete package build to the vendor’s advisory. Likewise, upgrading an application’s PHP dependency declaration does not replace its PHP interpreter. Red Hat’s bulletin distinguishes product versions, deployment configurations, package updates, and container rebuilds. Red Hat PHP bulletin
Updating packages, replacing containers, and restarting worker pools change the running service. Follow the deployment process for that application, then verify every serving instance and check normal requests. Keep the change time so the investigation can distinguish pre-update and post-update events.
For PHP 8.1 and older, establish whether a maintained vendor provides the relevant backport or move to a supported release. Do not infer protection from an old version’s absence in a scanner’s results. PHP update guidance
Keep the session upload issue separate
PHP’s October 23 notice describes CVE-2026-115560, a separate issue requiring an unusual configuration and application behavior: upload progress remains enabled while code changes the session serializer from php_binary or php_serialize to php before starting the session. Track that assessment separately from the original pair’s patch status. PHP session upload notice
Disabling session upload progress blocks documented session-related paths, but it is not a complete substitute for patching the original vulnerabilities. The request-state advisory also explains why hiding warnings or disabling error display does not remove the underlying memory-safety problem. PHP request-state advisory
Build a timeline from existing logs
Start with the period during which the vulnerable deployment was reachable. Identify the time zone and clock behavior of each source before combining events.
Useful sources include reverse-proxy access and error logs, PHP worker errors, deployment records, and existing host audit or process telemetry. Application logs can add request context, but they cover only the execution paths that reached the application.
The following fixture is synthetic. It demonstrates correlation and is not a PHP2Shell detection signature. Save it as incident.ndjson to try the query:
{"timestamp":"2026-10-31T08:11:03Z","host":"web-02","service":"php-worker","message":"Allowed memory size exhausted"}
{"timestamp":"2026-10-31T08:11:04Z","host":"web-02","service":"web-proxy","message":"Upstream closed before response headers","status":502}
{"timestamp":"2026-10-31T08:13:20Z","host":"web-02","service":"deployment","message":"Patched worker pool started","release":"web-20261031.2"}
{"timestamp":"2026-10-31T08:13:25Z","host":"web-02","service":"web-proxy","message":"Health request completed","status":200}
With jq, select one host and a bounded UTC window:
jq -c '
select(
.host == "web-02"
and (.timestamp | fromdateiso8601)
>= ("2026-10-31T08:10:00Z" | fromdateiso8601)
and (.timestamp | fromdateiso8601)
< ("2026-10-31T08:15:00Z" | fromdateiso8601)
)
| {timestamp, service, message}
' incident.ndjson
This query uses whole-second UTC timestamps ending in Z, as supplied by the fixture. Adapt timestamp parsing to the real source format before using it on collected records.
All four example events match. They establish an ordering within the sample: a worker error, a proxy failure, a deployment record, and a successful health request. They do not establish why memory was exhausted, whether the failure was malicious, or whether the deployment record accurately describes every worker.
Preserve the original records and access restrictions. A working timeline can use selected fields; it does not require copying authorization headers, cookies, request bodies, or other secrets into a new diagnostic file.
Read errors as symptoms, then check other evidence
CVE-2026-109618 involves corrupted state following an allocation failure. That mechanism does not turn every memory-exhaustion message into evidence of exploitation. PHP memory-corruption advisory
CVE-2026-109619 concerns request data that a worker retains after the memory holding it has been freed. A later request reaching the same worker can act on that stale data. An application error log may not record every step needed to establish that sequence. PHP request-state advisory
Similarly, HTTP 500 or 502 responses, worker exits, and timeouts can have many causes. Compare the affected period with an earlier baseline and a healthy peer. Check whether failures coincide with a deployment, resource pressure, or a change in traffic. The server error 500 guide explains the distinction between an HTTP symptom and its cause.
If suspicious activity remains unexplained, correlate it with independently collected evidence: unexpected process execution, changes to application files or scheduled tasks, unusual account activity, and outbound connections. Use the host’s established investigation tools and preserve evidence before remediation removes it. Linux audit logging can support this work when the relevant rules were already active.
Adding audit rules or centralized collection now cannot recreate an earlier event that was never recorded. Also check retention, rotation, collector failures, and which hosts actually reported during the period. Keep those gaps in the findings.
Investigate collected events in Fluxtail
For logs already delivered to Fluxtail, select the relevant stream and time window, then narrow by host or service. Search a stable message fragment such as Allowed memory size exhausted, inspect neighboring events, and compare the same interval across affected instances. The search and filters reference lists the supported filters.
Apply severity filters after the initial search so a proxy warning or deployment event remains visible. Use labels only when the collector and receiver actually mapped them. A request identifier inside a message does not automatically become an independently filterable field.
Live Tail helps observe new collected events during normal post-update checks. For new collection, follow a supported path such as Docker with Fluent Bit or TLS Syslog, then verify one harmless marker in the destination stream.
Fluxtail provides centralized log management. It does not establish a runtime’s patch status or turn an error search into a CVE scanner. Retained rows support an investigation; missing rows need a collection and retention assessment.
Record patch status and investigation findings separately
Keep two explicit results for each deployment:
- Patch status: the serving runtime, package or image evidence, worker replacement time, and verification result.
- Investigation findings: the period examined, available log sources, observed activity, remaining gaps, and any incident-response action.
A successful request after deployment supports a health check. A verified fixed runtime supports patch status. Neither replaces an assessment of the earlier exposure period.
For ongoing PHP application records, the PHP Monolog guide covers structured logging and collection. For a broader investigation sequence, see how to read logs.