On October 20, 2026, security intelligence channels alerted the web infrastructure community to two embargoed, critical vulnerabilities identified in PHP core. Identified under tracking designations CVE-2026-109618 and CVE-2026-109619, both flaws carry an official CVSS v4.0 rating of 9.2 from the upstream PHP security team. In research circles and threat tracking feeds, the vulnerability pair is being monitored under the label “php2shell.”
[!CAUTION] Active Exploitation in the Wild & CISA KEV Inclusion (November 2026 Status) The Cybersecurity and Infrastructure Security Agency (CISA) has officially added both CVE-2026-109618 and CVE-2026-109619 to its Known Exploited Vulnerabilities (KEV) Catalog. Threat intelligence telemetry from Amazon Threat Intelligence (MadPot), Arctic Wolf Labs, and GreyNoise confirms weaponized, automated botnet exploitation campaigns scanning globally. Attackers are mutating multipart headers (
multipart/form-data; boundary=...) and chaining heap state confusion to bypass naive WAF rules. Emergency patched builds (PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35) and vendor LTS backports (Canonical USN-7072-1, Debian DSA-5790-1) are live. Systems teams must immediately apply patches, hard restart all FastCGI pools, and flush RAM to purge vulnerable ghost workers.
Because preliminary details were leaked online ahead of the coordinated disclosure schedule, the PHP security team scheduled an emergency, out-of-cycle release for October 21 at 14:00 UTC, and published the fixes about twenty minutes early. Security researchers at firms such as watchTowr, Wiz Research, and Sansec have independently verified and reproduced the flaws in lab environments against stock installs of Magento, WordPress, Drupal, Joomla, and Nextcloud. Cloudflare observed early exploit attempts against its network at 07:43 UTC on October 21, roughly six hours before the patched builds were available, confirming that mass scanning began well before a public fix existed.
For systems engineers and site administrators, the primary operational challenge is not panic, but disciplined execution. Upstream vendor patches will only cover actively supported PHP branches: 8.2, 8.3, 8.4, and 8.5. Millions of public web servers, content management platforms, and legacy enterprise backends continue to run end-of-life runtimes like PHP 7.4, 8.0, and 8.1. Those legacy endpoints will not receive automatic upstream fixes unless covered by vendor LTS backports or third-party enterprise support.
This guide details verified facts, architectural impact, concrete CLI inventory commands, emergency patching workflows, and runtime hardening measures for servers that cannot be upgraded immediately. If your infrastructure also runs Node.js or edge reverse proxies handling Brotli compression, consult our emergency analysis of the HTTP2Shell Brotli vulnerability for coordinated edge filtering rules.

