🔐 Passkeys : rĂ©volution passwordless ou nouvelle illusion de sĂ©curitĂ© ?

Les mots de passe ont vĂ©cu, vive le passwordless đŸ€” — mais pas encore totalement enterrĂ©s. Entre rĂ©utilisation, phishing, fuites massives et usagers fatiguĂ©s, la gestion des identifiants est devenue la premiĂšre cause opĂ©rationnelle de compromission. Sans compter les MFA Fatigue : ou comment cliquer frĂ©nĂ©tiquement sur “Accepter” est devenu la nouvelle faille. C’est dans ce contexte que les passkeys émergent : une façon d’authentifier un utilisateur sans jamais transmettre ni stocker un secret rĂ©utilisable cĂŽtĂ© serveur, grĂące Ă  la cryptographie Ă  clĂ© publique. Les gĂ©ants et la communautĂ© standards poussent fort (FIDO, W3C/WebAuthn) : l’idĂ©e est simple sur le papier et sĂ©duisante en pratique — moins d’emails « mot de passe oubliĂ© », moins de phishing rĂ©ussi, moins de tickets helpdesk. FIDO Alliance

Mais attention : « sans mot de passe » ne veut pas dire « sans risques ». Le passage de la thĂ©orie (clĂ© publique/privĂ©e) Ă  la production dans des environnements hĂ©tĂ©rogĂšnes (desktop + mobile + applis legacy + reverse proxies + SSO fĂ©dĂ©rĂ©) introduit toute une sĂ©rie de surfaces d’attaque et de piĂšges opĂ©rationnels. On y revient plus bas, avec des scĂ©narios concrets. 

Sommaire
  1. đŸ§© Qu’est-ce qu’une passkey ?
  2. 🔑 Principe PKI & challenge-response (explication accessible, sans Diffie-Hellman)
    1. 🔐 FIDO / WebAuthn — ce que les devs doivent vraiment savoir
    2. 1) Inscription (registration) — checklist serveur
  3. ✅ Les 19 points de validation WebAuthn (registration)
    1. 🧭 Recommandations pratiques (checklist courte pour devs)
      1. En bref (piquant mais franc)
  4. 🧹 ScĂ©nario d’attaque — compromission d’un magasin de certificats (attestation)
    1. 🔎 Contexte rapide
    2. 🎯 Objectif de l’attaquant
    3. 🔱 DĂ©roulĂ© dĂ©taillĂ© de l’attaque (Ă©tapes)
    4. đŸ’„ ConsĂ©quences pratiques
    5. đŸ•”ïž Signaux & indicateurs de compromission (logiques Ă  surveiller)
    6. đŸ›Ąïž Mesures d’attĂ©nuation & bonnes pratiques (opĂ©rationnelles + techniques)
      1. A. Gouvernance & politique d’attestation
      2. B. Renforcer la chaüne d’attestation
      3. C. Durcissement cÎté client & OS
      4. D. Harden serveur & logging
      5. E. Processus de récupération & IR
      6. 🔚 Conclusion piquante
  5. 🌐đŸȘŸ WebAuthn & navigateurs — pourquoi le client web reste le maillon fragile
    1. 🔓 Extensions malveillantes et profils compromis
    2. 🧯 WebUSB, WebHID, WebBluetooth — trop de portes ouvertes
    3. ⚔ XSS + WebAuthn = mauvais mĂ©lange
    4. 🔁 Attaques de relay / clickjacking & user gestures
    5. 🧠 La confiance dans le navigateur — et pourquoi c’est un problùme d’infra
    6. ✅ Recommandations de base cĂŽtĂ© produit & infra
    7. đŸ—ïž Le problĂšme de fond : l’entreprise n’est pas Google
    8. 1. Active Directory & Azure AD
    9. 2. ERP & applis legacy
    10. 3. VPN & accÚs réseau
  6. 🧰 Bonnes pratiques d’implĂ©mentation (sans paillettes)
    1. 🔑 CĂŽtĂ© technique — devs & infra
    2. đŸ§‘â€đŸ’» CĂŽtĂ© utilisateurs — l’UX
    3. 🏱 CĂŽtĂ© organisation — l’entreprise
    4. ⚠ Les « don’t »
    5. ✅ RĂ©sumĂ© (utile)
    6. đŸ•·ïž Cas concret : attaque navigateur + WebAuthn (XSS et extension malveillante)
      1. 🎭 Le dĂ©cor
      2. đŸ§© Étape 1 : l’injection XSS
      3. đŸ§© Étape 2 : manipulation DOM et UX
      4. đŸ§© Étape 3 : extension malveillante (option bonus)
      5. 🎯 RĂ©sultat
      6. 🔧 Mitigation (ou comment Ă©viter de se faire avoir)
      7. 💡 Morale piquante
  7. đŸ€š Conclusion — « T’es vraiment sĂ»r, on y va ? »
    1. 🎯 Le mot de la fin
  8. ANNEXES
    1. Playbook IR : Compromission du magasin d’attestation (PKI / CA / FIDO metadata)
      1. 1) Activation & premiùres minutes (0–60 min)
      2. 2) Investigation rapide (60–240 min)
      3. 3) Containment (4–24 h)
      4. 4) Eradication & remediation (24h–7 jours)
      5. 5) Recovery & re-enrollment (J+3 → J+30)
      6. 6) Communication — templates (rapide & efficace)
      7. 7) Monitoring & détection post-incident (alerts à déployer)
      8. 8) RÎles & responsabilités (RACI bref)
      9. 9) Post-mortem & actions long terme (30–90 jours)
      10. Conclusion — la morale amùre
    2. 🎉 Cadeau : script PowerShell pour dĂ©tecter et lister certificats racine rĂ©cemment installĂ©s sur un parc.

đŸ§© Qu’est-ce qu’une passkey ?

Une passkey est, pour faire vite, un type de credential (identifiant cryptographique) basé sur le modÚle clé publique / clé privée. ConcrÚtement :

  • L’appareil de l’utilisateur crĂ©e localement une paire de clĂ©s.
  • La clĂ© publique est envoyĂ©e et stockĂ©e sur le serveur du service (le « relying party »).
  • La clĂ© privĂ©e reste sur l’appareil (smartphone, PC, clĂ© matĂ©rielle). Elle ne sort jamais.
    Lors de l’authentification, le serveur envoie un challenge (un petit paquet unique) que l’appareil signe avec la clĂ© privĂ©e. Le serveur vĂ©rifie la signature avec la clĂ© publique qu’il a stockĂ©e. Si la signature colle, l’utilisateur est authentifiĂ© — sans mot de passe Ă  taper, et sans secret cĂŽtĂ© serveur pouvant ĂȘtre rĂ©utilisĂ© sur d’autres sites. Ce mĂ©canisme est la base de WebAuthn/FIDO.

🔑 Principe PKI & challenge-response (explication accessible, sans Diffie-Hellman)

On va le dire simplement, étape par étape (pour un novice technique) :

  1. Enregistrement (inscription)
    • L’utilisateur clique « Enregistrer un passkey ». Sa machine gĂ©nĂšre une paire de clĂ©s (privĂ©e + publique).
    • La clĂ© publique est envoyĂ©e au serveur, avec des mĂ©tadonnĂ©es (type d’authenticator, attestation si disponible). Le serveur stocke la clĂ© publique associĂ©e Ă  l’utilisateur.
  2. Authentification (login)
    • Le serveur gĂ©nĂšre un challenge (nombre alĂ©atoire unique) et l’envoie au client.
    • Le client demande Ă  l’authenticator local (puce TPM / enclave/clĂ© USB) de signer ce challenge avec la clĂ© privĂ©e. L’utilisateur valide localement (PIN ou biomĂ©trie).
    • Le client renvoie la signature au serveur. Le serveur vĂ©rifie la signature avec la clĂ© publique stockĂ©e. Si OK → accĂšs accordĂ©.

Pourquoi c’est fort : la clĂ© privĂ©e ne transite jamais, elle n’est pas copiable (sauf si l’appareil est compromis ou si l’authenticator le permet). MĂȘme si un pirate vole la base de donnĂ©es du serveur, il n’obtient que des clĂ©s publiques — inutile pour se faire passer pour l’utilisateur. passkeycentral.org


🔐 FIDO / WebAuthn — ce que les devs doivent vraiment savoir

