← Back to Feed CACHED · 2026-05-31 15:11:15 · CACHE_KEY CVE-2026-7261
CVE-2026-7261 · CWE-416 · Disclosed 2026-05-10

PHP SoapServer session-persisted object use-after-free via SOAP header fault

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

This is less a front-door master key and more a brittle latch that only fails on one oddly wired side entrance

CVE-2026-7261 is a SoapServer use-after-free in PHP when an application uses SOAP_PERSISTENCE_SESSION, which stores the handler object in session state across requests. The bug is hit on an error path: if a SOAP header handler throws or returns failure, PHP frees the handler object but later still reuses it during session writeback. Affected upstream branches are PHP 8.2.0-8.2.30, 8.3.0-8.3.30, 8.4.0-8.4.20, and 8.5.0-8.5.5; fixed versions are 8.2.31, 8.3.31, 8.4.21, and 8.5.6.

The vendor-side reality is already telling you this is not a generic critical. PHP's own advisory scores it Moderate with CVSS v4 6.3, while NVD's CVSS v3.1 auto-style scoring shows 9.8 because it models the bug as a raw network-reachable memory safety issue and ignores the deployment friction. In real estates, the attacker needs a reachable SOAP endpoint, the app must specifically use SoapServer::setClass() with SOAP_PERSISTENCE_SESSION, and the exploit path depends on an error-producing header handler plus difficult heap control; that combination is why this lands in MEDIUM, not CRITICAL.

"This is a narrow, app-specific PHP SOAP bug, not a universal pre-auth internet RCE fire drill."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Find a live PHP SOAP server

The attacker first needs a reachable SOAP endpoint, typically by enumerating WSDLs or SOAP POST handlers with curl, Burp Suite, or a custom HTTP client. This is not 'all PHP on the internet'; it is only applications that actually expose ext-soap server functionality.
Conditions required:
  • A SOAP endpoint is network reachable
  • The endpoint is backed by PHP SoapServer rather than some other stack
Where this breaks in practice:
  • SOAP is now a minority pattern in many enterprises
  • Most internet scanning can identify PHP broadly but not confirm SoapServer usage
Detection/coverage: External scanners may find /wsdl or SOAP-style POST behavior, but commodity vuln scanners have weak direct coverage for this specific code path.
STEP 02

Hit the narrow vulnerable configuration

The vulnerable application must use SoapServer::setClass() and enable SOAP_PERSISTENCE_SESSION, which serializes the handler object into session storage between requests, per the PHP manual. Without that exact persistence mode, this CVE does not fire.
Conditions required:
  • Application uses SOAP_PERSISTENCE_SESSION
  • PHP ext-soap is installed and active
  • The vulnerable branch/version is deployed
Where this breaks in practice:
  • This flag is uncommon and app-specific
  • You cannot infer this setting from a banner or package scan alone
  • Many SOAP implementations use request-scoped handlers instead
Detection/coverage: Package scanners can flag vulnerable PHP versions, but only code/config inspection can confirm actual exposure to SOAP_PERSISTENCE_SESSION.
STEP 03

Trigger the header-fault error path

Using a crafted SOAP request, the attacker must force a header-handler failure, following the path documented in the PHP GHSA example. The issue is tied to failure handling in the header-processing path, not just any normal request.
Conditions required:
  • The endpoint accepts attacker-controlled SOAP input
  • A header handler exists and can be induced to throw or fail
Where this breaks in practice:
  • Malformed XML alone is not enough; the attacker needs the right application behavior
  • Many SOAP services do little or no custom header handling
Detection/coverage: Look for SOAP faults, repeated malformed header requests, and application exceptions in web logs, PHP error logs, and php-fpm logs.
STEP 04

Reuse the session and touch the dangling object

The attacker then reuses the same session and tries to reach the stale handler reference during session persistence/readback. The GHSA explicitly notes that a SOAP server usually handles only one SOAP request per PHP request, making reliable control of the freed chunk unlikely; the most realistic near-term impact is process instability, information disclosure, or a crash rather than clean code execution.
Conditions required:
  • Attacker can maintain or replay the same session
  • The allocator state is favorable enough for useful reuse of freed memory
Where this breaks in practice:
  • Heap shaping is hard in this path
  • A single-request execution model reduces attacker control
  • Modern hardening often turns memory bugs into crashes instead of RCE
Detection/coverage: EDR rarely sees much here on Linux web tiers; defenders should watch for worker segfaults, core dumps, php-fpm child respawns, and crash-looping around SOAP requests.
STEP 05

