GHSA-6vhm-xfmv-94pj: 
PHP Analyse et atténuation de la vulnérabilité

Summary

The HTTPRedirect::receive() method in simplesamlphp/saml2 calls PHP's gzinflate() on attacker-controlled compressed input without specifying a max_length parameter. An unauthenticated attacker can send a specially crafted SAML request via the HTTP-Redirect binding that decompresses from a few kilobytes to several megabytes (amplification ratios of 922:1 to 1002:1), causing a non-catchable PHP fatal error that kills the worker process.

Root Cause

The SAML HTTP-Redirect binding requires DEFLATE compression per the SAML 2.0 Bindings specification (section 3.4.4.1). The receive() method decompresses incoming messages using gzinflate() with no output size limit. PHP's gzinflate() accepts an optional max_length parameter (default 0, meaning unlimited), but the library does not use it. When the decompressed output exceeds the PHP process's memory_limit, a non-catchable E_ERROR terminates the worker process with exit code 255.

// src/Binding/HTTPRedirect.php, receive() method
$message = base64_decode($message, true);  // line 162: format check only
// ...
$message = gzinflate($message);           // line 167: no max_length parameter

Impact

An unauthenticated attacker who can reach a SAML Service Provider's SSO or SLO endpoint (typically exposed in publicly available SAML metadata) can crash PHP worker processes by sending crafted HTTP GET requests with a compressed decompression bomb as the SAMLRequest or SAMLResponse query parameter. At default web server URL limits (~8 KB), each request decompresses to approximately 5.5 MB plus additional DOM parsing overhead. At common non-default URL limits (32 KB or higher, frequently configured for SAML deployments with large attribute assertions), a single request can crash a worker when memory_limit is 64 MB or 128 MB. A sustained attack exhausts the PHP-FPM worker pool, denying all SAML authentication flows through the Service Provider.

Proof of Concept

Requires: PHP 8.x with zlib extension. No external dependencies or network access.

The following script demonstrates the amplification by simulating the exact base64_decode followed by gzinflate path from HTTPRedirect::receive():

<?php
// Generate repetitive valid SAML XML that compresses extremely well
$xml  = '<?xml version="1.0" encoding="UTF-8"?>';
$xml .= '<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"'
      . ' xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"'
      . ' ID="_poc" Version="2.0" IssueInstant="2026-01-01T00:00:00Z">';
$xml .= '<saml:Issuer>https://sp.example.com</saml:Issuer>';
$xml .= str_repeat('<e/>', 500000);
$xml .= '</samlp:AuthnRequest>';
$compressed = gzdeflate($xml);
$b64 = base64_encode($compressed);
// Simulate HTTPRedirect::receive() path
$message = base64_decode($b64, true);
echo "Compressed: " . round(strlen($message)/1024, 2) . " KB\n";
$message = gzinflate($message);
echo "Decompressed: " . round(strlen($message)/1024/1024, 2) . " MB\n";
echo "Ratio: " . round(strlen($message) / strlen($compressed)) . ":1\n";
Compressed: 2.12 KB
Decompressed: 1.91 MB
Ratio: 922:1

Triggering an out-of-memory crash:

$ php -d memory_limit=8M -r '$c = file_get_contents("bomb.deflate"); gzinflate($c);'
PHP Fatal error: Allowed memory size of 8388608 bytes exhausted
  (tried to allocate 4501167 bytes) in Command line code on line 1
Exit code: 255

The max_length parameter prevents the crash:

gzinflate($compressed, 1048576) returned false (rejected)
Adding max_length blocks amplification without affecting legitimate SAML messages.

Attack Chain

  1. Exposure: The SAML HTTP-Redirect binding endpoint (HTTPRedirect::receive()) is unauthenticated by design. Any SP deployment exposes it as the SSO or SLO endpoint, typically discoverable via SAML metadata.
  2. Control: The attacker controls the full SAMLRequest or SAMLResponse query parameter value. The only processing before decompression is base64_decode() with strict mode (line 162), which is a format check that all valid compressed payloads pass.
  3. Path: The value flows directly from $_GET['SAMLRequest'] (lines 144-151) through base64_decode() (line 162) to gzinflate() (line 167) with no intermediate size check, rate limit, or resource constraint.
  4. Guard: No guard exists. The gzinflate() call uses the default max_length of 0 (unlimited). PHP's memory_limit is the crash trigger, not a protection.
  5. Primitive: gzinflate() allocates memory for the full decompressed output before returning. When this exceeds memory_limit, PHP emits a non-catchable E_ERROR and the worker process terminates with exit code 255.
  6. Result: Worker process death. PHP-FPM respawns workers, but sustained requests crash them again. The SAML authentication service becomes unavailable.