WebAuthn (la couche standardisĂ©e cĂŽtĂ© web) + FIDO (les specs d’authenticators) forment la brique qui rend les passkeys utilisables par les navigateurs et les systĂšmes. C’est beau sur le papier : un navigateur parle Ă  l’authenticator (TPM, secure enclave, clĂ© USB), l’authenticator signe un challenge, et le serveur vĂ©rifie la signature. Mais pour qu’un dĂ©ploiement soit sĂ»r, le serveur doit faire un tas de vĂ©rifications — pas juste “vĂ©rifier la signature” et hop. La spec dĂ©finit une procĂ©dure dĂ©taillĂ©e (la fameuse procĂ©dure en ~19 points pour la validation d’enregistrement) que tout dev sĂ©rieux doit implĂ©menter ou dĂ©lĂ©guer Ă  une librairie fiable.


đŸ§Ÿ Le flux d’implĂ©mentation cĂŽtĂ© serveur (vue pragmatique)

1) Inscription (registration) — checklist serveur

Lorsqu’un client envoie la PublicKeyCredential aprĂšs navigator.credentials.create(), cĂŽtĂ© serveur il faut valider scrupuleusement :

  • VĂ©rifier que le RP ID (relying party id) correspond bien Ă  votre domaine / scope attendu.
  • VĂ©rifier l’origin dans le clientDataJSON (mĂȘme hĂŽte + protocol) : c’est la barriĂšre anti-phishing cĂŽtĂ© web.
  • VĂ©rifier que le challenge retournĂ© est bien celui que le serveur a Ă©mis (liĂ© Ă  la session utilisateur).
  • Parser attestationObject (CBOR), extraire authenticatorData et la clĂ© publique (COSE format) — attention au dĂ©codage base64url / CBOR.
  • VĂ©rifier le format d’attestation (fmt) et valider l’attestation en consĂ©quence (packed, tpm, fido-u2f, android-key, android-safetynet, apple, none). Selon le format, il faudra vĂ©rifier des certificats, signer des chaĂźnes, ou accepter l’absence d’attestation.
  • ContrĂŽler le signatureCounter initial (doit exister) et enregistrer la clĂ© publique + credential ID + counter + algorithme.
  • Respecter la politique d’attestation choisie : accepter les attestations « none » (anonymes) ou exiger une attestation vĂ©rifiable via la FIDO Metadata Service.
  • Valider flags uv (user verification) / up (user presence) selon votre requirement (MFA, passwordless strict, etc.).
  • GĂ©rer erreurs et rejets : logging, rĂ©ponse claire pour l’UX cĂŽtĂ© client.
    Ces Ă©tapes sont celles formalisĂ©es dans le spec — ne pas les faire, c’est s’exposer Ă  des contournements. Google for Developers+1

🔎 Attestation : utile mais dangereux — et pourquoi tu dois dĂ©cider d’une politique

L’attestation est la preuve que l’authenticator est bien fabriquĂ© par un fournisseur (attestation certificate chain). C’est utile pour dĂ©tecter des authenticators compromis ou non-conformes, mais :

  • Les formats sont variĂ©s : packed, tpm, fido-u2f, android-key, android-safetynet, apple, none. Chacun a une vĂ©rification diffĂ©rente. MDN Web Docs
  • Exiger l’attestation « full trust » (chaĂźne CA vĂ©rifiĂ©e) augmente la sĂ©curitĂ©, mais rĂ©duit l’interopĂ©rabilitĂ© (beaucoup d’authenticators vont renvoyer none ou packed sans chaĂźne publiquement vĂ©rifiable).
  • Il existe des services et listes (FIDO Metadata Service) pour vĂ©rifier les identifiants d’authenticators. Pour les environnements sensibles, activer la vĂ©rification metadata est recommandĂ© ; en revanche, c’est une gestion opĂ©rationnelle en plus.
    Bref : dĂ©cide si tu veux contrĂŽler le modĂšle d’authenticator, ou faire confiance au device & UX. Les deux approches ont un coĂ»t. W3C

✅ VĂ©rification d’assertion (login) — les checks impĂ©ratifs

Lors d’un login (assertion), le serveur doit :

  1. Récupérer le credentialId envoyé et retrouver la clé publique + counter associée.
  2. VĂ©rifier que l’origin et le rpId matchent.
  3. Vérifier que le challenge dans clientDataJSON correspond à celui émis par le serveur.
  4. VĂ©rifier la signature de l’authenticatorData || clientDataHash avec la clĂ© publique (algorithme COSE attendu).
  5. VĂ©rifier les flags up (user presence) et uv (user verification) selon la politique de l’app.
  6. VĂ©rifier que la signatureCounter est bien supĂ©rieure au compteur stockĂ© (dĂ©tection de clones/devices clonĂ©s). Si non — alerter / rĂ©voquer.
  7. Mettre à jour le compteur stocké.
  8. Rejeter si quoi que ce soit ne colle (mauvais algorithme, challenge mismatch, signature invalide, rpId mismatch, origin mismatch).
    Ces Ă©tapes (et d’autres variantes) sont listĂ©es par la spec et implĂ©mentĂ©es par des bibliothĂšques matures (Duo Labs, Yubico, SimpleWebAuthn, WebAuthn4J, etc.). DĂ©lĂ©guer Ă  une librairie testĂ©e rĂ©duit drastiquement les piĂšges.

đŸ§© Les piĂšges techniques qui vont te pourrir la vie (et comment les Ă©viter)

  • CBOR / COSE parsing : erreurs de parsing = vulnĂ©rabilitĂ©. Utiliser des libs Ă©prouvĂ©es.
  • Origin vs RP ID : si tu te trompes, tu acceptes des assertions depuis d’autres domaines (phishing). Toujours vĂ©rifier strictement l’origin.
  • Algorithmes supportĂ©s : n’accepte pas aveuglĂ©ment toutes les clefs/algos ; impose ECDSA P-256 (ES256) ou Ă©quivalents robustes.
  • Gestion du credentialId : doit ĂȘtre indexable et unique — attention aux collisions et formats (binary blob).
  • Compteurs : les authenticators logiciels peuvent ne pas incrĂ©menter correctement — politique de tolĂ©rance Ă  prĂ©voir mais aussi processus d’investigation.
  • Attestation CA compromise / magasin de certificats : si une CA d’attestation est compromise, tu dois pouvoir rĂ©voquer les attestations et forcer rĂ©enregistrement. (On dĂ©taille le scĂ©nario magasin de certificats dans la section attaque.) developers.yubico.com

đŸ§Ÿ Le “19 points” — que faut-il retenir ?

Le WebAuthn spec dĂ©crit une procĂ©dure en ~19 points pour valider l’enregistrement (registration) afin d’éviter que l’implĂ©mentation fasse un raccourci dĂ©lĂ©tĂšre. Ce n’est pas une check-list marketing : c’est la garantie que l’on n’a pas laissĂ© une faille triviale (mismatch origin, challenge, parsing CBOR, algos, attestation, flags
). Si tu veux ĂȘtre tranquille, implĂ©mente la procĂ©dure complĂšte ou utilise une librairie qui la suit Ă  la lettre — l’écosystĂšme a dĂ©jĂ  des implĂ©mentations robustes (Duo Labs, Yubico, SimpleWebAuthn, WebAuthn4J). Guide to Web Authentication

