CurveBall――偽の証明書を、なぜWindowsが信頼してしまったのか? ── CryptoAPIと楕円曲線のパラメーター

· · Windows, 情報セキュリティ, CVE, 証明書, 暗号

更新履歴(初版のみ・2026年09月16日公開)
初版公開

ダウンロードしたSetup.exeの署名を確認すると、有効と表示される。それでも発行元が偽物だったとしたら、何を確認し損ねたのでしょうか。CurveBallは、署名の計算を間違えなくても、信頼する相手を取り違え得ると示した脆弱性です。

1. 概要

CurveBall(CVE-2020-0601)は、WindowsのCryptoAPIが、細工されたECC証明書を信頼された認証局につながるものとして扱ってしまう脆弱性です。 コード署名の偽装や、TLS通信でのなりすましにつながりました。12

項目 内容
CVE CVE-2020-0601
通称 CurveBall、ChainOfFools
公開・修正 2020年1月14日(Microsoftの告知日)3
報告者 NSA4
対象機能 CryptoAPIのECC証明書検証、Crypt32.dll1
問題の性質 信頼済みの鍵との照合で、必要なパラメーターを確認しきれなかった5
悪用実績 CISAのKEVカタログに掲載6

暗号方式そのものの破綻ではありません。本物の認証局の秘密鍵を知らなくても、別の条件で作った鍵を本物と取り違えさせられた、という話です。78

2. 対象

当時の対象はWindows 10、Windows Server 2016・2019などです。製品別の更新はMicrosoftのCVE情報で確認できます。ここでは、未修正のWindowsで証明書を検証していた場面を扱います。39

影響するのはMicrosoft製アプリだけではありません。CERT/CCは、信頼されたルートまでたどれるかの判断をCertGetCertificateChainへ依存する第三者製アプリも対象になり得ると説明しています。画面を表示するアプリと、検証するライブラリーは別です。10

証明書検証を共有するWindowsアプリコード署名やTLSの検証をWindowsへ依頼するアプリでは、画面の違いだけで影響範囲を判断できません。コード署名を調べるアプリWindowsの証明書検証TLS証明書を調べるアプリ影響するCryptoAPIの処理

図1: 対象は、アプリの名前ではなく、問題のある検証経路を使うかで考えます。10

また、この攻撃で利用する明示的パラメーター付きECC鍵は、Windows 8.1以前・Server 2012 R2以前ではサポートされません。古い版が同じ経路では影響しないのは、証明書のその形式を受け付けないためです。11

3. 詳細

署名から、どこまでたどるのか

冒頭のSetup.exeを配る会社を「配布元B」、その証明書を発行する認証局を「ルートA」とします。説明を絞るため、中間認証局は省きます。

配布元Bは自分の秘密鍵でファイルに署名します。受け取る側は、Bの証明書にある公開鍵で署名を調べます。しかし、その証明書もB自身が勝手に作ったものなら、Bを信用する理由にはなりません。そこで証明書の発行元をたどり、もともと信頼している認証局まで確認します。12

ファイルの署名から信頼済みの認証局までたどるSetup.exeの署名を配布元Bの鍵で確認し、Bの証明書を発行したルートAが信頼の起点になる単純な構成です。Bの証明書に署名Bの公開鍵で確認信頼済みのルートA配布元Bの証明書Setup.exeの署名

図2: ファイルの署名が合うだけでなく、その鍵を誰のものとして信頼するかを確かめます。1213

ルートAが信頼されるのは、「自分で自分の証明書に署名したから」ではありません。信頼の起点として、あらかじめ採用されているからです。RFC 5280でも、信頼アンカーの情報は検証へ与える入力であり、自己署名証明書の形で与えられても、それ自体は検証対象の経路に含めないと整理されています。13

公開鍵の点だけでは、計算の条件が分からない

ルートAがECDSAを使う場合、公開鍵の点をQ、秘密の整数をd、計算の基準点をGとすると、関係は次のように書けます。14

Q = d × G

この掛け算は、点の座標をそれぞれd倍することではありません。楕円曲線で定義された点の足し算を繰り返すスカラー倍です。GQは公開してよい情報ですが、適切な大きさの曲線と固定されたGのもとでは、そこからdを求めることは困難です。14

証明書にも、点のデータだけが置かれているわけではありません。RFC 5480のSubjectPublicKeyInfoは、アルゴリズムとパラメーターを持つ部分と、公開鍵の点を収める部分に分かれています。15

