Design Partner Program
TLP:CLEAR SECURITY ADVISORY HRK-SA-2026-1028-03 Exploited in the wild

PHP2Shell (CVE-2026-109618 / 109619): unauthenticated code execution in PHP core

An out-of-memory fatal during request startup leaves a PHP worker pointing at memory it already freed. One anonymous request can reach code execution before your application runs. Upgrade to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, then restart every worker and prove it.

SEVERITY
Critical
PEAK CVSS
9.2
AUTH REQUIRED
None
PUBLIC POC
Yes
PUBLISHED
Oct 28, 2026
REVISION
v1.0 · @Melly
01 · EXECUTIVE SUMMARY

Bottom line

Hayrok Research Lab is tracking two critical, unauthenticated remote code execution flaws in PHP core, together called PHP2Shell. They share one root cause: a fatal out-of-memory error during request startup leaves worker state pointing at freed or half-built memory. They are being exploited now. Patch every PHP install, restart every worker, and prove the serving process is the patched one.

KEY JUDGMENTS
01
Exploitation was observed from Oct 21, 2026. CISA added CVE-2026-109618 to its KEV catalog on Oct 26.Observed
02
Public proof-of-concept code and a working tool exist. The trigger needs no authentication and no vulnerable application code.Observed
03
Apache mod_php is the highest-risk deployment: the attack lands during request startup, before application code runs.Assessed
04
A package update is inert until every PHP worker restarts. A patched version number alone is not proof of remediation.Reproduced
02 · VULNERABILITY DETAILS

Vulnerability summary

PHP out-of-memory state corruption RCE
CVE-2026-109618 NVD
9.2Critical
Companion CVE
CVE-2026-109619 (stale worker global state)
Component
Zend engine, request startup
Trigger path
main/rfc1867.c → php_variables.c → zend_hash.c
Weakness
CWE-824 access of uninitialized pointer
Affected
8.2 to 8.5 below fix; 7.4 to 8.1 via backport; 7.3 and older unfixed
Scoring
9.2 · CVSS v4.0, both CVEs
Impact
Remote code execution as the web server user. No authentication, no session.
EXPOSURE IS WIDE: ANY WEB-FACING PHP
01Serves web requestsPHP-FPM, mod_php, php-cgi, LiteSpeed or FrankenPHP.
02Below the fixed versionOr a distro package without the backport.
03Worker not restartedOld workers keep the vulnerable code in memory.
04Reachable over HTTPA public endpoint that accepts a POST body.
03 · THREAT ACTIVITY

Exploitation status and timeline

IN THE WILDObservedExploitation seen from Oct 21.
PUBLIC POCAvailableTool and writeups are public.
CISA KEVListed Oct 26CVE-2026-109618 added to KEV.
PATCHAvailableEmergency release shipped Oct 21.
DISCLOSURE AND ACTIVITY TIMELINE · 2026
Aug 1Calif finds the first bug with AI assistance during OpenAI's Patch the Planet program. Wiz finds it independently.
Oct 20Details leak before the planned disclosure date.
Oct 21PHP ships 8.5.12, 8.4.27, 8.3.36 and 8.2.35. watchTowr reports exploitation the same day.
Oct 23PHP advisory for CVE-2026-115560, a related session upload progress risk on the same servers.
Oct 26CISA adds CVE-2026-109618 to KEV. PHP ships Windows builds that also fix Brotli2Shell.
04 · AFFECTED PRODUCTS

Affected and fixed versions

Distributions backport the fix without changing the upstream version, so the version string can look old and still be patched. A patched package still does nothing until every worker restarts.

BRANCH
AFFECTED
FIXED IN
STATUS
PHP 8.5
before 8.5.12
8.5.12
Fixed
PHP 8.4
before 8.4.27
8.4.27
Fixed
PHP 8.3
before 8.3.36
8.3.36
Fixed
PHP 8.2
before 8.2.35
8.2.35
Fixed
8.1, 8.0, 7.4
all
Distro package or source backport
Backport
7.3 and older
all
None. Upgrade or isolate
No fix
PHP for Windows
also Brotli2Shell
8.2.35-1 to 8.5.12-1
Fixed
NO CONFIG FIXPHP states no configuration change fully fixes these flaws. Request-size limits and a tested WAF rule reduce exposure while you patch, but updating is the only complete fix.
05 · RECOMMENDED ACTIONS

What to do, in priority order

CriticalImmediately
Apache mod_php serversHighest priority. Patch, then restart Apache. The attack precedes your application.
Any internet-facing PHPPatch and restart every worker. Pull admin panels and legacy apps off the open internet.
HighWithin 72 hours
PHP-FPM behind nginxPatch, then restart every FPM pool. Confirm no old workers survive.
Container imagesRebuild on a patched base image and redeploy. An old image stays vulnerable.
Managed hosting or PaaSGet the fix and the restart confirmed in writing.
HighBefore closing
Every patched hostCompare each worker start time with the patch time, and record it as evidence.
WORKAROUNDS
Cap request size at the edge. Enforce limits on request size, multipart parts and header counts before PHP parses the body.Lower post_max_size. Set post_max_size to the smallest value your apps tolerate.Reduce exposure. Put any PHP admin panel or legacy app behind a VPN or an allow list.Test the WAF rule. Confirm a rule blocks the attack pattern rather than assuming it does.
06 · DETECTION AND HUNTING

