Back to Intelligence

PHP2Shell PHP Vulnerabilities Under Active Exploitation Attempts — Detection and Remediation Guide for Defenders

SA
Security Arsenal Team
October 21, 2026
11 min read

Security teams are in active remediation mode following the disclosure of two critical PHP vulnerabilities — being referred to collectively as "PHP2Shell" — after technical details leaked publicly and exploitation attempts were reported in the wild, according to Dark Reading. This is the nightmare scenario for defenders: vulnerabilities in one of the most ubiquitous server-side technologies on the planet, weaponization details circulating before many organizations have patched, and opportunistic attackers already probing.

PHP underpins an enormous share of the internet — from WordPress and Drupal deployments to custom line-of-business applications and embedded management interfaces. A critical remote code execution flaw in PHP isn't a niche application-security problem; it is a perimeter problem, a supply-chain problem, and in many environments a flat-network-into-the-datacenter problem. If you run PHP anywhere it is reachable from the network, treat this as an emergency change, not a scheduled maintenance item.

Technical Analysis

What "PHP2Shell" Means Operationally

The reporting describes a pair of critical vulnerabilities in PHP that, when successfully exploited, give an attacker command execution on the underlying server — effectively turning an HTTP request into an interactive shell. The class of bug matters more to defenders than the exact identifier: these flaws follow the pattern of PHP-CGI and query-string handling weaknesses, where a crafted request to a PHP endpoint causes the interpreter to process attacker-controlled input as configuration directives or executable code.

Key characteristics from a defender's perspective:

  • Attack vector: Remote, over HTTP/HTTPS. The attacker needs only network reachability to a PHP handler — no authentication, no prior foothold.
  • Affected components: PHP interpreter configurations where PHP handles web requests directly, most notably PHP-CGI deployments (common on Windows/IIS and Apache with Action/ScriptAlias mappings) and any setup where query-string data reaches PHP's argument parsing.
  • Exploitation mechanics: Crafted query strings and request parameters are used to inject interpreter options (historically, flags controlling auto_prepend_file, allow_url_include, or equivalent directive injection), causing PHP to execute attacker-supplied code in the context of the web server service account.
  • Blast radius: Code executes as the web server/PHP process user. On poorly segmented Windows hosts running IIS + PHP-CGI, that can mean immediate lateral movement opportunities. On Linux, it typically means the www-data, apache, or nginx context — which is frequently enough to read application configs, database credentials, and pivot further.

Who Is Exposed

Prioritize inventory across:

  1. Windows servers running PHP in CGI mode (IIS with PHP-CGI, XAMPP-style stacks, appliances bundling PHP-CGI) — historically the most exposed configuration for this bug class.
  2. Apache servers where PHP is wired via CGI rather than mod_php or PHP-FPM, especially where the PHP binary is reachable through ScriptAlias mappings.
  3. Appliances and management interfaces that silently embed PHP (backup consoles, network management UIs, CMS plugins) — these are the systems nobody inventories and attackers find first.
  4. Internet-facing CMS platforms (WordPress, Joomla, Drupal) where the front controller pattern (index.php) means every request touches PHP.

Exploitation Status

This is not theoretical. The reporting indicates that technical details leaked publicly and that exploitation attempts have been observed — the classic post-leak scramble where scanners and exploit kits integrate the bug within hours. Assume the following timeline pressure:

  • Vulnerable-but-unpatched internet-facing PHP instances are being enumerated by automated scanning right now.
  • Exploitation attempts will show up in web access logs as malformed or unusually crafted query strings against PHP endpoints.
  • Successful exploitation will manifest as the PHP/web server process spawning unexpected child processes or writing files to web roots (webshell staging).

Whether or not these specific bugs land in CISA's Known Exploited Vulnerabilities catalog, treat them with KEV-level urgency: patch first, hunt for compromise second, harden third.

Detection & Response

The most reliable detection surface for this bug class is process lineage: a healthy PHP handler almost never spawns shells, scripting interpreters, or download utilities. The second surface is query-string forensics in web logs. Both are high-fidelity and low-noise.

Sigma Rules

