Talk to us

Threat Intelligence

php2shell: The PHP Bug That Fires Before Your Code Runs

Aerovant Technologies Security Team

A laptop showing a crafted multipart POST request beside a cracked PHP logo, with the title php2shell, CVE-2026-109618, CVE-2026-109619, CVSS 9.2.

Most web vulnerabilities live in your code: a forgotten input check, a bad plugin, a weak password. php2shell is different. It lives in PHP itself, and on some servers it fires before a single line of your application runs.

On 21 October 2026, the PHP project shipped emergency fixes for two critical flaws, CVE-2026-109618 and CVE-2026-109619, nicknamed php2shell. An unauthenticated attacker on the internet can send crafted requests and potentially run code on your web server. No login, no user click, no vulnerable plugin required.

If you run WordPress, Laravel, Magento, Drupal or any custom PHP application, read on.

What happened

The bugs were found by researchers at Calif and reported to PHP for coordinated disclosure. The plan was a quiet release on 22 October. It did not go to plan: attackers were probing before the patch existed, details leaked, and PHP brought the release forward by a day.

Date (2026)Event
22 OctVendors update advisories. Neither CVE is yet in CISA’s Known Exploited Vulnerabilities catalog
21 OctPHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (14:00 UTC). Honeypots record exploitation attempts the same day
20 OctDetails leak on social media. PHP announces an emergency release, a day earlier than planned. watchTowr publicly confirms the bugs are real
17 OctAmazon’s MadPot honeypot records an attempt, four days before disclosure
EarlierLinux distributions and LTS vendors receive patches in advance

The 17 October hit is the detail that matters. Someone had a working idea of the attack before most defenders knew there was anything to patch.

How the two bugs work

Both flaws are memory-safety bugs in PHP’s C core, in the part that handles each incoming request. That is why they are so dangerous: they sit below every framework and every line of application code.

CVE-2026-109618: out-of-memory corruption

When PHP runs out of memory, it can abandon a request halfway through setting up its data. Cleanup code then runs over that half-built data as if it were complete.

  1. The attacker sends a crafted multipart request (the format used for file uploads and forms).
  2. The request pushes PHP into an out-of-memory condition, even within normal configured size limits.
  3. PHP stops mid-allocation, leaving partly initialised structures in memory.
  4. Cleanup trusts those structures, and the resulting memory corruption can be turned into code execution.

On Apache mod_php this all happens while the request body is parsed, before your application is called.

CVE-2026-109619: use-after-free across requests

PHP workers are reused. One process serves request after request, and it is supposed to wipe its state in between.

  1. Request A triggers a fatal error or timeout that interrupts normal cleanup.
  2. Some global state still points at memory that has already been freed.
  3. The same worker picks up request B, which reads that stale pointer.
  4. The attacker shapes what sits in the freed memory, leading to memory disclosure or code execution.

Session upload progress, which is enabled by default, is one known path that consumes this stale state. PHP lists memory disclosure as a confirmed impact.

What an attacker gets

Code execution with the privileges of the web server user (often www-data, apache or nginx). From there they can read the application’s configuration, including database passwords and API keys, plant a web shell, and move deeper into the network.

Who is affected

Every PHP installation that serves web requests is in scope. The vulnerable code path dates back to at least PHP 5, so age is no protection.

PHP branchStatusAction
8.5Affected below 8.5.12Upgrade to 8.5.12
8.4Affected below 8.4.27Upgrade to 8.4.27
8.3Affected below 8.3.36Upgrade to 8.3.36
8.2Affected below 8.2.35Upgrade to 8.2.35
7.4, 8.0, 8.1All versions affected; no official releaseDistribution or LTS vendor package, or PHP’s source backports. Plan a move to 8.2+
5.x to 7.3Affected, no fix at allUpgrade to a supported branch, or isolate the server

How PHP runs matters. PHP-FPM, php-cgi, FrankenPHP and LiteSpeed are all affected. Apache with mod_php is the highest-risk setup, because PHP parses the malicious request inside the web server before any application code, WAF logic in your app, or authentication check gets a chance to run.