Observables and hunting queries

No stable file hashes are published. Hunt on exploitation behavior and on unpatched, unrestarted workers.

TYPE
OBSERVABLE
SOURCE
Behavior
A PHP worker process spawning a shell or unexpected child
EDR, process telemetry
Behavior
Repeated worker crashes or Unknown on line 0 fatals
PHP and web server logs
Exposure
Worker start time earlier than the patch time
Process list on each host
HUNT · PHP2Shellunexpected shells under php
ps -ef --forest | grep -A3 -E "php-fpm|apache2" | grep -v grep
EXPOSURE · PHP2Shellworker age versus patch time
ps -eo pid,lstart,cmd | grep -E "php-fpm|apache2|httpd" | grep -v grep
07 · MITRE ATT&CK

Technique mapping

TACTIC
ID
TECHNIQUE
BASIS
Initial Access
T1190
Exploit Public-Facing Application
Observed
Execution
T1059
Command and Scripting Interpreter
Observed
08 · TECHNICAL ANALYSIS

Root cause and attack path

PHP parses the request body during php_request_startup(), before any script runs. A crafted multipart body can exhaust memory_limit during that parse, which calls zend_bailout(), a non-local jump that abandons the rest of startup. Worker globals that should have been reset are left pointing into the request heap.

Request shutdown then frees that heap, but the pointer in the worker global survives because it belongs to the process, not the request. That is the uninitialized pointer access, CWE-824. CVE-2026-109618 is the same request consuming its own invalid state; CVE-2026-109619 is a later request on the same worker consuming state left behind. The upstream fix is commit 506e87fa7d, which resets the state the jump used to leave dangling.

01 TRIGGER
Anonymous POST drives one request past memory_limit
Control: Cap request size and parts at the edge
02 BAILOUT
OOM fires zend_bailout(), skipping cleanup
Control: Upstream fix resets state on bailout
03 STALE STATE
Worker globals point at freed request memory
Control: Restart every worker after patching
04 EXECUTE
Next request reuses state, reaching RCE
Control: Patch to the fixed branch version
RELATED CVES
9.2 Critical
The companion flaw: stale worker global state consumed by a later request.
n/a Related
Session upload progress risk on the same servers, disclosed Oct 23.
AssessedPHP2Shell turns PHP's decades-old out-of-memory error model into a remote code execution primitive. Patching without restarting workers leaves the flaw live.
09 · VALIDATION

Confirm remediation

A rebuilt package is not a verdict. Each server should end with evidence: patched build running in the serving process, the old worker gone, or not reachable.

01
Inventory the running build, not the package
Read the version from the serving process, across every host and image.
php -v
apt changelog php8.3 2>/dev/null | grep -E 'CVE-2026-10961[89]'
rpm -q --changelog php | grep -E 'CVE-2026-10961[89]'
02
Prove the worker restarted
Compare each worker start time with your patch time.
ps -eo pid,lstart,cmd | grep -E 'php-fpm|apache2|httpd' | grep -v grep
03
Confirm reachability
Find which PHP endpoints take internet traffic and accept uploads.
# map public PHP endpoints from your edge or proxy config
04
Exercise the path, in scope
Drive the documented multipart pattern with no exploitation payload. A patched server rejects it cleanly.
# approved test only: documented multipart OOM pattern, no payload
05
Detect post-exploitation
Alert on a web server process spawning a shell.
ps -ef --forest | grep -A3 -E 'php-fpm|apache2' | grep -v grep
10 · EXPOSURE SELF-ASSESSMENT

Am I exposed?

CVE-2026-109618
01Do you run PHP that serves web requests (mod_php, PHP-FPM, php-cgi, LiteSpeed or FrankenPHP)?
02Is any PHP install below the fixed version, or on a distro package without the backport?
03Have the PHP workers been restarted since the patch was applied?
04Is any affected PHP endpoint reachable from the internet?
ANSWER TO SEE A VERDICT
Pick yes, no or not sure for each question.
11 · REFERENCES AND REVISION HISTORY
References
›PHP security advisory GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
›PHP security advisory GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
›CISA Known Exploited Vulnerabilities catalog
›NCSC-NL php2shell operational guidance
Revision history
1.0Oct 28, 2026Initial publication.

This advisory will be updated as exploitation activity or vendor guidance changes.

12 · FAQ
Is PHP2Shell being exploited?

Yes. Exploitation was observed from Oct 21, 2026, and CISA added CVE-2026-109618 to its KEV catalog on Oct 26.

I updated the package. Am I safe?

Not until every worker restarts. The old worker keeps the vulnerable code in memory until it is replaced.

Can a WAF or config change fix it instead of patching?

No. PHP says no configuration change fully fixes these flaws. A tested rule and tighter request limits reduce exposure while you patch.

Why two CVE numbers for one root cause?

109618 is the same request consuming its own invalid state. 109619 is a later request consuming state left by an earlier one. The fix is the same commit.

VALIDATE YOUR EXPOSURE

Prove your PHP exposure

Hayrok maps your PHP footprint, checks which assets are reachable, and tests whether your controls block the attack and your SOC sees a worker spawn a shell. Every result lands in Evidence Fabric.

At Hayrok Labs we question everything and Validate what matters.