
PEACH
Un cadre d’isolation des locataires
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.
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 parameterAn 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.
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:1Triggering 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: 255The max_length parameter prevents the crash:
gzinflate($compressed, 1048576) returned false (rejected)
Adding max_length blocks amplification without affecting legitimate SAML messages.HTTPRedirect::receive()) is unauthenticated by design. Any SP deployment exposes it as the SSO or SLO endpoint, typically discoverable via SAML metadata.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.$_GET['SAMLRequest'] (lines 144-151) through base64_decode() (line 162) to gzinflate() (line 167) with no intermediate size check, rate limit, or resource constraint.gzinflate() call uses the default max_length of 0 (unlimited). PHP's memory_limit is the crash trigger, not a protection.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.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.memory_limit: this is the crash mechanism, not a protection. Lower limits make the attack more effective (easier to trigger per request).simplesamlphp/saml2<= 6.3.0gzinflate() 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.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);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
Évaluation gratuite des vulnérabilités
É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.
Obtenez une démo personnalisée
"La meilleure expérience utilisateur que j’ai jamais vue, offre une visibilité totale sur les workloads cloud."
"Wiz fournit une interface unique pour voir ce qui se passe dans nos environnements cloud."
"Nous savons que si Wiz identifie quelque chose comme critique, c’est qu’il l’est réellement."