Aller au contenu

PD-276 — Revue Sécurité

Résumé

Critère Statut
Forbidden patterns ⅚ conformes (1 réserve)
Timing attacks Partiellement conforme
Zero-knowledge Non conforme (ambiguïté architecturale majeure)
Key material safety Partiellement conforme
Validation Non conforme

Verdict : NON_CONFORME

Audit des forbidden patterns

Pattern interdit Recherché Trouvé
Dépendance argon2 native Imports/usage natif Non trouvé dans extraits
Import crypto.hash/pbkdf2 pbkdf2, crypto.hash Non trouvé
Buffer.equals() pour tags Comparaison tags Non trouvé (timingSafeEqual utilisé)
K_master_user clé HMAC directe createHmac(..., kMasterUser) Non trouvé (HKDF intermédiaire)
Logger de K_binding/metadata_tag Logs sensibles Non trouvé
Math.random() Génération aléa Non trouvé
Injection log via metadata (pattern risqué connexe) Interpolation champs non-sanitized Trouvé (verifyTagOrThrow)

Tentatives de bypass

Attaque Résultat Commentaire
Timing attack Réussite partielle (oracle) timingSafeEqual est bon, mais retour anticipé si longueur tag ≠ 32 (false immédiat) crée un oracle de format/longueur.
Bypass validation Argon2id Réussite validateParams ne vérifie pas type numérique entier/safe integer. NaN, chaînes non numériques, voire valeurs exotiques peuvent contourner </> (comparaisons fausses).
Fuite K_binding Échec Bonne pratique: kBinding.fill(0) dans finally.
Canonical confusion Réussite conditionnelle Séparateur NUL seul: si un champ contient , ambiguïté de frontières possible (collision de concaténation inter-champs).
Violation Zero-Knowledge Réussite/confirmée Le backend dérive K_binding depuis K_master_user (hkdfService.deriveKey(...)). En tension directe avec INV-276-01 si interprété strictement.
Injection métadonnées Réussite logger.warn logge envelopeType et deviceId non neutralisés (CRLF/log forging possible).
Config mutation Réussite conditionnelle getConfig() expose la référence ARGON2_CONFIG; sans freeze runtime, mutation possible ailleurs.

Vulnérabilités identifiées

ID Description Gravité Fichier
VULN-276-01 Validation numérique incomplète (pas de Number.isFinite / entier / safe integer), bypass possible des bornes contractuelles Haute argon2.service.ts
VULN-276-02 Concaténation canonique avec séparateur NUL non échappé/encodé: confusion de champs possible si entrée contient Haute metadata-binding.service.ts
VULN-276-03 Violation potentielle du modèle zero-knowledge: dérivation HKDF côté backend Critique (si INV-276-01 strict) metadata-binding.service.ts
VULN-276-04 Injection de logs via champs metadata non sanitizés (envelopeType, deviceId) Moyenne metadata-binding.service.ts
VULN-276-05 Configuration exposée mutable (getConfig retourne l’objet source) Moyenne argon2.service.ts
VULN-276-06 Oracle de format (retour anticipé sur longueur tag invalide) Faible metadata-binding.service.ts

Recommandations

  • Renforcer validateParams: rejeter tout sauf Number.isFinite(value) && Number.isSafeInteger(value); vérifier explicitement type===2, hashLength===32, memory>=65536, iterations>=3, parallelism>=4.
  • Rendre la validation atomique et stricte sur le schéma DTO (class-validator + transformation contrôlée), puis revalider côté service.
  • Canonicaliser de façon non ambiguë: encodage TLV/length-prefix par champ (ex: len||value) au lieu de séparateur NUL seul; interdire en entrée si format actuel conservé.
  • Neutraliser les logs (replace(/[ ]/g, '_')) ou logger en structure JSON avec escaping.
  • Immutabiliser la config runtime (Object.freeze profond) et retourner une copie défensive dans getConfig().
  • Clarifier l’architecture INV-276-01 vs INV-276-06: si zero-knowledge strict, déplacer calcul/verification tag côté client ou enclave dédiée; sinon documenter explicitement l’exception et ses contrôles compensatoires.
  • Uniformiser le timing de verifyTag (même chemin de code pour longueurs invalides) pour réduire les oracles observables.