← Back to Feed CACHED · 2026-10-22 06:20:46 · CACHE_KEY tenable:369483
tenable:369483 · CWE-416 · Disclosed 2026-10-21

PHP < 8.2.35 / 8.3.x < 8.3.36 / 8.4.x < 8.4.27 / 8.5.x < 8.5.12 Multiple Vulnerabilities

PHP core session.upload_progress heap use-after-free enabling unauthenticated RCE

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Someone left the front door of every PHP web server unlocked, and burglars arrived before the locksmith

CVE-2026-109618 and CVE-2026-109619 — collectively dubbed php2shell — are use-after-free vulnerabilities in PHP's core request handling, not in any optional extension or application framework. CVE-2026-109618 triggers when an out-of-memory condition during request parsing leaves internal data partially initialized; cleanup treats invalid data as valid, corrupting the heap. CVE-2026-109619 occurs when a fatal error leaves global state pointing to freed memory; a subsequent request handled by the same worker reuses those stale pointers. Both allow unauthenticated remote code execution via a single crafted multipart/form-data POST request targeting session.upload_progress (enabled by default). The attack lands *before application code executes* on mod_php, meaning application-layer WAFs see nothing. Affected: every PHP version from 5.4 onward. Fixed in 8.2.35, 8.3.36, 8.4.27, and 8.5.12; source backports exist for 7.4/8.0/8.1.

The PHP CNA rates both CVEs at CVSSv4 9.2 (Critical); NVD assigned CVSSv3.1 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H). Red Hat's 8.1 with AC:H is the lone conservative outlier — and it is contradicted by confirmed in-the-wild exploitation observed by Cloudflare, Amazon Threat Intelligence, and watchTowr's honeypot network, plus multiple functional public PoCs. The vendor CRITICAL rating is, for once, entirely justified. If anything, the 9.2 CVSSv4 is modest given the zero-friction attack surface: no auth, default config, every SAPI, every PHP version shipped in the last 14 years. This is the PHP equivalent of Log4Shell — treat it accordingly.

"Unauthenticated RCE in PHP core, actively exploited, patch within hours"
02 · The Attack Path

5 steps from start to impact.

STEP 01

Identify target running PHP

The attacker scans for any HTTP server returning X-Powered-By: PHP headers, .php extensions, or PHP-typical response patterns. Shodan shows ~1.9 million internet-facing PHP hosts. Cortex Xpanse telemetry identifies 22.6 million exposed instances. Even without banners, a blind multipart POST costs nothing to attempt.
Conditions required:
  • Target serves HTTP/HTTPS on the internet or accessible network
Where this breaks in practice:
  • None — PHP is the most widely deployed server-side language on the web
Detection/coverage: Shodan dork: http.component:php. Censys: services.software.product: PHP. runZero asset inventory.
STEP 02

Craft multipart POST with PHP_SESSION_UPLOAD_PROGRESS

The attacker constructs a multipart/form-data POST containing a PHP_SESSION_UPLOAD_PROGRESS field. The field value — fully attacker-controlled — is written into PHP's session file at a predictable path (/var/lib/php/sessions/sess_<PHPSESSID>). The upload is designed to stall longer than session.upload_progress.min_freq (default 1s), triggering the vulnerable code path in ext/session/session.c.
Conditions required:
  • session.upload_progress.enabled = On (default)
  • PHP must handle the request (any SAPI)
Where this breaks in practice:
  • session.upload_progress.enabled is ON by default in all PHP distributions
  • No application endpoint or route required — the handler fires in the core
Detection/coverage: WAF rules matching PHP_SESSION_UPLOAD_PROGRESS in multipart bodies. Palo Alto Threat ID 543004.
STEP 03

Trigger heap use-after-free via OOM or fatal error

For CVE-2026-109618: the attacker forces an OOM condition during request initialization via longjmp(), leaving partially initialized zval* pointers in the session HashTable. Cleanup writes through stale pointers — a textbook use-after-free. For CVE-2026-109619: a fatal error leaves global state pointing to freed memory; the next request on the same worker reuses it. Both paths corrupt the heap predictably enough for weaponized exploitation, as confirmed by multiple independent researchers and live attacks.
Conditions required:
  • Vulnerable PHP version (5.4 through 8.2.34, 8.3.35, 8.4.26, 8.5.11)