Turn corruption into meaningful impact

A determined exploit author would need custom heap-feng-shui tooling, likely starting from the vendor proof snippet and extending it with target-specific allocator behavior. There is no evidence in the sourced material of a public weaponized RCE chain or in-the-wild campaign for this CVE.
Conditions required:
  • Advanced exploit development time
  • Target-specific reliability testing
Where this breaks in practice:
  • No public weaponized exploit found
  • No KEV listing or active exploitation evidence found
  • The path is too narrow for spray-and-pray internet exploitation
Detection/coverage: No dependable signature-based coverage for 'RCE attempt' exists here; rely on crash telemetry, SOAP request anomaly monitoring, and code-level confirmation.
03 · Compensating Control

1
Inventory PHP SOAP servers — Identify hosts exposing SOAP endpoints and confirm whether application code calls setPersistence(SOAP_PERSISTENCE_SESSION). For a MEDIUM verdict there is no noisgate mitigation SLA, so use this as immediate scoping work and go straight toward the 365-day remediation window.
2
Disable session persistence where feasible — If the application can tolerate it, remove SOAP_PERSISTENCE_SESSION or switch to request-scoped handling to kill the vulnerable path without waiting for a full stack uplift. There is no mitigation SLA for MEDIUM, but this is the cleanest interim risk reduction if you discover internet-facing SOAP services.
3
Restrict exposure to legacy SOAP endpoints — Put externally reachable SOAP services behind VPN, reverse-proxy allowlists, or strong application auth where business permits. Again, MEDIUM carries no mitigation SLA, but narrowing reachability materially cuts risk while you schedule the actual PHP upgrade inside the remediation window.
4
Monitor for SOAP fault crashes — Alert on php-fpm worker respawns, segfaults, core dumps, and bursts of SOAP faults from the same client/session. This does not remove the bug, but it raises the odds you catch probing or unreliable exploit development before it becomes an outage.
What doesn't work
  • Hiding PHP version banners does not help; the attacker's real problem is endpoint discovery and app behavior, not just banner parsing.
  • Composer/SCA-only dependency scanning does not reliably catch this because ext-soap is a built-in/runtime component, not just an application package in composer.lock.
  • A generic WAF rule for malformed XML does not guarantee coverage; the vulnerable path depends on valid-enough SOAP requests that trigger application header-handler failure.
04 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo authoritative exploitation evidence found in the sourced material. CISA KEV: not listed.
Proof-of-concept availabilityA vendor-authored reproducer exists in the GitHub advisory (GHSA-m33r-qmcv-p97q), but I found no public weaponized exploit repo or repeatable RCE chain.
EPSSUser-supplied EPSS is 0.0007; third-party mirrors around publication also show roughly 0.00059%-0.06% probability and an extremely low percentile. Read that as 'little market interest,' not zero risk.
KEV statusNo. Not present in the CISA Known Exploited Vulnerabilities catalog.
CVSS discrepancyNVD lists CVSS v3.1 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H), but the PHP CNA advisory uses CVSS v4 6.3 with AT:P, which better reflects the extra deployment prerequisite.
Affected versionsUpstream affected: 8.2.0-8.2.30, 8.3.0-8.3.30, 8.4.0-8.4.20, 8.5.0-8.5.5.
Fixed versionsUpstream fixed: 8.2.31, 8.3.31, 8.4.21, 8.5.6. Distro examples: Debian php8.2 8.2.31-1~deb12u1, Debian php8.4 8.4.21-1~deb13u1, Amazon Linux 2 php8.2 fixed in ALAS2PHP8.2-2026-011.
Exposure/scanning realityThere is no reliable internet census for SOAP_PERSISTENCE_SESSION usage. Shodan/Censys can help find public PHP or SOAP endpoints, but they cannot prove this specific runtime flag from the outside.
Disclosure timelinePHP released fixes on 2026-05-07; NVD/CVE publication shows 2026-05-10.
Reporter / sourceSource/CNA is PHP Group; advisory published in php/php-src GitHub Security Advisories.

Sources.

  1. PHP 8 changelog
  2. PHP GitHub security advisory GHSA-m33r-qmcv-p97q
  3. NVD CVE-2026-7261
  4. Ubuntu CVE-2026-7261
  5. Debian security tracker CVE-2026-7261
  6. PHP manual: SoapServer::setPersistence
  7. CISA Known Exploited Vulnerabilities catalog
  8. FIRST EPSS data and stats