A distribution caveat. Ubuntu, Debian, RHEL and similar distributions often backport security fixes without changing the version number. A server that reports 8.1.2 may be patched; one that reports a newer number may not be. Check your distribution’s advisory or package changelog for the CVE IDs rather than trusting the version string alone.

Is it being exploited?

Attackers are trying. Whether they are succeeding at scale is where vendors disagree.

SourceWhat they report
Amazon Threat IntelligenceFirst attempt on 17 Oct, four days before disclosure; more attempts from several sources on 21 Oct. Amazon says it is unclear whether any of them would have worked
watchTowr, CloudflareExploitation attempts observed on their sensor networks
Rapid7Many attempts, but no confirmed in-the-wild exploitation; public proofs of concept work only on specific OS, PHP version and web server combinations
PHP FoundationFound no functional public exploits at release
CISA KEVNot listed as of 22 Oct

For a defender, the disagreement does not change the decision. Memory-corruption exploits start out fragile and become reliable over time. Rapid7 itself warns a portable technique could appear at any moment. Treat this as an emergency patch, not a next-sprint ticket.

Why this hits Indian startups and SMEs hard

PHP quietly runs a large share of India’s business websites: WordPress company sites, WooCommerce stores, school and hospital portals, and Laravel or CodeIgniter apps built by agencies years ago. Three patterns make php2shell especially risky here.

  • The “built once, never touched” site. An agency delivered the site, the contract ended, and nobody owns the server. It may still run PHP 7.x, which will never get an official fix.
  • Self-managed VPS and cloud servers. A WordPress site on an EC2 instance, Lightsail, DigitalOcean or Hetzner box is patched by nobody unless you do it. Managed and shared hosts are patching for their customers; a VPS owner is the host.
  • Shared servers holding real data. The same box often hosts the website, an admin panel and a customer database. Code execution as the web user is frequently enough to read wp-config.php or .env and walk away with credentials.

If your answer to “which PHP version is our website on?” is “I’d have to ask someone”, start with the next section.

Check your exposure in 10 minutes

On WordPress: go to Tools → Site Health → Info → Server to see the PHP version. On managed or shared hosting, check your host’s status page or ask support directly: “Have you applied the 21 October PHP security release?”

On a server you manage, run these as an admin:

bash
# 1. PHP version (CLI)
php -v

# 2. How PHP is served: is Apache loading mod_php? (highest risk)
apachectl -M 2>/dev/null | grep -i php

# 3. Is PHP-FPM running, and which version?
ps aux | grep -E 'php-fpm|php[0-9.]*-fpm' | grep -v grep

# 4. Debian/Ubuntu: installed PHP packages and whether the fix is in
dpkg -l | grep -E '^ii +php'
apt changelog php8.3-fpm 2>/dev/null | grep -E 'CVE-2026-10961[89]'

# 5. RHEL/Rocky/Alma: package changelog
rpm -q --changelog php-fpm | grep -E 'CVE-2026-10961[89]'

Adjust package names to your version (for example php8.2-fpm or libapache2-mod-php8.1).

Watch out for:

  • More than one PHP. Servers often run several versions side by side (control panels, old sites). Check each one.
  • CLI is not the web. php -v shows the command-line binary. The web server may use a different version and a different php.ini. Confirm with a temporary phpinfo() page, then delete it immediately.
  • Containers. Check the PHP version inside your images (docker run --rm <image> php -v), not just the host. Rebuild and redeploy; a patched host does not patch the image.

Fix it

Patching is the only complete fix. Everything else only buys time.

1. Patch, then restart every worker

  • Distribution packages: update through your package manager (apt upgrade / dnf upgrade on the PHP packages).
  • Built from source or official images: move to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, and rebuild containers.
  • PHP 7.4 to 8.1: use your distribution’s or LTS vendor’s patched package, and schedule the move to 8.2+.
  • PHP 7.3 or older: there is no fix. Upgrade, or take the server off the internet until you can.

Then restart PHP-FPM and Apache. Updated files on disk do nothing while old workers are still running in memory.

Internet-facing servers come first, and Apache mod_php servers first among those.

