PHP JWT Library: RSA1_5 (RSAES-PKCS1-v1_5) decryption lacks implicit rejection, exposing a Bleichenbacher/Marvin padding oracle
The advisory, in context
Impact
RSACrypt::decryptWithRSA15() (used by the RSA1_5 key-encryption algorithm) implements RSAES-PKCS1-v1_5 decryption by inspecting the padding after RSADP and throwing InvalidArgumentException as soon as the padding is malformed. It does not implement the implicit-rejection countermeasure required by RFC 3447 §7.2.2 / RFC 8017 §7.1.2 (return a deterministic pseudo-random value of the expected length on padding failure and let the downstream step fail uniformly).
From a JWE caller this yields a Bleichenbacher/Marvin padding oracle: an attacker submitting adaptively crafted encrypted_key values can distinguish (a) padding rejected, (b) padding valid but wrong CEK length, and (c) padding valid and full AEAD executed — even though JWEDecrypter returns the same false in all cases — because each path performs a measurably different amount of work, amplifiable by enlarging the ciphertext (CWE-208 timing side channel). Enough adaptive queries can recover the wrapped CEK.
Affected configurations
Applications that register RSA1_5 in their decryption AlgorithmManager and hold an RSA private key.
Patches
PKCS#1 v1.5 decryption now performs implicit rejection: on invalid padding (or unexpected recovered length) it returns a random CEK of the expected size selected in constant time, so the full content-decryption (AEAD) step always runs and fails uniformly, removing the observable difference between padding-valid and padding-invalid ciphertexts. Users are still strongly encouraged to migrate to RSA-OAEP.
Workarounds
Prefer RSA-OAEP/RSA-OAEP-256; do not enable RSA1_5 for untrusted tokens.
References
- RFC 3447 §7.2.2 / RFC 8017 §7.1.2
- Bleichenbacher (1998); Marvin attack
- CWE-208: Observable Timing Discrepancy
Résolution
Un correctif a été préparé sur une branche dédiée basée sur 3.4.x, avec des tests anti-régression dédiés (fork privé temporaire de cette advisory, PR #1).
RSA1_5 — déchiffrement PKCS#1 v1.5 avec implicit rejection en temps constant (RFC 3447 §7.2.2) : un padding invalide n'est plus distinguable d'un padding valide, neutralisant l'oracle Bleichenbacher.
Validation : php -l OK, PHPUnit vert, aucune nouvelle erreur PHPStan introduite (différentiel nul vs 3.4.x), aucun commentaire ajouté dans le code source. Après merge, cascade prévue 3.4.x → 4.0.x → 4.1.x.
Affected packages
Start with the recorded fix for your release branch. Check your installed version and test compatibility before upgrading. Fixing this advisory does not rule out other vulnerabilities in the release.
Earlier releases before 3.4.10
Fixed in 3.4.10
16 explicitly affected versions
3.3.0, 3.3.1, 3.3.2, 3.3.3, 3.3.4, 3.3.5, 3.4.0, 3.4.1, 3.4.2, 3.4.3, 3.4.4, 3.4.5, 3.4.6, 3.4.7, 3.4.8, 3.4.9
View affected-version evidence
{
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.4.10"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"3.3.0",
"3.3.1",
"3.3.2",
"3.3.3",
"3.3.4",
"3.3.5",
"3.4.0",
"3.4.1",
"3.4.2",
"3.4.3",
"3.4.4",
"3.4.5",
"3.4.6",
"3.4.7",
"3.4.8",
"3.4.9"
]
}From 4.0.0 before 4.0.7
Fixed in 4.0.7
7 explicitly affected versions
4.0.0, 4.0.1, 4.0.2, 4.0.3, 4.0.4, 4.0.5, 4.0.6
View affected-version evidence
{
"ranges": [
{
"events": [
{
"introduced": "4.0.0"
},
{
"fixed": "4.0.7"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"4.0.0",
"4.0.1",
"4.0.2",
"4.0.3",
"4.0.4",
"4.0.5",
"4.0.6"
]
}From 4.1.0 before 4.1.7
Fixed in 4.1.7
7 explicitly affected versions
4.1.0, 4.1.1, 4.1.2, 4.1.3, 4.1.4, 4.1.5, 4.1.6
View affected-version evidence
{
"ranges": [
{
"events": [
{
"introduced": "4.1.0"
},
{
"fixed": "4.1.7"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"4.1.0",
"4.1.1",
"4.1.2",
"4.1.3",
"4.1.4",
"4.1.5",
"4.1.6"
]
}