The following rules target the two highest-fidelity behaviors: web/PHP processes spawning command interpreters (post-exploitation), and suspicious directive-injection patterns in web server query logs. Tune the parent-process list to your actual stack.

YAML
---
title: PHP or Web Server Process Spawning Shell - Possible PHP2Shell Exploitation
id: 3f8a1c2e-7b4d-4e91-a6c3-9d2e5f7b8a01
status: experimental
description: Detects PHP-CGI, PHP, or web server worker processes spawning command shells or scripting interpreters, consistent with remote code execution via PHP query-string/directive injection vulnerabilities such as the PHP2Shell bugs.
references:
  - https://www.darkreading.com/application-security/php2shell-bugs-red-alert-security-industry
  - https://attack.mitre.org/techniques/T1059/
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/02/10
tags:
  - attack.initial_access
  - attack.t1190
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\php-cgi.exe'
      - '\php.exe'
      - '\w3wp.exe'
      - '\httpd.exe'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\wscript.exe'
      - '\cscript.exe'
      - '\certutil.exe'
      - '\bitsadmin.exe'
      - '\curl.exe'
  condition: selection_parent and selection_child
falsepositives:
  - Rare; some legacy PHP applications invoke system commands. Investigate any hit on internet-facing servers as a priority.
level: high
---
title: Linux Web or PHP-FPM Process Spawning Shell or Downloader
id: 6b2d9f14-3c7a-4e58-b291-4a8c6d0e3f52
status: experimental
description: Detects Apache, Nginx, or PHP-FPM worker processes spawning shells, download utilities, or interpreters on Linux, consistent with post-exploitation activity following PHP remote code execution such as the PHP2Shell vulnerabilities.
references:
  - https://www.darkreading.com/application-security/php2shell-bugs-red-alert-security-industry
  - https://attack.mitre.org/techniques/T1059/
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/02/10
tags:
  - attack.initial_access
  - attack.t1190
  - attack.execution
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/php-fpm'
      - '/httpd'
      - '/apache2'
      - '/nginx'
      - '/php-cgi'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/zsh'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
      - '/python'
      - '/python3'
      - '/perl'
  condition: selection_parent and selection_child
falsepositives:
  - Some CMS plugins and backup tools legitimately shell out. Baseline per host and alert on first-seen parent/child pairs.
level: high
---
title: Suspicious PHP Directive Injection Patterns in Web Query Strings
id: 9c4e7a28-1f5b-4d63-8a47-2e9b3c5f6d18
status: experimental
description: Detects HTTP requests containing query-string patterns associated with PHP argument/directive injection attempts, including interpreter flags and auto_prepend_file style parameters observed in PHP-CGI exploitation such as the PHP2Shell bugs.
references:
  - https://www.darkreading.com/application-security/php2shell-bugs-red-alert-security-industry
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/02/10
tags:
  - attack.initial_access
  - attack.t1190
logsource:
  category: webserver
detection:
  selection:
    c-uri-query|contains:
      - 'auto_prepend_file'
      - 'allow_url_include'
      - 'allow_url_fopen'
      - '%ad'
      - '%2dd%20'
      - '-d+'
      - '-d%20'
  filter_status:
    sc-status:
      - 404
      - 400
  condition: selection and not filter_status
falsepositives:
  - Vulnerability scanners and legitimate developer tooling. Correlate with source IP reputation and whether the target host runs PHP-CGI.
level: medium

KQL — Microsoft Sentinel / Defender

This hunt query covers two surfaces in one pass: process lineage on endpoints (via Defender) and suspicious query strings in ingested web logs (IIS W3C logs and CEF/Syslog-ingested Apache/Nginx logs). Run it over at least the last 14 days for retro-hunting, then convert the process-lineage portion into a near-real-time analytics rule.

