Note: This post will be updated as exploitation, patch uptake and dark web activity develop.
PHP quietly runs most of the web. It sits behind WordPress blogs, Magento storefronts, government portals, and countless in-house banking and customer applications.
On 21 October 2026, the PHP project shipped emergency fixes for two critical flaws in the language engine itself, collectively nicknamed PHP2Shell. The bugs do not live in a plugin or a CMS. They live in how PHP handles a request before any application code runs, which means a single crafted HTTP request can reach them on a default setup. Exploitation attempts were already hitting honeypots four days before the patch existed.
This post sets out what CPX Threat Intelligence Center (TIC) knows, what we measured across the UAE, and what defenders should do this week.
Key highlights:
- Two CVEs, one root pattern: CVE-2026-109618 and CVE-2026-109619, both rated CVSS v4.0 9.2 (Critical), let an unauthenticated attacker corrupt PHP worker memory and, under the right conditions, execute code.
- Broad blast radius: every PHP branch from 5.4 (2012) to 8.5 is affected on web-serving setups, including Apache mod_php, PHP-FPM, php-cgi, FrankenPHP and LiteSpeed. Apache with mod_php carries the highest risk.
- Exploited before disclosure: the earliest known attempt was logged on 17 October 2026, four days before patches shipped. Attempts increased sharply once details leaked on 20 October.
- End-of-life gap: only PHP 8.2 to 8.5 received official releases. Versions 7.4, 8.0 and 8.1 got minimal source-only backports; 5.4 to 7.3 get nothing.
- UAE exposure: CPX-TIC’s Internet Scanners analysis found 4,065 UAE hosts advertising PHP, of which 853 run end-of-life branches and only 25 already showed a fixed build one day after release.
- Action window is hours, not weeks: patch, restart every PHP worker, isolate what cannot be patched, and hunt from 17 October onward.
Threat assessment
What is PHP2SHELL and why these vulnerabilities matter
PHP2Shell is the name given to two memory-safety flaws in the PHP engine, taken from a researcher tool that chained them into a working shell. Both share the same weakness: when PHP aborts a request abruptly, part of its internal state is not cleaned up, and a later step, or a later request handled by the same worker, trusts memory it should not.

CVE-2026-109618 (out-of-memory corruption): oversized form fields push a request past ‘memory_limit’ while PHP is still parsing it. Request data is left half-initialised, and the cleanup routine treats it as valid.
CVE-2026-109619 (stale global state): request-owned state survives after its memory is freed. Researchers reached it through session upload progress, the fatal-error backtrace path and an OPcache class-cache slot. A later request reuses the freed memory, a classic use-after-free.
Three properties make this more serious than a typical CMS bug:
- It runs before your application. PHP parses the request body before any application code executes. Login pages, application firewalls built into the CMS and maintenance modes give no protection.
- No authentication is needed. Any endpoint that accepts a POST can act as the trigger.
- It leaks across users. On long-lived workers (Apache prefork, PHP-FPM pools), one attacker request can poison state that another visitor’s request inherits. Researchers showed fragments of other users’ data, including session tokens and keys, coming back in an oversized ‘PHPSESSID’ cookie.
Reaching full code execution is harder than crashing a worker. It depends on heap layout and often needs hundreds of requests to defeat memory randomisation. That is a speed bump, not a barrier. History supports caution: CVE-2024-4577 (PHP-CGI) and CVE-2019-11043 (PHP-FPM) both moved from disclosure to botnet and ransomware tooling within days, and both remain in CISA’s Known Exploited Vulnerabilities catalogue. PHP2Shell is broader than either, because it does not need CGI mode or an unusual web server configuration.
UAE impact assessment
CPX-TIC’s Internet scanners queried on 22 October 2026, one day after the fix, and identified globally 2.23 million internet-facing hosts advertise PHP in their response headers, and roughly half of those that disclose a version run end-of-life branches. In the UAE we counted 4,065 hosts, the largest visible footprint in the GCC, ahead of Bahrain (1,205), Saudi Arabia (811), Qatar (253), Kuwait (108) and Oman (91).

