目次
■クラウド&インフラストラクチャ
2019.10.03 2024.02.20 約3分
本連載は、インターネット基盤技術やインターネットのインフラ技術と呼ばれる領域に関して、Webホスティングサービスの歴史やWebサーバの設計と実装を中心に執筆していきます。今回は、高集積マルチテナント環境において非常に重要かつ、とてもおもしろいセキュリティの研究動向を紹介します。
連載一覧:まつもとりーのインフラ入門
Apache httpd(以降Apache)は、歴史的にWebサーバのマルチテナントアーキテクチャのために様々な運用上の課題を解決し、改善した上で運用可能なレベルで機能追加が行われてきました。 本記事では、Apacheにおいて、高集積マルチテナントアーキテクチャを実現するVirtualHost機能を例に、仮想ホスト方式における権限分離の具体的な課題をまとめることで、現実的なセキュリティおよび実運用上の課題と具体的な手法を整理してみます。
ApacheのVirtualHostを採用した構成では、一般にOSのシステム領域でWebサーバプロセスを起動するため、Webサーバプロセスのユーザ権限や、動的コンテンツが実行される際のユーザ権限であっても、システム上の一般ユーザ権限で閲覧可能な/etc等のシステム領域のファイルを覗き見することができます。 また、閲覧できないようにすべてのシステム領域のパーミッションやオーナを修正するコストは非常に高くなります。
VirtualHostで動作しているApacheは、サーバプロセス権限で全てのリクエストを処理する必要があり、コンテンツファイルやディレクトリをサーバプロセス権限で操作可能にしなければなりません。 そのため、単純なマルチテナントアーキテクチャでは、異なるユーザが管理する他のホスト領域を覗き見することができてしまいます。
下の図に、他ホスト領域のファイルを覗き見するための一般的な仕組みと権限設定を示します。
この図では、index.cgiはWebサーバプロセスの権限であるuid500、gid101で実行されます。 また、/var/www/hosts/host1.example.com/ディレクトリはgid101からの読み取り権限があります。 さらに、ディレクトリ配下のホスト領域内部のファイル群はWebサーバプロセス権限でアクセスできるように全ユーザに読み取り権限を与えています。 そのため、host1を管理するユーザは、/var/www/hosts/host2.example.com/ディレクトリの下のコンテンツには直接アクセスできませんが、host1のindex.cgi内でシェル等の外部コマンドを実行することで、host2のindex.cgiのソースコードなどを閲覧できてしまいます。
また、CGIプログラムを経由せずとも、例えばシンボリックリンクを他ホスト領域のファイルに対して別名で設置するだけで、Webサーバプロセスを介した覗き見が可能となります。 これを防ぐために、CGIプログラムの実行時に利用できるsuEXECのようなアクセス制御モジュールを用いて、コンテンツの権限でCGIプログラムを実行し、適切に各ホスト領域の権限を設定することで、覗き見できないようにする方法が用いられます。
同時に、Apacheにおいてシンボリックリンク経由で他ホスト領域へ辿れないようにする設定も利用されます。 こんもシンボリックリンクについては、さらに深い議論が必要なケースもありますので、本記事では一旦言及せず、連載のどこかで紹介できればと考えております。
ApacheのsuEXEC機能を用いると、VirtualHostを採用していても他ホスト領域を閲覧できなくする構成をとることができます。 下図にsuEXECの利用例を示します。
この図では、上で覗き見について示した図と同様のパーミッションおよびオーナの設定をしています。 suEXECを採用すると、クライアントからCGIプログラムにアクセスがあった場合、ApacheによってCGIプログラムの実行処理をsuEXECに依頼します。 suEXECはindex.cgiを実行する際に、index.cgiの権限であるuid501、gid102を取得します。
そして、プロセスの権限を変更するシステムコール(setuid()、setgid()システムコールなど)を実行して、プロセスの権限を変更し、CGIプログラムを実行します。 そのためuid501、gid102のプロセスは、/var/www/hosts/host2.example.com/配下での読み取り権限であるuid502、gid101に対するアクセス許可がありません。 このように、suEXECを採用することで、他ホスト領域にアクセスすることができず、他の領域のindex.cgiの閲覧もできなくなります。
下の図にサーバプロセスとsuEXECの詳細なアーキテクチャを示します。
図のように、suEXECはプログラムを実行するたびに、一般ユーザからの実行であってもroot権限で実行されるように設定されたラッパープログラムを実行させて一旦root権限になり、そこから実行対象のプログラムの権限にsetuid()、setgid()システムコールを実行してからプログラムを実行します。 このように、CGIプログラム実行毎にプロセスの生成、破棄が必要となるため、性能が低くなるという問題があります。
Doerschは、システム領域や他ホスト領域を覗き見できないように、suEXEC時に各ホスト環境でchroot()システムコールにより、ルートディレクトリを各ホスト領域に移動し、隔離してからスクリプトを実行する手法を提案しています。
下の図はsuEXECプログラム内部でchroot()システムコールを実行する仕組みの概要図です。
これにより、CGIプログラムはホスト領域内の隔離された領域で実行されるため、利用しているホスト領域外のファイルを基本的に閲覧することができません。 一方、隔離された領域でプログラムを実行するため、ホスト単位で個別にライブラリを含んだ実行環境をドキュメントルートディレクトリ配下に事前に用意しておく必要があります。 ただし、複数の実行環境のファイル間をハードリンクし参照のみにすることにより、実行環境の構築や使用容量のコストを下げることは可能です。
ということで、今回は高集積マルチテナントアーキテクチャを採用したWebサーバにおいて、これまで述べてきた基礎概念から少し踏み込んで、マルチテナント環境において非常に重要となるセキュリティの研究動向について、まずはCGIという古くからの動的コンテンツの実行方式とそのアクセス制御について紹介しました。 次回も引き続き、セキュリティについてより踏み込んでいきたいと思います。
本連載は下記の私が執筆した論文を参考に、新しい読者へ広めるために平易な形へと再編集しています。
・ 松本 亮介, 栗林 健太郎, 岡部 寿男, Webサーバの高集積マルチテナントアーキテクチャと運用技術, 電子情報通信学会論文誌B, Vol.J101-B, No.1, pp.16-30, Jan 2018.
・ copyright©2018 IEICE
(記事:松本 亮介)