特権分離 (Privilege Separated) OpenSSH
私たちはプログラミング上のミスによる影響を、
特権 (root権限) をもたない子プロセス内に閉じこめることで
その影響を制限することにしています。
特権をもたない子プロセスからシステムをやぶることはできません。
つまり、私たちの目標は OpenSSH の中で完全に特権を分離することなのです。
特権分離には 2つのプロセスを使用します。
特権をもつ親プロセスは、特権をもたない子プロセスの進行を監視します。
子プロセスは特権をもっていません。これはその uid/gid を実際には使われない
ユーザのものに変更し、chroot() によってそのプロセスの
ファイルシステムへのアクセスを /var/empty に制限することで
達成されます。これはネットワークデータを処理するためだけのプロセスなのです。
特権をもつ親プロセスは、非常に小さな有限状態遷移機械として
モデル化することが可能であり、これによって特権をもった状態で実行される
コードについて理づめで考える (reasonする) のが容易になります。
特権をもつ親と、特権をもたない子の間で
きちんと定義されたインターフェイスがあれば、
子プロセスは特権を必要とする操作を親プロセスに委任することが可能です。
認証が成功したかどうかは親プロセスによって決定されます。
特権をもつプロセスともたないプロセス間における通信は、
パイプによって実現されます。パイプでは共有できない
それ以外のデータは、共有メモリに保持されます。
子プロセスは特権をもつ親に認証が成功したかどうかを尋ねる必要があります。
|
|
|
もし子プロセスがおかしくなって (corrupted)、リモートにいるユーザが認証できたと
信じてしまったとしても、親プロセスがそれと同じ結論に達しないかぎりアクセスが
許可されることはありません。
これまでの sshd では、これが認証前におかしくなっていまうこと
(corruption) は、すぐさまリモートからの root 権限取得につながる
可能性がありました。認証後におかしくなると、これは
ローカルでの root 権限取得の可能性があります。
特権分離は、このような攻撃を不可能ではないにせよ
非常にむずかしくします。
プロジェクトの状況
- 2002-03-18: 特権分離 OpenSSH が
OpenBSD cvs リポジトリに統合されました。
- 2002-03-16: ユーザからのフィードバックによって判明した
いくつかの枝葉な問題が解決されています。
- 2002-03-15: 最終バージョン。
フィードバックをまちます。
- 2002-03-14: 少々のバグフィックス。私のデスクトップマシンでは
どこでも非常に安定して動いています。
- 2002-03-13: SSHv1 も特権分離されました。
BSD-auth がサポートされ、その他の認証システムもじきに
特権分離された状態で動作するようになります。
- 2002-03-12: すべての OpenSSH は完全に特権が分離されました。
認証後に特権分離を使うためには、OS は
ファイル記述子 (file descriptor) の受け渡しをサポートする必要があります。
もしファイル記述子の受け渡しが使えないと、特権分離は認証が成功したあとで
終わってしまうでしょう。
- SSH v2 only:
特権分離はいまのところ SSH プロトコル バージョン 2 で動きます。
SSH プロトコル バージョン 1 に関しては目下作業中です。
- 2002-03-11: 認証前の段階では完全に特権が分離されるようになりました。
認証が成功したあとは特権をもたない子プロセスがその暗号状態と圧縮状態を
export し、特権をもつ親がそれをもとに処理します。
-
暗号状態:
OpenSSH は現在の IV と、ストリーム暗号化のために鍵の状態全体を
追う必要があります。いまのところは、EVP_CIPHER_CONTEXT 構造体から
このコンテキストを取得しています。
-
圧縮状態の export:
2つの共有メモリマップを作成する必要がありました。
zlib のメモリ割り当て関数をオーバーライドして
メモリマップ 1 を割り当てるようにします。
メモリマップ 1 の割り当て関数をオーバーライドして
メモリマップ 2 から要素を割り当てるようにします。
このプロセスが存在している間、メモリマップ 2 中に格納された
メモリマップ 1 から制御構造をすべて手にできます。
またメモリマップ 2 の情報をつかって、メモリマップ 1 の状態を
プロセス間で完全に同期させることができます。
zlib ライブラリには自前の割り当て機構に対するフックが用意されているので、
これは完全に透過的 (transparent) に実現されています。
参考文献
特権分離に関する論文はまもなく出ます。
ソースコード
ソースコードは OpenBSD CVS リポジトリから取得可能です。
謝辞
Markus Friedl
が特権分離のコードを書くのを手伝ってくれました。
コードの質が飛躍的に向上したのは彼の提案のおかげです。
移植性
移植性を確保することは急務です。
共有メモリへのインターフェイスがきれいに抽象化され、
匿名のメモリマップ (anonymous memory map) をサポートしていない
OS でも再実装が簡単になるようにすべきです。
移植版 OpenSSH は特権分離をサポートしています。
しかしいくつかの OS では多少の問題が残っており、
これについては現在作業中です。