要約

  • Debian は2008年5月、同ディストリビューション固有の OpenSSL 乱数生成器の欠陥を修正した。更新は将来の生成を直しただけで、2006年9月以降に作られ、別の機器へ移された SSH、OpenVPN、DNSSEC、X.509 の鍵を無効にはしなかった。
  • 復旧には、生成履歴の特定、既知の弱い鍵の拒否、安全な鍵の再生成、交換先の認証、古い認可の削除または証明書の失効、そして各依存側で旧鍵が実際に拒否されることの確認が必要だった。

更新後も開いたままの扉

DSA-1571-1 が2008年5月13日に公開されたとき、Debian の OpenSSL パッケージは予測可能な乱数を生成していたことが明らかになった。修正版を入れれば、以後の生成処理は正しい経路を使う。だが、前日に生成した秘密鍵のビット列は変わらない。

弱い鍵は壊れたファイルとして現れるわけではない。公開鍵の形式は正しく、秘密鍵との対応も取れ、SSH の署名検証も通る。X.509 証明書は有効期間内で、発行者の署名も正しい場合がある。欠陥は鍵の形ではなく、秘密を選んだ過去にあった。

Debian が全暗号素材の再生成を勧告した理由はここにある。対象は 0.9.8c-1 以降の影響版 OpenSSL で作られた鍵だった。DSA についてはさらに厳しい。健全に生成された鍵でも、影響を受けたシステムで署名時の乱数が予測可能なら、秘密鍵が導出され得る。

Ubuntu は、Debian 系以外も間接的に影響を受けると明記した。健全な OS が、脆弱なホストで作られた鍵を受け入れれば、その OS は依存側として事故に入る。パッチ対象の境界と、認可を取り消すべき境界は一致しなかった。

大きな鍵空間に見えた小さな集合

起点となった Debian bug #363516 は2006年4月、Valgrind が OpenSSL の乱数処理で未初期化メモリの読み取りを報告する問題として始まった。議論は警告を減らす方法を扱った。その後の記録は、変更された md_rand.c が実際のビルド位置へ移された 0.9.8c-1 から、脆弱なコードが有効になったと明確にしている。

Debian の SSLkeys 文書は、壊れた生成器が実質的に PID に依存していたと説明する。三つのアーキテクチャ群ごとに32,767通り、同文書のモデルでは合計98,301の乱数系列である。一般的な鍵種と長さなら、候補を事前計算し、観測した公開鍵に対応する秘密鍵を探せる規模だった。

この数字を万能な鍵件数として扱ってはならない。アプリケーションの呼び出し方、鍵長、アルゴリズム、アーキテクチャによって範囲は違い、後のブラックリストも全形式を覆わなかった。また、公式記録は攻撃成功件数を示していない。

それでも、信頼の前提が逆転したことは分かる。公開鍵を公開できるのは、そこから秘密鍵を求めるのが非現実的だからである。この事件では、公開鍵が小さな候補集合のどれかを特定する手掛かりになった。鍵は暗号鍵らしい外観を保ったまま、排他的であるという根拠を失った。

Debian はコード修正とは別に認証を止めた

Debian 自身の対応は重要である。アドバイザリ公開直後、プロジェクトは Debian インフラ全体で SSH 公開鍵認証を停止した。鍵を使う転送やビルド処理は、安全性の確認または交換が済むまで通常運転できなかった。

OpenSSL の更新だけで既存鍵が失効するなら、この停止は不要だった。実際には、生成器と認証サーバーは別の制御面だった。

翌日の DSA-1576-1 は openssh-blacklistssh-vulnkey を導入した。既知の弱いユーザー鍵を、受信側が可能な範囲で拒否できるようになった。ホスト鍵は管理者の確認を経て再生成できた。しかし交換経路も二種類に分かれた。

ホスト鍵を変えると、クライアントは「REMOTE HOST IDENTIFICATION HAS CHANGED」と警告する。正当な復旧でも、中間者攻撃でも、見える現象は同じである。したがって警告を一律に抑止せず、別の信頼できる経路で新しいフィンガープリントを確認する必要があった。

ユーザー鍵は逆方向に進む。利用者が新しい鍵対を作り、各サーバーの authorized_keys に新しい公開鍵を登録し、古い行を削除する。新鍵を追加しただけでは、入口が一つ増えるだけで、弱い鍵の権限は残る。

パッケージ、ブラックリスト、新鍵、指紋確認、遠隔の認可行は別々の主体が管理していた。一つでも欠ければ、技術的に正しい更新と、権限の終了は一致しない。

ブラックリストは神託ではなくローカル拒否だった

候補集合が有限だったため、防御側は既知の弱い公開鍵を列挙し、接続時に照合することができた。これは公開された証拠を、実行可能な拒否規則へ変える方法だった。