Where this breaks in practice:
  • Red Hat argues AC:H due to precise heap manipulation — but public PoCs and confirmed wild exploitation negate this
Detection/coverage: Monitor for PHP-FPM segfaults correlated with multipart POST bursts. Process monitoring for unexpected child processes (shells, curl, wget) spawned from httpd/php-fpm parent.
STEP 04

Achieve code execution as web worker

The use-after-free primitive gives the attacker control of a heap-allocated function pointer or zval type field. Exploitation yields arbitrary code execution with the privileges of the web server worker process (www-data, apache, nginx). On mod_php, this occurs *before* any application code runs — no PHP disable_functions, open_basedir, or framework-level security has a chance to intervene. The attacker can read files, establish reverse shells, pivot laterally, or deploy webshells.
Conditions required:
  • Steps 1-3 succeeded
Where this breaks in practice:
  • Worker runs as unprivileged user — but web server access to application data, database credentials, and internal network is typically sufficient for full compromise
Detection/coverage: HIDS/EDR detecting shell spawns from web server processes. File integrity monitoring on web roots. Network detection of reverse shell patterns.
STEP 05

Post-exploitation: credential harvesting and lateral movement

With code execution on a web server, the attacker harvests database credentials from config files (e.g., wp-config.php, .env, config.php), session tokens from the session store, and API keys from environment variables. CVE-2026-109618 also leaks freed worker memory — similar to Heartbleed — potentially exposing passwords, TLS private keys, and session tokens from *other users' requests*. The attacker pivots to databases, internal services, and adjacent hosts.
Conditions required:
  • Web server has access to databases, internal APIs, or sensitive config files (standard deployment)
Where this breaks in practice:
  • Network segmentation may limit lateral movement, but database credentials in web app configs are near-universal
Detection/coverage: Database audit logs for anomalous queries. Network flow analysis for unusual outbound connections from web tier.
03 · Compensating Control

1
CRITICAL 9.8→HIGH 7.5
SEVERITY REDUCED
Disable session.upload_progress.enabled immediately — Set session.upload_progress.enabled = Off in php.ini and restart PHP-FPM or Apache. This disables the vulnerable code path in ext/session/session.c for CVE-2026-109619 and significantly reduces the attack surface for CVE-2026-109618. Deploy within hours per the noisgate mitigation SLA for CRITICAL with active exploitation — this is a same-day emergency. Most applications do not use upload progress tracking; verify with grep -r 'upload_progress' /var/www/ before deploying.
2
CRITICAL 9.8→HIGH 7.0
SEVERITY REDUCED
Block or rate-limit multipart/form-data POSTs at WAF or reverse proxy — Configure your WAF (Cloudflare, AWS WAF, F5 ASM, ModSecurity) to block or heavily rate-limit multipart/form-data POST requests containing PHP_SESSION_UPLOAD_PROGRESS in the body. Palo Alto customers should enable Threat ID 543004 (Frontier Virtual Patching, deployed October 20). Deploy within hours. This breaks the known exploit delivery mechanism but may not cover all variants.
3
CRITICAL 9.8→IGNORE 0.0
SEVERITY REDUCED
Apply vendor patches (8.2.35 / 8.3.36 / 8.4.27 / 8.5.12) and restart — This is the definitive fix. Update PHP packages from upstream or your distro's security repository and restart PHP-FPM, Apache, or your SAPI. Deploy within 3 days per the noisgate mitigation SLA for CRITICAL, but given active exploitation, aim for hours. For distro-managed PHP: apt update && apt upgrade php* (Debian/Ubuntu) or dnf update php* (RHEL/Fedora). Verify with php -v or package changelog.
4
CRITICAL 9.8→HIGH 7.0
SEVERITY REDUCED
Migrate or isolate EOL PHP (5.x, 7.x, 8.0, 8.1) hosts — PHP 5.x and 7.x receive no upstream patches. Source backports exist for 7.4/8.0/8.1 but require manual compilation. Within 3 days, isolate these hosts behind a reverse proxy that strips multipart uploads, or migrate to a supported PHP branch. Long-term, these must be upgraded or decommissioned within the noisgate remediation SLA of 90 days for CRITICAL.
5
CRITICAL 9.8→CRITICAL 9.0
Deploy process-level monitoring for web worker child processes — Configure EDR or HIDS to alert on unexpected child process spawns (bash, sh, curl, wget, python, perl, nc) from httpd, apache2, php-fpm, or lsphp parent processes. Also monitor for new .php files appearing in web roots. This does not prevent exploitation but ensures rapid detection and containment. Deploy within 24 hours.
What doesn't work
  • Application-layer WAFs and disable_functions — the vulnerability fires in the PHP core *before* application code or PHP configuration directives like disable_functions and open_basedir take effect, especially on mod_php.
  • PHP memory_limit tuning — lowering memory_limit does not prevent the OOM corruption path; it may actually make it *easier* to trigger.
  • Upgrading only the application framework (WordPress, Laravel, etc.) — the bug is in the PHP interpreter, not in any application. Framework updates are irrelevant.
  • Network-level IP blocklisting — exploitation attempts are coming from diverse, rotating IPs. Blocklists cannot keep pace with the volume of scanning.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationConfirmed active. Amazon Threat Intel observed php2shell exploitation attempts on October 17 — four days before disclosure. Cloudflare reported attacks at 07:43 UTC October 21, six hours before the official patch release at 14:00 UTC. watchTowr's Attacker Eye honeypot network confirmed broad exploitation on October 21.