ECCの公開鍵情報は点とパラメーターを組にして読むSubjectPublicKeyInfoでは、公開鍵の点を収める部分とは別に、アルゴリズムと楕円曲線のパラメーターを表す部分があります。SubjectPublicKeyInfoalgorithmsubjectPublicKey:点Q方式とパラメーター曲線・基準点Gなどを特定

図3: 点Qのバイト列が一致しても、パラメーターまで同じとは限りません。1516

一般的なnamedCurveは、P-384などの名前を表すOIDでパラメーター一式を指定します。一方、公表攻撃では、パラメーターを個別に渡す形式が使われました。ここで、標準のGとは違う基準点を指定できたことが効いてきます。168

基準点を変えると、同じQを別の秘密鍵で作れる

攻撃者は、ルートAの秘密鍵dを解こうとはしません。公開されているQを、そのまま別の基準点G′に選ぶことを考えます。すると、整数1との組で同じQになります。17

本物の組:      基準点 G、秘密鍵 d、公開鍵の点 Q = d × G
別の組:        基準点 G′ = Q、秘密鍵 d′ = 1
別の組の計算:  d′ × G′ = 1 × Q = Q

元のdは、最後まで分かっていません。 同じQが得られても、基準点が違うので別の組です。元のルートAのパラメーターで検証すれば、これをルートAの正しい署名として使えるわけではありません。17

異なる基準点から同じ公開鍵の点が得られる本物はGをd倍してQを得ますが、別の組はQ自体を基準点にして1倍するため、点の値だけは一致します。秘密のd倍1倍点は一致、条件は不一致本物:基準点G公開鍵の点Q別の組:基準点G′=Q同じ点Q

図4: 曲線上の点Qを変えずに、その点を作る基準点と秘密鍵の組を変えています。17

数値でも確認しておきます。説明用にy² = x³ + 2x + 2 (mod 17)という小さな曲線を選び、G = (5, 1)を7倍するとQ = (0, 6)になります。今度はG′ = (0, 6)を基準にすれば、1倍で同じ点です。

G = (5, 1)
2G = (6, 3)
3G = (10, 6)
...
7G = (0, 6) = Q

G′ = (0, 6)
1G′ = (0, 6) = Q

これは本稿用の小さな計算例で、実用の鍵長でもWindowsの検証結果でもありません。計算スクリプト結果JSONに、入力と各段階を残しています。ポイントは、曲線の式まで変えなくても、基準点の変更だけでこの関係が成り立つことです。

計算は正しくても、ルートAではない

この別の組を使えば、攻撃者は自分が知っている秘密鍵で、下位の証明書へ署名できます。細工した認証局の情報とその下位証明書をまとめて渡すと、渡されたパラメーター同士では、署名の計算が合う構成を作れます。8

それだけなら、信頼されない認証局が発行した証明書にすぎません。問題は、その認証局をルートAと照合する段階でした。McAfeeのTLS経路の検証では、公開鍵情報を照合するときにECCのパラメーターまで比較しておらず、細工した認証局を信頼済みのものと取り違えていました。5

数学的に成立する署名を誤った信頼へ結び付けた攻撃者が渡した情報で署名の計算は成立しますが、異なる基準点を持つ認証局を、同じ点Qを持つ信頼済みルートへ誤って結び付けます。パラメーターの違いを見落とす渡された組:G′とQその組で署名は成立信頼済みルートとの照合信頼済みの組:GとQルートAにつながると誤認

図5: 署名の計算ではなく、計算に使った鍵を信頼済みの鍵と同一視するところが崩れます。185

つまり冒頭のSetup.exeでは、攻撃者の用意した署名用証明書に、偽の認証局を経由して信頼が与えられます。信頼済みストアへ偽のルートを追加してもらったのではなく、追加していない偽物を既存のルートへ結び付けてしまったのです。19

ただし、実際の成立条件を点Qの一致だけに省略してはいけません。Romaillerらの実証には、元のルートが一度読み込まれ、証明書キャッシュにある条件が記されています。また、McAfeeのTLS検証では、名前やシリアル番号が違っても成立しました。実証の手順に現れる値の一致を、全経路共通の必要条件と決めつけないようにします。2021

4. 影響

直接壊れたのは、証明書チェーンの信頼判定です。コード署名では、不正な実行ファイルを正規の発行元によるものに見せかけられます。ただし、署名が信用されたことと、そのファイルが実行されたこと、管理者権限を得たことは別です。後者へ進むには、利用者やアプリの実行・権限付与などが必要になります。219

TLSでは、利用者の接続を攻撃者のサーバーへ向けられるなどの条件と組み合わさると、偽の証明書を受け入れさせ、通信を読み取ったり変更したりする攻撃につながります。これは、保存済みの暗号通信を後から何でも復号できるという意味ではありません。2