Bypass Evidence

No guard, prior fix, or security boundary exists between the unauthenticated HTTP GET endpoint and the unbounded gzinflate() call. The following defenses were evaluated and found inapplicable:

  • base64_decode($message, true) (line 162): validates base64 encoding format; does not constrain decompressed output size.
  • gzinflate() return value check (line 168): catches malformed data, but the out-of-memory fatal error kills the process before gzinflate() returns, so this check never executes for the attack payload.
  • DOMDocumentFactory::fromString() (line 172): applies LIBXML_COMPACT | LIBXML_NONET | LIBXML_NO_XXE and rejects <!DOCTYPE>; none of these constrain document size. DOM parsing adds 2 to 5 times additional memory overhead, compounding the problem.
  • Web server URL length limits (typically ~8 KB): constrain the compressed payload size but do not prevent the attack. At default limits, the 922:1 amplification ratio still produces multi-megabyte allocations; concurrent requests exhaust the worker pool. Many SAML deployments increase URL limits to accommodate large attribute assertions.
  • PHP memory_limit: this is the crash mechanism, not a protection. Lower limits make the attack more effective (easier to trigger per request).

Affected Versions

  • Ecosystem: Composer
  • Package: simplesamlphp/saml2
  • Confirmed affected range: <= 6.3.0
  • Latest release checked: v6.3.0 on Packagist
  • Fix status: not fixed in any released version The unbounded gzinflate() call is present from the earliest available version through v6.3.0 (latest stable) and v7.0.0-rc1 (prerelease). The vulnerable code at src/Binding/HTTPRedirect.php has never been modified to add a max_length parameter. The advisory CVE-2026-49289 (GHSA-5cjr-mxj5-wmrx) addresses a different DoS vector (XPath transforms in processTransforms()) and its fix has no effect on the decompression path.

Suggested Fix

Add a max_length parameter to the gzinflate() call in HTTPRedirect::receive() to cap decompressed output at a safe size. A limit of 10 MB accommodates all legitimate SAML messages (typically under 100 KB decompressed) while blocking amplification attacks:

$message = gzinflate($message, 10 * 1024 * 1024);

When decompressed output exceeds the limit, gzinflate() returns false, which the existing error check at line 168 already handles by throwing an exception, avoiding the non-catchable fatal error. Applications relying on unusually large SAML messages could make this limit configurable, but a default of several megabytes is safe for standard SAML deployments. No interim mitigation is available within the library. Deployments can reduce exposure by lowering web server URL length limits (which constrains the compressed payload size) and increasing PHP memory_limit (which raises the crash threshold), but neither eliminates the vulnerability.

Reported by zx (GitHub: @manus-pi).


Source: NVD

Connexe PHP Vulnérabilités :

CVE ID

Gravité

Partition

Technologies

Nom du composant

Exploit CISA KEV

A corrigé

Date de publication

GHSA-6vhm-xfmv-94pjHIGH7.5
  • PHP logoPHP
  • simplesamlphp/saml2
NonNonNov 05, 2026
CVE-2026-123125MEDIUM6.3
  • PHP logoPHP
  • cpe:2.3:a:sensiolabs:symfony
NonOuiNov 05, 2026
CVE-2026-121949LOW2.3
  • PHP logoPHP
  • cpe:2.3:a:sensiolabs:symfony
NonOuiNov 05, 2026
CVE-2026-118517LOW2.3
  • PHP logoPHP
  • cpe:2.3:a:sensiolabs:symfony
NonOuiNov 05, 2026
GHSA-q2gc-fpw5-3v3cMEDIUMN/A
  • JavaScript logoJavaScript
  • tina4-python
NonOuiNov 05, 2026

Évaluation gratuite des vulnérabilités

Évaluez votre posture de sécurité cloud

Évaluez vos pratiques de sécurité cloud dans 9 domaines de sécurité afin d’évaluer votre niveau de risque et d’identifier les lacunes dans vos défenses.

Évaluation de la demande

Ressources Wiz supplémentaires

Obtenez une démo personnalisée

Prêt(e) à voir Wiz en action ?

"La meilleure expérience utilisateur que j’ai jamais vue, offre une visibilité totale sur les workloads cloud."
David EstlickRSSI
"Wiz fournit une interface unique pour voir ce qui se passe dans nos environnements cloud."
Adam FletcherChef du service de sécurité
"Nous savons que si Wiz identifie quelque chose comme critique, c’est qu’il l’est réellement."
Greg PoniatowskiResponsable de la gestion des menaces et des vulnérabilités