Proof-of-Concept AvailabilityMultiple public PoCs. GitHub repos: eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC, wakemeiflose/php2shell, ikow/php2shell-poc, syrex1013/php2shell, RemiPelloux/php-session-upload-progress-uaf. Additional PoCs indexed on Sploitus by TheMursalin, aduli198, adityaaravind, alanh0vx, dimasma0305, and BoheSama1999. watchTowr CEO Benjamin Harris confirmed reproduction of CVE-2026-109618 in lab.
EPSS ScorePending verification — both CVEs were disclosed October 21, 2026; EPSS model has not yet ingested sufficient data. Given confirmed wild exploitation, expect >90th percentile once scored.
CISA KEV StatusNot listed as of KEV version 2026.10.21 (14:04 UTC). However, CISA has "strongly urged organizations to immediately patch." KEV addition is expected imminently given confirmed exploitation.
CVSS VectorsNVD v3.1: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H → 9.8 Critical. Red Hat v3.1: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H → 8.1 Important (AC:H due to heap manipulation precision). PHP CNA CVSSv4.0: 9.2 Critical. The NVD AC:L assessment is validated by functional PoCs and wild exploitation.
Affected Version RangesPHP 5.4.0 through 8.2.34, 8.3.0–8.3.35, 8.4.0–8.4.26, 8.5.0–8.5.11. All SAPIs: mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed. Every PHP release shipped since 2012 is vulnerable.
Fixed Versions (incl. distro backports)Upstream: 8.2.35, 8.3.36, 8.4.27, 8.5.12. Source backports for 7.4/8.0/8.1. Ubuntu 22.04: php8.1 8.1.2-1ubuntu2.28. Ubuntu 24.04: php8.3 8.3.6-0ubuntu0.24.04.13. Debian 12: php8.2 8.2.35-1~deb12u1. Debian 13: php8.4 8.4.27-1~deb13u1. RHEL 9: php:8.2 module updated to 8.2.35.
Internet ExposureShodan: ~1.9M internet-facing PHP hosts (Henk Poley). Censys: ~1.5M of 2.6M scanned hosts unpatched shortly after disclosure. Cortex Xpanse: 22.6M exposed instances. ~884K hosts running EOL PHP 5/7 branches with no upstream fix.
Disclosure TimelineAug 1, 2026: Discovery by Ryan Austin (Calif). Aug 11: Coordinated disclosure to PHP. Oct 20, 15:00 UTC: Details leaked publicly. Oct 21, 07:43 UTC: Cloudflare observes first attacks. Oct 21, 14:00 UTC: Official patches released.
Reporting ResearchersRyan Austin (Calif) — primary discoverer. Wiz Research (Sagi Tzadik, Shir Tamari, Nir Ohfeld, Tomer Schwartz) — independent analysis confirming severity. OpenAI researchers — contributed to exploitation chain feasibility using frontier AI models. watchTowr (Benjamin Harris) — lab reproduction and wild exploitation confirmation.

