php2shell (CVE-2026-109618 & CVE-2026-109619) and how IONIX is helping you respond
Last updated: 21 Oct 2026, 17:42 UTC. This page is updated as the situation develops.
TL;DR
- Two critical PHP vulnerabilities (“php2shell”, CVE-2026-109618/109619, CVSS 9.2) can let an attacker run code on PHP servers with no login. PHP has released the fix: 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (21 Oct 2026). Patch now. Early in-the-wild attacks have been reported.
- IONIX has already mapped your potentially affected assets under Threat Intelligence -> Threat Center / Live Exposure Defense in the IONIX portal. Right now that list is every asset we detected running PHP, not yet filtered to vulnerable versions.
- Start now: open the CVE-2026-109618 entry in the IONIX portal and click “What should I fix first” for a prioritized, actionable plan. Patch PHP now (the fix is available) or apply initial mitigations as listed below.
- Coming next from IONIX: version-based narrowing, a safe exploitability test (if feasible), and confirmed WAF rule guidance. ETAs below.
What is happening
Two critical vulnerabilities in PHP, the language behind a large share of the web, were disclosed ahead of their fix. Nicknamed “php2shell,” they are rated Critical (CVSS 9.2) and could let a remote attacker run code on a PHP server without logging in. PHP has released the patch, and public PoCs appeared on GitHub within hours of disclosure, so treat unpatched hosts as exploitable now.
What IONIX has already done
We published a php2shell entry in your IONIX Threat Center/Live Exposure Defense page and mapped your potentially affected assets. Two things to know:
- How we find them: during normal discovery, we passively fingerprint each asset (for example from “Server” and “X-Powered-By” response headers) to see which run PHP. This uses only data we already collect.
- Why the list is broad: it currently includes every asset where we detected PHP, not only vulnerable versions, because a PHP asset can be affected regardless of the version string it advertises (for example distro-backported builds). We are being deliberately wide so nothing is missed, and we are narrowing it next.
Do this now
- Prioritize in one click: for customers with Live Exposure Defense, use “What should I fix first” to rank your affected assets by real risk and generate an operational remediation plan, taking into account all the data IONIX has about your assets, as well as WAF data (for customers with “WAF Posture Management”).
- Patch PHP at the server level now – upgrade to 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35, or your distro’s backport.
- Reduce exposure meanwhile: limit public access to PHP apps and watch those hosts for unusual activity. Also see interim/partial mitigation advice below.
Configuration mitigation (for hosts you cannot patch immediately)
Disclaimer: The fix is now published. Upgrade to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (or your distribution’s backport) – that is the only complete mitigation. The settings below reduce exposure on hosts you cannot patch right away, and on end-of-life branches (8.1 and older) that may not receive a fix. They are partial and were drawn from the official PHP advisories; apply and restart workers, then plan to patch.
php2shell is two separate bugs, and they need two different sets of config changes. Doing only the first (the session setting) leaves you exposed to the second.
A. CVE-2026-109619 (stale request state)
Session upload progress is one of several trigger paths, reachable by an unauthenticated request before your app runs. It is rarely used, so disabling it is safe for most deployments.
Set in php.ini, an FPM pool, or server config – not via ini_set() or a per-request .user.ini, which the advisory says do not reliably apply here. Restart all workers afterward.
session.upload_progress.enabled = 0
session.auto_start = 0 ; already the default; verify it wasn't turned on
fatal_error_backtraces = 0 ; PHP 8.5 only - the strongest demonstrated trigger
This closes the session and fatal-backtrace paths. It does not close the others, so also:
- Prefer startup php.ini or pool/server config over per-request overrides, and remove obsolete or deprecated directives (these raise diagnostics that feed the bug).
- Keep attacker-reachable requests from hitting fatal errors or the execution timeout.
- As a stopgap, pm.max_requests = 1 recycles workers more often (reduces, does not remove, the condition).
B. CVE-2026-109618 (memory-exhaustion corruption)
This one is triggered by exhausting PHP’s memory during request parsing, so the session setting does nothing for it. Reduce the memory pressure an unauthenticated request can create:
memory_limit = -1 ; enforce administratively (php_admin_value in the FPM pool / Apache)
post_max_size = 8M ; or 32M if you accept uploads; keep upload_max_filesize below it
max_input_nesting_level = 32 ; lower where feasible
max_input_vars = 1000
max_file_uploads = 20
Two things that trip people up here:
- memory_limit = -1 looks wrong, but the corruption happens when PHP hits a finite limit mid-operation. Removing the PHP limit avoids that path – then bound memory externally, with a per-worker container or cgroup memory.max, so an unbounded process cannot take down the host. Do not use RLIMIT_AS or RLIMIT_DATA; they make mmap() fail and trigger the vulnerable path.
- If a host or path never accepts file uploads, block multipart requests to it at your web server or WAF.
Verify the session setting took effect
This checks CVE-2026-109619’s session setting only (not the memory settings above). Check every version, pool, and container separately, plus any vhost or directory overrides.
command -v php-fpm >/dev/null || { echo "UNKNOWN: no php-fpm (mod_php/other SAPI)"; exit 2; }
G=$(php-fpm -i 2>/dev/null | grep -ci 'upload_progress.enabled => on')
P=$(php-fpm -tt 2>&1 | grep -i 'upload_progress.enabled' | tail -1)
[ -n "$P" ] && G=$(echo "$P" | grep -c '= *1')
[ "$G" -gt 0 ] && echo VULN || echo PATCHED
Apache with mod_php needs a different check (inspect phpinfo() served through the web SAPI, not the CLI).
If you cannot edit php.ini
Ask your host to apply the above platform-wide (full interim effect), or add the edge rules from the WAF section. CDN or cloud WAF rules are only partial and can be evaded, so treat those hosts as still exposed and patch them first.
Edge hardening at the WAF (partial, defense-in-depth)
These are memory and request-lifecycle corruption bugs reached through ordinary-looking requests, not attacks with a fixed payload to match. There is no WAF signature that reliably blocks them – Cloudflare and Akamai both rely on generic anomalous-execution / command-injection rules plus response-side inspection rather than a php2shell-specific signature, and Cloudflare reports attackers mutating payloads to bypass. Patching is the only complete fix.
If you use a managed WAF, its vendor rules are your fastest coverage – enable or confirm them before writing custom rules.
- Cloudflare: the Managed Ruleset’s “Generic Rules – Anomalous Execution” (1-7) cover both CVEs. Free plans get the Managed Free Ruleset (ID 77454fe2d30c4220b5701f6fdfb893ba) automatically; Pro/Business/Enterprise should confirm the Managed Ruleset (ID efb7b8c949ac4650a09736fc376e9aee) is in block mode. All plans also get the Managed Response Firewall default rule (ID afffe22785674c80a31875c848d2242a), which uses response-side (“full transaction”) detection.
- Akamai: Akamai states its Adaptive Security Engine rule 3000991 v1 detects attacks against both CVEs, and that its existing command-injection rules catch weaponized payloads. Confirm both are enabled and in deny/block mode.
- Coverage figures are the vendors’ own claims, not independently verified, and both vendors say to patch regardless.
The custom rules below are for teams that want explicit limits on top of (or in place of) a managed ruleset – they are not a replacement for patching. They map to PHP’s own interim mitigations, applied at the edge:
- Cap multipart upload size (helps CVE-2026-109618): CVE-2026-109618 is reached by exhausting PHP’s memory during request parsing. Enforcing a conservative request-body limit at the edge raises the bar.
Cloudflare (custom rule, action: Block or Managed Challenge):
(http.request.method eq "POST"
and any(http.request.headers["content-type"][*] contains "multipart/form-data")
and http.request.body.size > 8388608)
Akamai: set the request body inspection/size limit conservatively and add the equivalent custom rule on POST multipart requests.
- Block multipart where you don’t accept uploads (strongest single edge control for CVE-2026-109618).
If a host or path never receives file uploads, drop multipart POSTs to it entirely.
Cloudflare example (scope to your non-upload hosts):
(http.request.method eq "POST"
and any(http.request.headers["content-type"][*] contains "multipart/form-data")
and not http.host in {"uploads.example.com"})
- Alert on upload-progress probing (one path of CVE-2026-109619): Requests carrying the field name PHP_SESSION_UPLOAD_PROGRESS exercise one of several trigger paths for CVE-2026-109619. Use this as a detector, in alert mode, not a block – blocking it will break legitimate upload-progress functionality, and it covers only this one path.
Cloudflare (action: Log):
(http.request.method eq "POST"
and any(http.request.headers["content-type"][*] contains "multipart/form-data")
and (any(http.request.body.multipart.names[*] eq "PHP_SESSION_UPLOAD_PROGRESS")
or http.request.body.raw contains "PHP_SESSION_UPLOAD_PROGRESS"))
Akamai: a custom rule matching POST multipart requests whose body contains PHP_SESSION_UPLOAD_PROGRESS, set to Alert.
Know the limits of these mitigations:
- These apply best at your origin web server or an origin WAF, which sees the full request. CDN and cloud WAFs inspect only the first part of a request body, so a padded request can slip past them.
- Even the size cap misses the OOM variant that uses many small part-headers to exhaust memory under the size limit.
- Nothing at the WAF layer addresses CVE-2026-109619’s other paths (fatal errors, INI-configuration diagnostics, execution timeouts, and fatal_error_backtraces on PHP 8.5).
- Managed rules are partial too. Cloudflare states that request data alone often cannot distinguish an exploit from legitimate traffic (which is why it added response-side detection), and that it has observed attackers mutating payloads to bypass its rules.
- WAF coverage only applies to traffic that actually passes through the WAF. Traffic that reaches your origin directly, bypassing the CDN, is unprotected regardless of the rules above.
So: deploy these as hardening and detection, and prioritize patching to 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 (or your distribution’s backport). On end-of-life PHP (8.1 and older), which may not be patched, apply PHP’s configuration mitigations – memory_limit=-1 enforced administratively, a conservative post_max_size, and session.upload_progress.enabled=0 – alongside these edge rules.
What IONIX is shipping next (target ETAs)
| Capability | What it does | Target ETA |
|---|---|---|
| Version-based narrowing | Cuts the list from “runs PHP” to “runs an affected PHP version” | In progress – ETA: 10pm UTC |
| Safe exploitability test | Flags confirmed-exploitable assets, if it can be done safely | Currently it seems that exploitability testing crashes the PHP servers – so no current ETA for a safe exploit test. We are still tracking this. |
| WAF rule guidance | Recommended rules (e.g. Akamai, Cloudflare) to block exploitation while you patch | Done – see WAF recommendations above. |
Note: IONIX customers with the Live Exposure Defense add-on receive live updates in the IONIX portal / via push notifications. IONIX customers that do not have the Live Exposure Defense add-on will see the updated list of affected assets in Threat Center only after their next scan is complete. In the meantime, these customers can still manually identify all assets that run PHP in the Discovery view.
Follow live updates
This is moving fast. We are posting rolling updates here as each capability ships and as official details are confirmed.
Questions or need help reading your results? Please contact support or your account manager.