✅ Les 19 points de validation WebAuthn (registration)

  1. Recevoir la réponse client : clientDataJSON + attestationObject.
  2. VĂ©rifier la structure : s’assurer que clientDataJSON est bien JSON et que attestationObject est un CBOR valide.
  3. Extraire clientData et vérifier :
    • que type = "webauthn.create".
    • que le challenge correspond Ă  celui gĂ©nĂ©rĂ© par le serveur.
    • que l’origin est bien celui attendu (ex. https://tondomaine.com).
    • que tokenBinding (si prĂ©sent) est cohĂ©rent.
  4. Hacher clientDataJSON pour obtenir clientDataHash.
  5. Extraire authenticatorData de l’attestationObject.
  6. Vérifier le RP ID hash dans authenticatorData correspond au hash SHA-256 du RP ID attendu (ton domaine).
  7. Vérifier les flags dans authenticatorData :
    • UP (user present) = 1 (l’utilisateur a interagi).
    • UV (user verified) selon ta politique (PIN, biomĂ©trie).
  8. Extraire le compteur (signCount).
  9. Extraire la clé publique du attestedCredentialData (format COSE).
  10. Vérifier que le credentialId est unique (non déjà enregistré dans ta base).
  11. Vérifier que la clé publique est dans un algorithme supporté (ex. ES256).
  12. VĂ©rifier l’attestation : format (packed, tpm, fido-u2f, android-key, etc.).
  13. Valider la signature de l’attestation : signature faite avec la clĂ© d’attestation sur (authenticatorData + clientDataHash).
  14. VĂ©rifier la chaĂźne de certificats d’attestation (si applicable).
  15. Vérifier les métadonnées (via FIDO Metadata Service ou politique interne) : AAGUID, algorithme, validité.
  16. VĂ©rifier les extensions (si prĂ©sentes) : que leur traitement est conforme et qu’elles ne violent pas ta politique.
  17. Appliquer ta politique d’attestation : accepter ou refuser selon l’attestation (none, cert validĂ©, etc.).
  18. En cas de succÚs : stocker credentialId, clé publique, compteur initial, AAGUID, algorithme, flags, et attestation metadata.
  19. En cas d’échec : rejeter la crĂ©ation et loguer l’erreur pour analyse.

🧭 Recommandations pratiques (checklist courte pour devs)

  • N’ignore jamais clientDataJSON.origin et le RP ID.
  • Utilise une lib WebAuthn mature plutĂŽt que du code maison (par ex. WebAuthn4J, simplewebauthn, duo-labs).
  • DĂ©cide ta politique d’attestation (accept/reject none, metadata service?).
  • Ne stocke que : credentialId, clĂ© publique (COSE), algorithme, signatureCounter, date d’émission, attestation metadata.
  • Prends en charge la portabilité (passkey sync via vendor cloud) mais documente les risques et offre des alternatives (clĂ©s matĂ©rielles).
  • PrĂ©vois un processus de rĂ©cupĂ©ration sĂ©curisĂ© (par ex. rĂ©enregistrement avec MFA humaine, ou workflows identifiĂ©s), pas un reset trivial par helpdesk.
  • Ajoute du monitoring sur Ă©checs d’assertions, mismatch de counter, tentatives rĂ©pĂ©tĂ©es — ces signaux prĂ©cĂšdent souvent une attaque ciblĂ©e.

En bref (piquant mais franc)

WebAuthn/FIDO ne sont pas un gadget marketing Ă  cocher. C’est une techno solide, mais exigeante cĂŽtĂ© implĂ©mentation et gouvernance. Si tu traites ça comme « un simple remplacement de mot de passe » et que tu skips la validation, l’attestation ou la gestion des origins, tu vas juste dĂ©placer la surface d’attaque — et probablement te retrouver avec des erreurs sournoises en prod. Fais-le propre, confie ça Ă  des bibliothĂšques Ă©prouvĂ©es, et prĂ©pare-toi Ă  gĂ©rer attestation, policies, et rĂ©cupĂ©ration utilisateurs. Le diable est dans les 19 points. 


🧹 ScĂ©nario d’attaque — compromission d’un magasin de certificats (attestation)

🔎 Contexte rapide

La valeur ajoutĂ©e des passkeys/FIDO passe aussi par l’attestation : un authenticator peut fournir une preuve (certificat d’attestation) liant la clĂ© publique créée Ă  un fabricant/produit. Les serveurs peuvent utiliser ces attestations pour dĂ©cider s’ils acceptent ou non un authenticator. Mais si le magasin de certificats d’attestation (la chaĂźne de confiance, ou la PKI qui signe les attestations) est compromis — ou si un CA/Issuer est frauduleusement Ă©mis — on transfĂšre la confiance vers un composant qui peut ĂȘtre trahi. Bref : on a dĂ©placĂ© la cible.


🎯 Objectif de l’attaquant

CrĂ©er/prĂ©senter des attestations apparemment valides (ou corrompre la vĂ©rification) pour faire accepter des authenticators contrĂŽlĂ©s par l’attaquant, permettant la connexion sans possĂ©der les comptes lĂ©gitimes (ou pour faciliter d’autres escroqueries/implantations).


🔱 DĂ©roulĂ© dĂ©taillĂ© de l’attaque (Ă©tapes)

  1. Compromission initiale
    • Voie A : compromission d’un CA d’attestation (ex : vol de clĂ© privĂ©e d’un Ă©metteur d’attestation).
    • Voie B : compromission d’un service intermĂ©diaire (magasin de certificats interne, FIDO Metadata Service mal protĂ©gĂ©, ou systĂšme d’ingestion d’attestations).
    • Voie C : social engineering + installation d’un certificat racine local (Windows) sur des postes ciblĂ©s (deux clics « Installer ce certificat »).
  2. Fabrication d’attestations malveillantes
    • L’attaquant utilise la clĂ© d’attestation volĂ©e (ou un CA compromis) pour signer des attestationObjects qui contiennent des clĂ©s publiques contrĂŽlĂ©es par l’attaquant.
    • Ces attestations paraissent conformes au format attendu (fmt = packed|tpm|fido-u2f|...) et contiennent des chaĂźnes de certif valides ou faussĂ©es.
  3. EnrĂŽlement / propagation
    • L’attaquant enregistre massivement des credentials « lĂ©gitimes » sur des services ciblĂ©s (inscriptions automatisĂ©es via API ou via sessions de phishing ciblĂ©es).
    • Si le serveur exige ou vĂ©rifie l’attestation, celle-ci passe la validation (CA compromise), donc le credential est acceptĂ©.
  4. Évasion & persistance
    • Les credentials malveillants sont utilisĂ©s pour authentifier, contourner MFA, ou crĂ©er des sessions persistantes.
    • Alternativement, l’attaquant installe des backdoors cĂŽtĂ© serveur (modifie vĂ©rifications, bypass origin checks) pour faciliter l’usage ultĂ©rieur.
  5. Escalade et exploitation
    • Avec accĂšs, l’attaquant peut demander rĂ©initialisation d’accĂšs, escroquerie interne, exfiltration, ou mouvement latĂ©ral vers des systĂšmes sensibles.

đŸ’„ ConsĂ©quences pratiques

  • Comptes compromis malgrĂ© l’usage de passkeys « hardware » ou « verified ».
  • Perte de confiance dans la chaĂźne d’attestation ; nĂ©cessitĂ© d’un forcé rĂ©enregistrement massif.
  • Impact fort si l’attaque touche un provider cloud (synchronisation passkey compromise).
  • CoĂ»t opĂ©rationnel Ă©norme (revocation, forensics, communication, obligations lĂ©gales).

đŸ•”ïž Signaux & indicateurs de compromission (logiques Ă  surveiller)

  • Pics d’enregistrement : vagues anormales d’enrĂŽlements d’authenticators avec le mĂȘme AAGUID / mĂȘme chaĂźne d’attestation.
  • Multiples credentialId associĂ©s Ă  un mĂȘme attestation certificate serial.
  • SignatureCounter qui n’augmente pas correctement (ou qui augmente bizarrement) — clones ou authenticators non conformes.
  • Origin / RP ID mismatches dans logs de clientDataJSON (tentatives d’inscription via des origins inattendues).
  • Échecs d’attestation parsing suivis d’acceptations manuelles ou bypass cĂŽtĂ© infra.
  • ÉvĂ©nements SIEM : connexions rĂ©ussies hors horaires, IPs gĂ©o-anormales, nouveaux devices non inventoriĂ©s.

Exemples de requĂȘtes SIEM (pseudo) :

  • SELECT count(*) FROM webauthn_registrations WHERE aaguid = 'XXXX' AND timestamp > now()-1h GROUP BY serial
  • search logs where event='assertion' and signatureCounter <= previous_counter

đŸ›Ąïž Mesures d’attĂ©nuation & bonnes pratiques (opĂ©rationnelles + techniques)

A. Gouvernance & politique d’attestation

  • Politique claire : dĂ©finir si tu acceptes fmt=none ou si tu exiges attestation CA vĂ©rifiable. Pour les comptes sensibles, n’accepte que les attestations vĂ©rifiĂ©es via FIDO MDS.
  • Inventory AAGUID : maintenir une liste blanche d’AAGUIDs approuvĂ©s (pour comptes sensibles).
  • Rotation & rĂ©vo : prĂ©parer un plan de rĂ©vocation d’attestations (et d’IDs compromis) — pas trivial mais indispensable.

B. Renforcer la chaüne d’attestation

  • ProtĂ©ger les PKI/CA : HSM pour les clĂ©s d’attestation, MFA forte pour accĂšs aux CA, audits rĂ©guliers, journaux immuables.
  • VĂ©rifier la Metadata FIDO : utiliser la FIDO Metadata Service pour valider les authenticators et dĂ©tecter anomalies.
  • Ne pas faire confiance aveuglĂ©ment : cross-check du cert chain, vĂ©rifier les EK certs TPM/nonce si possible.

C. Durcissement cÎté client & OS

  • Éduquer utilisateurs : bloquer l’installation de certificats racine par utilisateurs non-admin ; renforcer politiques Windows GPO.
  • Bloquer WebUSB / extensions non-trusted : restreindre extensions navigateur via listes blanches, dĂ©sactiver WebUSB si non nĂ©cessaire.

D. Harden serveur & logging

  • Valider strictement origin & RP ID ; refuser tout mismatch.
  • VĂ©rifier challenge/session binding pour Ă©viter replay.
  • Stocker counters et monitorer ; alerter sur anomalies.
  • Ne pas dĂ©lĂ©guer l’attestation aveuglĂ©ment : stocker la trace complĂšte de l’attestation pour forensics.

E. Processus de récupération & IR

  • Processus de rĂ©cupĂ©ration robustes (rĂ©enregistrement avec 2 facteurs physiques, vĂ©rification manuelle).
  • Playbook IR : isoler, rĂ©voquer credentials identifiĂ©s, forensics sur CA/metadata, communication aux tiers, forcing re-enroll.
  • Table-top exercises sur scĂ©narios de CA compromise.

🔚 Conclusion piquante

La passkey rend la vie plus dure aux phishing-kickers et aux failles classiques de mot de passe. Mais si tu confies la vĂ©rification Ă  un magasin de certificats ou Ă  une chaĂźne d’attestation non-protĂ©gĂ©e, tu donnes Ă  un attaquant une clĂ© maĂźtresse morale : il pourra fabriquer l’apparence de lĂ©gitimitĂ©. En clair : la passkey te protĂšge d’un certain nombre d’attaques, pas d’une mauvaise gouvernance de la PKI. La sĂ©curitĂ© rĂ©elle vient d’un triptyque : implĂ©mentation correcte (19 points), chaĂźne d’attestation bien protĂ©gĂ©e, et procĂ©dures de rĂ©ponse testĂ©es


🌐đŸȘŸ WebAuthn & navigateurs — pourquoi le client web reste le maillon fragile

Les passkeys sont superbes
 jusqu’à ce que le navigateur fasse la connerie. WebAuthn repose sur un axiome : le navigateur fait bien son boulot (vĂ©rifie l’origin, relaye proprement les challenges, n’expose pas la clĂ© privĂ©e). Malheureusement, dans la vraie vie, le navigateur n’est pas un bunker inviolable — il a des extensions, des APIs riches (WebUSB, WebAuthn, WebCrypto, etc.), et un DOM qui peut ĂȘtre manipulĂ© par du code injectĂ©. Voici oĂč ça coince, et comment s’en prĂ©munir.

🔓 Extensions malveillantes et profils compromis

Les extensions de navigateurs sont une porte trop souvent laissĂ©e ouverte. Une extension malveillante ayant des permissions Ă©tendues (activeTab, webRequest, file access) peut injecter du JS dans des pages, modifier le DOM, ou intercepter des rĂ©ponses. RĂ©sultat : un script malveillant pourrait lancer des flows d’enregistrement/connexion (navigator.credentials.create() / navigator.credentials.get()) en contexte utilisateur trompĂ©, forcer des prompts, ou exfiltrer des mĂ©tadonnĂ©es.
MĂȘme si la clĂ© privĂ©e ne sort jamais, une extension qui simule l’UX (popup biomĂ©trique factice) peut conduire Ă  des actions d’acceptation par l’utilisateur. Bref : les extensions, c’est la roulette russe.

Mitigation : force de la whitelist d’extensions via MDM/GPO, audit pĂ©riodique des extensions en production, et blocage des extensions non-essentielles pour les comptes Ă  privilĂšges.

🧯 WebUSB, WebHID, WebBluetooth — trop de portes ouvertes

Les APIs modernes (WebUSB / WebHID / WebBluetooth) permettent aux pages d’interagir avec du hardware. Combinaison dangereuse : une page piĂ©gĂ©e qui accĂšde Ă  un authenticator mal configurĂ© (ou Ă  un dongle USB mal protĂ©gĂ©) peut tenter des opĂ©rations non voulues. MĂȘme si WebAuthn reste soumis Ă  origin checks et user gestures, ces APIs augmentent la surface d’attaque.

Mitigation : désactiver WebUSB/ WebHID dans les environnements sensibles via politiques navigateur, ou restreindre par extension.

⚔ XSS + WebAuthn = mauvais mĂ©lange

Le modĂšle WebAuthn s’appuie fortement sur la confiance dans le DOM : si un site est vulnĂ©rable Ă  une XSS, un attaquant peut injecter un script qui dĂ©clenche l’authentification ou l’enregistrement, redirige les challenges, ou manipule l’UI pour tromper l’utilisateur. MĂȘme si clientDataJSON.origin protĂšge contre le phishing cross-site, la XSS intervient sur le mĂȘme origin, donc l’origin check devient inutile : tu es sur la mĂȘme origine, mais contrĂŽlĂ©e par l’attaquant.
En clair : WebAuthn arrĂȘte les phishers, pas un site lui-mĂȘme compromis.

Mitigation : renforcer CSP, audits XSS fréquents, SRI pour les scripts tiers, scanner automatisé des payloads XSS.

🔁 Attaques de relay / clickjacking & user gestures

WebAuthn exige souvent une interaction utilisateur. Les attaquants inventent des moyens de la simuler ou de la tromper (clickjacking, overlays, social engineering). Les techniques de relay (Evilginx-like) restent plus difficiles avec passkeys mais des variantes existent, notamment si la chaine d’attestation ou la logique serveur est faible.

Mitigation : SameSite cookies stricts, frame-ancestors CSP, protection anti-clickjacking, UI nette et non-spoofable cÎté OS (préférer prompts natifs).

🧠 La confiance dans le navigateur — et pourquoi c’est un problùme d’infra

WebAuthn ne remplace pas la nĂ©cessitĂ© d’un navigateur sĂ©curisĂ© : profils sync (sauvegarde de session), extensions, ou installations de certificats racine (via clics utilisateurs) peuvent compromettre la chaĂźne. Si un profil Chrome/Edge est sync et compromis, l’attaquant gagne un vecteur d’accĂšs. Les entreprises doivent considĂ©rer le navigateur comme une piĂšce d’infra critique Ă  durcir.

Mitigation infra : dĂ©sactiver/sĂ©curiser le sync de profils pour comptes sensibles, contrĂŽler GPO/MDM, forcer mises Ă  jour et appliquer policies d’extensions.


✅ Recommandations de base cĂŽtĂ© produit & infra

  • Bloquer ou limiter les extensions pour comptes sensibles.
  • DĂ©sactiver WebUSB/HID si inutiles.
  • Mettre CSP strict et scanner XSS en continu.
  • Forcer userVerification (uv) pour opĂ©rations sensibles (exiger biomĂ©trie/PIN).
  • Afficher un prompt OS-natif non spoofable pour les actions critiques (hardware auth).
  • Monitorer les enrollments anormaux et les patterns d’extensions.

🔄 InteropĂ©rabilitĂ© & migration dans les environnements legacy

đŸ—ïž Le problĂšme de fond : l’entreprise n’est pas Google

Oui, les passkeys sont jolies quand tu as un écosystÚme flambant neuf et que tout ton SI tourne en SaaS moderne compatible WebAuthn. Dans la vraie vie, tu as :

  • un Active Directory qui traĂźne depuis Windows Server 2008,
  • un ERP (SAP, IBM i, AS/400) qui n’a jamais entendu parler de FIDO,
  • des applis maison qui s’authentifient encore en LDAP simple bind (oui, en clair parfois),
  • et des VPN SSL oĂč on a bricolĂ© du SAML avec des bouts de scotch.

Bref : implĂ©menter les passkeys ne veut pas dire « appuyer sur ON ». C’est une migration progressive, avec des couches qui doivent cohabiter.


đŸ§© Les couches de compatibilitĂ©

1. Active Directory & Azure AD

  • Azure AD (dĂ©sormais Entra ID) sait gĂ©rer les passkeys nativement, intĂ©grĂ©s Ă  FIDO2.
  • Mais ton AD on-prem ? LĂ , c’est du Kerberos/NTLM, pas de WebAuthn. Pour faire le pont, tu dois mettre un Identity Provider moderne (ADFS, Ping, Okta
) qui joue la traduction.
  • ConsĂ©quence : le vrai login AD classique (Ctrl+Alt+Del) continuera longtemps d’exiger mot de passe ou smartcard. Les passkeys viendront surtout pour les apps web fĂ©dĂ©rĂ©es.

2. ERP & applis legacy

  • SAP a introduit du support partiel (via SSO, SAML, OIDC).
  • IBM i / AS400 ? LĂ , tu oublies WebAuthn natif. La seule option c’est un proxy d’authentification qui valide la passkey cĂŽtĂ© web et Ă©met un ticket interne (LDAP bind, EIM, etc.).
  • Pour les applis maison, il faudra patcher : ajouter un module OIDC / SAML qui sache dialoguer avec un IdP passkey-compatible.

3. VPN & accÚs réseau

  • Beaucoup de VPN (Cisco AnyConnect, Palo Alto, Fortinet) ajoutent petit Ă  petit du support FIDO2. Mais encore beaucoup reposent sur RADIUS + LDAP.
  • La migration passe par des proxies d’authentification ou par l’ajout d’une authentification adaptative : si passkey dispo → FIDO, sinon fallback mot de passe/MFA.

đŸ•žïž L’architecture hybride en pratique

En rĂ©alitĂ©, tu auras une cohabitation :

  • Des apps modernes → authentifiĂ©es 100% passkey via IdP.
  • Des systĂšmes legacy → authentifiĂ©es par translation (SAML/OIDC ↔ LDAP/Kerberos).
  • Des comptes admin/domain controllers → encore en smartcards ou mots de passe costauds (parce que FIDO2 n’est pas partout).

Donc non, on ne devient pas « passwordless » du jour au lendemain. On vit dans un patchwork.


⚠ Les piĂšges typiques

  1. Double UX : l’utilisateur doit parfois se connecter avec passkey, parfois encore avec mot de passe — rĂ©sultat : confusion + tickets helpdesk.
  2. Fallbacks mal gĂ©rĂ©s : si tu gardes le mot de passe comme « secours » mais qu’il est faible, tu as simplement dĂ©placĂ© le problĂšme.
  3. Licences & coĂ»ts IdP : beaucoup d’éditeurs font payer le support passkeys/FIDO comme un module premium.
  4. SĂ©curitĂ© de la translation : un proxy d’authentification mal configurĂ© devient la nouvelle « clĂ© de voĂ»te vulnĂ©rable ».
  5. Shadow IT : certains éditeurs SaaS non compatibles vont te forcer à garder les mots de passe, ce qui ruine la promesse « passwordless ».

đŸ› ïž Bonnes pratiques pour la migration

  • Cartographier les flux d’authentification actuels (AD, LDAP, SAML, OIDC, VPN, applis internes).
  • Prioriser : commencer par les apps web fĂ©dĂ©rĂ©es (portail RH, CRM, SharePoint Online).
  • Installer un IdP compatible FIDO2 qui sert de traducteur.
  • Planifier le fallback : smartcards matĂ©rielles pour les comptes sensibles, mots de passe robustes pour les apps legacy mais sous politique renforcĂ©e.
  • Former les utilisateurs : oui, il faudra encore leur dire « parfois passkey, parfois mot de passe », au moins au dĂ©but.
  • Surveiller : logs d’enrĂŽlement, anomalies, et flux hybrides.

🧠 Conclusion

Le marketing « passwordless » donne envie de croire que demain matin, tu te connectes partout avec ton empreinte digitale et basta. La rĂ©alitĂ©, c’est que ton vieux SAP ou ton AS/400 n’a aucune idĂ©e de ce qu’est une passkey — et qu’un proxy mal fichu vaut un mot de passe rĂ©utilisĂ©.
La migration est donc plus une cohabitation bordĂ©lique qu’une rĂ©volution instantanĂ©e. Les passkeys sont un outil puissant, mais elles ne font pas disparaĂźtre ton legacy d’un coup de baguette magique.


🧰 Bonnes pratiques d’implĂ©mentation (sans paillettes)

Mettre en place des passkeys, ce n’est pas un bouton magique « passwordless ». C’est un vrai chantier technique et organisationnel. Voici la checklist Ă  avoir sous la main avant de foncer tĂȘte baissĂ©e.


🔑 CĂŽtĂ© technique — devs & infra

  • Valide tout : respecte la procĂ©dure WebAuthn complĂšte (19 points de validation). Origin, rpId, challenge, algorithme, counters → pas d’approximation.
  • N’utilise pas du code maison : prends une librairie WebAuthn Ă©prouvĂ©e (ex. SimpleWebAuthn, WebAuthn4J, Duo-labs). Tu n’écris pas ton propre parseur CBOR Ă  3h du matin.
  • Algorithmes stricts : impose ES256 (P-256) et refuse le reste si tu n’as pas de cas d’usage spĂ©cifique.
  • Attestation policy : dĂ©cide si tu acceptes none ou si tu exiges une chaĂźne d’attestation vĂ©rifiĂ©e. Pour les comptes sensibles, whitelist d’AAGUID + vĂ©rif via FIDO Metadata Service.
  • Monitoring : logue tout (enrĂŽlements, assertions, mismatches, counters non incrĂ©mentĂ©s). Mets des alertes SIEM sur anomalies.
  • Fallback solide : pas un simple reset par helpdesk avec une question secrĂšte. Mets une procĂ©dure MFA manuelle, une preuve physique, ou une clĂ© matĂ©rielle alternative.

đŸ§‘â€đŸ’» CĂŽtĂ© utilisateurs — l’UX

  • Clarté : explique simplement Ă  quoi sert une passkey (un badge numĂ©rique qui reste dans ton appareil).
  • Multiples devices : documente le fonctionnement cloud sync (Apple iCloud, Google Password Manager, MS Authenticator). Si tu l’acceptes → assume la dĂ©pendance au vendor.
  • Process de perte : dis clairement « si tu perds ton tĂ©lĂ©phone, voici comment tu rĂ©cupĂšres ». Rien de pire qu’un utilisateur qui panique en croyant avoir perdu son job avec son smartphone.
  • Communication : prĂ©pare des guides avec captures d’écran pour chaque OS/navigateur (sinon ton support va te haĂŻr).

🏱 CĂŽtĂ© organisation — l’entreprise

  • Cartographie : liste toutes tes applis → lesquelles supportent WebAuthn, lesquelles sont legacy.
  • Priorisation : commence par les applis SaaS fĂ©dĂ©rĂ©es (Office 365, Salesforce, CRM) → ROI rapide.
  • Politiques d’accĂšs : impose passkeys pour les comptes sensibles (admins AD, comptes cloud).
  • MFA by design : la passkey est dĂ©jĂ  une MFA (facteur device + biomĂ©trie/PIN). Mais ne l’oublie pas pour les environnements oĂč tu gardes des mots de passe.
  • Shadow IT : surveille les applis tierces non compatibles qui vont forcer les utilisateurs Ă  garder des mots de passe.

⚠ Les « don’t »

  • ❌ Ne fais pas confiance au navigateur « par dĂ©faut » : configure CSP, bloque les extensions, durcis le poste client.
  • ❌ Ne pense pas que les passkeys suppriment tous les risques → elles rĂ©duisent phishing & vol de mots de passe, pas la compromission du navigateur ni la corruption du serveur.
  • ❌ Ne garde pas un mot de passe faible comme « secours ». C’est comme verrouiller ta porte blindĂ©e et laisser la clĂ© sous le paillasson.
  • ❌ N’ignore pas la gouvernance PKI → un magasin de certificats compromis annule tout le gain de sĂ©curitĂ©.

✅ RĂ©sumĂ© (utile)

Tu veux ĂȘtre « passwordless » ? Parfait. Mais sois prĂȘt Ă  :

  1. GĂ©rer une PKI et un IdP comme si ta vie en dĂ©pendait (parce que c’est un peu le cas).
  2. Former tes utilisateurs pour Ă©viter qu’ils fassent n’importe quoi.
  3. Accepter qu’un monde hybride passkeys + legacy va durer longtemps.
  4. Répondre à un incident PKI en mode pompier (et avoir un plan écrit, pas sur un post-it).

đŸ•·ïž Cas concret : attaque navigateur + WebAuthn (XSS et extension malveillante)

🎭 Le dĂ©cor

Imaginons une entreprise qui déploie fiÚrement les passkeys pour son portail RH. Tout est conforme : challenge signé, clé privée dans le TPM, origin check nickel.
Mais
 le navigateur des utilisateurs est Chrome/Edge avec :

  • des extensions non contrĂŽlĂ©es (ex. « gestionnaire de PDF » un peu louche),
  • un portail RH codĂ© vite-fait avec une faille XSS stockĂ©e (un champ « commentaire » non filtrĂ©).

đŸ§© Étape 1 : l’injection XSS

Un attaquant dĂ©pose un script malveillant dans le champ commentaire du portail RH. Lorsqu’un utilisateur lĂ©gitime ouvre la page, le script s’exĂ©cute dans le mĂȘme origin que le portail (https://rh.entreprise.com).

  • Du coup, le script peut appeler directement navigator.credentials.get() pour lancer un flux WebAuthn.
  • Le navigateur ne voit aucun problĂšme : origin valide, challenge renvoyĂ© par le serveur, tout semble lĂ©gitime.

đŸ§© Étape 2 : manipulation DOM et UX

Le script affiche un faux pop-up (« Votre session a expiré, reconnectez-vous »).
L’utilisateur clique, le navigateur demande la validation biomĂ©trique (empreinte, FaceID). L’utilisateur valide sans se poser de questions.
RĂ©sultat : l’attaquant rĂ©cupĂšre une assertion signĂ©e valide, qui peut ĂȘtre relayĂ©e vers son propre serveur (attaque de type credential relay).


đŸ§© Étape 3 : extension malveillante (option bonus)

Une extension installĂ©e par l’utilisateur (aprĂšs avoir cliquĂ© sur un joli bouton « installer ») peut aussi :

  • Intercepter ou modifier les rĂ©ponses du serveur.
  • Injecter son propre JavaScript sur toutes les pages RH.
  • Forcer l’appel à navigator.credentials.create() pour enregistrer une nouvelle clĂ© publique sous contrĂŽle de l’attaquant (si la logique serveur est trop laxiste sur l’attestation).

🎯 RĂ©sultat

  • L’attaquant a un accĂšs utilisateur lĂ©gitime, validĂ© par WebAuthn.
  • Le systĂšme a fait tout ce qu’il fallait, mais la faille venait du navigateur (XSS, extensions) et du site vulnĂ©rable.
  • La promesse « phishing-resistant » des passkeys est tenue
 sauf que ça n’empĂȘche pas le compromis cĂŽtĂ© clientou le code malicieux dans ton propre site.

🔧 Mitigation (ou comment Ă©viter de se faire avoir)

  • Durcissement appli web : CSP strict, nettoyage des entrĂ©es, XSS scanner, SRI sur scripts tiers.
  • Durcissement navigateur : bloquer les extensions non approuvĂ©es (GPO/MDM), dĂ©sactiver WebUSB/WebHID si inutile.
  • UX anti-spoofing : prĂ©fĂ©rer prompts natifs (Windows Hello, TouchID) qui s’affichent hors DOM, limitant les faux popups.
  • Monitoring : surveiller les enregistrements inattendus (navigator.credentials.create()), origins, et flux de relai.

💡 Morale piquante

Une passkey ne t’immunise pas contre ton propre JavaScript pourri ni contre une extension que ton utilisateur a installĂ©e aprĂšs avoir cliquĂ© sur « Recevoir mes horoscopes quotidiens ».
En bref : tu ne peux pas te cacher derriÚre WebAuthn si ton site est une passoire XSS ou si tu laisses tes navigateurs en mode « Far West ».


đŸ€š Conclusion — « T’es vraiment sĂ»r, on y va ? »

Alors, les passkeys, c’est la fin des mots de passe ? Oui
 et non.

  • Oui, parce que tu rĂ©duis drastiquement le phishing et le credential stuffing (adieu les « azerty123 » recyclĂ©s sur 12 sites).
  • Oui, parce que le support IT va moins se taper de tickets « j’ai oubliĂ© mon mot de passe ».
  • Oui, parce que c’est plus fluide pour l’utilisateur final (un clic, une empreinte, basta).

Mais.

  • Non, ça ne supprime pas le problĂšme des applis legacy qui vivent encore en LDAP simple bind.
  • Non, ça ne protĂšge pas ton infra si ton magasin de certificats ou ta PKI est compromis.
  • Non, ça n’empĂȘche pas un XSS bien placĂ© ou une extension malveillante de dĂ©tourner le flow cĂŽtĂ© navigateur.
  • Non, ça ne t’exonĂšre pas de gouvernance : politique claire, procĂ©dures de rĂ©enrĂŽlement, plan IR testĂ©.

En fait, les passkeys ne sont pas le Saint-Graal du “passwordless”, mais plutĂŽt une Ă©volution sĂ©rieuse du MFA. Elles rĂ©solvent un paquet de problĂšmes, mais elles en introduisent de nouveaux : dĂ©pendance aux gĂ©ants du cloud pour la synchro, complexitĂ© d’intĂ©gration dans ton SI legacy, gestion des fallback, et nĂ©cessitĂ© de durcir ton navigateur et ton code applicatif.


🎯 Le mot de la fin

Adopter les passkeys, c’est comme passer d’un cadenas en plastique Ă  une serrure Ă©lectronique biomĂ©trique : oui, c’est plus costaud, mais si tu laisses la fenĂȘtre ouverte (XSS, PKI mal gĂ©rĂ©e, utilisateurs crĂ©dules), tu invites quand mĂȘme le cambrioleur Ă  entrer.

Alors, t’es vraiment sĂ»r d’ĂȘtre « passwordless » ? Ou tu viens juste d’acheter une nouvelle illusion de sĂ©curitĂ© qui fera joli dans le rapport annuel ?


ANNEXES


Playbook IR : Compromission du magasin d’attestation (PKI / CA / FIDO metadata)

Isoler rapidement l’impact, identifier l’étendue (services / credentials affectĂ©s), empĂȘcher l’utilisation frauduleuse d’attestations malveillantes, restaurer la confiance et rĂ©-enrĂŽler de façon contrĂŽlĂ©e.


1) Activation & premiùres minutes (0–60 min)

Actions immédiates (qui, quoi) :

  • Qui : SOC lead / on-call IR lead (R), Head of Security (A), Infra ops, App owners, Legal, Comms (I/C).
  • Objectif : arrĂȘter l’hĂ©morragie, collecter preuves immuables, prĂ©server la chaĂźne de custody.

TĂąches urgentes :

  1. Isoler le(s) service(s) affecté(s) : mettre en mode maintenance / disable enrollment endpoints API publiques (e.g., /webauthn/register, /webauthn/assert).
  2. Activer journalisation complÚte (if not already): augmenter verbosité des logs WebAuthn, reverse proxies (NGINX/ALB), WAF, IdP/SSO logs.
  3. Collecter artefacts immuables : exporter snapshots des bases WebAuthn (credentialId, public key, attestationObject, aaguid, attestation cert chain, signatureCounter), export DB backups, capture memory on key servers if possible.
  4. Prendre images des serveurs/VMs et verrouiller accÚs administratif (change admin creds, block malicious sessions).
  5. Notifier legal / conformité si données à caractÚre personnel potentiellement impactées.

2) Investigation rapide (60–240 min)

