{"id":"GHSA-3prj-6hqw-cm82","title":"PHP JWT Library: PBES2-HS*+A*KW unwrap accepts an unbounded p2c iteration count, enabling CPU-amplification denial of service","summary":"PHP JWT Library: PBES2-HS*+A*KW unwrap accepts an unbounded p2c iteration count, enabling CPU-amplification denial of service","severity":"high","cwe":["CWE-400","CWE-770"],"vendor":"web-token","product":"web-token/jwt-library","affected":["web-token/jwt-library < 3.4.10","web-token/jwt-framework <= 4.1.6","web-token/jwt-library >= 4.0.0, < 4.0.7","web-token/jwt-library >= 4.1.0, < 4.1.7"],"patched":["web-token/jwt-library 3.4.10","web-token/jwt-library 4.0.7","web-token/jwt-library 4.1.7"],"published":"2026-06-18","updated":"2026-06-18","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-3prj-6hqw-cm82","references":[{"url":"https://github.com/web-token/jwt-framework/security/advisories/GHSA-3prj-6hqw-cm82"},{"url":"https://github.com/FriendsOfPHP/security-advisories/blob/master/web-token/jwt-library/GHSA-3prj-6hqw-cm82.yaml"},{"url":"https://github.com/advisories/GHSA-3prj-6hqw-cm82"}],"tags":["ghsa","composer"],"ingestedAt":"2026-06-19T03:39:00.765Z","ecosystem":"composer","slug":"GHSA-3prj-6hqw-cm82","body":"## Overview\n\n### Impact\n\nWhen a JWE uses a password-based key-encryption algorithm (`PBES2-HS256+A128KW`, `PBES2-HS384+A192KW`, `PBES2-HS512+A256KW`), `PBES2AESKW::unwrapKey()` reads the `p2c` (PBKDF2 iteration count) parameter directly from the attacker-controlled JOSE header and passes it to `hash_pbkdf2()` with **no upper bound**. The only validation performed (`checkHeaderAdditionalParameters()`) was `is_int($p2c) && $p2c > 0`.\n\nAn unauthenticated attacker can craft a single JWE whose protected header sets a very large `p2c` (e.g. `100_000_000` ≈ 87 s of CPU, or `PHP_INT_MAX`), forcing a worker to spend an arbitrary amount of CPU inside PBKDF2 **before** the key unwrap can even fail. The decrypter swallows the eventual exception, so the attacker pays almost nothing while the server burns CPU. JSON General serialization (multiple recipients) and multi-key JWKSets multiply the cost. This is a classic uncontrolled-resource-consumption (CWE-400) denial of service.\n\n### Affected configurations\n\nApplications that register any `PBES2-HS*+A*KW` algorithm in their decryption `AlgorithmManager`.\n\n### Patches\n\n`PBES2AESKW` now enforces a configurable maximum iteration count (`DEFAULT_MAX_COUNT = 1_000_000`, well above realistic legitimate values which are a few thousand) in `checkHeaderAdditionalParameters()`, before any PBKDF2 computation. The bound is exposed as a constructor argument so operators can tune it.\n\n### Workarounds\n\nBefore upgrading: validate/limit the `p2c` header with a custom header checker, or do not enable PBES2 algorithms for untrusted tokens.\n\n### References\n\n- RFC 7518 §4.8 (PBES2)\n- CWE-400: Uncontrolled Resource Consumption\n\n## Résolution\n\nUn 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).\n\n**PBES2** — `PBES2AESKW::unwrapKey()` borne désormais le paramètre `p2c` (constante `DEFAULT_MAX_COUNT = 1_000_000`, configurable via le constructeur) avant tout appel à `hash_pbkdf2()`, empêchant l'amplification CPU (DoS).\n\n**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`.\n\n## Affected packages\n\n- `web-token/jwt-library < 3.4.10`\n- `web-token/jwt-framework <= 4.1.6`\n- `web-token/jwt-library >= 4.0.0, < 4.0.7`\n- `web-token/jwt-library >= 4.1.0, < 4.1.7`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `web-token/jwt-library 3.4.10`\n- `web-token/jwt-library 4.0.7`\n- `web-token/jwt-library 4.1.7`","depth":"twilight","depthScore":41,"depthScoreParts":{"impact":41.3,"likelihood":0,"exploitation":0,"ransomware":0},"changes":[]}