Sources.

  1. Tenable: php2shell FAQ (CVE-2026-109618, CVE-2026-109619)
  2. PHP Foundation: Today's PHP Security Release
  3. Palo Alto Unit 42: Threat Brief CVE-2026-109618 / CVE-2026-109619
  4. Sansec: PHP2Shell Research
  5. Red Hat: CVE-2026-109618
  6. Rapid7: ETR — Critical Unauthenticated RCE in PHP
  7. watchTowr: PHP CVE-2026-109618 FAQ
  8. Help Net Security: PHP2Shell Patched
05 · The Call

Final Verdict
↑ UPGRADED to CRITICAL (9.8/10)

Why this verdict

  • Zero-friction attack surface: Unauthenticated, no special application endpoint, no non-default configuration required. session.upload_progress.enabled is ON by default. The attacker needs nothing more than HTTP access to any PHP page — or even a non-existent one on mod_php.
  • Confirmed active exploitation before patch availability: Amazon Threat Intel saw attacks October 17 (4 days pre-disclosure). Cloudflare logged attacks at 07:43 UTC October 21, six hours before the 14:00 UTC patch release. This is not theoretical — it is happening now.
  • Weaponized public PoCs eliminate complexity argument: Red Hat's AC:H rating is contradicted by 6+ public GitHub PoC repos, Sploitus listings, and confirmed reproduction by watchTowr and Wiz. The heap manipulation is solved; the exploit is scriptable.
  • Role multiplier: PHP is the *canonical* web application runtime — W3Techs estimates ~76% of server-side web uses PHP. High-value roles include: (a) E-commerce platforms (Magento confirmed exploitable — PCI-scoped payment data, fleet of merchant sites), (b) Enterprise CMS (WordPress/Drupal powering corporate and government sites), (c) SaaS API backends (Laravel/Symfony applications holding customer data), (d) Hosting providers (shared hosting = one exploit compromises hundreds of tenants). The bug is in the interpreter core, so *every* PHP deployment is in the blast radius regardless of application. This is fleet-scale by definition. ≥10% of PHP installs occupy high-value roles → verdict floor is CRITICAL.
  • Memory disclosure amplifier: CVE-2026-109618 also leaks freed worker memory to the attacker (Heartbleed-style), potentially exposing passwords, session tokens, API keys, and TLS private keys from other users' requests — even without achieving full RCE.
  • Massive exposure footprint: 1.9M+ internet-facing hosts on Shodan, 22.6M on Cortex Xpanse. 884K hosts on EOL branches with no upstream fix available. The denominator is enormous.

Why not higher?

A 9.8 is already at the top of the practical scale. The only reason this isn't a theoretical 10.0 is that exploitation on PHP-FPM requires slightly more nuance than mod_php (application-level code paths may be needed), and the web worker process runs as an unprivileged user, adding one hop before root-level system compromise. These are marginal frictions that do not meaningfully reduce urgency.

Why not lower?

Every downgrade argument collapses under scrutiny. Red Hat's AC:H is disproven by confirmed wild exploitation and public PoCs. The 'requires heap manipulation precision' friction is solved — researchers published working exploit chains. No authentication is needed. No non-default configuration is needed. The attack surface is the largest on the internet (PHP powers the majority of web servers). Active exploitation was observed *before* patches were available. There is no credible basis for rating this below CRITICAL.

06 · Verification

