← gociux.comall insights

Active threat · developing

PHP2Shell (CVE-2026-109618, CVE-2026-109619): are you affected, and what to do now

, Gociux · published 23 Oct 2026 · last updated 23 Oct 2026 · 9 min read · check a site

If you only read this box

Free check · passive · no exploit traffic

Is a site exposed to PHP2Shell?

Enter a domain. We make three ordinary page requests to it and report what the site reveals: whether it runs PHP, which version it advertises, and which CDN or WAF edge is detectable in front of it. A WAF attached behind an edge (AWS WAF on CloudFront, for example) isn't visible from outside. It can flag exposure. It cannot prove a site is safe.

What happened

On 20 October 2026 the PHP project announced emergency security releases for the following day and said it might release earlier if details went public. Details did leak ahead of the planned disclosure. Patched versions shipped on 21 October at 14:00 UTC.

The two CVEs are memory-safety bugs in request handling. One lets a crafted multipart upload get around request-size limits and exhaust memory. The other is a use-after-free, where request state such as session data is not reset before memory is freed. Chained, they give an attacker code execution in the PHP process.

The exploitation picture is mixed, and you should plan for the worse version of it. A public proof of concept exists, though the SANS Internet Storm Center describes it as unreliable and incomplete. Cloudflare deployed emergency WAF rules and reported seeing early attack attempts. The Canadian Centre for Cyber Security had not confirmed active exploitation at the time of its alert. Expect working exploits to improve quickly now that patches can be diffed.

Are you affected?

If PHP serves web requests anywhere in your estate, assume yes until you have checked. Researchers report that versions back to PHP 5 are affected, and every common way of running PHP is in scope: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The PHP project rates mod_php as the highest risk, because the bug can be triggered before your application code even runs.

The PHP you forget about is the dangerous PHP. Look beyond your own codebase:

BranchVulnerableFixed in
PHP 8.5< 8.5.128.5.12
PHP 8.4< 8.4.278.4.27
PHP 8.3< 8.3.368.3.36
PHP 8.2< 8.2.358.2.35
PHP 8.1 and olderallno upstream fix · vendor backport or upgrade

Find every PHP runtime you own

Run these on each host. They are read-only.

# version of the CLI on the box (FPM/Apache may use a different binary — check those too)
php -v

# Debian / Ubuntu: every installed PHP package and its version
dpkg -l 'php*' | awk '/^ii/{print $2, $3}'

# RHEL / Rocky / Alma / Fedora
rpm -qa 'php*'

# which PHP services are actually running (these are the ones that matter)
systemctl list-units --type=service --state=running | grep -Ei 'php|apache2|httpd|litespeed|frankenphp'

# containers: running images that contain PHP
for c in $(docker ps -q); do
  docker exec "$c" sh -c 'command -v php >/dev/null && echo "$(hostname): $(php -r "echo PHP_VERSION;")"' 2>/dev/null
done

# Kubernetes: images in use that look like PHP
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}' | grep -i php

From the outside, some servers announce their PHP version in an X-Powered-By header. Many don't, so a missing header proves nothing. You can see what your sites expose with our security headers check.

Patch, then restart, then verify

Use your distribution's packages rather than compiling from php.net, unless you already build PHP yourself.

# Debian / Ubuntu — upgrade only the installed PHP packages
sudo apt update
sudo apt install --only-upgrade $(dpkg -l 'php*' | awk '/^ii/{print $2}')

# RHEL family
sudo dnf upgrade 'php*'

# restart whatever runs PHP — adjust the unit names to your host
sudo systemctl restart php8.3-fpm      # or php-fpm on RHEL
sudo systemctl restart apache2         # or httpd, if using mod_php

# containers — rebuild from a freshly pulled base, don't just restart
docker build --pull -t yourapp:patched .
The version-number trap: distributions backport security fixes without changing the upstream version. A fully patched Ubuntu box can still report something like 8.1.2 in php -v. On those systems, check the package changelog for the CVE IDs instead of comparing version numbers. For Ubuntu, the relevant notice is USN-8948-1.
# Debian / Ubuntu: confirm the fix is in the installed package
apt changelog php8.1-cli 2>/dev/null | grep -E 'CVE-2026-10961[89]'

# RHEL family
rpm -q --changelog php-cli | grep -E 'CVE-2026-10961[89]'

If you cannot patch today

These steps reduce exposure. None of them is a fix, and the measures circulating publicly are unverified, so treat this as buying hours, not weeks.

  1. Put a WAF in front. Cloudflare and other vendors have shipped rules for these CVEs. If you use Cloudflare, read the section below: the rules only see traffic that is actually proxied.
  2. Turn off upload progress tracking. Set session.upload_progress.enabled = Off in php.ini and reload PHP. SANS describes this as partial protection.
  3. Cap request sizes at the web server, before PHP sees the request: client_max_body_size in nginx, LimitRequestBody in Apache. Set them as low as your application allows.
  4. Block multipart/form-data on endpoints that never accept uploads. Doing this globally will break forms and file uploads.
  5. Take admin interfaces off the internet (CMS admin, phpMyAdmin, appliance UIs). Put them behind a VPN or zero-trust access.
  6. Isolate anything internet-facing that cannot be patched or shielded until it can be.

Using Cloudflare? Check that the protection actually reaches you

Cloudflare deployed PHP2Shell rules on 21 October, a few hours before public disclosure. There is no DNS-level block. DNS only decides where traffic goes, so the protection depends on two things: whether your traffic passes through Cloudflare's proxy, and which plan you are on.

