任意アクセス制御による単一のサーバプロセスの権限分離モデルを考える

以前から、単一のサーバプロセスで複数のユーザの処理を担う場合に、プロセスやアクセス制御レベルで適切に各ユーザで権限分離するにはどういうモデルが考えられるのかを既存の手法を踏まえつつ思考実験していました。それらを今回は簡単にまとめてみようと思います。

まずは前提として、

  • 単一のサーバプロセスで複数のユーザを権限分離する
  • 任意アクセス制御(Discretionary Access Control:DAC)による権限分離を前提とする
  • 不特定多数のクライアントからサーバへのアクセスがある
  • クライアントはサーバに自身のユーザ権限で任意のプログラムを配置する事ができる
  • 設置プログラムを介してシステムを変更されないようにする
  • 他のクライアントのプログラムを変更できないようにする

であり、このような状況でプロセス(スレッド)やアクセス制御のレベルでいかに権限分離を行いセキュリティを担保できるかを考えてみました。この前提条件の意図は最後のまとめでも言及しますが、これを達成するためにはどういう権限分離のモデルが考えられるのでしょうか。ではいってみましょう。

この場合、性能を考慮した権限分離モデルとしては大きく以下の6つの方式に分けられるように思います。

1.ユーザ権限のサーバプロセス+管理者権限の権限分離用プログラム

このモデルでは、サーバプロセスを一般ユーザ権限で起動しておきます。そして、各クライアントは自身のユーザ権限でプログラムを設置します。サーバプロセスは権限分離のために、クライアントのプログラムをクライアントのユーザ権限でそれぞれ実行する必要がありますが、サーバプロセス自体がユーザ権限で起動しているため、他のユーザ権限で実行する事は通常できません。そこで、ユーザ権限であっても管理者権限で実行のみ可能な外部プログラムを用意しておき(例えばpingプログラムは似たような仕組みをとっています)、サーバプロセスはその権限分離用プログラムを介して一旦管理者権限となり、その上でクライアントのユーザ権限に変更してから、クライアントのプログラムを実行します。

これによって、各クライアントのプログラムは各クライアントのユーザ権限で動作するので、適切に権限分離されます。しかし、デメリットとしては権限変更に外部プログラム呼び出しとプロセス生成が必要となり、また、権限を変更したプロセスはユーザ権限のプロセスとなるため、そこから他のユーザ権限に再度変更することはできません。そのため、プロセスを破棄する必要があり権限分離のための処理のコストが高くなります。

脆弱性があった場合の影響も考えてみます。サーバプロセスそのものに任意の操作が可能な脆弱性があった場合のリスクとしては、悪意のあるクライアントが自由に管理者権限で実行のみ可能な権限分離用プログラムを介してプログラムを実行可能になります。そのため、権限分離用プログラム内で許可されている権限変更が可能になります。ですので、権限分離用プログラム内では管理者権限ではクライアントプログラムを実行できないようにする、といった処理にしておく必要があります。また、その権限分離用プログラムの脆弱性のリスクも同様に考える必要があり、このプログラムで任意の操作可能な脆弱性が存在すると、このプログラム経由で管理者権限となりシステムを任意に変更されるリスクもあります。

2.管理者権限のサーバプロセス+プロセスの権限を変更

このモデルでは、サーバプロセスを管理者権限で起動しておき、サーバプロセスは自由に権限を変更可能な状態にしておきます。そして、クライアントのプログラムをそのクライアントのユーザ権限で実行する場合、実行するサーバプロセスそのもの、あるいは、forkしたプロセスの権限をクライアントのユーザ権限に変更してからクライアントのプログラムを実行します。

これによって、プログラムはそれを所持するクライアントのユーザ権限に分離されます。しかし、一般ユーザに権限変更されたプロセスは元の権限には戻れないので破棄する必要があります。そのため、これもまた1のモデルと同様、権限分離にプロセスの生成破棄のコストが必要となります。ただし、1のような権限分離用の外部プログラム実行のコストはありません。

サーバプロセスに任意の操作が可能な脆弱性があった場合のリスクとして、サーバプロセスが管理者権限で起動しているので、システムのあらゆる変更操作が可能となってしまい、非常に危険です。

3.管理者権限のサーバプロセス+権限分離用スレッド

このモデルでは、2のモデルにおいて権限分離のために新たにプロセスをforkしましたが、その代わりにスレッドをcreateします。これによって権限分離に必要なコストがスレッドの生成・破棄となり、プロセスの生成・破棄と比較してコストが非常に低くなります。サーバプロセスに脆弱性があった場合のリスクは2と同様です。