2. If you cannot patch today

These settings reduce exposure but do not make a server safe. Set them in php.ini, the FPM pool config or the web server config, then restart all workers:

ini
; CVE-2026-109619: close the session upload progress path
session.upload_progress.enabled = 0

; CVE-2026-109618: avoid the out-of-memory path
; (enforce so applications cannot override it)
memory_limit = -1

; PHP 8.5 only
fatal_error_backtraces = 0

Also:

  • Use container or cgroup memory limits as the outer guard, since memory_limit = -1 removes PHP’s own cap.
  • Bound request sizes at the edge. Keep post_max_size modest (8M or 32M) with upload_max_filesize below it, and limit body size, multipart parts and headers in Nginx, Apache or your load balancer.
  • Block multipart requests on endpoints that never take uploads.
  • Turn on WAF rules. Cloudflare has deployed rules on all plans. On paid plans, make sure managed rules are set to block, not just log. This only protects traffic that actually flows through the WAF.
  • Isolate what you cannot fix. CERT-EU recommends isolating internet-facing applications until a fix is applied and verified.

3. What not to do

  • Don’t use ini_set() in application code or .user.ini for these settings. They apply too late.
  • Don’t set RLIMIT_AS or RLIMIT_DATA process limits. They can push PHP into the very allocation-failure path you are trying to avoid.
  • Don’t treat silent logs as proof of safety. Hiding errors with display_errors, log_errors or @ does not remove the exposure.
  • Don’t assume your host has patched. Ask, and get a yes in writing.

Detect and verify

No vendor has published reliable indicators of compromise for php2shell yet. Until they do, hunt for the side effects that memory-corruption attacks and post-exploitation usually leave. Treat these as leads to investigate, not proof.

Signs worth investigating, from 17 October onwards:

  • Worker crashes. PHP-FPM logs showing child ... exited on signal 11 (SIGSEGV), or Apache Segmentation fault entries, especially in bursts.
  • Out-of-memory fatals (Allowed memory size ... exhausted) on endpoints that normally never hit them.
  • Unusual multipart POSTs in access logs: to pages that never accept uploads, from a single IP, or in rapid repetition.
  • Unexpected child processes of the web user, such as sh, bash, curl, wget, python or nc spawned by php-fpm or apache2.
  • New or changed files in the web root or upload folders, especially .php files where none should be.
  • Outbound connections from the web server to unfamiliar IPs.

After patching, verify:

  • Each server’s PHP package or version shows the fix, per the distribution changelog.
  • All PHP workers were restarted after the update (check process start times).
  • Containers were rebuilt from patched base images and redeployed.
  • If you found any of the signs above, rotate secrets: database passwords, API keys and the keys in wp-config.php or .env. Then scan for web shells. A patched server can still have an attacker inside.

The lesson beyond this CVE

php2shell will be patched and forgotten within weeks. The conditions that make it dangerous will not.

  • You cannot patch what you don’t know you run. Keep an inventory of every server, its runtime version and who owns it.
  • End-of-life software is a standing liability. PHP 7.x will never get an official fix for this or the next bug.
  • Defence in depth still matters. The web user should not be able to read every secret; databases should not trust the web server blindly; outbound traffic from web servers should be restricted.
  • Someone has to be watching. The first attack landed four days before the advisory. Only monitoring would have caught it.

How Aerovant can help

If you are unsure where PHP runs in your environment, or whether last week’s traffic was more than noise, our team can help:

  • Exposure check: identify internet-facing PHP servers, versions and how they are served.
  • Patch and hardening support for self-managed servers, cloud VMs and containers on AWS.
  • Compromise assessment: log review and web shell hunting on servers that were exposed.
  • VAPT and Managed SOC to find the next weak point before an attacker does, and to watch for it after hours.

Write to admin@aerovanttech.com or get in touch.

This article reflects public information as of 23 October 2026. Details may change as vendors publish further analysis; always follow your distribution’s and PHP’s official advisories.

Sources

All insights

Worried about your own exposure?

Tell us what you run. We will tell you plainly what to check first.