KQL — Microsoft Sentinel / Defender
let lookback = 14d;
let suspiciousQueryPatterns = dynamic(["auto_prepend_file", "allow_url_include", "allow_url_fopen", "%ad", "%2dd", "-d+", "-d%20"]);
let shellChildren = dynamic(["cmd.exe", "powershell.exe", "pwsh.exe", "certutil.exe", "bitsadmin.exe", "curl.exe", "sh", "bash", "dash", "curl", "wget", "nc", "ncat", "python3", "perl"]);
let webParents = dynamic(["php-cgi.exe", "php.exe", "w3wp.exe", "httpd.exe", "php-fpm", "httpd", "apache2", "nginx", "php-cgi"]);
// Surface 1: Web/PHP processes spawning shells or downloaders
DeviceProcessEvents
| where TimeGenerated > ago(lookback)
| where InitiatingProcessFileName has_any (webParents)
| where FileName has_any (shellChildren)
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, AccountName, InitiatingProcessRemoteIP = InitiatingProcessCommandLine
| summarize count() by DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine, bin(TimeGenerated, 1h)
| order by TimeGenerated desc;
// Surface 2: Directive-injection patterns in IIS logs
W3CIISLog
| where TimeGenerated > ago(lookback)
| where csUriQuery has_any (suspiciousQueryPatterns)
| where scStatus !in ("400", "404")
| summarize Attempts = count(), DistinctTargets = dcount(csUriStem), StatusCodes = make_set(scStatus) by cIP, csUriStem, bin(TimeGenerated, 1h)
| order by Attempts desc;
// Surface 3: Same patterns in CEF/Syslog-ingested Apache or Nginx logs
CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestURL has_any (suspiciousQueryPatterns)
| summarize Attempts = count() by SourceIP, RequestURL, DeviceProduct, bin(TimeGenerated, 1h)
| order by Attempts desc

Note: the three sections are separated for clarity — run Surface 1 as your high-severity analytic rule, and use Surfaces 2 and 3 for hunting and scoping (which source IPs are probing, which hosts they touched).

Velociraptor VQL

Use this artifact during scoping to identify (a) web/PHP processes with suspicious children across your fleet, and (b) recently created or modified PHP files in web roots — a strong indicator of webshell staging after successful exploitation.

VQL — Velociraptor
-- PHP2Shell scoping: suspicious child processes of web/PHP parents and recent web-root file drops
LET suspicious_children = ('cmd.exe', 'powershell.exe', 'pwsh.exe', 'certutil.exe', 'bitsadmin.exe', 'sh', 'bash', 'dash', 'curl', 'wget', 'nc', 'ncat', 'python3', 'perl')
LET web_parents = ('php-cgi', 'php', 'w3wp', 'httpd', 'apache2', 'nginx', 'php-fpm')

SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Name =~ '(?i)(' + join(array=web_parents, sep='|') + ')'
  AND get(field='Ppid') IN (
        SELECT Ppid FROM pslist()
        WHERE Name =~ '(?i)(' + join(array=suspicious_children, sep='|') + ')'
      )

-- Hunt: recently modified PHP files in common web roots (potential dropped webshells)
SELECT FullPath, Size, Mtime, Ctime
FROM glob(globs=['C:/inetpub/**/*.php', 'C:/xampp/htdocs/**/*.php', '/var/www/**/*.php', '/srv/www/**/*.php', '/usr/share/nginx/html/**/*.php'])
WHERE Mtime > (now() - 1209600)
ORDER BY Mtime DESC

Run the webshell glob over a window starting before the leak became public — attackers who exploited early may have already established persistence.

Remediation & Verification Script

The following Bash script checks PHP versions in use, flags CGI-mode exposure, applies an Apache query-string mitigation (blocking directive-injection patterns at the web layer), and snapshots recent web-root file changes for triage. Test in staging; the rewrite block assumes Apache with mod_rewrite.

Bash / Shell
#!/bin/bash
# PHP2Shell emergency triage and mitigation — run on each PHP host
set -euo pipefail

echo "=== [1] Installed PHP version(s) ==="
php -v 2>/dev/null || echo "php CLI not found"
php-cgi -v 2>/dev/null || echo "php-cgi binary not found"

echo "=== [2] CGI-mode exposure check (highest-risk configuration) ==="
if command -v php-cgi >/dev/null 2>&1; then
  echo "[!] php-cgi PRESENT — verify against vendor advisory whether this build is affected"
