2020年年明け早々、世界中のセキュリティ研究者は、Curveballと呼ばれるMicrosoftの重大な証明書の脆弱性(CVE-2020-0601)のセキュリティ調査で大忙しでした。調査の大部分は、パッチを当てていないWindows 10システムが信頼してしまう偽の認証局(CA)で署名された悪意のあるバイナリによる攻撃についてでした。もう1つの攻撃ベクトルであるHTTPSサーバー証明書は、Saleem RashidがTwitterで最初に動作するPOCを投稿して注目され、その後、Kudelski Securityと”Ollypwn”でPOCの作成方法の詳細を公開しました。
当社は同じアプローチを取り、攻撃を再現することに成功しました。さらに、クライアントがMcAfeeのWeb GatewayまたはWeb Gateway Cloud Serviceに保護され証明書検証ポリシーを実行している場合、パッチが適用されていないWindowsシステムを介して閲覧するユーザーが保護されることを確認しました。これは通常、SSLスキャナーの一部ですが、SSLインスペクションを実行する必要がない場合でも、個別の情報セキュリティポリシーとして利用できます(詳細についてはKB92322を参照)。
まず、Windowsの信頼されたルート証明機関の証明書ストアから偽のCAを使用してサーバー証明書に署名し、HTTPS接続の確立が必要な場合にのみサーバー証明書を発行しました。これは失敗し、なりすましが見破られたと想定しました。さらに、偽造のCAはサーバー証明書と一緒に処理する必要が実はあり、そうすれば一連の証明書がパッチ未適用のWindows 10システムで受け入れられることがわかりました。
その理由は何でしょう?偽造したバージョンを送信したことで、これが信頼されたストアに存在する証明書ではなく、即座に拒否する必要があることが明らかになります。また、最初は、偽造されたCAを可能な限り元のCAに似せようとしました(同じコモンネーム、同じシリアル番号など)。Windowsが実際に証明書の検証を行うときには、そうしたことが何の意味も持たないことがわかったのです。
なぜそんなことが起こるのかを知る手がかりは、Windows自身の証明書情報ダイアログにすでに提供されています。まず、Windowsの信頼されたルート証明機関のカタログの「UserTrust ECC証明書」から始めました。それには馴染みのある「Sectigo ECC」のネームがついています。次に、そのCAの偽バージョンを作成し、「EVIL CA」という新しいコモンネームを付けました。これにより、テストネットワークに新しいテストHTTPSサーバーをセットアップし、ユーザーがブラウザにhttps://www.google.comと入力したときにサーバーに到達するようにテストクライアントのルーティングを操作するのは簡単でした。テストサーバーは、Googleコンテンツではなく、デバッグ目的でSSLセッション情報を示していました。
鍵記号をクリックすると、ブラウザは接続が有効で信頼できるものとして受け入れられ、元の「Sectigo ECC」ルートCAがサーバー証明書に署名したことを通知します。
しかし、これは想定外で、事前の予測とは異なり、Windowsは「Sectigo ECC」に対しするサーバー証明書を検証すらしませんでした。同梱された偽のCAと比較していました。それは、「証明書を表示する」をクリックする際に起きました:
スクリーンショットにあるように、まだ同じSSLセッションにいます(マスター鍵は両方の写真で同じです)が、Windowsはサーバー証明書の(本物の)発行者がなりすましの「EVIL CA」であることを示しています。
Windowsの暗号署名検証は正常に機能
幸いなことに、Windowsは、楕円曲線証明書の署名を検証するための暗号化機能に実際に問題はありません。検証は正しく機能しているのです。問題は、一連の署名が信頼されたルートCAのカタログで正しく終了していることを証明するために、信頼チェーンの比較がどのように行われるかです。
攻撃は、信頼されたルートCAストアのエントリを指すCAの署名を使用し、署名の検証が制限されるため、本物のCAではなく偽物のCAで署名されていても署名が受け入れられると想定しました。しかし実際には、Windowsは組み込みの証明書チェーン(完全に有効で暗号的に正しい)を検証し、署名証明書を信頼されたルートCAストアのエントリと照合します。この最後の部分は、システムパッチの前に正しく行われていないものです。
私たちのテストでは、Windowsが証明書の照合さえ試みていないことが明らかになりました。 証明書の公開鍵のみを照合(さらにいくつかの比較とチェックも)するだけで、比較は不完全です。それがこの脆弱性の実際のバグでした(少なくともWebサイトの証明書に関する限り)。
信頼された証明書ストアとは実は信頼された公開鍵ストア
SSL/TLS通信の信頼チェーンとは、信頼されたルートCAにたどり着くまで、あるCAによって署名された証明書チェーンを意味します。しかし、Microsoftは証明書の大部分を無視し、証明書の公開鍵のチェーンを管理しています。この比較では、アルゴリズムもその対象です。RSA証明書のみが使用されていた時代には、それで十分でした。攻撃者は、信頼できる証明書と同じ公開鍵を使用して独自の鍵のペアを作成することはできませんでした。Elliptic Curve Cryptography(楕円曲線暗号、ECC)の導入により、アルゴリズムと公開鍵のみのMicrosoftによる比較には欠陥があります。楕円曲線自体の特性も比較できません。この追加のパラメーターを使用しないと、単に同じ公開鍵(曲線点)が異なる曲線上に再び作成されるだけです。これがPatch-Tuesdayで修正されたものです。公開鍵の情報の比較に曲線の特性が含まれるようになりました。
このスクリーンショットを見ると、右側の本物の証明書と左側の偽のCAがとても違うことがわかります。異なるコモンネーム、および完全に異なる楕円曲線(元のCAの標準曲線と偽造によるもの)ですが、「pub」エントリの下に表示される署名は同一です。これによって、埋め込まれた偽のCAが証明書ストアの信頼されたCAと同じであるとWindowsはあっさりと信じ込んでしまうのです。
なぜ証明書をネームやシリアル番号で比較しないのか?
別の(そしておそらくより自然な)アルゴリズムは、証明書をコモンネームおよび/またはシリアル番号で比較し、一致する場合はいつでも、信頼ストア内の証明書で信頼チェーンと検証を続行します。 Windowsはなぜそうせずに、公開鍵を比較するのでしょうか?推測の域を出ませんが、すべてのクライアントコンピューターに新しいルートCAを展開せずに証明書を交換したい企業にとっては利点があるのかもしれません。たとえば、独自の公開鍵基盤を持ち、信頼できる証明書のストアに独自のルートCAをインストールしている組織があると考えてください。これらの会社が合併や買収をすると、会社名が変わる場合があります。このときこそ、署名証明書のコモンネームも変更する良い機会です。ただし、すべてのクライアントをリモートで管理し、信頼できるストアの証明書を更新する良い方法がない場合、安易に企業に対して本物の公開鍵と秘密鍵のペアを使用して新しい証明書を作成するように指示する方が容易です。新しい証明書は古い証明書と一致するため、クライアントの更新の必要はありません。便利に思えるかもしれませんが、しかし安全でしょうか?この時点では、実際には信頼できる証明書のチェーンではなく、信頼できる公開鍵のチェーンです。
古い証明書の有効期限が切れたときに、これを悪用して新しい証明書を作成できるかどうかをテストしましたが、うまくいきませんでした。公開鍵を比較した後も、Windowsは信頼されるストア内の証明書の有効期限を使用して、チェーンがまだ有効であるかどうかを判断し、それでよしとしています。
プロセスを強化する方法
このアプローチの根本的な問題は、埋め込まれた証明書にも完全な暗号検証が行われ、検証後に初めて信頼されたルートCAストアのエントリとの照合が行われることです。この脆弱性で見てきたように、これだと常に見落としと不完全なマッチングアルゴリズムの余地があります。安全なアプローチは、最初に証明書(または公開鍵)を照合し、信頼されたルートCAストアで対応するエントリを見つけ、その信頼された証明書を使用して署名検証を続行することです。これにより、安全面の検証が行われず、壊れたチェーンを簡単に特定できます。
パッチが適用されたWindowsバージョンによって修正されたかどうか、またはマッチングアルゴリズムだけが改善されたかどうかは不明です。そうでない場合は、この代替アプローチを確認し、オペレーティングシステムとブラウザの実装をさらに強化することをお勧めします。
※本ページの内容は、2020年1月17日(US時間)更新のMcAfee Blogの抄訳です。
原文:What CVE-2020-0601 Teaches Us About Microsoft’s TLS Certificate Verification Process
著者:McAfee Labs