Objectifs : confirmer compromission, scope, vecteur (CA private key leak, metadata poisoning, social install of root certs).

Checks techniques rapides :

  • Inspecter attestations rĂ©cemment acceptĂ©es : rechercher patterns (mĂȘme issuer serial, mĂȘmes AAGUIDs, mĂȘme subject CN).
  • VĂ©rifier FIDO MDS / metadata updates : timestamp/manifest rĂ©cents — anomalies de signature.
  • VĂ©rifier PKI / CA logs : accĂšs aux HSM, opĂ©rations de signing inhabituelles.
  • VĂ©rifier endpoints de provisioning : IPs clients, user agents, origins liĂ©s aux nouveaux enregistrements.

RequĂȘtes SIEM / Splunk (exemples) :

  • Splunk (pseudo) : index=webauthn sourcetype=registration | stats count by aaguid, attestation_cert_serial | where count > 10
  • ELK/Kibana (pseudo) : POST /webauthn/_search { "query": { "bool": { "must": [{"match":{"event":"register"}}, {"range":{"@timestamp":{"gte":"now-1h"}}}]}}}
  • Counter anomalies : index=webauthn event=assertion | timechart span=1h count by signatureCounter → alerte si pattern non-incrĂ©mental.

Forensics (Windows/Linux):

  • Windows: lister certificats racine utilisateur/local : certutil -viewstore -user Root / certutil -store My ; supprimer certificat racine malveillant : certutil -delstore Root "<SerialNumber>".
  • PowerShell: Get-ChildItem Cert:\LocalMachine\Root | Where-Object {$_.Thumbprint -eq "<thumbprint>"}
  • Linux: vĂ©rifier /etc/ssl/certs, openssl x509 -in cert.pem -noout -text pour inspecter CN/SNs.
  • DB dump: mysqldump --single-transaction --skip-lock-tables webauthn_db > dump.sql (preserve immutability, hash the dump).
  • Capture HTTP transactions (reverse-proxy logs): extract origins, user-agents, IPs.