fi
grep -RsiE 'ScriptAlias|Action.*php|application/x-httpd-php' /etc/apache2/ /etc/httpd/ 2>/dev/null || echo "No obvious CGI mappings found in Apache configs"

echo "=== [3] Apache query-string mitigation (mod_rewrite) ==="
cat > /etc/apache2/conf-available/php2shell-mitigation.conf <<'EOF'
<IfModule mod_rewrite.c>
  RewriteEngine On
  # Block PHP directive-injection and encoded-dash argument patterns in query strings
  RewriteCond %{QUERY_STRING} (^|&)(%2d|-)[^=]*(%20|\s) [NC,OR]
  RewriteCond %{QUERY_STRING} auto_prepend_file [NC,OR]
  RewriteCond %{QUERY_STRING} allow_url_include [NC,OR]
  RewriteCond %{QUERY_STRING} %ad [NC]
  RewriteRule .* - [F,L]
</IfModule>
EOF
a2enconf php2shell-mitigation 2>/dev/null || true
apache2ctl configtest 2>/dev/null && systemctl reload apache2 || echo "[!] Config test failed — review before reloading"

echo "=== [4] Recent web-root modifications (possible webshell staging) ==="
find /var/www /srv/www /usr/share/nginx/html -name '*.php' -mtime -14 2>/dev/null | head -50

echo "=== [5] Suspicious recent child processes of web services (from auth/syslog if audited) ==="
grep -hE 'php|httpd|apache|nginx' /var/log/syslog /var/log/messages 2>/dev/null | grep -iE 'sh -c|/bin/(ba)?sh|curl |wget ' | tail -20 || echo "No matching log entries"

echo "=== DONE — patch PHP to the vendor-fixed release immediately; mitigation is NOT a substitute ==="

Remediation

  1. Patch immediately. Upgrade PHP to the fixed releases published in the official advisories at php.net and your distribution's security channel (e.g., Debian/Ubuntu security trackers, RHEL errata). Do not wait for the next maintenance window — with exploitation details public and attempts observed, this is an emergency change.
  2. Inventory CGI-mode exposure first. Prioritize any host where php-cgi is directly reachable by the web server — Windows/IIS + PHP-CGI stacks and Apache ScriptAlias/Action configurations are the highest-risk posture for this bug class. Where possible, migrate to PHP-FPM, which removes the CGI argument-parsing attack surface entirely.
  3. Apply web-layer mitigations while patching. Block directive-injection query strings at Apache (mod_rewrite rules above), Nginx (if ($query_string ~ ...) return 403), or your WAF. Cloud WAF customers (Cloudflare, AWS WAF, Akamai) should confirm managed rulesets have been updated for these bugs — vendors typically ship virtual patches within hours of public exploitation.
  4. Hunt before you assume clean. Because details leaked before widespread patching, treat every internet-facing PHP host as potentially compromised: check web-root file modifications, review access logs for the query-string patterns above, and look for web/PHP processes that spawned shells.
  5. Reduce the service account blast radius. Ensure PHP-FPM pools and web workers run under dedicated low-privilege accounts with no sudo rights, read-only access outside the web root where feasible, and open_basedir restrictions enforced.
  6. Disable dangerous interpreter settings regardless of patch status: allow_url_include = Off, allow_url_fopen = Off where applications permit, and disable_functions covering exec, shell_exec, system, passthru, proc_open, popen for anything internet-facing.
  7. Verify appliance and embedded PHP. Network management consoles, backup UIs, and monitoring appliances frequently bundle PHP and are rarely in patch automation. Open vendor tickets now; if no fix exists, put the interface behind a VPN or ACL it to management networks.

The pattern here is one we've seen repeatedly with interpreter-adjacent bugs: disclosure to mass scanning in hours, and to ransomware-adjacent access brokers within days. The organizations that come out clean are the ones that patched in the first 48 hours and hunted in parallel — not sequentially.

Related Resources

Security Arsenal Managed SOC Services AlertMonitor Platform Book a SOC Assessment soc-mdr Intel Hub

Is your security operations ready?

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