Crowdsourced verification payload.

Run this script on each target host as any user with read access to the PHP binary (no root required). Invoke with: bash check_php2shell.sh. The script checks all PHP binaries found in PATH and common locations, compares versions against the fixed releases, and also checks the session.upload_progress.enabled setting as a secondary risk indicator.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_php2shell.sh — Detect PHP vulnerable to CVE-2026-109618 / CVE-2026-109619 (php2shell)
# Outputs: VULNERABLE / PATCHED / UNKNOWN per PHP binary found
# Exit codes: 0 = all patched, 1 = at least one vulnerable, 2 = unknown/no PHP found

set -euo pipefail

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; NC='\033[0m'
FOUND_VULN=0
FOUND_PHP=0

version_ge() {
  # Returns 0 if $1 >= $2 using sort -V
  printf '%s\n%s' "$2" "$1" | sort -V -C
}

check_php() {
  local php_bin="$1"
  if [[ ! -x "$php_bin" ]]; then return; fi
  FOUND_PHP=1
  local full_version
  full_version=$( "$php_bin" -r 'echo PHP_VERSION;' 2>/dev/null ) || { echo -e "${YELLOW}[UNKNOWN]${NC} $php_bin — could not determine version"; return; }
  local major_minor
  major_minor=$( echo "$full_version" | grep -oP '^\d+\.\d+' )

  local fixed=""
  case "$major_minor" in
    8.5) fixed="8.5.12" ;;
    8.4) fixed="8.4.27" ;;
    8.3) fixed="8.3.36" ;;
    8.2) fixed="8.2.35" ;;
    8.1|8.0|7.*|5.*) fixed="" ;; # EOL — no upstream fix
    *) echo -e "${YELLOW}[UNKNOWN]${NC} $php_bin — unrecognized branch $major_minor ($full_version)"; return ;;
  esac

  if [[ -z "$fixed" ]]; then
    echo -e "${RED}[VULNERABLE]${NC} $php_bin — $full_version (EOL branch, no upstream fix available)"
    FOUND_VULN=1
    return
  fi

  if version_ge "$full_version" "$fixed"; then
    echo -e "${GREEN}[PATCHED]${NC} $php_bin — $full_version (>= $fixed)"
  else
    echo -e "${RED}[VULNERABLE]${NC} $php_bin — $full_version (needs >= $fixed)"
    FOUND_VULN=1
  fi
}

# Check session.upload_progress.enabled
check_sup() {
  local php_bin="$1"
  local sup
  sup=$( "$php_bin" -r 'echo ini_get("session.upload_progress.enabled") ? "On" : "Off";' 2>/dev/null ) || return
  if [[ "$sup" == "On" ]]; then
    echo -e "  ${YELLOW}↳ session.upload_progress.enabled = On (attack surface active)${NC}"
  else
    echo -e "  ${GREEN}↳ session.upload_progress.enabled = Off (mitigated)${NC}"
  fi
}

echo "=== php2shell (CVE-2026-109618 / CVE-2026-109619) Check ==="
echo ""

# Collect PHP binaries from PATH and common locations
mapfile -t PHP_BINS < <( { which -a php php8.2 php8.3 php8.4 php8.5 php-fpm php-fpm8.2 php-fpm8.3 php-fpm8.4 php-fpm8.5 2>/dev/null; find /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /opt -maxdepth 3 -name 'php*' -type f -executable 2>/dev/null; } | sort -u )

for bin in "${PHP_BINS[@]}"; do
  check_php "$bin"
  check_sup "$bin"
done

if [[ $FOUND_PHP -eq 0 ]]; then
  echo -e "${YELLOW}[UNKNOWN]${NC} No PHP binaries found on this host."
  exit 2
fi

echo ""
if [[ $FOUND_VULN -eq 1 ]]; then
  echo -e "${RED}RESULT: VULNERABLE — patch immediately.${NC}"
  exit 1
else
  echo -e "${GREEN}RESULT: PATCHED — all detected PHP binaries are at fixed versions.${NC}"
  exit 0
fi