1. Make sure every PHP hostname is proxied. In the dashboard, go to DNS → Records. Every record that points at a PHP server must show Proxy status: Proxied (orange cloud). A DNS only (grey cloud) record bypasses the WAF completely. Check from a terminal too:

# a proxied hostname answers with Cloudflare headers (cf-ray) and server: cloudflare
curl -sI https://www.example.com | grep -iE '^(server|cf-ray):'

# list your zone's hostnames and check each one — forgotten subdomains are the usual gap
for h in example.com www.example.com shop.example.com admin.example.com; do
  printf '%-28s ' "$h"; curl -sI --max-time 5 "https://$h" | grep -qi '^cf-ray:' && echo proxied || echo NOT-PROXIED
done

2. Close the back door to the origin. If anyone can reach your server's IP directly, they skip Cloudflare entirely. Old DNS history, mail records and certificate logs leak origin IPs all the time. Only accept web traffic from Cloudflare:

# ufw example: allow 443 only from Cloudflare's published ranges, then deny the rest
for r in $(curl -s https://www.cloudflare.com/ips-v4) $(curl -s https://www.cloudflare.com/ips-v6); do
  sudo ufw allow proto tcp from "$r" to any port 443
done
sudo ufw deny 443/tcp

# then confirm the origin refuses a direct request (should time out or be refused)
curl -sk --max-time 5 --resolve www.example.com:443:ORIGIN_IP https://www.example.com -o /dev/null -w '%{http_code}\n'

Better still, put the origin behind a Cloudflare Tunnel, so it has no open inbound port at all. Enable Authenticated Origin Pulls where you can, so the origin only accepts requests that come from Cloudflare.

3. Watch it work. Go to Security → Analytics → Events and filter on the managed rules. Hits there are attack attempts against your PHP, which is also a good reason to treat the patch as urgent rather than optional.

Still not a fix. Cloudflare's own guidance is to patch PHP even with the rules on. Attackers are already varying payloads to get past the rules, managed rules only inspect request bodies up to a plan-dependent size, and a skip rule placed earlier can quietly disable the ruleset. Use the WAF to buy time, not to replace the patch.

Using AWS WAF?

AWS says it has updated the AWS WAF PHP application managed rule group to cover both CVEs. Two conditions decide whether that reaches you:

  1. The rule group has to be in your web ACL. The PHP rule group is an application-specific group, not part of the baseline groups, so many web ACLs don't include it. Check each web ACL attached to a CloudFront distribution, ALB or API Gateway that fronts PHP.
  2. You need the default (latest) version. AWS says customers on the default version are protected automatically, but if you pinned a static version of the rule group, you must move to the latest one to get the update.

The same caveats as Cloudflare apply. AWS WAF only sees traffic that goes through the CloudFront distribution or ALB it is attached to, so lock the origin down: security groups that only allow the load balancer, or the CloudFront managed prefix list. It is still a stop-gap, not a fix. The AWS bulletin also covers platform-specific steps: updated Elastic Beanstalk platform versions, patched Amazon Linux packages, new Lightsail blueprints (running instances need to be migrated, not updated in place), and redeploying Lambda functions that bring their own PHP runtime.

Other providers (Akamai, Imperva, Fastly, Azure Front Door, F5 and so on): ask your vendor whether a PHP2Shell rule exists, whether it is enabled on your configuration, and whether it is blocking or only logging. Don't assume that having a WAF means having this rule.

Check whether you were hit before you patched

Patching closes the door. It does not remove anyone who came in. Look back to at least 20 October, when details started leaking. These are hunting leads, not confirmed indicators.

# memory errors and worker crashes in PHP / web server logs
sudo grep -hE 'Allowed memory size|SIGSEGV|signal 11|exited on signal' \
  /var/log/php*-fpm.log /var/log/apache2/error.log /var/log/httpd/error_log /var/log/nginx/error.log 2>/dev/null | tail -50

# shells or downloaders running as the web server user
ps -eo user,pid,ppid,lstart,cmd | awk '$1 ~ /^(www-data|apache|nginx)$/' | grep -Ei ' (ba)?sh |curl|wget|nc |python|perl'

# PHP files created or modified in the web root since 20 Oct
sudo find /var/www -type f -name '*.php*' -newermt '2026-10-20' -ls

If any of these turn something up, treat the host as compromised. Isolate it, preserve logs and a disk image before you clean anything, rotate every credential the application could reach (database, API keys, cloud tokens), and rebuild from a known-good state rather than trying to clean in place. Depending on your sector, regulatory reporting clocks may also be running. Under NIS2 the early warning is due within 24 hours.

About the severity scores

You will see different numbers. The PHP project rates each flaw CVSS v4.0 9.2, SANS lists 9.4, and some researchers say 10.0. For deciding what to do, the difference doesn't matter: this is unauthenticated remote code execution in software that sits on the internet. That is an emergency change, not a sprint ticket. Also watch the CISA KEV catalog. A KEV listing would confirm reliable in-the-wild exploitation, and as we argue in our KEV and EPSS guide, at that point the debate is over.

For the record, gociux.com is not affected. The site has no PHP runtime. Pages are static files served by Cloudflare, and the backend is JavaScript on Cloudflare Workers. That is a deliberate design choice: the cheapest component to patch is the one you never deployed.

Not sure where PHP is running in your estate?

We can inventory every PHP runtime you own (servers, containers and appliances), patch or shield them, and hunt for signs of compromise before the patch landed. Tell us what you run and we'll reply by email with a straight read.

Get in touch →

Sources

This is a developing situation. We'll update this page as vendors publish advisories and exploitation status changes. Always confirm against your vendor's advisory before acting.