Vulnerability DatabaseGHSA-wwcr-82mc-w3pw

GHSA-wwcr-82mc-w3pw: 
PHP vulnerability analysis and mitigation

Impact

RSACrypt::decryptWithRSAOAEP(), where the RSA-OAEP and RSA-OAEP-256 key encryption algorithms (and the experimental RSA-OAEP-384 and RSA-OAEP-512) end, did not require the JWE Encrypted Key to be a single RSAES-OAEP ciphertext. It split the value into blocks of the modulus length, decrypted each block with the private key and returned the concatenation of the plaintexts; only the total length was checked afterwards, against the CEK size of the enc header parameter. RSAES-OAEP decryption takes exactly one ciphertext of the modulus length, and the RSA1_5 path of the same class already enforced it. Anyone holding the recipient's public key can build blocks that decrypt to bytes of their choice, and place the encrypted key of a captured JWE among them. AES-CBC-HMAC content encryption takes the first half of the CEK as the HMAC key and checks the tag before anything else: with such an enc, the attacker chooses the whole HMAC key but one byte, which comes from the captured CEK. If the application reveals whether a token was decrypted, the attacker finds that byte with at most 65,536 tokens, then the next ones, and finally reads the content of the captured JWE. With RSA-OAEP-256, a captured A256GCM token and A256CBC-HS512 accepted by the application, the 32-byte CEK was recovered with about a million tokens and the captured payload decrypted with it. The same loop has two more effects:

  • blocks can be added to the encrypted key of a valid JWE without the token being rejected, which defeats a replay cache or a deny list keyed on the serialized token;
  • one compact token costs one private key operation per block: 1.3 s for a 342 kB token with GMP and 1.8 s for a 7 kB token with BCMath, against 2 ms and 90 ms for a genuine token.

Affected configurations

Applications that decrypt JWEs with RSA-OAEP or RSA-OAEP-256, or with the experimental RSA-OAEP-384 and RSA-OAEP-512. The key recovery also requires that the application accepts an AES-CBC-HMAC content encryption algorithm whose HMAC key is at least as long as the CEK of the captured token minus one byte: A256CBC-HS512 for 32-byte CEKs (A256GCM, A128CBC-HS256), A128CBC-HS256 or A192CBC-HS384 for 16- or 24-byte CEKs. Tokens encrypted with A192CBC-HS384 or A256CBC-HS512 are out of reach. The attacker needs the recipient's public key, a copy of the target JWE and a way to tell a decrypted token from a rejected one. Applications that accept only AES-GCM content encryption are exposed to the malleability of the encrypted key and to the per-block cost, not to the key recovery. RSA1_5 is not affected. Every release is affected: the loop dates from the initial commit.

Patches

RSA-OAEP decryption now handles a single block of the length of the modulus. An encrypted key longer than the modulus is rejected before any private key operation, with the same RuntimeException as any other invalid encrypted key. On encryption, the CEK is encrypted as a single block and is no longer split over several. 3.4.13 is the last release of the 3.x line, which has reached its end of life. Users of 3.x should plan the move to 4.x. Compatibility. Tokens from conforming senders are decrypted as before. Three cases change:

  • a CEK that does not fit in one RSA-OAEP block now raises InvalidArgumentException("Message too long") on encryption. This only happens with keys shorter than 2048 bits, for example RSA-OAEP-256 with a 1024-bit key and A256CBC-HS512 (62 bytes fit, 64 are needed), or the experimental RSA-OAEP-384 with a 1024-bit key and a CEK of more than 30 bytes. The tokens previously produced that way had an encrypted key of several blocks, which other implementations do not decrypt and which is no longer decrypted either;
  • an encrypted key shorter than the modulus is still decrypted, as before: once left-padded with zero bytes, it is a single block. Conforming senders always produce the full length; a shorter key comes from a sender that strips leading zero bytes. It is deprecated in 4.3.0 and will be rejected in 5.0.0;
  • an empty encrypted key is rejected with a RuntimeException instead of a PHP warning followed by a TypeError.

Workarounds

Until you upgrade, do not accept the AES-CBC-HMAC content encryption algorithms next to RSA-OAEP for decryption, or reject a token whose encrypted key is longer than the RSA modulus before decrypting it. Limiting the size of the tokens you accept bounds the per-block cost.

References

  • RFC 8017, section 7.1.2 (RSAES-OAEP-DECRYPT), step 1.b
  • RFC 7518, sections 4.3 (Key Encryption with RSAES OAEP) and 5.2.2.1 (AES_CBC_HMAC_SHA2)
  • GHSA-5739-39v2-5754, the decryption oracle of RSA1_5

Credits

Reported by Anthropic's OSS Scanner (ANT-2026-18B9GZYU).


Source: NVD

Related PHP vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-wwq7-mh3q-hwrhHIGH8.2
  • PHP logoPHP
  • web-token/jwt-framework
NoYesNov 08, 2026
GHSA-jgv7-g4jg-6hqvHIGH8.2
  • PHP logoPHP
  • web-token/jwt-framework
NoYesNov 08, 2026
GHSA-jc6j-46g2-xwqcHIGH8.2
  • PHP logoPHP
  • web-token/jwt-framework
NoYesNov 08, 2026
GHSA-96f8-m4jr-72xjHIGH8.2
  • PHP logoPHP
  • web-token/jwt-framework
NoYesNov 08, 2026
GHSA-wwcr-82mc-w3pwMEDIUM6.3
  • PHP logoPHP
  • web-token/jwt-framework
NoYesNov 08, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Additional Wiz resources

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management