05 · The Call

Final Verdict
↓ DOWNGRADED to MEDIUM (5.2/10)

Why this verdict

  • Baseline down from 9.8: the raw memory-corruption class is scary, but the PHP CNA itself scores this 6.3 because exploitation needs extra attack requirements, not just a socket.
  • Population is narrow: the attacker needs a public or reachable SOAP service using PHP ext-soap, SoapServer::setClass(), and specifically SOAP_PERSISTENCE_SESSION; each prerequisite compounds downward pressure.
  • Impact is not cleanly reliable: the advisory says SOAP usually handles one request per PHP request, so controlling the freed chunk is unlikely; in many real deployments the plausible outcome is crash or unstable worker behavior before dependable RCE.

Why not higher?

I am not taking this to HIGH or CRITICAL because it is not a universal pre-auth path against generic PHP. The attack requires a rare application pattern and a brittle error path, and there is no KEV entry, no sourced in-the-wild exploitation evidence, and no public weaponized exploit chain showing reliable code execution.

Why not lower?

I am not dropping this to LOW because the bug is still remotely triggerable with no authentication if the vulnerable app pattern exists. It sits in a server-side memory-safety path, so a reachable affected SOAP service can still suffer process crashes or possibly information disclosure, which is more than backlog-only hygiene.

06 · Verification

Crowdsourced verification payload.

Run this on the target PHP application host. Save it as check-cve-2026-7261.sh and run bash check-cve-2026-7261.sh /var/www to also inspect deployed code for SOAP_PERSISTENCE_SESSION; no root is required unless the PHP binary or app tree is restricted.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2026-7261.sh
# Detect likely exposure to CVE-2026-7261 on a host.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -u

APP_PATH="${1:-}"
PHP_BIN="${PHP_BIN:-php}"

ver_lt() {
  # returns 0 if $1 < $2
  [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" != "$2" ] && return 1
  [ "$1" = "$2" ] && return 1
  return 0
}

in_vuln_range() {
  local v="$1"
  if ver_lt "$v" "8.2.31" && ! ver_lt "$v" "8.2.0"; then return 0; fi
  if ver_lt "$v" "8.3.31" && ! ver_lt "$v" "8.3.0"; then return 0; fi
  if ver_lt "$v" "8.4.21" && ! ver_lt "$v" "8.4.0"; then return 0; fi
  if ver_lt "$v" "8.5.6"  && ! ver_lt "$v" "8.5.0"; then return 0; fi
  return 1
}

if ! command -v "$PHP_BIN" >/dev/null 2>&1; then
  echo "UNKNOWN: php binary not found in PATH"
  exit 2
fi

PHP_VERSION="$($PHP_BIN -r 'echo PHP_VERSION;' 2>/dev/null)"
if [ -z "$PHP_VERSION" ]; then
  echo "UNKNOWN: unable to determine PHP version"
  exit 2
fi

SOAP_LOADED="$($PHP_BIN -m 2>/dev/null | awk 'BEGIN{IGNORECASE=1} /^soap$/{print "yes"}')"
if [ "$SOAP_LOADED" != "yes" ]; then
  echo "UNKNOWN: ext-soap not loaded in this PHP SAPI; verify web SAPI separately"
  exit 2
fi

if ! in_vuln_range "$PHP_VERSION"; then
  echo "PATCHED: PHP $PHP_VERSION is outside the affected upstream ranges"
  exit 0
fi

if [ -z "$APP_PATH" ]; then
  echo "UNKNOWN: PHP $PHP_VERSION is in an affected range and ext-soap is loaded; rerun with app path to check for SOAP_PERSISTENCE_SESSION usage"
  exit 2
fi

if [ ! -d "$APP_PATH" ]; then
  echo "UNKNOWN: app path '$APP_PATH' does not exist or is not a directory"
  exit 2
fi

MATCHES=$(grep -RInE 'SOAP_PERSISTENCE_SESSION|setPersistence\s*\(\s*1\s*\)' "$APP_PATH" 2>/dev/null | head -n 20 || true)
if [ -n "$MATCHES" ]; then
  echo "VULNERABLE: PHP $PHP_VERSION is affected, ext-soap is loaded, and app code appears to use SOAP_PERSISTENCE_SESSION"
  echo "$MATCHES"
  exit 1
fi

echo "UNKNOWN: PHP $PHP_VERSION is affected and ext-soap is loaded, but no obvious SOAP_PERSISTENCE_SESSION usage was found under $APP_PATH"
exit 2