PHP2Shell. Check Exposure. Hunt for Compromise.
A passive domain check for public signs of PHP, clear steps to update and isolate, and a reactive hunt pack to find abuse across your estate or your clients'.
At a Glance
Facts from PHP's security advisory and public alerts. Last updated 21 October 2026, 17:25 BST, after PHP's security release (fixed versions 8.5.12, 8.4.27, 8.3.36 and 8.2.35).
9.2
CVSS v4.0, both flaws. Rated by the PHP security team.
Two RCEs
CVE-2026-109618 and CVE-2026-109619. Unauthenticated remote code execution as the web worker account.
Fix released
Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35. Released 21 Oct 2026, 14:00 UTC (15:00 BST).
Attempts reported
Public exploit code exists and attack attempts have been reported. Not yet in CISA's Known Exploited Vulnerabilities catalogue.
Leak of two PHP RCE flaws. PHP publishes advance notice the same evening.
PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35 with full advisories. Every version below these in each branch is affected.
Update internet facing PHP first, Apache mod_php servers before anything else. Apply PHP's interim settings where you cannot update yet, and hunt for PHP workers spawning shells.
What to Do in the Next 24 Hours
Proactive on the left. Reactive on the right. Tick both tracks.
Shrink exposure
- Inventory every PHP install, including vendor appliances, Windows bundles, cPanel and Plesk.
- Update now to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or your vendor's patched package. Internet facing first, mod_php first of all.
- Cannot update today? Apply PHP's interim settings (step 6 below) and restart every worker. They reduce exposure but do not make a server safe.
- PHP 8.1 and older: apply a vendor or PHP source backport, upgrade, or take the system off the internet until you can.
Hunt and respond
- Alert on php-fpm, php-cgi, httpd or apache2 launching shells, interpreters or download tools.
- Scan web roots for new .php files. Review logs for odd multipart POSTs, fatal errors, 'Maximum execution time exceeded' and unexpected PHP-FPM child exits.
- Check outbound connections from PHP workers, new cron jobs, users and SSH keys.
- If you find something: isolate, preserve web and PHP logs, then look for webshells and persistence.
Check a Domain
Enter a domain you own or manage. We make one normal request to its home page and look for public signs of PHP. Nothing else is sent. Exact versions and raw headers are never shown.
A passive check cannot prove a server is safe. Many servers hide their PHP version, and PHP can run on paths, subdomains or servers this check does not see. Results are a starting point; confirm on the server with the steps below.
Proactive: Check Your Servers
The only reliable answer comes from the server. Work through these on every host that runs PHP.
Check the PHP version
On each server, run:
php -vThe command line can use a different PHP build from the web server, so also check the version your sites run under. On Windows, run php -v from the PHP install folder, and remember PHP can be bundled inside vendor software.
Compare the result with the fixed release for its branch: 8.5.12, 8.4.27, 8.3.36 or 8.2.35. Anything lower in the same branch is affected. Anything on 8.1 or older needs a backported fix or an upgrade.
Use phpinfo safely
A phpinfo() page shows the exact version and the Server API (SAPI) the site uses, but it also exposes configuration that helps attackers. Prefer:
php -i | grep -iE "PHP Version|Server API"If you must use a web page, give it a random file name, restrict it to your IP, and delete it straight after.
Check how PHP runs: PHP-FPM, CGI or module
Find which PHP processes and handlers are in use. Every way of serving web requests is affected (PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed), but PHP rates mod_php as highest risk, so update those servers first.
ps aux | grep -E "php-fpm|php-cgi|httpd|apache2" | grep -v grep
systemctl list-units --type=service | grep -i php
php-fpm -v
apachectl -M 2>/dev/null | grep -i php
grep -Rni "fastcgi_pass" /etc/nginx 2>/dev/nullList installed PHP packages
Linux distributions and long term support vendors received the fix in advance and often backport it without changing the upstream version number. Check the package changelog or your vendor's security tracker for CVE-2026-109618 and CVE-2026-109619 as well as the version string.
# Debian / Ubuntu
dpkg -l | grep php
# RHEL family
rpm -qa | grep -i php
# Alpine
apk info | grep -i php
# Docker
docker images | grep -i phpCheck hosting control panels
On cPanel, open MultiPHP Manager to see the PHP version set for each domain. On Plesk, check Tools and Settings, then PHP Settings, and each subscription's Hosting Settings. Shared hosting and managed WordPress platforms set PHP per site, so check every site, not just the server default.
Interim settings if you cannot update yet
PHP lists these measures to reduce exposure until you can update. Set them in php.ini, the FPM pool or server configuration, not with ini_set() or .user.ini.
; php.ini or FPM pool
session.upload_progress.enabled = 0
post_max_size = 8M ; 32M if uploads are needed
upload_max_filesize = 4M ; keep below post_max_size
fatal_error_backtraces = 0 ; PHP 8.5 only
; Enforce memory_limit=-1 so applications cannot override it
php_admin_value[memory_limit] = -1 ; FPM pool
php_admin_value memory_limit -1 ; Apache mod_phpRestart every PHP worker afterwards. Enforce request size, field, part, header and nesting limits at the web server or proxy, including requests without a usable Content-Length. Use a container or cgroup memory limit, never RLIMIT_AS or RLIMIT_DATA. Hiding errors with error_reporting, display_errors or @ does not help. PHP is clear that updating is the only complete fix.
After you update, review memory_limit and post_max_size. The fix adds a hard memory limit above memory_limit that ends the PHP process straight away if it is reached. PHP still advises a conservative post_max_size and request limits at the proxy after patching, to reduce that risk and denial of service.
Free Checker Scripts
Tested by the CybaVerse threat hunt team. Run them on any Linux or Windows host that runs PHP to get a clear verdict per PHP install, whether you look after your own business or your clients' estates.
check-php2shell.sh
Finds every PHP binary (CLI, PHP-FPM, php-cgi, mod_php, cPanel, Plesk, Bitnami, XAMPP and container installs), reads the version and checks the package changelog for distro backports on Debian, Ubuntu, RHEL, Rocky and Alma. On Alpine it checks the package version only, because Alpine packages have no changelog to read (install bash first with apk add bash). It reports key ini values and partial mitigations, then hunts PHP-FPM, Apache, nginx, PHP, syslog and journald logs for memory exhaustion and worker crashes.
sudo bash check-php2shell.shRun as root so it can read every log and package database.
Check-PHP2Shell.ps1
Finds PHP for IIS and FastCGI, XAMPP, WAMP, Laragon, Plesk and anything on PATH, reads each version and key ini values, and hunts PHP and web server logs plus Application event log crashes of php executables.
powershell -ExecutionPolicy Bypass -File .\Check-PHP2Shell.ps1Unzip the download first, then run from an elevated PowerShell so it can read logs and the event log.
Read-only by design
Both scripts read files and query package and event databases. The only programs they run are the PHP binaries they find, with -v and -i and a timeout. On Linux a file is only run if it has a PHP binary name (such as php, php8.3, php-fpm or php-cgi) and is a compiled binary, so tools like phpunit or phpcs and wrapper scripts are never run. On Windows only php.exe and php-cgi.exe are run. The scripts do not change configuration, restart services or write files. Review any script before you run it.
Verdicts
- PATCHEDThe package changelog mentions both CVE IDs (a distro backport), or the version is at or above the fixed release for its branch.
- LIKELY VULNERABLEThe version is below the fixed release, or the branch has no listed fix (8.1 and older), and the changelog mentions neither CVE.
- UNKNOWNThe version can't be read, only one CVE is in the changelog, the package looks vendor-specific, or it is a release candidate or development build (RC, beta, -dev) that may not contain the final fix. Check with your vendor.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Everything PATCHED, or no PHP found |
| 1 | At least one LIKELY VULNERABLE |
| 2 | At least one UNKNOWN, none vulnerable |
| 3 | Nothing vulnerable or unknown, but the log hunt found entries to review |
MSPs and internal IT teams can use the exit code in RMM or deployment tooling to flag hosts at scale.
Know the limits
- Verdicts rely on versions and package changelogs only. The scripts cannot confirm a patch in custom builds, vendor-bundled PHP or packages whose changelogs don't list CVEs.
- PHP published minimal source backports for 7.4, 8.0 and 8.1. The scripts cannot detect these in custom builds and report them as LIKELY VULNERABLE, so confirm with whoever built your PHP.
- The ini values come from php.ini and conf.d. The scripts miss per-site overrides such as FPM pool settings,
.htaccess,.user.iniand IISweb.config, so check those by hand. - Only standard log paths are searched. A clean log is not proof of safety, because a failure can happen before PHP writes anything.
Reactive: How to Hunt
Hunt on behaviour: look for the activity that follows successful exploitation of a PHP server. CybaOps can run these hunts across your estate or your clients'.
PHP workers spawning shells
Exploitation of PHP RCE flaws usually shows as a web server process starting an unexpected child process. Alert when php-fpm, php-cgi, httpd or apache2 starts a command shell, a scripting interpreter, or a network download utility. Also watch for recon commands run from the web stack.
# Live process tree (Linux)
ps -ef --forest | grep -E "php-fpm|php-cgi|httpd|apache2" | head -80
# Children of PHP workers (example with audit logs)
ausearch -i -sc execve 2>/dev/null | grep -E "php-fpm|php-cgi|apache2|httpd" | grep -Ei "bash|curl|wget|python|perl" | tail -50New .php files in web roots
Look for recently changed PHP files under document roots and upload directories. Review any unexpected file before you delete it.
# Last 48 hours of .php under common roots (adjust paths)
find /var/www /home/*/public_html /usr/share/nginx/html -type f -name "*.php" -mtime -2 -printf "%T+ %p\n" 2>/dev/null | sort
# Review recently changed PHP in upload dirs
find /var/www -type d -iname "*upload*" -o -iname "*tmp*" 2>/dev/null | while read d; do
find "$d" -type f -name "*.php" -mtime -2 -ls 2>/dev/null
doneSuspicious requests in access logs
PHP's advisories confirm the attack paths run through multipart request parsing, out of memory errors and session upload progress. Review large or malformed multipart POSTs (especially with a PHPSESSID cookie or upload progress field), bursts of POSTs to the same path, and odd User-Agents. Check PHP and web server error logs for memory exhaustion, fatal errors and execution timeouts. On PHP-FPM, also look for child processes exiting unexpectedly, because FPM ends a child when request startup fails. A quiet log is not proof of safety.
# Recent POSTs (nginx / apache style)
grep -E ' "POST ' /var/log/nginx/access.log /var/log/apache2/access.log 2>/dev/null | tail -200
# Multipart or session-cookie heavy traffic
grep -Ei "multipart/form-data|upload_progress|PHPSESSID" /var/log/nginx/access.log /var/log/apache2/access.log 2>/dev/null | tail -100
# Unusual or empty User-Agents
awk -F\" "$6==\"\" || length($6)<3 {print}" /var/log/nginx/access.log 2>/dev/null | tail -50
# Memory exhaustion, fatal errors and timeouts (adjust log paths)
grep -Ei "Allowed memory size|Out of memory|PHP Fatal|Maximum execution time" /var/log/php*fpm*.log /var/log/apache2/error.log /var/log/httpd/error_log 2>/dev/null | tail -100Outbound from PHP workers
PHP workers should rarely open long lived outbound sockets to the internet.
# Established connections involving PHP workers
ss -tpn | grep -E "php-fpm|php-cgi|apache2|httpd" || true
lsof -nP -iTCP -sTCP:ESTABLISHED 2>/dev/null | grep -E "php-fpm|php-cgi|apache2|httpd" | head -50Persistence: cron, users, SSH keys
# New or odd cron
ls -la /etc/cron.* /var/spool/cron 2>/dev/null
crontab -l 2>/dev/null
# Recent users and authorised keys
getent passwd | awk -F: "$3>=1000 {print}"
find /home /root -name authorized_keys -mtime -7 -ls 2>/dev/nullTested detection pack: KQL and Sigma
Behavioural hunts from the CybaVerse threat hunt team. PHP's advisories publish no IOCs, so these look for crafted multipart requests, PHP memory exhaustion, crashing PHP workers and shells spawned by PHP. Treat hits as leads, and baseline your environment before you alert. Run them in CybaOps or any SIEM that supports KQL or Sigma.
The KQL queries are built for Microsoft Sentinel and Defender XDR. Test them in your environment first and tune the thresholds to your baseline.
KQL hunting queries (Sentinel and Defender XDR)
Loading queries. If they don't appear, use the download link below.Sigma: Web server: POST requests returning HTTP 500 to PHP endpoints
title: PHP2Shell - POST Requests Returning HTTP 500 to PHP Endpoints
id: 4f1c2a6e-6b0d-4d1e-9a51-1d6b0c9e2a01
status: experimental
description: |
Detects POST requests to PHP endpoints that end in HTTP 500. Exploitation of CVE-2026-109618 /
CVE-2026-109619 (GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp) drives PHP into memory exhaustion or fatal
errors via crafted (typically multipart) request bodies, commonly visible as repeated 500 responses
from one source. Correlate by source IP and time window in your SIEM (e.g. >=5 in 10 minutes).
references:
- https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
- https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
author: Cybaverse
date: 2026-10-21
tags:
- attack.initial-access
- attack.t1190
- cve.2026-109618
- cve.2026-109619
logsource:
category: webserver
detection:
selection:
cs-method: POST
sc-status: 500
php:
- cs-uri-stem|endswith: '.php'
- cs-uri-query|contains: '.php'
condition: selection and php
falsepositives:
- Application bugs or broken deployments returning 500
- Legitimate large uploads or imports exceeding memory_limit
- Authorised vulnerability scanning
level: lowSigma: Linux syslog: PHP memory exhaustion or FPM worker killed by a signal
title: PHP2Shell - PHP Memory Exhaustion or FPM Worker Killed by Signal
id: c2d9a4f0-7e1b-4a3c-b6d5-0f8e2a9c4b03
status: experimental
description: |
Matches PHP 'Allowed memory size ... exhausted' / 'Out of memory' errors and PHP-FPM children exiting on a
signal. Per GHSA-w8hw-w9fx-j79w, exploitation relies on controllable OOM; FPM exits the child when request
startup fails. Bursts of these messages on internet-facing hosts warrant investigation. Note the advisory
warns a failure may occur before PHP writes any message.
references:
- https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
- https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
author: Cybaverse
date: 2026-10-21
tags:
- attack.initial-access
- attack.t1190
- cve.2026-109618
- cve.2026-109619
logsource:
product: linux
service: syslog
detection:
keywords:
- 'Allowed memory size of'
- 'PHP Fatal error: Out of memory'
- 'exited on signal'
condition: keywords
falsepositives:
- Memory-hungry legitimate scripts and leaky plugins
- Deliberate restarts / kills of PHP-FPM children
level: lowSigma: Linux process creation: shell or recon tool spawned by a PHP worker
title: PHP2Shell - Shell or Recon Tool Spawned by PHP Worker
id: 8b3e7d21-2c4a-4f6e-8e0a-5a7c9d1f3b02
status: experimental
description: |
Successful exploitation of CVE-2026-109618 / CVE-2026-109619 yields code execution as the web worker.
Detects php-fpm, php-cgi, lsphp or Apache (mod_php) spawning a shell or common recon/download tool.
references:
- https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
- https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
author: Cybaverse
date: 2026-10-21
tags:
- attack.execution
- attack.t1059.004
- attack.persistence
- attack.t1505.003
- cve.2026-109618
- cve.2026-109619
logsource:
product: linux
category: process_creation
detection:
parent:
ParentImage|contains:
- '/php-fpm'
- '/php-cgi'
- '/lsphp'
- '/httpd'
- '/apache2'
child:
Image|endswith:
- '/sh'
- '/bash'
- '/dash'
- '/curl'
- '/wget'
- '/nc'
- '/ncat'
- '/python3'
- '/perl'
- '/base64'
- '/id'
- '/whoami'
- '/uname'
condition: parent and child
falsepositives:
- Applications that legitimately exec helpers (ImageMagick wrappers, git, wp-cli, mail via sendmail wrapper scripts)
- Apache piped loggers or CGI scripts
level: mediumCybaVerse guidance
Our own advice from the CybaVerse threat hunt team, in addition to PHP's advisories:
- Hunt for oversized
PHPSESSIDcookies in responses. A session cookie far longer than your normal baseline is worth investigating. - If you find signs of compromise, rotate the secrets your PHP processes held: database passwords, API keys, session tokens and certificates. Patching does not undo what an attacker may already have read.
- Updating WordPress, Laravel or another application does not patch the PHP runtime. Update PHP itself, or the package your vendor ships.
PHP2Shell FAQ
Short answers based on PHP's security advisory and public alerts as of 21 October 2026.
What is PHP2Shell?
PHP2Shell is the name researchers use for two critical PHP vulnerabilities, CVE-2026-109618 and CVE-2026-109619. PHP rates both 9.2 on CVSS v4.0. They let an unauthenticated attacker run code on a web server as the web worker account by abusing how PHP handles memory when a request fails. The name is the researchers', not PHP's.
Which PHP versions are affected?
Every PHP version below 8.5.12, 8.4.27, 8.3.36 and 8.2.35 in its branch, plus PHP 8.1 and older unless your vendor has backported the fix. All PHP installations serving web requests are at risk, including PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP rates mod_php as highest risk.
Is there a patch?
Yes. PHP released 8.5.12, 8.4.27, 8.3.36 and 8.2.35 on 21 October 2026 at 14:00 UTC (15:00 BST). Linux distributions and long term support vendors received the fix in advance, so check your vendor for updated packages. PHP says there are no complete mitigations and updating is the only safe choice. After updating, review memory_limit and post_max_size: the fix adds a hard memory limit that ends the PHP process if it is reached.
What if I cannot update straight away?
PHP lists interim settings that reduce exposure but do not make a server safe. Set memory_limit=-1 administratively (for example with php_admin_value), keep post_max_size low (8M, or 32M if you need uploads), set session.upload_progress.enabled=0 in php.ini or the FPM pool, set fatal_error_backtraces=0 on PHP 8.5, enforce request size limits at the web server or proxy, then restart every worker. If you cannot do that quickly, take the system offline until it is updated.
Is PHP2Shell being exploited?
Public proof of concept code is available and attack attempts against websites were reported on 21 October 2026. Government agencies had not confirmed successful exploitation at the time of writing, and the flaws were not yet in CISA's Known Exploited Vulnerabilities catalogue. Treat internet facing PHP as a target and update now.
What if I run PHP 8.1 or older?
The PHP project no longer updates 8.1 and older. Some Linux distributions and long term support vendors provide backported fixes, and PHP's security team published minimal source backports for PHP 7.4, 8.0 and 8.1 for people who build from source. Otherwise upgrade to a supported branch, or take the system off the internet until you can. PHP 8.2 reaches end of life on 31 December 2026, so plan that upgrade too.
Does a clean result from the checker mean I am safe?
No. The checker only reads what a site shares publicly on its home page. Many servers hide the PHP version, and PHP can still run on other paths, subdomains, admin panels or behind a proxy or CDN. Always confirm on the server itself.
What does the checker send to my site?
One normal web request for the home page, over HTTPS first and then HTTP, the same as a browser visit. It sends no exploit code or attack traffic, and IP addresses and private or internal names are refused.
Detect and Remediate PHP2Shell Across Your Estate
CybaOps finds vulnerable PHP across every system you look after, whether that's your own business or your clients'. It runs hunts like the KQL and Sigma rules above through our SOC and drives remediation through to a verified fix, so proactive remediation and reactive hunting happen in one place.
Sources
- PHP: Security advisory, critical remote code execution vulnerabilities (21 October 2026)
- PHP advisory GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618)
- PHP advisory GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619)
- NCSC: Critical security issue affecting PHP
- CERT-EU advisory 2026-018