Aller au contenu

PD-251 — Revue Sécurité

Résumé

Critère Statut
Forbidden patterns
Injection SQL
Auth/Authz
Fuite données
Validation ⚠️

Verdict : ❌ NON_CONFORME

Raison principale : plusieurs vecteurs d'attaque applicatifs reproductibles (IDOR/absence d'authorization fine, absence de rate limiting sur opérations critiques, contrôle append-only DB non démontré par migration, et transition d'état non journalisée de manière strictement préalable).

Barrières primaires identifiées

Barrière Composant Atténuation
HSM PKCS#11 (signature) IntegrityJournalService, ForensicSnapshotServiceImpl, IncidentReportService Limite la falsification cryptographique des preuves lorsque HSM disponible
Requêtes SQL paramétrées DataSource.query(..., [params]) dans guards/services/processors Réduit fortement le risque d'injection SQL sur entrées utilisateur
Verrou distribué Redis (SET NX PX) PeriodicRunProcessor, ReconciliationProcessor Empêche l'exécution concurrente du même type d'opération
Guard JWT global controller IntegrityController (@UseGuards(JwtAuthGuard)) Exige une authentification avant accès aux endpoints integrity

Note defense-in-depth : ces barrières n'atténuent pas l'absence de contrôle d'autorisation objet (ownership/tenant) sur les endpoints de lecture d'incident, ni l'absence de limitation de débit sur déclenchements manuels.

Audit des forbidden patterns

Pattern interdit Recherché Trouvé
Ajouter un état enum hors machine ArchiveIntegrityState + ALLOWED_TRANSITIONS ✅ (non trouvé)
Schéma hors vault_integrity (entités PD-251) @Entity(... schema: 'vault_integrity') ✅ (non trouvé)
Math.random() pour identifiants Recherche usages ID ✅ (non trouvé)
Transition sortante depuis état terminal ArchiveStateMachineService.transition ✅ (bloqué)
UPDATE/DELETE journal applicatif services/repositories ✅ (non trouvé dans code applicatif)
Trigger append-only journal effectivement déployé migration 1740800000000-PD-251-CreateIntegritySchema.ts ❌ (fichier vide, garantie DB non démontrée)
Transition sans journal préalable ArchiveStateMachineService.transition ❌ (journal écrit post-commit)

Tentatives de bypass

Attaque Résultat Commentaire
Injection SQL via archiveId="'; DROP TABLE--" sur endpoints UUID Bloqué ParseUUIDPipe stoppe l'entrée, et SQL paramétré côté query
Bypass auth sans JWT sur /integrity/* Bloqué JwtAuthGuard au niveau contrôleur
Accès incident d'une archive tierce avec JWT valide d'un autre user Réussi Aucun contrôle ownership/tenant explicite dans getIncidents/getLatestReport
DoS logique via spam POST /integrity/runs Réussi partiellement Lock Redis évite concurrence d'exécution, mais pas flood de soumissions; pas de ThrottlerGuard
Tampering journal par UPDATE/DELETE SQL Potentiellement possible Trigger append-only requis par contrat mais migration fournie est vide

Vulnérabilités identifiées

ID Description Gravité Fichier
S-01 IDOR / Broken Object Authorization: tout utilisateur authentifié peut lire incidents/snapshots/tentatives d'une archive arbitraire via UUID (GET /integrity/archives/:archiveId/incidents, GET /integrity/archives/:archiveId/latest-report). Aucun check owner/tenant/rôle sur ces endpoints. MAJEUR src/modules/integrity/controllers/integrity.controller.ts
S-02 Action sensible sans autorisation forte: POST /integrity/runs accessible à tout JWT authentifié, sans rôle ops/admin ni scope dédié. Permet déclenchement d'opérations lourdes et création de bruit d'audit. MAJEUR src/modules/integrity/controllers/integrity.controller.ts
S-03 Absence de rate limiting sur opérations critiques (contrat SEC-02): aucun ThrottlerGuard visible sur POST /integrity/runs (et aucun endpoint restore/reconciliation côté API montré avec throttling). Attaque: flood de requêtes authentifiées => saturation BullMQ/Redis/DB. MAJEUR src/modules/integrity/controllers/integrity.controller.ts, src/modules/integrity/integrity.module.ts
S-04 Contrôle append-only DB non prouvé/déployé: migration de création du schéma intégrité vide. Sans trigger SQL anti UPDATE/DELETE sur integrity_journal_entries, l'invariant d'immutabilité probatoire peut être contourné si compte DB compromis. MAJEUR src/database/migrations/1740800000000-PD-251-CreateIntegritySchema.ts
S-05 Violation contractuelle de séquencement journal/transition: transition d'état committée puis journalisation ensuite. Si échec journal (panne DB partielle, quota, table lock), transition sans trace append-only signée. MAJEUR src/modules/integrity/services/archive-state-machine.service.ts
S-06 Exposition de données de preuve à large périmètre: endpoint incidents retourne expectedHashSha3, observedHashSha3, références d'artefacts et historique de restauration sans filtrage de rôle. Augmente surface d'énumération et intelligence d'attaque. RESERVE src/modules/integrity/controllers/integrity.controller.ts, src/modules/integrity/dto/incident-response.dto.ts
S-07 Validation incomplète des bornes runtime: validateRunParams() ne borne pas timeoutSeconds contrairement au contrat global de bornes. Risque de run excessif si branché sur overrides API futurs. MINEUR src/modules/integrity/services/integrity-config-validator.service.ts

Détails d'exploitation (vecteurs concrets)

  • S-01 (IDOR):
  • Précondition: JWT valide utilisateur A.
  • Payload: GET /integrity/archives/<uuid_archive_B>/incidents.
  • Impact: lecture de métadonnées d'incident d'un autre propriétaire (état, hashes de preuve, snapshots, tentatives).
  • S-02/S-03 (abuse opérationnel):
  • Précondition: JWT valide non privilégié.
  • Payload: rafale POST /integrity/runs (ex. 200 req/min).
  • Impact: files de jobs gonflées, contention Redis/DB, dégradation service; lock Redis empêche concurrence d'exécution, mais pas la pression de soumission.
  • S-04 (tampering journal):
  • Précondition: accès SQL applicatif compromis ou insider DB.
  • Payload: UPDATE vault_integrity.integrity_journal_entries SET payload='{}' ... / DELETE ....
  • Impact: altération effaçable de la traçabilité probatoire si triggers absents en base.

Recommandations

  • Mettre un contrôle d'autorisation objet strict sur endpoints incidents/reports (owner match via RLS effective ou vérification explicite archive.owner_id == user.sub; rôle investigateur/admin pour consultation transverse).
  • Restreindre POST /integrity/runs à rôle dédié (INTEGRITY_INVESTIGATOR/ADMIN ou rôle ops distinct) et journaliser refus d'accès.
  • Ajouter rate limiting (ThrottlerGuard) sur endpoints critiques selon contrat (scope userId+IP, bornes opsRateLimit).
  • Implémenter la migration SQL PD-251: schéma, tables, index, triggers anti UPDATE/DELETE sur journal, et tests d'intégration PostgreSQL réels prouvant l'immutabilité.
  • Rendre la transition d'état atomique avec la trace (transaction unique avec insertion journal append-only préalable/inline, ou pattern outbox probatoire avec garantie de non-perte prouvée en test crash).
  • Réduire la surface de fuite des DTO incidents (masquage hashes/références pour rôles non-investigation; réponse minimale pour owner standard).