The Technical Anatomy: Core Runtime vs. Application Code
Most engineers associate PHP security incidents with application-layer mistakes: an unvalidated SQL query in a custom theme, a vulnerable WordPress file upload plugin, or an insecure deserialization call in an older framework. In those situations, fixing the site requires updating an individual plugin or rewriting application business logic.
Core runtime vulnerabilities are fundamentally different. They reside inside the PHP binary itself or its internal C-level parsing routines, memory allocators, or Server Application Programming Interfaces (SAPIs). When a parser bug allows memory corruption or command injection during request handling, an unauthenticated external HTTP request can trigger code execution before your application frameworks, authentication gates, or access control lists execute.
Under standard hosting environments, PHP processes execute with the privileges of the web worker pool: typically www-data, nginx, apache, or a dedicated per-tenant system user in shared hosting setups. If an attacker triggers unauthenticated remote code execution at the core runtime level, they obtain an interactive shell under that execution context. From there, malicious actors attempt local privilege escalation, read database credentials from configuration files, dump database tables, or install persistent web shells.
Security research from watchTowr Labs and Sansec, alongside alerts from CERT-EU, confirms that the vulnerability mechanism permits unauthenticated arbitrary code execution under specific request conditions. The upstream advisory is blunt about scope: mod_php is confirmed exploitable end-to-end before any application code runs, PHP-FPM is susceptible (the session upload-progress path has a confirmed FPM route), and FrankenPHP and LiteSpeed LSAPI are expected to behave similarly to their respective models. Because automated scanning bots routinely reverse engineer upstream git diffs within two to six hours of public commit releases, and working proof-of-concept code was already circulating on October 20, the window between patch publication and automated exploitation attempts has effectively closed to zero.
The C-Level Mechanics: RFC 1867 and the Longjmp Unwind
The root defect centers on ext/session/session.c, specifically the php_session_rfc1867_callback routine that tracks upload progress when an incoming request carries multipart form data:
- CVE-2026-109618 (Heap Use-After-Free during OOM Unwind): When an unauthenticated request delivers malformed or oversized multipart boundaries, PHP attempts memory allocation for internal progress tracking structures. If memory allocation fails, PHP executes
zend_bailout(), which invokes the C standard librarylongjmp()function. Becauselongjmp()immediately unwinds the execution call stack without executing local cleanup handlers, internal session progress hash tables remain in a corrupted, half-initialized state. When the request shutdown sequence runs, it attempts to clean up this invalid structure, dereferencing freed pointers and triggering memory corruption that can be steered into arbitrary code execution. - CVE-2026-109619 (Cross-Request Worker State Confusion): In persistent worker environments such as PHP-FPM pools or Apache worker processes, global worker-level memory is preserved across successive requests to maximize throughput. When a fatal error aborts request execution via
longjmp(), global state retains pointers to request-scoped memory that was subsequently deallocated. When a second, legitimate request is dispatched to that exact same worker, the worker reads or writes through those dangling pointers. Attackers exploit this cross-request persistence in a two-stage sequence: Request 1 primes the corrupted pointer in worker memory, and Request 2 triggers code execution or memory disclosure.
If your web stack also interfaces with backend daemons or custom automation agents, reviewing our guide on MCP server security hardening covers the process boundary controls required to prevent compromised web workers from pivoting into internal service buses.
Phase 1: Fleet Identification and Asset Inventory
Before downloading packages or altering production configurations, you must identify every instance of PHP running across your fleet. It is common for production servers to host multiple PHP versions concurrently, or to run background worker daemons on a different binary than the public Nginx or Apache reverse proxy.
1. Check the Active CLI and SAPI Versions
Log into your target host and query the system PATH binary:
php -v
php -m | grep -E "curl|openssl|mbstring|xml"
Next, identify which Server API (SAPI) is actively handling external web traffic. On modern Linux deployments, this is almost always PHP-FPM (FastCGI Process Manager):
# Check running PHP processes
ps aux | grep -E "php-fpm|php-cgi|apache2|httpd" | grep -v grep
# Verify active systemd service units
systemctl list-units --type=service | grep php
2. Detect Alternate or Multiple Binaries
Enterprise control panels such as cPanel, Plesk, and CloudLinux store isolated PHP runtimes outside standard /usr/bin locations. Run a filesystem sweep to detect all installed interpreters:
# Search common alternate binary paths
which -a php
ls -d /opt/cpanel/ea-php* 2>/dev/null
ls -d /opt/plesk/php/* 2>/dev/null
ls -d /etc/php/* 2>/dev/null
find /usr/bin /usr/local/bin -name "php*" -type f 2>/dev/null
If you manage web hosting automation via Webmin or cPanel, our operational overview on top 10 WHM security practices provides actionable steps for locking down multi-tenant PHP pools and disabling legacy compilers.
3. Inventory Containerized Environments
If your workloads run in Docker or Kubernetes, your host system will not show local PHP binaries. Inspect your running containers directly:
# List containers running PHP processes
docker ps --format '{{.ID}}\t{{.Image}}\t{{.Names}}'
# Query PHP version inside a specific container
docker exec -it <container_id_or_name> php -v
Record the exact version, patch level, and SAPI type for every web root on your network before proceeding to remediation.
4. Audit Active Upload Progress Directives
Because the primary attack vector targets the RFC 1867 progress tracking callback, check whether your active interpreter has the feature enabled:
# Quick CLI evaluation of active session upload progress status
php -r 'echo "session.upload_progress.enabled: " . (ini_get("session.upload_progress.enabled") ? "ENABLED (EXPOSED)" : "DISABLED (SAFE)") . "\n";'
# Sweep all FPM pool configs and ini files for explicit overrides
grep -rnE "session\.upload_progress" /etc/php/ /etc/php.ini /etc/php.d/ 2>/dev/null
5. Automated Fleet Reachability Scanning
For infrastructure teams managing dozens of virtual hosts, running manual checks across every container and virtual machine is time-consuming. Open-source non-destructive testing utilities (such as 0xrsydn/php2shell-scan and 0x4148/CVE-2026-109618-php2shell-lab) allow operators to verify whether an external domain or internal IP is actively exposing the vulnerable multipart callback without transmitting weaponized memory corruption payloads.

Phase 2: Patching Supported PHP Branches
For systems running officially supported releases (PHP 8.2, 8.3, 8.4, or 8.5), applying upstream vendor updates is your direct resolution. The patched builds released on October 21, 2026 are:
| Ecosystem / Distribution | Version / Package Identifier | Security Status / Advisory |
|---|---|---|
| Upstream PHP 8.5 | 8.5.12 | Official emergency release |
| Upstream PHP 8.4 | 8.4.27 | Official emergency release |
| Upstream PHP 8.3 | 8.3.36 | Official emergency release |
| Upstream PHP 8.2 | 8.2.35 | Official emergency release (8.2 EOL Dec 31, 2026) |
| Ubuntu 24.04 LTS (Noble) | 8.3.6-0ubuntu0.24.04.2 |
USN-7072-1 security update |
| Ubuntu 22.04 LTS (Jammy) | 8.1.2-1ubuntu2.20 |
USN-7072-1 LTS backport |
| Ubuntu 20.04 LTS (Focal) | 7.4.3-4ubuntu2.24 |
USN-7072-1 (Ubuntu Pro ESM backport) |
| Debian 12 (Bookworm) | 8.2.26-1~deb12u1 |
DSA-5790-1 security update |
| Debian 11 (Bullseye) | 7.4.33-1+deb11u8 |
DSA-5790-2 security update |
| RHEL / Rocky / AlmaLinux 9 | php-8.3.36-1.el9.remi / php-8.4.27-1.el9.remi |
Remi modular repository builds live |
| Alpine Linux (v3.20 & Edge) | 8.3.36-r0 / 8.4.27-r0 |
Alpine community repository packages live |
| Docker Official Images | php:8.2-fpm, php:8.3-fpm, php:8.4-fpm |
Multi-arch images (amd64/arm64) verified live |
Run php -v after any upgrade and confirm the output matches or exceeds the patched level above. Version strings alone are not proof of remediation on all platforms, since distribution backports (such as Ubuntu’s 8.1.2-1ubuntu2.20 on 22.04 LTS) carry the fix under an older-looking major version, but upstream tarball installs should show the exact upstream numbers.
Official security advisories and checksums are posted directly on the PHP.net Security Advisories page and in the upstream GitHub advisories for CVE-2026-109618 and CVE-2026-109619.
Repository availability, as of the October 21 evening update: Patched packages are live across all primary repositories. Canonical published USN-7072-1 providing backported security fixes for both Ubuntu 22.04 LTS (PHP 8.1.2) and Ubuntu 20.04 LTS (PHP 7.4.3 via ESM). Debian released emergency security updates via DSA-5790-1 for Debian 12 and Debian 11. Remi Collet published updated RPMs for Enterprise Linux (RHEL 8/9, Rocky Linux, and AlmaLinux). Official Docker php:* images completed multi-architecture builds for linux/amd64 and linux/arm64. Mattias Geniar maintains a continuously updated patch availability tracker confirming package deployment across secondary mirrors.
Debian and Ubuntu (Ondřej Surý PPA or Official Repos)
Update your local repository metadata cache and upgrade the specific PHP packages:
sudo apt-get update
# Upgrade only PHP packages to prevent unintended system-wide package churn
sudo apt-get --only-upgrade install "php8.2*" "php8.3*" "php8.4*"
# Hard restart the PHP FastCGI daemon (see ghost worker warning below)
sudo systemctl stop php8.2-fpm php8.3-fpm php8.4-fpm 2>/dev/null
sudo systemctl start php8.3-fpm # start your specific active version
# Verify service status
sudo systemctl status php8.3-fpm --no-pager
RHEL, Rocky Linux, and AlmaLinux (Remi Repository)
On Enterprise Linux systems utilizing EPEL and Remi:
sudo dnf clean all
sudo dnf check-update php\*
sudo dnf upgrade php\*
# Hard restart PHP-FPM and web servers
sudo systemctl stop php-fpm
sudo systemctl start php-fpm
sudo systemctl reload nginx || sudo systemctl reload httpd
Alpine Linux (Edge and Community Repositories)
On Alpine Linux virtual machines or lightweight container hosts:
# Update APK package indices
apk update
# Upgrade PHP core, FPM, and session extensions
apk add --upgrade php83-fpm php83-session php83-common
# Or for PHP 8.4:
apk add --upgrade php84-fpm php84-session php84-common
# Hard restart the PHP FastCGI process manager
rc-service php-fpm83 restart || { kill -9 $(pidof php-fpm); php-fpm83; }
The Ghost Worker Hazard: Why Graceful Reload Leaves Servers Exposed
One of the most dangerous operational traps observed across systems teams on October 21 is the ghost worker phenomenon.
When you execute apt --only-upgrade or dnf upgrade, the package manager writes new binary files to /usr/sbin/php-fpm and replaces shared libraries in /usr/lib/. However, standard package maintenance hooks often invoke a graceful reload (systemctl reload php-fpm or kill -USR2).
In persistent FastCGI pool architectures, child worker processes holding open file descriptors or active memory mappings to older shared object libraries (.so) frequently fail to terminate. The parent supervisor process remains running, while child workers continue processing incoming web requests using deleted, unpatched libraries mapped in RAM.
To verify whether your host is silently harboring ghost workers executing unlinked vulnerable code, run:
# Detect active PHP processes executing deleted in-memory libraries
sudo lsof -n | grep -i 'php.*(deleted)'
If the output returns lines showing (deleted) files (such as /usr/lib/x86_64-linux-gnu/libphp8.3.so (deleted) or /usr/sbin/php-fpm8.3 (deleted)), your system is still actively vulnerable to exploitation despite the package manager reporting that the upgrade succeeded.
To eliminate ghost workers, execute an explicit, hard stop and start across all PHP-FPM service units:
# Force full termination of all worker pools
sudo systemctl stop 'php*-fpm'
# Verify all child workers exited
pgrep -l php-fpm || echo "All worker processes cleared"
# Start the clean service
sudo systemctl start php8.3-fpm # adjust for your active version
# For Apache mod_php servers:
sudo systemctl restart apache2 || sudo systemctl restart httpd
Re-run sudo lsof -n | grep -i 'php.*(deleted)' to confirm zero stale memory references remain.
Dockerized Workloads
For microservices running on base images such as php:8.3-fpm-alpine or php:8.2-fpm:
- Update your Dockerfile base tag or pull the newly rebuilt upstream container image:
docker pull php:8.3-fpm-alpine
Because official Docker images lag the source release by hours, verify both the pulled version string and the unique RepoDigest before deploying:
# Inspect the live container binary version
docker run --rm php:8.3-fpm-alpine php -v
# Verify the cryptographic container image digest
docker inspect --format='{{index .RepoDigests 0}}' php:8.3-fpm-alpine
The output must show 8.3.36 or newer (or the matching patched level for your tag). If it still shows 8.3.35, upstream has not rotated the image yet and your build remains vulnerable.
- Rebuild your application image in your staging pipeline:
docker build -t yourregistry.com/app:v2.4.1 .
- Deploy with zero downtime using rolling updates in Kubernetes or Docker Swarm, ensuring old pods terminate only after healthy new pods pass HTTP readiness probes.

Phase 3: Defensive Hardening for End-of-Life (EOL) Deployments
A massive percentage of internet sites cannot migrate from PHP 7.4 or 8.0 on zero notice without breaking critical business software. PHP 8.1 and older receive no official binary patches for this incident, although minimal source-only backports for 7.4, 8.0, and 8.1 were published for teams building interpreters from source. If you operate an unpatched instance, you must enforce defense-in-depth isolation at the interpreter, web server, and network perimeter layers.
One critical framing point from the official advisories: these mitigations are partial. CVE-2026-109618 is exploitable through multipart request parsing, and on mod_php even a normal application/x-www-form-urlencoded POST can trigger it. There is no configuration flag that fully closes the hole. Treat everything in this section as a containment bridge measured in hours, not a substitute for patching or taking the host offline.
0. Interim Mitigations That Directly Reduce Attack Surface
The PHP security team and community responders converged on a short list of configuration changes that blunt the confirmed exploitation paths. All of these must be set in php.ini or the FPM pool configuration, followed by a full worker restart. Calls to ini_set(), .user.ini files, and .htaccess overrides apply too late in the request lifecycle to protect you.
; Disable session upload progress tracking (kills the CVE-2026-109619
; session-based path on mod_php and FPM). Must be set globally.
session.upload_progress.enabled = 0
; Disable fatal error backtrace capture (PHP 8.5 only, on by default)
fatal_error_backtraces = 0
; Remove per-request INI override capability consumed by the
; cross-request state confusion paths
; In the FPM pool file: php_admin_flag[allow_url_include] = off
; Strip PHP_VALUE / PHP_ADMIN_VALUE fastcgi_param lines from nginx configs
Two further runtime knobs, with important caveats:
- Set
memory_limit = -1paired with OS-level cgroups. The memory corruption in CVE-2026-109618 occurs when PHP’szend_bailout()aborts execution vialongjmp()during an out-of-memory allocation failure insidephp_session_rfc1867_callback. Becauselongjmp()jumps directly over stack unwinding routines, internal hash tables remain partially initialized, corrupting the heap when request shutdown occurs. Removing PHP’s internal allocation ceiling (memory_limit = -1inphp.ini) preventszend_bailout()from firing during header parsing. However, unconstrained memory allows a denial of service if unmonitored. By constraining memory externally via Linux cgroups (systemdMemoryMaxor Docker--memory), the Linux kernel cleanly terminates or throttles the process if exhausted, bypassing PHP’s internallongjmp()flaw entirely:
# /etc/systemd/system/php-fpm.service.d/memory-limit.conf
[Service]
MemoryMax=4G
MemoryHigh=3.5G
- Set
pm.max_requests = 1on PHP-FPM. In/etc/php/8.x/fpm/pool.d/www.conf, settingpm.max_requests = 1forces FastCGI to terminate and respawn each worker process immediately after servicing a single request. Exploitation of CVE-2026-109619 requires a two-stage state confusion sequence: Request 1 primes corrupted pointers in worker global memory, and Request 2 triggers code execution on that same persistent worker. Recycling the worker after Request 1 makes cross-request memory reuse structurally impossible, though it incurs noticeable CPU overhead on high-traffic nodes.
Block multipart bodies at the web server for hosts that do not accept file uploads. Threat intelligence indicates attackers are mutating request casing and whitespace (MultiPart/Form-Data) to evade simple regexes. Enforce case-insensitive inspection:
# nginx: reject multipart/form-data requests with case-insensitive matching
if ($http_content_type ~* "(?i)multipart/form-data") {
return 403;
}
An equivalent Apache 2.4 rule works even in .htaccess where overrides are permitted. Verify the block from an external host with:
curl -s -o /dev/null -w '%{http_code}\n' -F a=b https://example.com/
A 403 confirms the filter is active. Remember this protects FPM deployments only; mod_php remains exposed through urlencoded POSTs. If you run mod_php on an unpatched branch, the honest options are migrating to PHP-FPM behind these filters, or taking the virtual host offline.
Selective WAF filtering for sites that require uploads: If your application (such as WooCommerce or WordPress Media Library) depends on legitimate file uploads, blanket-blocking multipart/form-data breaks business operations. Deploy targeted virtual patching that drops requests carrying the RFC 1867 upload progress trigger parameter regardless of casing:
# ModSecurity 3 / OWASP CRS custom virtual patch rule
SecRule REQUEST_HEADERS:Content-Type "@rx (?i)multipart/form-data" \
"id:1096181,phase:2,deny,status:403,log,chain,msg:'php2shell CVE-2026-109618 session upload progress probe blocked'"
SecRule ARGS_NAMES|REQUEST_BODY "@rx (?i)PHP_SESSION_UPLOAD_PROGRESS"
For Cloudflare edge WAF, deploy this custom expression using lowercase normalization to isolate and drop upload progress triggers while allowing normal files:
(lower(http.request.headers["content-type"][0]) contains "multipart/form-data" and any(http.request.body.form[*].names[*] == "PHP_SESSION_UPLOAD_PROGRESS"))
For a fast edge-level containment without touching servers, Cloudflare users reported success with a simple custom rule blocking non-GET methods (http.request.method in {"POST" "PUT" "PATCH" "DELETE"}), and Cloudflare deployed managed WAF rules covering the known exploit vectors to all plans, including free, on October 21. CloudLinux Imunify360 (ModSecurity ruleset 8.83) and Bunny Shield also published managed detections. Note that WAF rules are a stopgap: public proof-of-concept code is circulating and variants will bypass signature filters.
Safe non-destructive probe to test WAF and edge defenses: Systems administrators can verify whether their edge WAF or web server rules are actively intercepting the attack parameter without sending weaponized memory corruption payloads:
curl -s -o /dev/null -w "%{http_code}\n" -X POST \
-H "Content-Type: multipart/form-data; boundary=---------------------------safecheck" \
--data-binary $'-----------------------------safecheck\r\nContent-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"\r\n\r\n1\r\n-----------------------------safecheck--\r\n' \
https://example.com/
If the response returns 403 Forbidden, your edge filter or web server rule is intercepting the trigger parameter correctly.
Do not waste time on these: hiding errors with display_errors = 0 or error_reporting does nothing (the bug fires before error handling matters); file_uploads = Off does not stop the multipart parser from running; application-layer middleware, login pages, CSRF tokens, and maintenance mode plugins are all bypassed because the vulnerable code executes before your application boots; blocking PHPSESSID cookies at the proxy breaks sessions without closing the parser path; and disabling only the PHP handler while leaving the files reachable serves your source code, including database credentials, as plain text.
1. Hardening php.ini Directives
Open the active configuration file for your FastCGI pool (for example, /etc/php/7.4/fpm/php.ini or /etc/php.ini) and configure the following parameters:
; Prevent leaking PHP presence and exact version numbers in HTTP headers
expose_php = Off
; Disable remote resource inclusion via file functions
allow_url_fopen = Off
allow_url_include = Off
; Prevent script error details from displaying to end users
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
; Restrict file system operations strictly to application directory trees
open_basedir = "/var/www/html/:/tmp/"
; Disable dangerous OS execution and process control functions
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,highlight_file,pcntl_exec
Applying disable_functions neutralizes the vast majority of automated payload staging scripts. Even if an attacker finds a parsing bug that attempts to invoke shell execution routines, the interpreter aborts the request before the command reaches the operating system kernel.
2. Web Server Ingress Boundaries (Nginx)
Ensure that your Nginx reverse proxy blocks direct script execution inside writable upload directories, and scrubs invalid FastCGI query arguments.
In your Nginx site configuration (/etc/nginx/sites-available/your-site.conf):
server {
listen 443 ssl http2;
server_name example.com;
root /var/www/html;
# Deny direct execution of scripts inside uploads or static asset paths
location ~* /(?:uploads|files|wp-content/uploads|media|cache)/.*\.php$ {
deny all;
access_log off;
log_not_found off;
}
# Block access to hidden dotfiles (.git, .env, .htaccess)
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location ~ \.php$ {
# Enforce that the target file actually exists before passing to FPM
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
# Mitigate CGI environment injection
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_PROXY "";
}
}
Reload Nginx after validating configuration syntax:
nginx -t && sudo systemctl reload nginx
For teams re-evaluating whether Nginx maintenance overhead is worth it compared to modern alternatives with native ACME issuance, our engineering comparison of Caddy vs Nginx for small teams details performance benchmarks and reverse proxy config syntax side-by-side.
If your architecture includes broader frontend layers, our detailed breakdown of web security for frontend developers breaks down how HTTP headers, cookie security flags, and Content Security Policies prevent attackers from weaponizing compromised origin data.
3. Edge Firewall and Cloudflare WAF Filters
If your traffic passes through Cloudflare, Fastly, or AWS CloudFront, apply strict edge inspection rules:
- Block Direct Origin Access: Ensure attackers cannot bypass edge WAF filters by hitting your web server IP directly. Restrict incoming TCP port 80 and 443 traffic exclusively to Cloudflare edge CIDR ranges using UFW or
iptables. - Payload Inspection Rules: Enable managed Core Web Application Firewall rules targeting generic PHP remote code execution signatures.
- Rate Limiting: Implement strict throttling on administrative endpoints like
/wp-login.php,/admin/, or custom API dispatchers. Our playbook on API rate limiting and cost management outlines token-bucket and sliding-window rules that protect origin compute from automated scanning bursts.

Phase 4: Threat Hunting and Post-Patch Integrity Verification
Patching protects against future intrusions, but it does not remove an adversary who compromised your server during the pre-patch exposure window, which in this incident began with the October 20 leak. Conduct a thorough forensic sweep of your web root and operating system state.
One nuance that changes your hunt: the memory-disclosure and cross-request-state paths do not always drop a traditional web shell on disk. Attackers can read worker memory (which can contain database passwords, API keys, and session material) without writing a single file. If your logs suggest exploitation but the filesystem looks clean, rotate every credential reachable by the PHP worker, including database passwords, cloud keys, and session secrets, and treat the worker pool’s memory-resident secrets as exposed.
1. Audit Recently Modified Script Files
Inspect your web root for PHP files created or modified within the past 48 to 72 hours:
find /var/www/html -type f -name "*.php" -mtime -3 -ls
If your deployment process uses Git, check the working tree for unauthorized files or modifications:
cd /var/www/html
git status --ignored
Any modified or untracked .php file in a version-controlled repository warrants immediate quarantine and investigation.
2. Search for Common Web Shell Patterns
Adversaries deploying PHP web shells frequently rely on string obfuscation routines to evade standard anti-malware signatures. Execute a recursive regex scan across your document roots:
grep -rnE "(eval\s*\(|base64_decode\s*\(|assert\s*\(|gzinflate\s*\(|str_rot13\s*\(|preg_replace\s*\(.*\/e)" /var/www/html/ --exclude-dir={cache,vendor}
Investigate matches that involve concatenated variable execution patterns such as $_POST['cmd'], $$variable, or hex-encoded payload arrays.
3. Inspect System Persistence Mechanisms
Threat actors rarely remain confined to document roots once they gain code execution. Review system-level scheduling tables and temporary execution directories:
# Check user cron jobs and system schedules
crontab -l
ls -la /etc/cron*
cat /etc/crontab
# Audit writable temporary execution spaces
ls -la /tmp /var/tmp /dev/shm
Ensure that /tmp and /dev/shm are mounted with noexec,nosuid,nodev flags in /etc/fstab. This prevents untrusted binaries dropped by web processes from executing directly from temporary scratch spaces.
4. Monitor Suspicious Outbound Sockets
A compromised web worker will typically open an outbound TCP socket to establish a reverse shell or contact a command-and-control server. Run an active network socket inspection:
# List all active outbound connections established by web server users
ss -tupn | grep -E "php-fpm|nginx|apache"
# Cross-reference with process trees
lsof -i -n -P | grep -E "php|www-data"
If an active process linked to www-data or php-fpm maintains an established connection to an unknown external IP address over arbitrary ports, terminate the process tree immediately and isolate the host from the local network.
For organizations monitoring federal compliance directives and global threat notifications, authoritative updates are maintained in the CISA Known Exploited Vulnerabilities Catalog. CISA officially cataloged both CVE-2026-109618 and CVE-2026-109619 following widespread, weaponized exploitation. Federal agencies and enterprise operators are mandated to patch or isolate affected assets immediately. Technical reporting is also tracked on BleepingComputer.
5. Threat Intelligence Telemetry & Dual-Vector Attack Chaining
Telemetry published by Amazon Threat Intelligence (monitoring the MadPot distributed honeypot system), Arctic Wolf Labs, and GreyNoise demonstrates that exploitation shifted rapidly from manual proof-of-concept testing to automated botnet monetization. Key observed threat patterns include:
- Cryptominer Droppers (Kinsing): Attackers exploit PHP2Shell heap confusion to execute transient curl and wget one-liners that download Kinsing miners into
/dev/shmor/tmpbefore spawning background daemons. - Header Mutation and Case Alternation: Automated scanners cycle through mutated headers such as
Content-Type: multipart/form-data; boundary=...,MultiPart/Form-Data, andmultipart/mixedwith arbitrary whitespace padding to bypass simple regex WAF filters. - Attack Chaining with WordPress Core RCE: In multi-tenant environments, scanners are observed dual-probing hosts. Attackers test for PHP2Shell to hijack worker memory and simultaneously probe staging paths for the WordPress Core RCE Vulnerability (CVE-2026-119977) during package upgrade windows. Chaining the two vulnerabilities allows attackers to elevate transient worker execution into persistent rootkit installations inside WordPress upload directories.
6. Network IDS and Runtime Security Rules (Suricata & Falco)
To supplement web server log greps, network defense teams and Kubernetes platform engineers should deploy automated detection rules at the packet and kernel runtime layers.
Suricata IDS Signature (Network Ingress Detection)
This Suricata signature alerts on raw HTTP request bodies attempting to pass the session upload progress trigger parameter inside multipart forms:
alert http any any -> $HTTP_SERVERS any ( \
msg:"VEDUIS SEC - PHP2Shell RFC 1867 Upload Progress Exploit Probe (CVE-2026-109618)"; \
flow:established,to_server; \
http.method; content:"POST"; \
http.header; content:"multipart/form-data"; nocase; \
http.request_body; content:"name=\"PHP_SESSION_UPLOAD_PROGRESS\""; nocase; fast_pattern; \
classtype:web-application-attack; \
sid:202610961; rev:2; \
reference:cve,2026-109618; \
reference:url,veduis.com/blog/php-core-vulnerability-emergency-remediation-guide/; \
)
Falco Runtime Detection Rule (Kernel Audit / eBPF)
In containerized Kubernetes deployments or Linux hosts running Falco, monitor unexpected process spawns initiated by the PHP FastCGI manager:
- rule: Unauthorized Shell or Downloader Spawned by PHP Worker
desc: Detects PHP-FPM or Apache workers spawning interactive shells or download utilities indicative of PHP2Shell post-exploitation
condition: >
spawned_process and
(proc.pname in (php-fpm, php-fpm8.2, php-fpm8.3, php-fpm8.4, apache2, httpd)) and
(proc.name in (bash, sh, dash, zsh, ksh, curl, wget, python, python3, perl, nc, ncat, netcat))
output: >
ALERT: PHP worker spawned unauthorized child process (user=%user.name command=%proc.cmdline parent=%proc.pname pid=%proc.pid container=%container.id)
priority: CRITICAL
tags: [security, attack, cve-2026-109618, cve-2026-109619, php2shell]
7. Log Indicators Specific to This Incident
Standard web shell greps miss the php2shell patterns. Based on detection guidance published by Wiz and circulated through community incident channels, prioritize these signals in your access and error logs:
- Multipart requests to endpoints that never accept uploads, especially sequences of oversized part headers with no valid
Content-Length - Bursts of HTTP 500 responses preceded by PHP memory-limit fatal errors in the FPM or Apache error log, which indicate attempted OOM-trigger exploitation
- Abnormally large or malformed
PHPSESSIDrequest cookies, consistent with the memory-disclosure probing researchers demonstrated - PHP worker crash loops or rapid
pm.max_requestschurn disproportionate to legitimate traffic - Any FPM or mod_php worker spawning child shells (
sh,bash), download utilities (curl,wget), or establishing outbound connections, which remains the single highest-confidence compromise signal
A practical grep starting point against web server access logs:
# Identify top IP addresses hitting non-upload paths with multipart payloads
grep -E "multipart/form-data" /var/log/nginx/access.log | \
awk '{print $1, $7}' | sort | uniq -c | sort -rn | head -50
# Sweep request logs for explicit session upload progress parameter names in URI strings
grep -rnEi "PHP_SESSION_UPLOAD_PROGRESS" /var/log/nginx/ /var/log/apache2/ 2>/dev/null
# Scan PHP-FPM error logs for fatal out-of-memory triggers associated with CVE-2026-109618
grep -rnE "Allowed memory size of [0-9]+ bytes exhausted" /var/log/php*-fpm.log /var/log/php_errors.log 2>/dev/null
Cross-reference the top source IPs and request paths against your application’s legitimate upload endpoints. Anything left over after that filter deserves immediate containment and credential rotation.
Operational Triage Checklist
Print or distribute this verification checklist across your operations team to track progress during the patch cycle:
| Step | Action Item | Verification Method | Status |
|---|---|---|---|
| 01 | Inventory all running PHP versions across hosts | Run php -v and ps aux | grep php-fpm |
Complete |
| 02 | Identify unpatched EOL versions (PHP 7.4, 8.0, 8.1) | Flag hosts requiring isolated mitigation | Complete |
| 03 | Apply upstream vendor updates (PHP 8.2 - 8.5, Ubuntu/Debian/Remi) | Run apt --only-upgrade or pull updated Docker images |
Complete |
| 04 | Hard restart all PHP-FPM service daemons | Run systemctl stop php*-fpm && systemctl start php*-fpm |
Complete |
| 05 | Audit RAM for ghost workers holding deleted libraries | Run sudo lsof -n | grep -i 'php.*(deleted)' |
Complete |
| 06 | Restrict php.ini directives on legacy systems |
Verify disable_functions and open_basedir |
Complete |
| 07 | Enforce Nginx/Apache script execution blocks | Block .php execution in static upload folders |
Complete |
| 08 | Lock down origin IP access behind edge WAF | Verify edge CIDR restrictions in firewall | Complete |
| 09 | If unpatched: set session.upload_progress.enabled=0, restart workers |
Run php-fpm8.4 -i | grep upload_progress to confirm |
Complete |
| 10 | If unpatched on FPM: block multipart or non-GET methods at proxy | External safe synthetic curl probe returns 403 |
Complete |
| 11 | Deploy Suricata and Falco runtime detection rules | Verify IDS alerts on RFC 1867 progress probes | Complete |
| 12 | Audit webroot file integrity for web shells | Run find -mtime and obfuscation pattern grep |
Complete |
| 13 | Review logs for php2shell indicators and rotate worker-reachable credentials | Check multipart bursts, 500 storms, worker shells | Complete |
| 14 | Inspect cron jobs, /tmp, and outbound sockets |
Check crontab, /dev/shm, and ss -tupn |
Complete |
Summary and Long-Term Architecture
Emergency vulnerability disclosures test the maturity of your operational playbooks. While the disclosure of CVE-2026-109618 and CVE-2026-109619 demands immediate action, the engineering teams that manage these response windows cleanly are those who approach triage systematically.
Take inventory first. Upgrade supported production runtimes immediately upon package availability. Lock down legacy, end-of-life installations at the SAPI and web server configuration layers. Verify file integrity to confirm your environment remained uncompromised during the pre-patch disclosure window.
Long-term, treat this incident as an architectural catalyst. Transition legacy workloads toward containerized, immutable infrastructure with read-only root filesystems, minimal base images, and automated rolling deployment pipelines. When runtime environments are isolated by default, a core vulnerability becomes an orderly patch deployment rather than an organizational crisis. If this incident exposed how long your fleet would need to move off an end-of-life branch, that migration timeline is now a quantified business risk worth funding.
If you need this containment sequence run against a live PHP estate, Veduis offers legacy PHP and WordPress hardening as a scoped engagement.
Edit notice: This article was originally published October 20, 2026, ahead of the coordinated disclosure, and was substantially updated on October 21, 2026 as emergency PHP builds shipped. On November 1, 2026, the guide was refreshed to document CISA’s official addition of both CVE-2026-109618 and CVE-2026-109619 to the Known Exploited Vulnerabilities Catalog, live threat intelligence from Amazon MadPot and Arctic Wolf Labs observing mutated multipart headers and WordPress upgrade race condition chaining, as well as production Suricata IDS and Falco runtime detection rules.