TLSのなりすましでは暗号化と接続相手の確認を分ける利用者が攻撃者側へ接続する条件がある場合、偽の証明書を受け入れると攻撃者との暗号化通信が成立し得ます。本物のサーバーの秘密鍵を解いたわけではありません。偽の証明書を受け入れる別の接続で中継する場合利用者のアプリ攻撃者側の接続先本物のサーバー

図6: 通信が暗号化されていても、接続相手を間違えれば、その相手には内容が届きます。2

Microsoftは2020年1月14日の公表時点では、実際の攻撃への利用を確認していないと説明しました。一方、CISAのKEVには2021年11月3日付で掲載されています。「公表時には未確認」を「その後も悪用されていない」と読み替えてはいけません。KEVの登録日は、最初の攻撃日を示すものではありません。36

5. 対策

比較する対象を、点Qだけで終わらせない

Microsoftは2020年1月14日の更新で対処しました。McAfeeの修正後の分析では、公開鍵情報の比較に曲線のパラメーターも含まれるようになったと説明されています。322

同じ点でも異なるパラメーターの鍵を信頼しない信頼済みルートの鍵と照合する際、点Qだけでなく、基準点を含む必要なパラメーターも確認すれば、今回の別の組を同じ鍵として扱えません。Qは同じ、Gが違う必要な情報が一致提示された鍵の情報信頼済みの鍵と一致?同じ鍵として信頼しない他の検証条件も確認

図7: 修正の要点は、同じ公開鍵に見える値を、その解釈に必要な条件と一緒に比べることです。22

この図は修正の意味を示すもので、Windows内部の全処理順を再現したものではありません。McAfeeも、検証順自体まで変わったかは分からないとしています。パッチの効果と、未確認の実装詳細は分けておきます。23

なおRFC 5480のPKIX向け規定は、そもそもnamedCurveを使い、明示的なspecifiedCurveを使わないと定めています。これは当時のWindowsが受理していた形式の説明とは別です。「仕様が禁止しているから実装も受け付けないはず」と考えるだけでは、実際の入力経路を見落とします。16

Windowsの更新を確認する

対策の基本は、この修正を含む適切なWindowsの更新です。NSAも、一部の攻撃を検出・遮断する方法はあっても、包括的な対処はパッチだと説明しています。特定のブラウザーで偽の証明書を拒否しただけでは、同じOS上の別アプリまで確認したことにはなりません。2410

運用では、対象のWindowsと更新履歴を確認し、証明書を信頼できないというエラーを無効化して回避しないことが重要です。開発側でも、自作の簡略な比較処理へ置き換えるのではなく、更新済みの検証基盤を使い、用途に必要な信頼・名前・有効期限などを確認します。1213

6. 教訓

CurveBallで見落とされたのは、数値そのものよりも、その数値をどう解釈するかという条件でした。点Qだけを見れば一致する。しかし、Gで作った鍵とG′で作った鍵を同一視すると、元の秘密鍵を知らない相手へ信頼を渡してしまいます。

この違いはテストにもできます。「正しい鍵なら通る」「点を変えたら落ちる」だけでは足りません。点はそのまま、基準点だけ変えたものを、同じ信頼済み鍵として受け入れないかを確かめる。正常例の値を一つだけ変えたとき、その変更が最終的な信頼判定まで届くかを追う、という点検です。

署名の計算に成功したら確認終了、ではありません。計算が成立した鍵と、信頼していた鍵は本当に同じか。冒頭の「有効な署名なのに偽物」という疑問は、そこまでたどると矛盾ではなくなります。

本稿は公開資料に基づく解説です。数値例は独自の小さな曲線上で計算しましたが、未修正Windowsでの脆弱性再現、偽造証明書の作成・配布、通信の傍受は行っていません。

図の実線は常に成り立つ関係、破線は条件付きの関係です(成立条件は詳細ページの各関係の説明に記載)。関係すべての一覧(全5件、根拠・確度つき)と主要概念の定義は知識マップ詳細ページにまとめています。データ: JSON-LD / Turtle

関連記事

