May 6, 2026·6 min read·33 visits
phpseclib before versions 1.0.23, 2.0.47, and 3.0.36 suffers from a computational DoS flaw where parsing maliciously crafted X.509 certificates with massive explicit primes triggers an unbounded Miller-Rabin primality test, leading to CPU exhaustion.
A computational Denial of Service (DoS) vulnerability in phpseclib allows unauthenticated attackers to exhaust CPU resources by supplying malformed X.509 certificates. The vulnerability arises from missing bit-length upper bounds in the Miller-Rabin primality test implementation when evaluating explicit elliptic curve field parameters.
The phpseclib library provides cryptographic operations and certificate parsing for PHP applications. Versions 1.x prior to 1.0.23, 2.x prior to 2.0.47, and 3.x prior to 3.0.36 contain an uncontrolled resource consumption vulnerability (CWE-400). Unauthenticated attackers can trigger a denial-of-service condition by supplying maliciously crafted X.509 certificates.
This vulnerability manifests as a computational denial-of-service, specifically targeting the mathematical operations underlying primality testing. The issue was introduced inadvertently as a regression during the remediation of a prior security flaw, CVE-2023-27560. The subsequent patch expanded the circumstances under which the library evaluates primality without enforcing corresponding size boundaries on the integer inputs.
Academic researchers categorized this specific attack vector under the "X.509DoS" class of vulnerabilities. Cryptographic libraries parse explicit Elliptic Curve parameters contained within ASN.1 structures. By abusing the explicit field parameter definition within an X.509 certificate, an attacker forces the server to execute astronomically expensive mathematical validations.
The root cause lies within the Math_BigInteger::isPrime() and Math_BigInteger::randomPrime() methods. These functions utilize the Miller-Rabin probabilistic primality test to determine if a given large integer is prime. The algorithmic complexity of the Miller-Rabin test scales according to $O(k \cdot \log^3 n)$, where $n$ is the integer under evaluation and $k$ represents the number of iteration witnesses.
As the bit-length of the integer $n$ increases, the CPU time required to compute the necessary modular exponentiations grows cubically. The library failed to implement upper bounds on the bit-length of numbers passed to these primality validation functions. When a system parses an X.509 certificate specifying custom Elliptic Curve (EC) configurations, the library extracts the field prime $p$ from the explicit parameters.
An attacker constructs a DER-encoded X.509 certificate containing an arbitrary, massively sized integer in place of a legitimate field prime. Upon invocation of the getPublicKey() method, phpseclib dynamically validates the extracted parameters. The library passes the unbounded field prime directly into the isPrime() function, immediately monopolizing the CPU thread as the Miller-Rabin algorithm attempts to process millions of bits.
The remediation strategy introduces static guardrails into the Math_BigInteger::isPrime() function. The maintainers implemented a strict upper limit of 8,196 bits for any integer subjected to primality testing. This threshold derives from the maximum safe RSA key size (16,384 bits), halved to account for the prime factors.
The patch relies on the getLength() method to evaluate the integer size prior to executing the Miller-Rabin iterations. The following code block demonstrates the patched logic introduced in the 3.x branch.
function isPrime($t = false) {
$length = $this->getLength();
// Cap at 8196 bits (derived from max RSA key size 16384/2)
if ($length > 8196) {
throw new \RuntimeException("Primality testing is not supported for numbers larger than 8196 bits ($length)");
}
// ... expensive Miller-Rabin logic proceeds only if under limit
}A significant discrepancy exists in how the legacy 1.x and 2.x branches implement this patch. Instead of throwing a fatal \RuntimeException, the backported patches utilize the PHP user_error() function. By default, user_error() emits an E_USER_NOTICE and permits execution to continue.
Unless the host application explicitly registers a custom error handler via set_error_handler() to trap E_USER_NOTICE emissions, the vulnerability remains exploitable on the 1.x and 2.x branches. The library generates a notice in the server logs but subsequently proceeds directly into the unbounded primality test, failing to mitigate the computational exhaustion.
Exploiting this vulnerability requires the attacker to submit a malformed DER-encoded X.509 certificate to an application endpoint that utilizes phpseclib for certificate processing. No authentication or privileged access is required to transmit the payload. The attacker merely requires a functional application feature that invokes the X509::loadX509() and X509::getPublicKey() methods.
The malicious certificate must specify the id-ecPublicKey Object Identifier (1.2.840.10045.2.1) and utilize explicit ECParameters. The attacker populates the field prime $p$ within the ASN.1 structure with an artificially large integer, frequently exceeding 100,000 bits.
use phpseclib3\File\X509;
$cert = file_get_contents('mal-cert-01.der');
$x509 = new X509();
$x509->loadX509($cert);
$x509->getPublicKey(); // Triggers continuous CPU executionExecution of the getPublicKey() method triggers the vulnerability synchronously. The targeted PHP process enters a continuous loop executing modular exponentiation. The process consumes 100% of a single CPU core and halts further execution until the server hardware or an operating system timeout terminates the process.
The vulnerability carries a CVSS v3.1 base score of 7.5, reflecting a high severity impact strictly limited to system availability. The attack vector is completely network-based and demands low complexity from the adversary. Successful exploitation requires no elevated privileges or user interaction.
In a production environment running PHP-FPM or similar worker pool architectures, this flaw enables asymmetric resource exhaustion. An attacker transmitting a minimal payload forces the server to allocate maximum CPU resources to a single worker indefinitely. Sequential malicious requests rapidly exhaust the entire pool of available worker processes.
Once the worker pool depletes, the application cannot process legitimate traffic, resulting in a total denial of service. The application server returns HTTP 502 or 504 errors to all clients. The exploit operates silently at the process level without causing segmentation faults, making it difficult to detect through standard crash monitoring systems.
Organizations must upgrade phpseclib to versions 1.0.23, 2.0.47, or 3.0.36 to receive the length-validation guardrails. Software developers should prioritize migration to the 3.x branch. The 3.x branch correctly terminates execution by throwing a \RuntimeException when it encounters an oversized integer.
Applications constrained to the 1.x or 2.x branches require immediate configuration changes. Developers must implement a custom error handler using set_error_handler() to convert E_USER_NOTICE emissions into fatal exceptions. Failure to implement this handler nullifies the security benefits of the patch.
As a defense-in-depth measure, administrators should configure strict file size limits for any certificate upload functionality. Additionally, enforcing strict max_execution_time directives in php.ini ensures that stalled worker processes eventually terminate. While timeouts do not prevent the initial CPU spike, they prevent permanent worker pool exhaustion.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
phpseclib phpseclib | 1.x < 1.0.23 | 1.0.23 |
phpseclib phpseclib | 2.x < 2.0.47 | 2.0.47 |
phpseclib phpseclib | 3.x < 3.0.36 | 3.0.36 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 |
| Attack Vector | Network |
| CVSS v3.1 Score | 7.5 (High) |
| EPSS Score | 0.00204 (42.24%) |
| Impact | Denial of Service (CPU Exhaustion) |
| Exploit Status | Proof of Concept |
| CISA KEV | No |
Uncontrolled Resource Consumption
CVE-2026-69252 represents a missing authorization check (CWE-862) in the files API route (`/api/v1/files`) of Flowise, a drag-and-drop user interface for building LLM flows. Prior to version 3.1.3, an authenticated API key or user could list, access, and delete files across arbitrary workspaces inside an organization, completely bypassing workspace logical boundaries.
A comprehensive technical analysis of CVE-2026-45584, a high-severity heap-based buffer overflow in Microsoft Defender's QEX parsing logic. The vulnerability resides within mpengine.dll and allows unauthenticated remote code execution or denial of service when processing crafted archives designed to trigger threat remediation and QEX history logging.
A medium-severity vulnerability in Undici's retry interceptor causes body-length mismatches with the Content-Length header during HTTP 206 response resumption. Forwarding these inconsistent headers downstream leads to HTTP response desynchronization, connection hangs, or potential protocol smuggling.
CVE-2026-16729 (GHSA-v3r7-h72x-cjcm) is a medium-severity cookie attribute injection vulnerability in Undici's web-compliant cookie utility module. Due to insufficient validation of domain parameters and raw attributes in the unparsed options array, arbitrary attributes like SameSite, HttpOnly, and Secure can be injected. This allows attackers to bypass CSRF protections, strip security flags, or override intended cookie behaviors when applications pass user-controlled values to these properties.
An interpretation conflict (CWE-436) in the cache interceptor of the undici HTTP client for Node.js causes whitespace-padded Cache-Control directives to be parsed incorrectly, leading to shared cache pollution and the unauthorized disclosure of sensitive, private, or authenticated user information (CWE-524).
CVE-2026-15157 details an improper neutralization of CRLF sequences ('CRLF Injection') within undici, a widely used Node.js HTTP/1.1 client. The vulnerability is triggered when processing request bodies that exhibit a duck-typed blob-like interface. When an application accepts untrusted data and assigns it to the .type property of such an object without setting an explicit Content-Type on the request, undici appends the value directly to the outgoing headers array without validating it against control characters. This allows remote attackers to inject carriage return and line feed sequences, culminating in arbitrary header injection, HTTP response splitting, or HTTP request smuggling.