Back to Intelligence

PHP2Shell (CVE-2026-109618, CVE-2026-109619): Detecting and Remediating Critical Unauthenticated PHP Remote Code Execution

SA
Security Arsenal Team
October 21, 2026
12 min read

The PHP security team has shipped emergency out-of-band security releases addressing two critical unauthenticated remote code execution vulnerabilities — CVE-2026-109618 and CVE-2026-109619 — being tracked collectively as PHP2Shell. As the name implies, the flaws allow a remote, unauthenticated attacker to execute arbitrary code on the underlying host through a PHP-driven web application, effectively handing over a shell without ever touching a login page.

PHP powers an enormous share of the internet — content management systems, e-commerce platforms, internal admin panels, and legacy line-of-business applications that haven't been revisited since the last compliance audit. An unauthenticated RCE in the language runtime itself sits below every WAF rule and every application-layer access control your developers wrote. If your organization runs PHP in any exposed capacity, this is a patch-now, hunt-immediately event.

From an IR perspective, the scenarios that keep me up at night here are the forgotten assets: the marketing microsite on a shared host, the WordPress instance nobody owns anymore, the internal reporting dashboard that was supposed to be decommissioned two years ago. These are exactly the systems that won't get patched this week — and exactly where threat actors will land first.

Technical Analysis

What We Know

AttributeDetail
CVE IDsCVE-2026-109618, CVE-2026-109619
Common namePHP2Shell
Vulnerability classUnauthenticated remote code execution
Authentication requiredNone
Affected componentPHP language runtime (via web-facing request handling)
Patch statusEmergency security releases available from the PHP project

The vulnerabilities affect the PHP runtime itself — meaning exploitation is independent of any specific application code flaw. This is a critical distinction for defenders: your developers writing secure code does not protect you. Any request path that reaches an unpatched PHP interpreter is potentially an exploitation vector, regardless of whether the application itself has a bug.

