コード署名と鍵の置き場所: 5方式に共通する穴
ここまでの4章で、同じ話が何度も出てきました。配られてきたものを、機械はなぜ信じられるのか。
方式ごとにばらばらに書いてきたので、ここでまとめます。
この章の検証状態: 実装の検証はしていません。仕様とドキュメントから言える範囲で、5方式の性質を整理しています。
2つの信じ方
信頼の置き方は2種類しかありません。
| 何を信じるか | 破られる条件 | |
|---|---|---|
| 経路を信じる | 「この繋がりの向こうに居るのは本人だ」 | 経路の資格情報が漏れる |
| 中身を信じる | 「このデータには本人の署名がある」 | 署名鍵が漏れる |
決定的な違いは、中身を信じる型では、途中の置き場所を信用しなくていいことです。
pull 型でストレージを使う場合、経路だけを信じているとそのストレージが単一障害点になり、書き込み権限を取られた時点で全機械に任意のコードが配れます。HTTPS は関係ありません。HTTPS が守るのは通信経路であって、置かれている中身ではないので、正しい証明書で正しく暗号化された偽物が、正しく届きます。
署名があると話が変わります。ストレージを取られても、鍵が無ければ検証を通るものは作れません。置き場所を「信用しなくていい場所」に格下げできるのが、署名の一番の効き目です。
ただし中身を信じる型にも上限があります。署名鍵を持つアカウントごと乗っ取られると、正規の署名が付いた偽物が正しく検証を通ります。npm で実際にそれが起きたときに何が素通りしたかはnpmサプライチェーン攻撃Shai-Huludにまとめました。
5方式の現在地
| 方式 | 既定でどちら | 穴 |
|---|---|---|
| push 型 | 経路 | CI の秘密鍵が漏れたら、正規の経路で偽物が配られます |
| pull 型 | 経路 | 置き場所が単一障害点。署名は自分で足すことになります |
| パッケージ型 | 中身 | 署名の鎖が仕組みとして入っています |
| コンテナ型 | 経路寄り | 署名の仕組みはありますが、既定で必須ではありません |
| A/B 型 | 中身 | 署名を必須にしている実装があります |
既定で中身を信じる型になっているのは2つだけです。残り3つは、自分で足すか、足さないまま運用するかの選択になります。
足すこと自体は難しくありません。配る前に署名を作り、受け取ってから検証します。処理としては数行です。難しいのはこの先の2つです。
難しいこと1: 鍵をどこに置くか
署名鍵を CI の秘密情報に置くと、CI を踏まれた時点で有効な署名が作れます。
これは実質、経路を信じる型に戻っています。攻撃者から見れば「置き場所を取る」が「CI を取る」に変わっただけで、取るべき対象が1つであることは何も変わっていません。署名を足したのに、単一障害点が移動しただけという状態はよく起きます。
判断の出発点は、鍵を持っている主体が何個あるかを数えることだと思います。1個なら、それが落ちたときの被害範囲がそのまま全体です。
分ける方向はいくつもあります。人手を挟む承認、ハードウェアに閉じ込めた鍵、署名だけを担当する別系統。どれを選ぶかは、配る頻度と守りたい範囲で変わります。週に数回の設定配布と、数千台への OTA では答えが違います。ここに一般解を書くと嘘になるので書きません。

難しいこと2: 古い版を配り直される
見落とされやすい穴です。
過去に正規に配られた版は、正しい署名を持っています。署名の検証しかしていない機械はそれを受け入れるので、攻撃者が古い版を保存しておいて後から配り直すだけで、すでに修正済みの脆弱性を持った状態へ機械を戻せます。
署名では止まりません。有効な署名だからです。
止め方の方向は2つあります。受け取り側が版の新しさを見るか、配布情報に有効期限を持たせるか。
apt には後者の仕組みがあります。リポジトリの Release ファイルに Valid-Until という項目があり、Debian のリポジトリ仕様には「その時刻以降、クライアントは期限切れとみなしてよい」と書かれています。
ただし同じ仕様には、「期限切れの Release ファイルに対するクライアントの挙動は未規定である」とも書かれています。つまり弾いてくれる保証はありません。警告だけ出して通す実装も、キャッシュを使い続ける実装もありえます。
仕組みがあることと、守られることは別です。自分で配る側に回るなら、受け取り側が実際にどう振る舞うかを確かめてから、その仕組みに寄りかかるかを決めることになります。
初回の鍵をどうやって入れるか
もう1つ、静かな前提があります。検証に使う公開鍵は、どうやって機械に入ったのか。
最初の1回を配送経路で送ってしまうと、その1回を取られた時点で全部が崩れるので、実務では製造時に焼き込む、初期セットアップで人手で入れる、といった形で配送経路の外から入れることになります。
ここは方式の選択とは独立していて、5方式のどれを選んでも同じ問題が残ります。このシリーズで唯一、技術の選択で解けない部分です。
この章の結論
改ざん耐性の軸だけで方式を選ぶなら、パッケージ型と A/B 型が有利です。すでに書かれていて、受け取り側の実装も配布済みだからです。
ただしこの軸だけで決めるのは早すぎます。設定ファイルを1台に配るために apt リポジトリを立てるのは、改ざん耐性の1軸を取るために他の6軸を全部差し出しているのと同じです。署名は後から足せますが、常駐物は後から減らせません。
次の最終章で、7軸を自分の状況に当てて2つまで絞る手順を作ります。
参考
- DebianRepository/Format —
InRelease/Release.gpgの署名、Valid-Untilと「期限切れ時のクライアント挙動は未規定」の記述 - RAUC — Basic Concepts — バンドル署名を必須とする設計判断
この記事は役に立ちましたか?