3) Containment (4–24 h)

But : neutraliser l’usage des attestations compromises.

Actions techniques :

  • Blacklister AAGUIDs / attestation cert serials dans ta DB d’enrĂŽlements et dans la validation : toute assertion provenant d’une credential avec ces AAGUID/serial → reject.
  • DĂ©sactiver l’acceptation d’attestations signĂ©es par la CA compromise (update validate-attestation logic).
  • Forcer rejection des nouveaux enregistrements: fermer endpoint register public, autoriser uniquement via change control pour le rĂ©enrĂŽlement contrĂŽlĂ©.
  • Bloquer synchronisation vendor-cloud (si enterprise utilise Apple/Google passkey sync) en informant les fournisseurs si nĂ©cessaire.
  • Appliquer GPO / MDM pour empĂȘcher l’installation de certificats racine par utilisateurs.

Opérations légÚres :

  • Rotation des credentials d’administration applicatifs qui ont pu ĂȘtre exposĂ©s.
  • Patch immĂ©diat si tampering trouvĂ© sur serveur d’enrĂŽlement.

4) Eradication & remediation (24h–7 jours)

  • RĂ©voquer / marquer invalides les credentials identifiĂ©s : set status=revoked in DB, invalidate sessions.
  • Roll-back / reissue : si CA compromise → rĂ©voquer CA cert + publier CRL/OCSP, gĂ©nĂ©rer CA propre dans HSM, mise Ă  jour de toute la chaine.
  • Nettoyer endpoints, corriger vulnĂ©rabilitĂ©s qui ont permis compromission (accĂšs non MFA, ports ouverts, scripts non durcis).
  • Auditer MDS : vĂ©rifier metadata authenticity; faire incident report to FIDO Alliance if metadata poisoned.
  • Forensically analyse HSM logs; si fuite de key material confirmĂ©e, plan de remplacement total.