Exploitation Model (Defender's View)

Historically, runtime-level PHP RCEs follow one of a few observable patterns, and defenders should prepare detections for all of them:

  1. Direct web-to-shell: The attacker sends a crafted HTTP request (typically a POST with a malicious body, or a GET with weaponized query parameters) that results in the PHP interpreter executing attacker-supplied code. On disk, this manifests as the web server or PHP handler process spawning a shell or command interpreter — a behavior that has no legitimate reason to exist in production.
  2. Webshell staging: Initial code execution is used only to write a persistent webshell (.php file) into the web root. Subsequent commands then flow through that webshell, making the initial exploit a one-time event that's easy to miss in logs.
  3. In-memory payloads / reverse shells: More sophisticated actors skip disk entirely and use the code execution primitive to spawn a reverse shell or pull a second-stage payload directly.

The defensive chokepoint is consistent across all three: the PHP interpreter or web server worker process performing actions that a web application has no business performing — spawning command interpreters, writing executable files into web-accessible directories, or making unexpected outbound network connections.

Exploitation Status

The PHP team's decision to ship emergency out-of-band patches — rather than waiting for a scheduled release cycle — is itself a strong signal of severity and anticipated or observed exploitation. Treat these flaws as actively targeted until proven otherwise. Runtime-level, unauthenticated RCEs in PHP historically attract mass scanning and opportunistic exploitation within hours to days of public disclosure, and webshell-based persistence means the compromise can long outlive the disclosure news cycle. Monitor the PHP security advisories, the BleepingComputer report, and CISA's Known Exploited Vulnerabilities catalog for updates on in-the-wild exploitation status and any KEV deadlines that would apply to federal and critical-infrastructure organizations.

Detection & Response

Patching is the fix, but detection is how you answer the harder question: were we hit before we patched? The detections below target the post-exploitation behaviors common to web-runtime RCE — they are intentionally behavioral rather than signature-based, because exploit payloads will vary while post-exploitation tradecraft converges.

Sigma Rules

YAML
---
title: PHP Process Spawning Command Interpreter
title_alt: PHP2Shell Post-Exploitation
tid: 3f9c1a72-8b4d-4e6a-9c2f-7d1e5a8b3c4d
status: experimental
description: Detects PHP CGI/FPM/CLI processes spawning command shells or scripting interpreters, a hallmark of runtime-level PHP RCE exploitation such as PHP2Shell (CVE-2026-109618, CVE-2026-109619).
references:
  - https://www.bleepingcomputer.com/news/security/php-ships-emergency-patches-for-critical-php2shell-flaws/
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/04/09
tags:
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\php-cgi.exe'
      - '\php.exe'
      - '\php-fpm.exe'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\wscript.exe'
      - '\cscript.exe'
      - '\mshta.exe'
      - '\rundll32.exe'
      - '\certutil.exe'
      - '\bitsadmin.exe'
  condition: selection_parent and selection_child
falsepositives:
  - Rare legitimate installer or maintenance scripts executed under PHP CLI
  - Some CMS admin functions invoking system commands (e.g., image processing) — tune per application baseline
level: high
---
title: Linux Web Server Worker Spawning Shell
id: 8e2b4d61-5c7f-4a39-b1e8-2d6f9a4c7e5b
status: experimental
description: Detects Apache, Nginx, PHP-FPM, or other web server worker processes spawning interactive shells on Linux, consistent with exploitation of PHP runtime RCE flaws like PHP2Shell.
references:
  - https://www.bleepingcomputer.com/news/security/php-ships-emergency-patches-for-critical-php2shell-flaws/
  - https://attack.mitre.org/techniques/T1059/004/
author: Security Arsenal
date: 2026/04/09
tags:
  - attack.execution
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/php-fpm'
      - '/php'
      - '/httpd'
      - '/apache2'
      - '/nginx'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/zsh'
      - '/python'
      - '/python3'
      - '/perl'
      - '/nc'
      - '/ncat'
      - '/socat'
      - '/wget'
      - '/curl'
  condition: selection_parent and selection_child
falsepositives:
  - Legitimate admin tooling invoked by web management panels (cPanel, Plesk) — scope exclusions to known management paths
  - Health-check scripts in some container images
level: high
---
title: Webshell Dropped in Web-Accessible Directory
id: 5a1d8f3e-2b6c-4d97-a4f1-9e3c7b2d8a6f
status: experimental
description: Detects creation of PHP script files in web root directories by web server or PHP processes, consistent with webshell staging following PHP2Shell exploitation.
references:
  - https://www.bleepingcomputer.com/news/security/php-ships-emergency-patches-for-critical-php2shell-flaws/
  - https://attack.mitre.org/techniques/T1505/003/
author: Security Arsenal
date: 2026/04/09
tags:
  - attack.persistence
  - attack.t1505.003
logsource:
  category: file_event
  product: linux
detection:
  selection_path:
    TargetFilename|contains:
      - '/var/www/'
      - '/srv/www/'
      - '/usr/share/nginx/'
      - '/htdocs/'
      - '/public_html/'
  selection_ext:
    TargetFilename|endswith:
      - '.php'
      - '.phtml'
      - '.phar'
  filter_deploy:
    Image|endswith:
      - '/composer'
      - '/git'
      - '/rsync'
      - '/scp'
      - '/sftp-server'
  condition: selection_path and selection_ext and not filter_deploy
falsepositives:
  - CI/CD deployments and CMS plugin updates — filter on the deploying process rather than the file path
  - Developer activity via deployment tooling
level: medium

KQL (Microsoft Sentinel / Defender)

The query below hunts for web server and PHP processes spawning command interpreters or egress-capable utilities. It works against Defender for Endpoint data (DeviceProcessEvents) as well as Linux Syslog/CEF-ingested environments via the Syslog table. Run it over at least 14 days pre-patch to catch pre-remediation compromise.

KQL — Microsoft Sentinel / Defender
// PHP2Shell post-exploitation hunt: web/PHP processes spawning shells or egress tools
let lookback = 14d;
let web_parents = dynamic(["php-cgi.exe", "php.exe", "php-fpm", "php", "httpd", "apache2", "nginx", "w3wp.exe"]);
let suspicious_children = dynamic(["cmd.exe", "powershell.exe", "pwsh.exe", "sh", "bash", "dash", "python", "python3", "perl", "nc", "ncat", "socat", "wget", "curl", "certutil.exe", "mshta.exe"]);
union isfuzzy=true
(DeviceProcessEvents
| where TimeGenerated > ago(lookback)
| where InitiatingProcessFileName in~ (web_parents)
| where FileName in~ (suspicious_children)
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, AccountName, InitiatingProcessRemoteIp = RemoteIP
),
(Syslog
| where TimeGenerated > ago(lookback)
| where Facility == "auth" or SyslogMessage has_any ("php-fpm", "apache", "nginx")
| where SyslogMessage has_any ("/bin/sh", "/bin/bash", "wget ", "curl ", "nc -", "python -c")
| project TimeGenerated, Computer, ProcessName, SyslogMessage
)
| order by TimeGenerated desc

A second, complementary hunt for webshell staging against file creation telemetry:

KQL — Microsoft Sentinel / Defender
// Webshell staging: .php files written to web roots by non-deployment processes
let lookback = 14d;
DeviceFileEvents
| where TimeGenerated > ago(lookback)
| where FolderPath has_any ("/var/www/", "/srv/www/", "/htdocs/", "/public_html/", "\\inetpub\\wwwroot\\")
| where FileName endswith ".php" or FileName endswith ".phtml"
| where InitiatingProcessFileName !in~ ("git", "rsync", "composer", "scp", "sftp-server", "sshd")
| project TimeGenerated, DeviceName, FolderPath, FileName, InitiatingProcessFileName, InitiatingProcessCommandLine, SHA256
| order by TimeGenerated desc

Velociraptor VQL

Use this hunt across your web server fleet to enumerate PHP-interpreter child processes and any script files modified in web roots within the exploitation window. The CreateTime/mtime correlation is your timeline anchor for scoping.

VQL — Velociraptor
-- PHP2Shell triage: suspicious web-process children and recent webshell artifacts
LET proc_hunt = SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Name =~ '(?i)php|httpd|apache2|nginx|w3wp'

LET shell_children = SELECT Pid, Ppid, Name, CommandLine, Username, CreateTime
FROM pslist()
WHERE Ppid IN (SELECT Pid FROM proc_hunt)
  AND Name =~ '(?i)cmd|powershell|pwsh|sh$|bash|dash|python|perl|nc|ncat|wget|curl'

LET webshell_candidates = SELECT FullPath, Mtime, Size
FROM glob(globs=['/var/www/**/*.php', '/srv/www/**/*.php', 'C:\\inetpub\\wwwroot\\**\\*.php'])
WHERE Mtime > now() - 1209600
ORDER BY Mtime DESC

SELECT * FROM shell_children
UNION ALL
SELECT NULL AS Pid, NULL AS Ppid, 'WEBSHELL_FILE' AS Name, FullPath AS CommandLine, NULL AS Username, Mtime AS CreateTime FROM webshell_candidates

Remediation & Verification Script

The Bash script below inventories PHP installations and versions across a Linux host, flags end-of-life or unpatched runtimes, and snapshots web-root .php files so you can diff for webshell staging. Run it on every PHP host — including containers and shared hosting shells where you have access.

Bash / Shell
#!/usr/bin/env bash
# PHP2Shell (CVE-2026-109618 / CVE-2026-109619) triage and verification script
# Run as root. Review PHP official advisories for fixed version numbers and pin EXPECTED_MIN accordingly.
set -u

echo "=== [1] Installed PHP versions ==="
for bin in php php8 php8.1 php8.2 php8.3 php8.4; do
  if command -v "$bin" >/dev/null 2>&1; then
    printf "%s -> " "$bin"; "$bin" -r 'echo PHP_VERSION, "\n";' 2>/dev/null
  fi
done
dpkg -l 2>/dev/null | grep -E '^ii\s+php' | awk '{print $2, $3}'
rpm -qa 2>/dev/null | grep -i '^php'

echo "=== [2] PHP-FPM / SAPI processes running ==="
ps -eo pid,user,comm,args | grep -E 'php-fpm|php-cgi|php ' | grep -v grep

echo "=== [3] Recently modified PHP files in web roots (last 7 days) ==="
for root in /var/www /srv/www /usr/share/nginx /home/*/public_html; do
  [ -d "$root" ] && find "$root" -name '*.php' -o -name '*.phtml' | \
    xargs -r find 2>/dev/null -mtime -7 -printf '%T@ %TY-%Tm-%Td %TH:%TM %p\n' | sort -rn | head -50
done

echo "=== [4] Web server child processes spawning shells RIGHT NOW ==="
for wp in $(pgrep -f 'php-fpm|httpd|apache2|nginx'); do
  children=$(pgrep -P "$wp" -a 2>/dev/null | grep -E '/bin/(sh|bash|dash)|python|nc |ncat|socat' || true)
  [ -n "$children" ] && echo "ALERT: web pid $wp spawned: $children"
done

echo "=== [5] Outbound connections from web/PHP processes (possible reverse shells) ==="
ss -tunp 2>/dev/null | grep -E 'php|httpd|apache2|nginx' | grep -v ':80\|:443\|:9000'

echo ""
echo "NEXT STEPS:"
echo " 1. Compare installed versions against the PHP security advisory fixed releases."
echo " 2. Patch via your package manager or rebuild from source, then restart php-fpm/apache."
echo " 3. Investigate any ALERT lines and recent web-root PHP files as potential compromise."

For Windows/IIS environments running PHP (PHP-CGI under w3wp.exe), the equivalent verification in PowerShell:

PowerShell
# PHP2Shell triage for Windows/IIS hosts running PHP via FastCGI
# 1) Enumerate PHP installations and versions
Get-ChildItem -Path 'C:\php','C:\Program Files\PHP','C:\Program Files (x86)\PHP' -Recurse -Filter 'php-cgi.exe' -ErrorAction SilentlyContinue |
    ForEach-Object { "$($_.FullName) -> $((Get-Item $_.FullName).VersionInfo.ProductVersion)" }

# 2) Detect web server worker processes spawning command interpreters (live triage)
$webPids = (Get-Process w3wp,php-cgi,php -ErrorAction SilentlyContinue).Id
Get-CimInstance Win32_Process |
    Where-Object { $webPids -contains $_.ParentProcessId -and
                   $_.Name -match 'cmd.exe|powershell.exe|pwsh.exe|mshta.exe|certutil.exe' } |
    Select-Object ProcessId, ParentProcessId, Name, CommandLine, CreationDate

# 3) Webshell staging: .php files written to wwwroot in the last 7 days
Get-ChildItem 'C:\inetpub\wwwroot' -Recurse -Include *.php,*.phtml -ErrorAction SilentlyContinue |
    Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } |
    Sort-Object LastWriteTime -Descending |
    Select-Object LastWriteTime, FullName, Length

Remediation

  1. Patch immediately. Apply the emergency PHP security releases to every runtime instance — not just internet-facing ones. Internal PHP apps are reachable the moment an attacker gains any foothold. Verify the exact fixed version numbers against the official PHP security advisories and the PHP project's release announcements, then confirm post-patch with the inventory scripts above. Do not forget container images: rebuild and redeploy any image that bakes in an unpatched PHP binary — patching the host does nothing for containers.
  2. Inventory before you patch. You cannot patch what you don't know exists. Enumerate every PHP runtime: bare metal, VMs, containers, shared hosting, control panels (cPanel/Plesk ship their own PHP builds), and applications that bundle an embedded PHP interpreter. Asset inventory gaps are where PHP2Shell compromises will live for the next eighteen months.
  3. Assume breach on unpatched exposure windows. If a PHP instance was internet-facing and unpatched between disclosure and your patch time, run the detection content above against that window. Webshell staging means a single successful exploit becomes persistent access that survives patching. File-integrity the web root, review access logs for anomalous POSTs to endpoints that shouldn't receive them, and check for new local users, unexpected cron entries, and modified systemd units.
  4. Apply compensating controls while patching. Where immediate patching is operationally impossible:
    • Restrict PHP application access at the edge (IP allowlisting, VPN-gating internal tools).
    • Enforce WAF rules blocking request bodies and query strings carrying shell metacharacter sequences and encoded command payloads, with the explicit understanding that WAF rules for runtime-level bugs are speed bumps, not fixes.
    • Disable dangerous PHP functions (exec, shell_exec, system, passthru, proc_open, popen) via disable_functions in php.ini — this degrades many webshells and one-shot RCE payloads even when the interpreter is compromised.
    • Set open_basedir to constrain PHP's filesystem reach to the application directory.
  5. Harden the runtime's blast radius. Run PHP-FPM workers as dedicated low-privilege users per application. Mount web roots read-only where the application permits. Block outbound egress from web server segments except to explicitly required destinations — this kills the reverse-shell and payload-fetching stages that follow exploitation.
  6. Monitor for KEV inclusion. Given the severity profile (unauthenticated, runtime-level, RCE, ubiquitous target), watch the CISA KEV catalog closely. KEV listing will carry a federal remediation deadline and is a reliable indicator of confirmed in-the-wild exploitation.

The lesson here is the same one every runtime-level PHP RCE teaches: the interpreter is the attack surface, not just the application. Organizations that treat language runtimes as patch-managed, behaviorally-monitored assets will absorb events like PHP2Shell as a routine emergency change. Everyone else will find out during incident response.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.