参考リンク

  1. CERT/CC, VU#849224: Microsoft Windows CryptoAPI fails to properly validate ECC certificate chains. 参照箇所: OverviewとDescriptionの第1段落。ECC証明書の検証不備とCrypt32.dllの関係。最終更新2020-01-15。  2

  2. CERT/CC, VU#849224. 参照箇所: Impactの本文。X.509証明書チェーンの偽装、TLS通信の傍受・変更、Authenticode署名の偽装。本稿の実行・権限付与との区別と図6は、この直接の影響から条件を整理した説明。  2 3 4

  3. Microsoft MSRC, January 2020 Security Updates: CVE-2020-0601. 参照箇所: 2020年1月14日付本文のThis month we addressedで始まる段落。修正、Windows 10・Server 2016/2019、当時の悪用未確認の記載。重大度の公式表記はImportantで、Criticalではない。  2 3 4

  4. NSA, A Very Important Patch Tuesday. 参照箇所: 本文末のNSA contributedで始まる段落。NSAによる発見・分析とMicrosoftへの報告。公開2020-01-14。 

  5. Jan Schnellbächer / Martin Stecher, McAfee Labs, What CVE-2020-0601 Teaches Us About Microsoft’s TLS Certificate Verification Process. 参照箇所: The Trusted Certificate Store is actually a Trusted Public Key Store節の最初の2段落。公開鍵の照合にECCのパラメーターが欠けていたという、同社のTLS経路の分析。公開2020-01-17。  2 3

  6. CISA, Known Exploited Vulnerabilities Catalogの公式JSON. 参照箇所: vulnerabilities配列のcveIDがCVE-2020-0601の要素。dateAddedは2021-11-03。確認したカタログ版は2026.09.14、参照確認日2026-09-16。登録日は初回攻撃日ではなく、knownRansomwareCampaignUseのUnknownからランサムウェア利用を断定していない。  2

  7. NSA, A Very Important Patch Tuesday. 参照箇所: This kind of vulnerabilityで始まる段落。技術・標準ではなく、PKI証明書検証の実装の問題であるという説明。 

  8. Yolan Romailler, CVE-2020-0601: the ChainOfFools/CurveBall attack. 参照箇所: Root cause節。明示的パラメーター、基準点の取り替え、元の秘密鍵を求めず同じ公開鍵の点を持つ別の組を作る説明。2020年のKudelski Security研究記事を著者本人が保存した版を参照。旧ブログURLがトップページへ転送されるため、この保存版を出典とする。  2 3

  9. Microsoft MSRC, CVE-2020-0601 — Windows CryptoAPI Spoofing Vulnerability. 製品別更新を確認するための案内先。本文の対象製品の根拠は別掲の2020年1月14日付MSRC告知とCERT/CCのDescription。 

  10. CERT/CC, VU#849224. 参照箇所: Description内のAny softwareから始まる文。第三者製を含めCertGetCertificateChainに依存するソフトウェアの範囲。図1は検証を依頼する関係の説明図で、全アプリが同じ実装を使うとはしていない。  2 3

  11. CERT/CC, VU#849224. 参照箇所: Descriptionの最終段落。明示的パラメーター付きECC鍵への対応の有無と、Windows 8.1以前・Server 2012 R2以前の扱い。 

  12. Microsoft Learn, Certificate Chains. 参照箇所: 冒頭から第4段落。subject・issuer、末端・中間・ルートの構成とチェーン検証の説明。図2は中間認証局を省略した本稿の例であり、全構成を網羅する図ではない。  2 3

  13. IETF, RFC 5280 §6.1 Basic Path Validation / §6.1.1 Inputs. 参照箇所: §6.1のWhen the trust anchor is providedから始まる段落と、§6.1.1(d)(1)–(4)。信頼アンカーは検証への入力であること、信頼する発行者・方式・公開鍵・必要なパラメーターの区別。  2 3

  14. Yolan Romailler, CVE-2020-0601: the ChainOfFools/CurveBall attack. 参照箇所: Mandatory recallの整数と曲線上の点の関係、およびRoot causeの既存の公開鍵と未知の秘密鍵の説明。本稿では秘密の整数をd、公開鍵の点をQと表記した。  2

  15. IETF, RFC 5480 §2 Subject Public Key Information Fields. 参照箇所: SubjectPublicKeyInfoとAlgorithmIdentifierのASN.1定義、それぞれのフィールド説明。点の符号化は§2.2 Subject Public Key。図3はこの構造の要約。  2

  16. IETF, RFC 5480 §2.1.1 Unrestricted Algorithm Identifier and Parameters. 参照箇所: ECParametersのCHOICEとnamedCurve・specifiedCurveの説明、§2.1.1.1のNamed Curve。PKIXではspecifiedCurveを使わないという規定と、当時のWindowsでの受理は区別する。  2 3

  17. Steve Povolny, McAfee Labs, CurveBall – An Unimaginative Pun but a Devastating Bug. 参照箇所: Creating the proof-of-concept節のQ = k*Gの説明から、G′ = Q・k′ = 1を選ぶ段落まで。図4はこの関係を描いたもの。mod 17の数値は原資料ではなく本稿の計算例。公開2020-01-17。  2 3

  18. Jan Schnellbächer / Martin Stecher, McAfee Labs, What CVE-2020-0601 Teaches Us About Microsoft’s TLS Certificate Verification Process. 参照箇所: Windows’ cryptographic signature verification works correctly節。渡された証明書チェーンの暗号計算は成立する一方、その後の信頼済み情報との照合が不完全だったという同社の検証結果。 

  19. Steve Povolny, McAfee Labs, CurveBall – An Unimaginative Pun but a Devastating Bug. 参照箇所: Creating the proof-of-concept節の最初の2段落と、From there, we followedで始まる段落。異なるパラメーターの認証局を信頼済みと認識する問題と、ファイル署名側の検証。Setup.exeと配布元B・ルートAは本稿の仮名。  2

  20. Yolan Romailler, CVE-2020-0601: the ChainOfFools/CurveBall attack. 参照箇所: PoC   GTFO節末尾のAs long as the root certificate was loaded once alreadyという括弧書き、およびPublic test節。元のルートがキャッシュへ読み込まれているという実証条件。

  21. Jan Schnellbächer / Martin Stecher, McAfee Labs, What CVE-2020-0601 Teaches Us About Microsoft’s TLS Certificate Verification Process. 参照箇所: 導入部のBut why is that?から始まる段落。common nameとserial numberを変更しても成立したというTLS経路での観測。 

  22. Jan Schnellbächer / Martin Stecher, McAfee Labs, What CVE-2020-0601 Teaches Us About Microsoft’s TLS Certificate Verification Process. 参照箇所: The Trusted Certificate Store is actually a Trusted Public Key Store節の第2段落末尾。修正後は公開鍵情報の比較に曲線の特性を含むとの分析。図7はその意味を整理した説明図。  2

  23. Jan Schnellbächer / Martin Stecher, McAfee Labs, What CVE-2020-0601 Teaches Us About Microsoft’s TLS Certificate Verification Process. 参照箇所: How to harden the process?節の最終段落。検証の順序まで変更されたかは不明だとする限定。 

  24. NSA, A Very Important Patch Tuesday. 参照箇所: CVE-2020-0601 poses significant riskで始まる段落。パッチが包括的な対策で、一部の検出・遮断方法だけでは完全ではないという説明。 

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