5) Recovery & re-enrollment (J+3 → J+30)

Objectif : restaurer accÚs légitime, minimiser friction.

Processus recommandé :

  1. Communiquer (voir templates ci-dessous) aux utilisateurs affectés : expliquer mesures, pas de panique, procédure de ré-enrÎlement.
  2. Ré-enrÎlement contrÎlé :
    • Step 1 : administratively verify user identity (MFA + helpdesk validation).
    • Step 2 : issue temporary fallback (time-limited OOB code) or require physical key (YubiKey) for high privilege.
    • Step 3 : call navigator.credentials.create() only after verification. Log everything.
  3. Revoke old credentials en batch.
  4. Offer hardware keys for critical users (ops, admins): policy to require U2F/YubiKey for privileged accounts.
  5. Post-recovery monitoring: heightened monitoring 30 days, watch counters and enrollment patterns.

6) Communication — templates (rapide & efficace)

Internal (short) — to Execs:

Objet : Incident sĂ©curitĂ© — compromission magasin attestations (passkeys) — action et impact
RĂ©sumĂ© : Nous confirmons une compromission affectant la chaĂźne d’attestation utilisĂ©e pour les passkeys. Actions immĂ©diates : endpoints d’enrĂŽlement fermĂ©s, blacklist AAGUIDs, rĂ©vo des credentials suspects. Impact : possibilitĂ© de sessions frauduleuses limitĂ©e. Nous travaillons le containment, l’éradication et la notification. DĂ©tails et next steps suivront.

