SchwachstellendatenbankGHSA-96f8-m4jr-72xj

GHSA-96f8-m4jr-72xj: 
PHP Schwachstellenanalyse und -minderung

Impact

RSAKey, which every RSA algorithm uses, accepted a modulus n and a public exponent e of any length. Two costs followed from it.

  1. RSA public operation in PHP. The PS256, PS384 and PS512 signature algorithms, and key encryption with RSA-OAEP, RSA-OAEP-256 and RSA1_5, compute the RSA public operation in PHP (RSAKey::exponentiate(), through brick/math) with n and e as given. The cost grows with the length of e times the square of the length of n, with or without the GMP extension.
  2. Base conversions without GMP. RSAKey converted the members of the key between base 16 and base 10 with brick/math, in its constructor and again in toPEM(), for every RSA algorithm, RS256/RS384/RS512 included. Without the GMP extension, the cost of these conversions grows roughly with the cube of the length of n in pure PHP, and with its square when only BCMath is available. It is paid before OpenSSL sees the key, so OpenSSL's own limits do not bound it. The library never takes an RSA key from a token on its own. Applications do, in standard protocols:
  • DPoP: the proof carries its public key in the jwk header and is verified with that key, before any authentication;
  • key proofs of OpenID for Verifiable Credential Issuance, and self-issued ID tokens;
  • keys registered by clients (private_key_jwt, signed request objects), and encryption towards a key registered by a client. An application that verifies such tokens, or encrypts to a key chosen by a peer, can be made to spend seconds of CPU per token. In the DPoP case, no authentication is needed. Nothing is disclosed and no token is accepted: the impact is a denial of service. A single gmp_powm() call is not interrupted by max_execution_time. Measurements, PHP 8.5, brick/math 1.0:
  • PS256, with GMP, compact JWS verified against the key of its own jwk header, with n and e of equal length: 0.16 s for a 5 kB token, 0.46 s for 7.7 kB, 0.97 s for 10 kB and 2.8 s for 15 kB, against 0.0002 s for a genuine proof made with an RSA-2048 key. With BCMath and without GMP, a 2.7 kB token costs 2.7 s.
  • RSA-OAEP-256 encryption, with GMP, to a key with 2048-byte n and e: about 1 s.
  • RS256, one verify() call with a wrong signature and an ordinary exponent: | Length of n | Neither GMP nor BCMath | BCMath only | GMP | |---|---|---|---| | 256 bytes (RSA-2048) | 0.75 s | 0.03 s | 0.01 s | | 512 bytes | 4.1 s | 0.04 s | 0.01 s | | 1024 bytes | 29.5 s | 0.11 s | 0.01 s | | 8192 bytes | not measured | 6.3 s | 0.01 s | Tokens sent in a header are limited by the header size the front end accepts (8 kB by default with nginx and Apache), and tokens sent in a request body by the body size.

Affected configurations

  • Verification of PS256, PS384 and PS512 signatures with a key chosen by the sender of the token, and encryption with RSA-OAEP, RSA-OAEP-256 or RSA1_5 to a key chosen by a peer: with or without GMP.
  • Any RSA algorithm with a key chosen by someone else, on PHP without the GMP extension. Not affected: keys configured by the application itself; RS256, RS384 and RS512 with GMP, since OpenSSL computes them and refuses moduli over 16384 bits and public exponents over 64 bits when the modulus is over 3072 bits. Every release is affected.

Patches