Windowsのショートカットは、移動したファイルをどうやって見つけるのか? ── ファイルの「場所」と「同じファイルであること」は別の話

元のファイルを移動したのに、ショートカットから開けるのはなぜでしょうか。一つの企画書を移動・改名・コピーして考えながら、Windowsがパス以外の識別情報や特徴を手がかりにリンク先を探す仕組みと、その限界を解説します。

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

この記事は次のサービスページにつながります。近い入口からご覧ください。

よくある質問

この記事のテーマについて、相談時によくある質問をまとめています。

CurveBallでは認証局の秘密鍵が盗まれたのですか?
いいえ。公表された仕組みでは、本物の秘密鍵を取り出さず、楕円曲線の基準点を変えた別の鍵の組を使います。公開鍵の点が同じでも、パラメーターが違えば同じ鍵として信頼してはいけません。
楕円曲線暗号そのものが破られたのですか?
いいえ。問題はWindowsの証明書検証の実装でした。固定された正しいパラメーターのもとで秘密鍵を求める問題を解いたのではなく、別のパラメーターを持つ鍵を信頼済みの鍵と取り違えさせました。
攻撃者は偽のルート証明書をあらかじめインストールする必要がありましたか?
公表された経路は、偽のルートを利用者に信頼登録させることを前提にしません。渡された証明書を既に信頼された認証局へ誤って結び付ける問題です。ただし、対象OS、検証経路、証明書キャッシュなどの成立条件があります。
Windows 7や8.1にも同じ問題がありましたか?
CERT/CCは、Windows 8.1以前とWindows Server 2012 R2以前は攻撃に使う明示的パラメーター付きECC鍵をサポートせず、この経路の証明書を信頼しないと説明しています。古いOS全般の安全性や利用推奨を意味するものではありません。
ブラウザーだけ更新すれば対策になりますか?
この問題を含むWindowsのセキュリティ更新が基本です。CryptoAPIで証明書チェーンを検証する別のアプリも影響を受け得るため、あるブラウザーで警告が出ることだけではOS全体の対策完了を判断できません。

著者プロフィール

記事の著者プロフィールページです。

小村 豪

合同会社小村ソフト 代表

Windows ソフト開発、技術相談、不具合調査を中心に、既存資産が残る案件や原因が見えにくい障害調査に強みがあります。

ブログ一覧に戻る