User-facing (concise):

Objet : SĂ©curitĂ© — procĂ©dure de rĂ©-enrĂŽlement passkey
Contenu : Nous avons dĂ©tectĂ© une anomalie technique liĂ©e au systĂšme d’enrĂŽlement des passkeys. Par mesure de prĂ©caution, certains accĂšs vont ĂȘtre temporairement rĂ©initialisĂ©s. Vous recevrez un email avec instructions pour vous rĂ©-enregistrer. Nous n’avons pas de preuve de compromission directe de comptes individuels <ou prĂ©ciser si oui>. Merci de suivre les instructions.

Legal / regulators: prepare timeline + data scope; include forensic artifacts hash.


7) Monitoring & détection post-incident (alerts à déployer)

  • Alarme : New registrations from same attestation cert serial > N/hour
  • Alarme : signatureCounter decrease or no-increment
  • Alarme : Origin mismatch during registration
  • Alarme : Spike in DB writes to credentials table
  • Alarme : New attestation format fmt not in whitelist

8) RÎles & responsabilités (RACI bref)

  • R : SOC (detection), IR lead (orchestration), App owner (closure)
  • A : Head of Security
  • C : Legal, Comms, Vendor support (Yubico / FIDO)
  • I : Execs, affected user groups

9) Post-mortem & actions long terme (30–90 jours)

  • Rotate PKI, force metadata re-validation, mandate hardware keys pour admins, update runbooks, run TTX (table-top exercises) sur CA compromise, renforcer governance FIDO MDS, GPO pour cert installation.

Annexes techniques utiles

Commands / snippets (concise)

  • Export webauthn table (MySQL):
    mysqldump -u root -p webauthn_db credentials > webauthn_credentials.sql && sha256sum webauthn_credentials.sql
  • Inspect cert (OpenSSL):
    openssl x509 -in attestation_cert.pem -noout -text
  • Delete Windows cert by thumbprint:
    certutil -delstore Root "THUMBPRINT"
  • Example Splunk:
    index=webauthn sourcetype=webauthn_register | stats count by att_cert_serial, aaguid | where count>5

Conclusion — la morale amùre

Tant que tu dĂ©pends d’une chaĂźne d’attestation, tu dois gĂ©rer la PKI comme un bijou : HSM, rotation, monitoring, et playbooks testĂ©s. Les passkeys ferment de grandes portes aux attaques classiques, mais si tu laisses la cave (PKI/metadata) ouverte, un attaquant rentre par la cheminĂ©e.


🎉 Cadeau : script PowerShell pour dĂ©tecter et lister certificats racine rĂ©cemment installĂ©s sur un parc.

<#
PowerShell script — Detecter et lister les certificats racine rĂ©cemment installĂ©s sur un parc

Fonctions:
 - Get-RootCertificates      : liste les certificats des stores Root (LocalMachine + CurrentUser) pour un hĂŽte
 - Save-CertsBaseline       : enregistre un baseline CSV pour comparaison ultérieure
 - Compare-CertsBaseline    : compare l'état courant à un baseline et retourne les certificates ajoutés/supprimés
 - Find-RecentCerts         : heuristique qui retourne les certificats dont NotBefore est dans les X derniers jours
 - Collect-FromHosts        : collecte les certificats depuis plusieurs machines via Invoke-Command (WinRM)

Limitations importantes:
 - Windows ne stocke pas un "install timestamp" explicite pour un certificat dans le store. Nous utilisons deux approches:
   1) comparaison par baseline (fiable si vous avez une baseline antérieure)
   2) heuristique sur le champ NotBefore (indique la date de validitĂ©, pas la date d'installation — utile comme indice)
 - Pour inventaire à l'échelle, activez WinRM / PSRemoting et exécutez Collect-FromHosts avec des comptes ayant droits d'administration.

Usage exemple (local):
  # créer un baseline
  Save-CertsBaseline -FilePath "C:\temp\certs_baseline.csv" -IncludeCurrentUser:$false

  # vérifier les changements depuis le baseline
  Compare-CertsBaseline -FilePath "C:\temp\certs_baseline.csv" -IncludeCurrentUser:$false

  # trouver les certs avec NotBefore dans les 30 derniers jours
  Find-RecentCerts -Days 30 -IncludeCurrentUser:$false

Usage exemple (parc):
  $hosts = @('host1','host2')
  $cred = Get-Credential
  Collect-FromHosts -ComputerNames $hosts -Credential $cred -OutputDir "C:\temp\webauthn_inventory"

#>

function Get-RootCertificates {
    [CmdletBinding()]
    param(
        [Parameter()]
        [bool]$IncludeCurrentUser = $true
    )

    $results = @()

    # LocalMachine Root
    try {
        $lm = Get-ChildItem -Path Cert:\LocalMachine\Root -ErrorAction Stop
        foreach ($c in $lm) {
            $results += [PSCustomObject]@{
                Store        = 'LocalMachine\\Root'
                Thumbprint   = $c.Thumbprint
                Subject      = $c.Subject
                Issuer       = $c.Issuer
                NotBefore    = $c.NotBefore
                NotAfter     = $c.NotAfter
                HasPrivateKey= $c.HasPrivateKey
                FriendlyName = $c.FriendlyName
                SerialNumber = $c.SerialNumber
                SignatureAlgorithm = $c.SignatureAlgorithm.FriendlyName
                RawDataHash  = ([System.BitConverter]::ToString(($c.GetCertHash()))).Replace('-','')
                ExportedAt   = (Get-Date)
            }
        }
    }
    catch {
        Write-Warning "Impossible d'énumérer Cert:\LocalMachine\Root - $_"
    }

    if ($IncludeCurrentUser) {
        try {
            $cu = Get-ChildItem -Path Cert:\CurrentUser\Root -ErrorAction Stop
            foreach ($c in $cu) {
                $results += [PSCustomObject]@{
                    Store        = 'CurrentUser\\Root'
                    Thumbprint   = $c.Thumbprint
                    Subject      = $c.Subject
                    Issuer       = $c.Issuer
                    NotBefore    = $c.NotBefore
                    NotAfter     = $c.NotAfter
                    HasPrivateKey= $c.HasPrivateKey
                    FriendlyName = $c.FriendlyName
                    SerialNumber = $c.SerialNumber
                    SignatureAlgorithm = $c.SignatureAlgorithm.FriendlyName
                    RawDataHash  = ([System.BitConverter]::ToString(($c.GetCertHash()))).Replace('-','')
                    ExportedAt   = (Get-Date)
                }
            }
        }
        catch {
            Write-Warning "Impossible d'énumérer Cert:\CurrentUser\Root - $_"
        }
    }

    return $results
}

function Save-CertsBaseline {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$FilePath,
        [bool]$IncludeCurrentUser = $true
    )

    $data = Get-RootCertificates -IncludeCurrentUser:$IncludeCurrentUser
    $data | Select-Object Store, Thumbprint, Subject, Issuer, NotBefore, NotAfter, HasPrivateKey, FriendlyName, SerialNumber, SignatureAlgorithm, RawDataHash, ExportedAt |
        Export-Csv -Path $FilePath -NoTypeInformation -Encoding UTF8

    Write-Host "Baseline saved to $FilePath" -ForegroundColor Green
}