Fixed in 3.4.13, 4.0.9, 4.1.11 and 4.2.6. 3.4.13 is the last release of the 3.4 branch. RSAKey now measures n and e from their bytes, leading zero bytes aside, before converting anything. Like OpenSSL, it refuses:

  • a modulus longer than 16384 bits;
  • a public exponent longer than the modulus;
  • a public exponent longer than 64 bits when the modulus is longer than 3072 bits. Every RSA algorithm goes through this check, so a key beyond these limits is refused before any computation. The 10 kB PS256 proof above is now rejected in a few milliseconds. toPEM() writes the key from the bytes of its members, and the big integers are only built when an operation computed in PHP needs them. RS256, RS384 and RS512 therefore convert nothing: with a 16384-bit key, an RS256 verification takes about 20 ms in pure PHP. Without GMP, PS256, PS384, PS512, RSA-OAEP, RSA-OAEP-256 and RSA1_5 still compute the RSA operation in PHP in these releases. The limits make that cost finite, but not small:
  • up to about 1.2 s per operation with BCMath;
  • about 5.5 s in pure PHP for a PS256 verification with an ordinary RSA-2048 key. Install the GMP extension if your application verifies PS* signatures or encrypts to keys chosen by others. The next minor release, 4.3.0, computes the RSA public operation with OpenSSL: PS* verification, and RSA-OAEP and RSA1_5 encryption. Its cost then no longer depends on GMP. Compatibility. Every key that OpenSSL accepts is still accepted, and toPEM() returns the same PEM byte for byte. Three behaviours change:
  • every RSA algorithm now refuses a key beyond the limits with an InvalidArgumentException. Before, RS256, RS384 and RS512 verification returned false for such a key, because OpenSSL refused it, and PS256, PS384, PS512, RSA-OAEP, RSA-OAEP-256 and RSA1_5 computed with it;
  • only direct calls to the algorithm classes see that exception. JWSVerifier and JWEDecrypter catch it and try the next key, so such tokens are rejected as before;
  • a key whose n or e is empty raises an InvalidArgumentException instead of brick/math's NumberFormatException.

Workarounds

Upgrade. Install the GMP extension as well if your application verifies PS256, PS384 or PS512 signatures, or encrypts with RSA-OAEP, RSA-OAEP-256 or RSA1_5 to keys chosen by others. Until you upgrade, check every RSA key received from a peer before using it. Refuse a modulus longer than 4096 bits or a public exponent other than 65537, or do not accept PS256, PS384 and PS512 with such keys. Limiting the size of request headers and bodies also limits the size of the keys a token can carry.

References

  • RFC 9449 (DPoP), section 4.2
  • OpenSSL limits on RSA public keys: OPENSSL_RSA_MAX_MODULUS_BITS (16384), and OPENSSL_RSA_MAX_PUBEXP_BITS (64) above OPENSSL_RSA_SMALL_MODULUS (3072 bits)

Credits

Reported by Anthropic's OSS Scanner (ANT-2026-9EHC9J38 and ANT-2026-WD2XF3WZ).


Quelle: NVD

Verwandte Themen PHP Schwachstellen:

CVE-ID

Schwere

Punktzahl

Technologieen

Bauteilname

CISA KEV-Exploit

Hat Lösung

Veröffentlichungsdatum

GHSA-wwq7-mh3q-hwrhHIGH8.2
  • PHP logoPHP
  • web-token/jwt-framework
NeinJaNov 08, 2026
GHSA-jgv7-g4jg-6hqvHIGH8.2
  • PHP logoPHP
  • web-token/jwt-framework
NeinJaNov 08, 2026
GHSA-jc6j-46g2-xwqcHIGH8.2
  • PHP logoPHP
  • web-token/jwt-framework
NeinJaNov 08, 2026
GHSA-wwcr-82mc-w3pwMEDIUM6.3
  • PHP logoPHP
  • web-token/jwt-framework
NeinJaNov 08, 2026
GHSA-44cp-9fph-8778MEDIUMN/A
  • PHP logoPHP
  • austintoddj/canvas
NeinJaNov 08, 2026

Kostenlose Verwundbarkeitsbewertung

Benchmark für Ihre Cloud-Sicherheitslage

Bewerten Sie Ihre Cloudsicherheitspraktiken in 9 Sicherheitsbereichen, um Ihr Risikoniveau zu bewerten und Schwachstellen in Ihren Verteidigungen zu identifizieren.

Anforderungsbewertung

Zusätzliche Wiz-Ressourcen

Eine personalisierte Demo anfordern

Sind Sie bereit, Wiz in Aktion zu sehen?

"Die beste Benutzererfahrung, die ich je gesehen habe, bietet vollständige Transparenz für Cloud-Workloads."
David EstlickCISO
"„Wiz bietet eine zentrale Oberfläche, um zu sehen, was in unseren Cloud-Umgebungen vor sich geht.“ "
Adam FletcherSicherheitsbeauftragter
"„Wir wissen, dass, wenn Wiz etwas als kritisch identifiziert, es auch wirklich kritisch ist.“"
Greg PoniatowskiLeiter Bedrohungs- und Schwachstellenmanagement