May 6, 2026·6 min read·10 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