Ken Thompsonの信頼するに足る信頼
ソースを全部読んでもバックドアを見抜けない――コンパイラに悪意を自己再生産させるThompsonの古典的攻撃を解剖し、サプライチェーンを疑う目とビルド信頼の限界という実務の勘所を持ち帰れる。
- 1983年、Ken Thompsonはコンパイラへバックドアを仕込み、ソースに痕跡を残さない攻撃を示した。login認証を破る細工と、自己コンパイル時に細工を再注入する二段構えだ。
- コンパイラのソースを綺麗に戻して再コンパイルしても、既に汚染された実行ファイルが新しい実行ファイルへ悪意を移植する。ソースをいくら査読しても防げず、信頼はバイナリと道具の連鎖そのものに宿るという含意を突いた。
- 自作していないコンパイラ、OS、ハードウェア、依存物をどこまで信頼できるかを問う。サプライチェーン攻撃の原典であり、再現可能ビルドやDiverse Double-Compilingの出発点だ。
何のコードか(背景と何が有名か)
Ken Thompson は UNIX と C 言語の共同開発者で、Dennis Ritchie とともに1983年のチューリング賞を受賞しました。その受賞記念講演が Reflections on Trusting Trust(信頼を信頼することについての考察)です。講演は1983年に行われ、翌1984年8月号の Communications of the ACM に掲載されました。わずか3ページの小論ですが、セキュリティの歴史で最も引用される文章の一つになっています。
有名なのは結論の鋭さです。Thompson は「ソースコードをどれだけ精査しても検出できないバックドア」を、実際に動くアイデアとして提示しました。標的は UNIX の login プログラム。ここに、特定のパスワードで誰のアカウントにもログインできる裏口を仕込みます。しかも login のソースにも、コンパイラのソースにも、その痕跡は一切残らない。攻撃はコンパイラという「道具」の中に潜み、コンパイラを綺麗なソースから作り直しても自己再生産します。「自分で作っていないコードを信頼できるか」という問いを、コードそのもので突きつけたのが本作です。
コードと仕組みの解説
横にスクロール
攻撃は三段階で組み立てられます。順に見ると、なぜソース査読で防げないかが分かります。
第一段階は素朴なバックドアです。C コンパイラ cc に細工を入れ、コンパイル対象が login のソースだと認識したら、生成コードにこっそり裏口を足します。
/* cc の中に埋め込まれた細工(概念コード) */
compile(char *s) {
if (match(s, "login のソースの特徴パターン"))
compile("裏口を追加するコード"); /* 認証を素通しする細工を注入 */
/* 通常のコンパイル処理 */
}
これだけなら、cc のソースを読めば match の一節が見つかり、露見します。そこで第二段階。「コンパイラが自分自身のソースをコンパイルしている」ことを検知したら、上記の login 用細工を新しいコンパイラのバイナリに再び書き込むコードを注入します。つまりコンパイラは、自分を再生産するときに悪意ごと自分をコピーします。
第三段階が決め手です。この二つの細工を C コンパイラのソースから削除し、細工入りバイナリだけを配布します。以後の流れはこうです。
1. 綺麗なコンパイラのソース(cc.c)を用意する
2. それを「汚染されたコンパイラのバイナリ」でコンパイルする
3. 汚染バイナリが、自分がコンパイラをビルド中だと気づき、
login 用の細工とこの再注入ロジックを、新しいバイナリへ埋め込む
4. できあがった新しいコンパイラも汚染されている
―― ソース cc.c は完全に綺麗なのに
要点は、この仕掛けが自己複製するプログラム(クワイン)の応用だということです。プログラムが自分自身のソースを出力するクワインの技法を使い、細工は「自分のソース表現」を保持して次のバイナリへ焼き付けます。結果として、コンパイラのソースにも login のソースにも証拠は無く、汚染は代々のバイナリを渡り歩きます。ソースを綺麗に保ったまま、悪意だけがバイナリの系譜に受け継がれる――これが「Trusting Trust」攻撃の骨子です。
バグや裏口を探す通常の防御は「ソースを読む」ことに帰着します。しかしこの攻撃では、login のソースもコンパイラのソースも完全に無害です。悪意はコンパイラの実行ファイルにのみ存在し、ビルドのたびに次の実行ファイルへ自己注入されます。ソース全行を証明的に検証しても、それをコンパイルする道具が汚染されていれば無意味だ、という点が核心です。
逸話と経緯
Thompson 自身が講演で断っているとおり、着想は完全な独創ではありません。彼は、この自己再生産する細工の原型を Multics に対する米空軍のセキュリティ評価(Karger と Schell による1974年の報告、いわゆる trap door 研究)に見たと明言しています。俗説では「Thompson が発明した攻撃」と語られがちですが、正確には先行研究のアイデアを、UNIX の C コンパイラという具体で実装可能なものとして磨き上げ、広く知らしめたのが彼の功績です。
もう一つ、しばしば混同される事実があります。Thompson は「実際にこの細工入りコンパイラを作ったのか」。彼の証言によれば、細工そのものは実装したものの、社外に流通させてはいません。あくまで概念実証であり、野に放たれた実害の記録ではない――ここは事実と伝説を分けるべき点です。講演の締めくくりで彼はこう述べています。信頼できるのは、自分が完全に自作したコードだけである、と。C コンパイラのような他人の道具を、ソースを読んだくらいで信頼してよいのか、という警句です。
| よくある俗説 | 史実 |
|---|---|
| Thompsonが攻撃を発明した | 原型はKarger-SchellのMultics評価(1974)にあり、Thompsonが実装可能な形に発展させた |
| 講演は1984年 | 講演は1983年(受賞年)。CACM掲載が1984年8月 |
| 細工入りコンパイラが世に出回った | 本人は概念実証を作ったが流通はさせていないと証言 |
| ソースを読めば防げる | ソースは無害。汚染はバイナリの系譜に潜み査読では検出できない |
遺産と教訓
この小論は、今日いうサプライチェーン攻撃の原典です。標的のソースではなく、それを生み出す道具(ビルドツールチェーン、依存ライブラリ、配布バイナリ)を汚染するという発想は、後の SolarWinds 事件やパッケージレジストリを狙う攻撃に直結します。信頼の対象は成果物だけでなく、それを作った連鎖の全体だ――Thompson の指摘は年を追うごとに重みを増しました。
防御は不可能ではありません。David A. Wheeler が2005年以降に定式化した Diverse Double-Compiling(DDC、多様な二重コンパイル) は、この攻撃を実務的に検出できます。要は、疑わしいコンパイラのソースを独立した別のコンパイラでもビルドし、両者が生成したバイナリが(正規化後に)ビット単位で一致するかを突き合わせる手法です。もし片方だけに細工が潜んでいれば出力が食い違うため露見します。同じ発想の延長に、誰がビルドしても同一バイナリになることを保証する再現可能ビルド(Reproducible Builds)があり、Debian などが長年推進しています。
- 攻撃の二段構え: (1) login への裏口注入 (2) コンパイラ自己再コンパイル時の細工再注入。後者がクワイン技法による自己再生産の核
- 決定的含意: ソース査読では防げない。信頼はソースではなくバイナリと道具の連鎖に宿る
- 史実: 1983年チューリング賞講演、1984年CACM掲載。原型はKarger-SchellのMultics評価
- 対抗策: Diverse Double-Compiling(独立コンパイラで突き合わせ)と再現可能ビルド
学べる原則は明快です。第一に、信頼はどこかで根拠なく置かざるを得ないが、その置き場所を意識せよ。コンパイラ、OS、CPU のマイクロコードまで遡れば、自作していない層は必ず残ります。第二に、検証は一つの視点に頼るな。DDC のように独立した経路で突き合わせれば、単独の道具に潜む悪意を炙り出せます。原理としての信頼境界やビルド再現性の考え方はセキュリティを、コンパイラや処理系の内部動作はプログラミングを参照してください。「自分が作っていないものをどこまで信頼できるか」――この問いに終わりはなく、だからこそ古びない一編です。
コード遺産の記事ガイド
Ken Thompsonの信頼するに足る信頼を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
セキュリティ
比較で見る軸
難易度: advanced / カテゴリ: コード遺産 / タグ数: 6
導入後に効く点
コンパイラのソースを綺麗に戻して再コンパイルしても、既に汚染された実行ファイルが新しい実行ファイルへ悪意を移植する。ソースをいくら査読しても防げず、信頼はバイナリと道具の連鎖そのものに宿るという含意を突いた。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- コード遺産
- タグ数
- 6
判断チェックリスト
- 自社の用途が「セキュリティ / コンパイラ」に近いか確認する。
- 強みである「1983年、Ken Thompsonはコンパイラへバックドアを仕込み、ソースに痕跡を残さない攻撃を示した。login認証を破る細工と、自己コンパイル時に細工を再注入する二段構えだ。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。