← Back to Blog

CVE-2020-0601 (CurveBall) : usurper un certificat par la courbe elliptique

La CryptoAPI de Windows vérifiait la clé publique d'un certificat ECC, mais pas le générateur de sa courbe. Une faute d'arithmétique, et n'importe quelle racine de confiance devenait usurpable.

Windows faisait confiance à un certificat à courbe elliptique dès que sa clé publique correspondait à celle d'une autorité racine de confiance, sans vérifier que la courbe présentée était bien la courbe standard. En choisissant lui-même le générateur, un attaquant pouvait fabriquer un certificat qui porte la clé publique d'une racine de confiance tout en en connaissant la clé privée. De quoi signer du code ou usurper un site HTTPS au nom d'une autorité en qui tout Windows avait confiance. Signalée par la NSA, corrigée le 14 janvier 2020 : le correctif Windows est la seule protection.

Fiche d'identité

ChampValeur
CVECVE-2020-0601 (« CurveBall », « ChainOfFools », « NSACrypt »)
Publication14 janvier 2020, Patch Tuesday Microsoft ; signalée par la NSA
ProduitsWindows 10, Windows Server 2016 et 2019 (versions antérieures non affectées)
Composantcrypt32.dll (Windows CryptoAPI)
Typevalidation incorrecte de paramètres cryptographiques, usurpation (CWE-295)
ScoreCVSS 3.1 : 8.1, élevé (AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N)
Prérequisaucun privilège ; une interaction (ouvrir un fichier signé, visiter un site)
Impactusurpation d'une AC racine ECC : signature de code, MITM TLS
Exploitationau catalogue KEV de la CISA ; CISA ED 20-02 imposait le correctif sous 10 jours
Contournementaucun : seul le correctif de janvier 2020 protège

Rappel : comment Windows fait confiance à un certificat ECC

Un certificat à courbe elliptique porte une clé publique qui est un point Q sur une courbe. Cette clé est liée à une clé privée d (un simple entier) par la relation :

Q = d · G

où G est le générateur (ou point de base) de la courbe, et d · G l'addition de G avec lui-même d fois. Connaître Q et G ne permet pas de retrouver d : c'est tout l'intérêt de l'ECC.

Normalement, une courbe est désignée par un nom (un OID, par exemple nistP256). Ce nom fige tous ses paramètres, générateur compris : les deux bouts de la connexion partent du même G officiel. Mais le format X.509 autorise aussi des courbes à paramètres explicites : le certificat embarque lui-même le corps, les coefficients de l'équation et le générateur G. C'est cette option qui ouvre la faille.

Pour valider une chaîne, la CryptoAPI devait vérifier que le certificat se rattache à une autorité racine de confiance. Elle retrouvait la racine en comparant la clé publique Q présentée à celles des racines connues.

Le bug : la clé publique vérifiée, le générateur oublié

La faute tient en une phrase : quand la courbe était donnée en paramètres explicites, crypt32.dll vérifiait que la clé publique Q correspondait à une racine de confiance, mais ne vérifiait pas que le générateur G était bien celui de la courbe standard. Elle acceptait le G fourni par le certificat.

Or une clé publique Q ne détermine pas le couple (d, G) : pour un même Q, il existe une infinité de couples valides. L'attaquant part donc de la clé publique Qₓₐ d'une racine de confiance (elle est publique, dans le magasin de certificats), et choisit ses propres paramètres :

G′ = Qₓₐ et d′ = 1
⇒ d′ · G′ = 1 · Qₓₐ = Qₓₐ

Le certificat forgé déclare donc le générateur G′ = Qₓₐ et une clé publique égale à Qₓₐ — exactement celle de la racine de confiance. Windows retrouve la racine par cette clé publique, ne contrôle pas G′, et accepte la chaîne. Et comme l'attaquant a fixé d′ = 1, il connaît la clé privée du certificat forgé : il peut signer tout ce qu'il veut au nom de cette autorité. (On peut prendre n'importe quel d′ connu en posant G′ = (d′)⁻¹ · Qₓₐ ; d′ = 1 est le cas le plus simple.)

Le mot « générateur » est trompeur : avec G′ = Qₓₐ, le point de base ne génère plus forcément tout le groupe, mais la vérification de signature, elle, passe quand même. C'est ce qui suffit à tromper Windows.

Ce que ça donne concrètement

L'exploit public fabrique, à partir d'une AC racine ECC de confiance (par exemple une racine de signature de code), un certificat intermédiaire usurpé, puis signe avec lui :

Chrome et Firefox, qui n'utilisent pas la CryptoAPI pour cette validation, étaient moins exposés sur le volet TLS ; la signature de code Windows, elle, passe par crypt32.dll.

Patcher

Il n'y a pas de contournement : il faut la mise à jour cumulative de janvier 2020 (ou une plus récente) sur tout Windows 10, Server 2016 et Server 2019. Après correctif, la CryptoAPI valide les paramètres explicites d'une courbe — générateur compris — contre la courbe nommée attendue, et rejette un G qui ne correspond pas.

Détecter

Le correctif ajoute aussi de la journalisation : un Windows à jour qui rencontre un certificat exploitant la faille écrit un évènement, ce qui en fait un bon signal de tentative.

SignalOù le voir
Tentative d'usurpation détectée par un hôte patchéJournal Application, source Microsoft-Windows-Audit-CVE, Event ID 1
Certificat ECC à paramètres explicites (rare et suspect en usage normal)inspection des certificats présentés, logs TLS, proxy
Exécutable signé par une racine ECC inattenduevérification Authenticode, EDR

Côté durcissement : pousser le correctif en priorité (c'est une faille de confiance, pas d'exécution directe), remonter l'Event ID 1 au SIEM, et se méfier de tout certificat à paramètres de courbe explicites, qui n'a presque aucune raison d'exister dans une PKI saine.

Pourquoi ce bug est intéressant

CurveBall ne casse pas l'ECC : la cryptographie sous-jacente reste solide. Il casse une vérification. C'est l'illustration qu'un schéma cryptographique n'est sûr que si l'on valide tous ses paramètres, pas seulement ceux qu'on regarde d'habitude. Oublier de contrôler le générateur revient à vérifier une signature sans vérifier de quelle clé elle vient. La leçon se généralise : valider l'intégralité des paramètres d'un algorithme (courbe, groupe, nonce, longueurs) est aussi important que l'algorithme lui-même.

Références

Faits vérifiés par recoupement de plusieurs sources ; date, score et mécanisme concordent.