function Compare-CertsBaseline {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$FilePath,
        [bool]$IncludeCurrentUser = $true
    )

    if (-not (Test-Path $FilePath)) { throw "Baseline file not found: $FilePath" }

    $baseline = Import-Csv -Path $FilePath
    $current  = Get-RootCertificates -IncludeCurrentUser:$IncludeCurrentUser

    # Nouveaux certificats = présents dans current mais pas dans baseline (par Thumbprint)
    $new = $current | Where-Object { -not ($baseline.Thumbprint -contains $_.Thumbprint) }

    # Certificats supprimés = présents dans baseline mais pas dans current
    $removed = $baseline | Where-Object { -not ($current.Thumbprint -contains $_.Thumbprint) }

    $report = [PSCustomObject]@{
        GeneratedAt = (Get-Date)
        NewCerts    = $new
        RemovedCerts= $removed
        BaselineFile = (Get-Item $FilePath).FullName
    }

    # Affichage confort
    if ($new.Count -gt 0) {
        Write-Host "Nouveaux certificats détectés : $($new.Count)" -ForegroundColor Yellow
        $new | Format-Table Thumbprint, Subject, Issuer, NotBefore, Store -AutoSize
    } else { Write-Host "Aucun nouveau certificat détecté." -ForegroundColor Green }

    if ($removed.Count -gt 0) {
        Write-Host "Certificats retirés depuis le baseline : $($removed.Count)" -ForegroundColor Magenta
        $removed | Format-Table Thumbprint, Subject, Issuer, NotBefore, Store -AutoSize
    }

    return $report
}

function Find-RecentCerts {
    [CmdletBinding()]
    param(
        [int]$Days = 30,
        [bool]$IncludeCurrentUser = $true
    )

    $cutoff = (Get-Date).AddDays(-1 * [int]$Days)
    $current = Get-RootCertificates -IncludeCurrentUser:$IncludeCurrentUser

    # Heuristique : NotBefore récent
    $recentByNotBefore = $current | Where-Object { $_.NotBefore -ge $cutoff }

    # Heuristique alternative : certs dont ExportedAt récent (utile si baseline non dispos)
    $recentByExport = $current | Where-Object { $_.ExportedAt -ge $cutoff }

    return [PSCustomObject]@{
        Cutoff = $cutoff
        RecentByNotBefore = $recentByNotBefore
        RecentByExport    = $recentByExport
    }
}

function Collect-FromHosts {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string[]]$ComputerNames,
        [Parameter(Mandatory=$true)]
        [System.Management.Automation.PSCredential]$Credential,
        [Parameter(Mandatory=$true)]
        [string]$OutputDir,
        [bool]$IncludeCurrentUser = $false
    )

    if (-not (Test-Path $OutputDir)) { New-Item -Path $OutputDir -ItemType Directory | Out-Null }

    $scriptBlock = {
        param($IncludeCurrentUser)
        # retourner la table de certificats simplifiée
        $res = @()
        try { $lm = Get-ChildItem -Path Cert:\LocalMachine\Root -ErrorAction Stop } catch {$lm = @()}
        foreach ($c in $lm) {
            $res += [PSCustomObject]@{
                Host = $env:COMPUTERNAME
                Store = 'LocalMachine\\Root'
                Thumbprint = $c.Thumbprint
                Subject = $c.Subject
                Issuer = $c.Issuer
                NotBefore = $c.NotBefore
                NotAfter = $c.NotAfter
                FriendlyName = $c.FriendlyName
                SerialNumber = $c.SerialNumber
            }
        }
        if ($IncludeCurrentUser) {
            try { $cu = Get-ChildItem -Path Cert:\CurrentUser\Root -ErrorAction Stop } catch {$cu = @()}
            foreach ($c in $cu) {
                $res += [PSCustomObject]@{
                    Host = $env:COMPUTERNAME
                    Store = 'CurrentUser\\Root'
                    Thumbprint = $c.Thumbprint
                    Subject = $c.Subject
                    Issuer = $c.Issuer
                    NotBefore = $c.NotBefore
                    NotAfter = $c.NotAfter
                    FriendlyName = $c.FriendlyName
                    SerialNumber = $c.SerialNumber
                }
            }
        }
        return $res
    }

    foreach ($host in $ComputerNames) {
        Write-Host "Collecte depuis $host ..." -ForegroundColor Cyan
        try {
            $out = Invoke-Command -ComputerName $host -Credential $Credential -ScriptBlock $scriptBlock -ArgumentList $IncludeCurrentUser -ErrorAction Stop
            $file = Join-Path $OutputDir "certs_$host.csv"
            $out | Export-Csv -Path $file -NoTypeInformation -Encoding UTF8
            Write-Host "Exporté: $file" -ForegroundColor Green
        }
        catch {
            Write-Warning "Échec collection depuis $host : $_"
        }
    }
}

# Helper: suppression (manuelle & prudente) d'un certificat racine sur la machine locale
function Remove-RootCertificate {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$Thumbprint,
        [ValidateSet('LocalMachine','CurrentUser')]
        [string]$StoreLocation = 'LocalMachine'
    )

    $storePath = "Cert:\$StoreLocation\Root"
    try {
        $c = Get-ChildItem -Path $storePath | Where-Object { $_.Thumbprint -eq $Thumbprint }
        if ($null -eq $c) { Write-Warning "Certificat $Thumbprint introuvable dans $storePath"; return }
        Write-Host "Suppression du certificat $Thumbprint dans $storePath" -ForegroundColor Yellow
        # action destructive: ask confirmation
        Remove-Item -Path ($c.PSPath) -Confirm
    }
    catch {
        Write-Error "Erreur lors de la suppression: $_"
    }
}

<#
Exemples d'utilisation rapide:
# 1) Sauvegarder un baseline local
Save-CertsBaseline -FilePath "C:\temp\certs_baseline.csv" -IncludeCurrentUser:$false

# 2) Comparer le baseline
Compare-CertsBaseline -FilePath "C:\temp\certs_baseline.csv" -IncludeCurrentUser:$false

# 3) Chercher les certs dont NotBefore < 30 jours
Find-RecentCerts -Days 30 -IncludeCurrentUser:$false | Select-Object -ExpandProperty RecentByNotBefore | Format-Table -AutoSize

# 4) Collecter depuis 2 hĂŽtes (WinRM requis)
$hosts = @('host1','host2')
$cred = Get-Credential
Collect-FromHosts -ComputerNames $hosts -Credential $cred -OutputDir "C:\temp\webauthn_inventory" -IncludeCurrentUser:$false

# 5) Supprimer manuellement un certificat (locale)
Remove-RootCertificate -Thumbprint "‎DEADBEEF..." -StoreLocation LocalMachine
#>

🔐 Passkeys : rĂ©volution passwordless ou nouvelle illusion de sĂ©curitĂ© ?
Partager cet article : Twitter LinkedIn WhatsApp

đŸ–‹ïž PubliĂ© sur SecuSlice.com

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Retour en haut