The UAE estate is newer than the global average, with 29% of versioned hosts on end-of-life PHP against 51% worldwide. That still leaves 853 hosts on branches PHP will not fix, led by PHP 5.6 and 8.1. Of the 2,122 hosts on supported branches, only 25 showed a fixed build a day after release; some of the rest may run distribution backports that keep an old version string, so each must be verified rather than assumed.
Three further signals matter for UAE defenders
- Apache leads the stack. Apache, the deployment where PHP reports a demonstrated exploit path, fronts more UAE PHP hosts than any other server, and about one in seven hosts with an identified OS still runs end-of-life CentOS.
- Non-standard ports. Around half the UAE hosts answer on ports such as 8080, 8081 and 81, typical of admin panels, staging and test systems that often fall outside patch cycles. Exposed phpMyAdmin and Zabbix consoles were among them.
- Attribution needs care. About 60% of UAE-geolocated hosts sit on a single foreign hosting provider’s address space, which likely reflects IP registration rather than physical location. Organisation-level exposure should come from attack surface management, not country filters.
These are floor figures: servers that hide their PHP version, or sit behind a CDN, are not counted. Financial, government and education services in the UAE rely heavily on PHP-based portals, and the UAE Cyber Security Council has issued PHP-specific alerts before, most recently for CVE-2024-4577.
Exploitation, POC status and DDW activity
CPX-TIC assesses that exploitation activity is currently active at the reconnaissance and attempted exploitation stage, although no publicly confirmed large-scale compromises have been attributed to PHP2Shell at the time of reporting.
Multiple independent telemetry providers, including cloud-service honeypots, WAF operators, attack-surface monitoring vendors, and application-security companies, have reported observing PHP2Shell-related attack traffic shortly before and after public disclosure.
Proof-of-concept status is mixed. The original researchers demonstrated pre-authentication code execution against lab builds of WordPress, Drupal, Joomla and Magento, but did not release a turnkey tool. Several public GitHub proof-of-concepts appeared within hours of the patch; some depend on a second application flaw such as local file inclusion, and the PHP security team found none fully functional at release. Vendors have also warned of fake, trojanized exploit code circulating, a common lure aimed at researchers and defenders.
Dark web activity shows the criminal ecosystem taking it seriously.
- A moderator of BreachForums, operating as ‘HasanBroker’, announced on Telegram that the forum would stay offline “until PHP is patched globally”.
- DarkForums posted a similar notice, and BreachForums and Dread were reported offline or in maintenance.
- On a hacking forum, an unnamed user asked members to share a working PHP2Shell exploit because the public one failed on some versions, and another replied eager to start compromising servers.
- Forum operators run PHP stacks themselves and fear being breached by rivals or law enforcement, so their shutdowns are a telling signal. The open demand for a reliable exploit suggests private versions will be traded once one stabilises.
- CPX-TIC has not yet seen stolen data or initial-access listings attributed to PHP2Shell, which typically follow mass exploitation by days to weeks.
Detection/hunting queries
No vendor-confirmed indicators exist beyond a handful of shared anonymisation IPs, so detection has to be behavioural. Start the look-back on 17 October 2026, and treat a clean result as reassuring, not conclusive:
PHP Session Upload Progress Requests
KQL
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where RequestMethod =~ "POST"
| where strcat(RequestURL, " ", AdditionalExtensions, " ", Message) has "PHP_SESSION_UPLOAD_PROGRESS"
| summarize Count=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated),
URLs=make_set(RequestURL,10), UserAgents=make_set(RequestClientApplication,5),
Actions=make_set(DeviceAction)
by SourceIP, DestinationIP
SPL
index=<name> http_method=POST "PHP_SESSION_UPLOAD_PROGRESS"
| stats count earliest(_time) as first_seen latest(_time) as last_seen values(uri) as uri values(status) as status values(http_user_agent) as user_agent by src_ip dest
| convert ctime(first_seen) ctime(last_seen)
PHP2Shell Exploit Patterns in Web Traffic
KQL
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where RequestMethod =~ "POST"
| extend Raw = strcat(RequestURL, " ", AdditionalExtensions, " ", Message)
| extend Hit = case(
Raw has "PHP_SESSION_UPLOAD_PROGRESS", "UploadProgress",
Raw matches regex @"(?i)name=.?PHPSESSID", "PHPSESSID_FormField",
Raw has "<?php" or Raw matches regex @"\|O:\d+:", "Payload_in_Filename",
Raw matches regex @"(?i)/(tmp|var/lib/php)[^ ]*sess_", "SessionFile_LFI",
"")
| where isnotempty(Hit)
| summarize Count=count(), URLs=make_set(RequestURL,10), Actions=make_set(DeviceAction)
by SourceIP, DestinationIP, Hit, DeviceVendor
SPL
index=<name> http_method=POST
| eval hit=case(match(_raw,"PHP_SESSION_UPLOAD_PROGRESS"),"UploadProgress",
match(_raw,"(?i)name=.?PHPSESSID"),"PHPSESSID_FormField",
match(_raw,"<\?php|\|O:\d+:"),"Payload_in_Filename",
match(_raw,"(?i)/(tmp|var/lib/php)\S*sess_"),"SessionFile_LFI",
match(_raw,"(?i)chunked") AND match(_raw,"(?i)multipart"),"Chunked_Multipart")
| where isnotnull(hit)
| stats count values(uri) as uris by src_ip dest_ip hit
Suspicious Process Execution by PHP / Web Server
KQL
let web = dynamic(["php","php-fpm","php-cgi","php-cgi.exe","php.exe","httpd","apache2","nginx","lsphp","frankenphp","w3wp.exe"]);
DeviceProcessEvents
| where Timestamp > ago(14d)
| where InitiatingProcessFileName in~ (web) or InitiatingProcessParentFileName in~ (web)
| where FileName in~ ("curl","wget","nc","ncat","socat","python","python3","perl","base64","whoami","id","uname","chmod","crontab","useradd","cmd.exe","powershell.exe","certutil.exe")
| summarize Count=count(), FirstSeen=min(Timestamp), LastSeen=max(Timestamp)
by DeviceName, AccountName, InitiatingProcessFileName, FileName, ProcessCommandLine
| order by Count asc
SPL
index=* parent_process_name IN ("php","php-fpm*","php-cgi*","php.exe","httpd","apache2","nginx","lsphp*","frankenphp","w3wp.exe")
process_name IN ("curl","wget","nc","ncat","socat","python*","perl","base64","whoami","id","uname","chmod","crontab","useradd","cmd.exe","powershell.exe","certutil.exe")
| stats count earliest(_time) as first_seen latest(_time) as last_seen values(process) as command_line by host user parent_process_name process_name
| convert ctime(first_seen) ctime(last_seen)
| sort count
Note: Identifies command execution from PHP or web server processes that may indicate successful exploitation; may return high volume due to legitimate application activity, tune the query based on your environment
Failed POST Requests with Server Errors
KQL
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where RequestMethod =~ "POST"
| where DeviceCustomNumber1 in (500, 502, 503)
| summarize Count=count(), URLs=make_set(RequestURL,10) by SourceIP, DestinationIP
| where Count >= 5
Note: Use this hunt to find possible attempts on the memory-exhaustion path (CVE-2026-109618) when PHP error logs aren’t available. Tune the threshold based on your environment.
Recommended actions
- Patch now. Upgrade to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or install your distribution’s package that carries the fix. Check the package changelog for both CVE IDs rather than trusting the version string, then restart every PHP worker; a patched binary does nothing while old workers keep running.
- Isolate what cannot be patched. PHP 8.1 and older have no official release. Move them behind strict WAF rules, take them offline, or apply a commercial or distribution backport, and schedule the upgrade.
- Apply interim controls where patching lags. Set session.upload_progress.enabled = 0 (and fatal_error_backtraces = 0 on 8.5), cap memory at the container or cgroup level, and block or tightly inspect abnormal multipart/form-data at the edge. These reduce risk; they do not replace the patch.
- Hunt from 17 October. Run the queries above across web, WAF and EDR telemetry. Where compromise is suspected, rotate session secrets, API keys, database credentials and, if memory disclosure is possible, TLS private keys. Purge session.save_path after patching.
- Rebuild your PHP inventory from the outside in. Hidden versions, non-standard ports and forgotten staging servers are where patch programmes fail. Attack surface data finds what the CMDB misses.
How CPX can help
CPX-TIC recommends the following measures:
Our Attack Surface Management service discovers and fingerprints internet-facing PHP and confirms closure after patching.
Digital Risk Protection service monitors forums, marketplaces and Telegram for PHP2Shell exploit trading and client-specific exposure.
Cyber Threat Intelligence service delivers hunting packs, IOC feeds and daily updates as the situation evolves. Clients can also request the CPX PHP2Shell Exposure Check, a safe, non-intrusive tool that flags vulnerable and end-of-life PHP across their estate.