ただし、一覧を公開しただけでは鍵は止まらない。受信アプリケーションが対応パッケージを持ち、形式を解析でき、その鍵種と長さが一覧に含まれ、拒否分岐を実行したときだけ効く。Debian は「可能な場合」に拒否すると述べ、Ubuntu は Unknown (no blacklist information) が安全を意味しないと注意した。

DSA-1576-2 は初版ツールの盲点を直した。強制コマンドやポート転送禁止などのオプションで始まる authorized_keys 行を見落とすことがあり、サーバーが受け入れる弱い鍵が報告に出ない可能性があった。その後も Ubuntu は X.509、証明書要求、raw modulus、追加 RSA 長の検査を拡張した。

ブラックリストは有効だった。影響版 OpenSSL を一度も使っていないサーバーでも、持ち込まれた既知弱鍵を拒否でき、将来の再登録も止められる。しかし、陰性結果の強さはパーサー、コーパス、形式の範囲を超えない。既知の悪い鍵は拒否する。未知を安全と呼ばない。それが適切な権限境界だった。

プロトコルごとに退役地点が違った

CERT は SSH、OpenVPN、DNSSEC、X.509 を影響例に挙げた。同じ欠陥源でも、共通の「失効」ボタンはない。

SSH ユーザー鍵の権限は、各サーバーの認可ファイルにある。完了証拠は旧秘密鍵でログインできないことだ。SSH ホスト鍵の信頼はクライアントの known_hosts と新指紋の確認にある。サーバーだけの変更では閉じない。

OpenVPN の共有鍵は全ピアで同期交換が必要である。証明書方式なら、鍵と証明書を替え、旧証明書を拒否させる必要がある。USN-612-3 は、他システム用に生成した材料も、その配置先で探して交換せよとした。

X.509 では、新しい秘密鍵を作って再発行しても旧証明書は消えない。発行者が失効状態を提供し、サーバーが新しいチェーンを配備し、クライアントが新しい状態を参照する。RFC 5280 は証明書と CRL の処理を定めるが、全クライアントが直ちに実行することまでは保証しない。

DNSSEC では署名済み委任やキャッシュを含むロールオーバーが要る。自動化鍵はイメージ、バックアップ、ビルドジョブ、取引先に残り得る。元ホストからファイルを消しても、受信側の認可は変わらない。

修復の単位はマシンではなく、資格情報の系譜だった。どこで作られ、どこへコピーされ、何を主張し、誰が受け入れ、誰が拒否できるかを結ぶ必要があった。

数学的妥当性と正当な権限の分離

弱い秘密鍵を再構成した攻撃者は、数学的に正しい SSH 署名を作れる。プロトコルは「提示者がこの秘密を持つ」ことを検証するが、「秘密が正当な本人だけのものか」は検証しない。排他性が崩れた後も、検証結果だけは成功する。

Lu Heng の running-code に関する公開論考は、この点を分析するレンズになる。ただし Debian の経緯を証明する資料ではない。アドバイザリ、パッチ、ブラックリスト、証明書状態は証拠と規則である。実効的な拒否は SSH サーバー、VPN ピア、PKI クライアントが規則を走らせた地点で成立する。

Debian はパッケージと自らのインフラを制御できたが、世界中の認可ファイルを一括変更する権限はなかった。一方、健全な OS の管理者も、弱い輸入鍵を受け入れるなら事故の外ではない。依存側のローカル拒否権が、最後の実効点だった。

閉鎖に必要な四つの台帳

生成台帳には日付、場所、パッケージ、ライブラリ、アプリ、アーキテクチャ、アルゴリズム、鍵長を記録する。配布台帳には秘密鍵の複製、証明書、サーバー、認可ファイル、VPN ピア、イメージ、バックアップ、外部パートナーを記録する。

交換台帳は旧指紋と新指紋、交換を認証した経路、責任者、期限を結ぶ。拒否台帳は、旧ユーザー鍵が失敗し、旧ホスト鍵が配信されず、旧証明書がテスト対象クライアントで拒否され、例外に期限があることを示す。

パッチ率は生成台帳の指標である。事故終了は拒否台帳でしか証明できない。

証拠の限界

公式資料は欠陥、期間、影響対象、対処を示すが、弱い鍵の総数や悪用件数は示さない。98,301系列は限定モデルである。Unknown は安全でも脆弱でもない。バックアップや誤った時計はファイル時刻を変え得る。GnuPG と GnuTLS は別の乱数源を使った。ホスト鍵の自動再生成はパッケージと管理判断で異なる。再発行は全クライアントの失効確認を証明しない。

確実なのは、修正版が以後の生成を直し、過去の鍵は各受入点で発見・拒否されるまで権限を保ったことである。

出典