4.権限変更の特権を持ったユーザ権限のサーバプロセス+プロセスの権限を変更

このモデルでは、管理者権限の特権を細分化して、権限の変更のみ可能な特権を与えたユーザ権限でサーバプロセスを起動させておきます。その上で、クライアントのプログラムを実行する際は、その特権を利用してサーバプロセス、あるいは、forkしたプロセスをクライアントの一般ユーザ権限に変更してからクライアントのプログラムを実行します。

このモデルでは、サーバプロセスがユーザ権限であっても権限を自由に変更可能なので、プログラム実行時にプロセスの権限を変更後は即座に権限変更の特権を剥奪してからプログラムを実行しなければいけません。特権を保持したままプログラムを実行してしまうと、悪意のあるクライアントがプログラム内で任意の権限に変更できてしまうからです。そのため、2と同様プログラム実行後は権限分離したプロセスを破棄する必要があり、コストが高くなります。

サーバプロセスに脆弱性があった場合は、任意の権限に変更して操作が可能になりますが、サーバプロセスは管理者権限の持つ特権のうち、権限変更以外の特権は全て落とされているので、管理者権限の主要な特権操作はできない状態です。そのため、管理者権限の特権を全て保持した状態の2や3のモデルと比べるとリスクは低くなります。

5.権限変更の特権を持ったユーザ権限のサーバプロセス+権限分離用スレッド

このモデルでは、4のモデルにおいて権限分離のために新たにプロセスをforkしましたが、その代わりにスレッドをcreateします。これによって権限分離に必要なコストがスレッドの生成・破棄となり、プロセスの生成・破棄と比較してコストが非常に低くなります。サーバプロセスに脆弱性があった場合のリスクは4と同様です。

6.ユーザ権限のサーバプロセス+各クライアント用のプログラム実行用デーモンプロセス

このモデルでは、サーバプロセスをユーザ権限で動作しておき、さらに別にクライアント毎にクライアントのユーザ権限で動作するプログラム実行用デーモンプロセスを前もって起動させておきます。これによって、プログラムを実行する際は、各クライアントの権限に対応したデーモンプロセス上でプログラムが実行されるため、クライアント毎に権限が分離されます。

デメリットとして、クライアントに比例してその数のデーモンプロセスを予め起動させておく必要があります。また、アクセスがあったらしばらくの間起動させておいて次のアクセスを待ち受け、アクセスが長時間来ない場合はデーモンプロセスを停止させるといった設計も可能になります。ただし、各クライアントの持つプログラムに不特定多数から大量のアクセスが来るような状況では、デーモンプロセスの起動が大量に生じたりするので、アクセスパターンにあった最適な実装が必要になると考えられます。

サーバプロセスに任意の操作が可能な脆弱性があった場合は、任意の権限でプログラム実行用のデーモンプロセスを割り当て、あるいは、起動できますが、管理者権限で起動させるような事はできないと考えられます。また、プログラム実行用のデーモンプロセスに脆弱性があった場合も考慮する必要があります。この辺りはモデル1のリスクと似ています。プログラム実行のデーモンプロセスが管理者権限で起動してしまわないような実装が必要となるでしょう。

まとめ

以上が、前提条件に基づいたサーバプロセスにおける権限分離モデルになると考えています。サーバプロセスのセキュリティを考える上で、上記のようなモデルを想定して実装を行うと良いのではないでしょうか。

ここで最初に述べた前提条件に関して言及します。前提条件として少し敷居の高い「クライアントはサーバに自身のユーザ権限で任意のプログラムを配置する事ができる」がありますが、これは例えば公開しているWebアプリの脆弱性によって任意のファイルや改竄が可能になった状況というのは、この前提条件の状況と同意であると考えられます。そのため、これらを意識してサーバプロセスの権限分離を実装しておけば、いざというときにも被害を最小限にとどめられるように思います。

ということで、頭の中で考えていたサーバプロセスの権限分離モデルを吐き出してみました。まだまだその他のモデルが考えられると思いますし、MACを考慮しだすとより複雑なモデルが定義できそうに思います。また、アクセス制御レベルではなくchrootによるファイルシステムの分離、LXCによるプロセスの隔離等のレイヤーではまた別のモデルが定義できそうです(このレイヤーでの話もいつか書きたいです)。今回は、最低限DACにおけるシンプルな権限分離として、上記の分類を把握しておくだけでも、サーバプロセスのセキュリティにおける問題をある程度回避できるのではないかと思っています。