エンジニアの生き様をウォッチするメディア

まつもとりーのインフラ入門-第七回「高集積マルチテナントアーキテクチャのセキュリティ(2)」

みなさん、こんにちは。まつもとりーのインフラ入門第七回です。本連載では、主にインターネット基盤技術、または、インターネットのインフラ技術と呼ばれる領域に関して、Webホスティングサービスの歴史やWebサーバの設計と実装を中心に執筆していくと第一回で述べました。第七回では、第六回のセキュリティの話について、更に踏み込んでいきます。

DSO実行方式のためのセキュリティ機構

DSO実行方式は、動的コンテンツとして実行したいプログラムをApacheで実装するために、Apacheモジュールとして当該インタプリタをApacheのサーバプロセスに組み込み、サーバプロセスがプログラムを直接実行するため、一般的にCGI実行方式と比較して、リクエスト時にプロセスの生成と破棄やインタプリタのロードが必要なくなり性能が高くなります。代表的なDSO実行方式の実装として、mod_phpやmod_perl、mod_rubyなどが挙げられるます。筆者が実装しているmod_mrubyやngx_mrubyも基本的には同様のアーキテクチャになります。

・Ryosuke M, mod_mruby,
https://github.com/matsumotory/mod_mruby
・Ryosuke M, ngx_mruby,
https://github.com/matsumotory/ngx_mruby

また、スクリプトの処理を渡すインタプリタを指定するために、スクリプトの行頭に記述するシェバン行や権限を細かく設定する必要もありません。

しかし、Apacheに組み込まれて実行される以上、基本的にはApacheのサーバプロセス権限で実行されるため、以前紹介した下図と同様の他ホストが覗き見される問題が生じます。

以下、DSO実行方式を安全に利用するためのセキュリティ機構としてこれまでに提案されているものを紹介するとともに、それらの課題について論じます。

PHPのセーフモード

DSO実行方式において、広く使われているDSO版PHP(モジュール名はmod_php)は、他ホストの領域を閲覧できないようにするため、セーフモードという機能がありました。セーフモード機能を利用すると、DSO版PHPであっても他ホスト領域のファイルを覗き見することができません。しかし、PHP特有のセキュリティ機構でありOSやミドルウェアのレイヤーからみたときには汎用性が低いこと、共有サーバ上のOSやファイルシステム上のセキュリティ問題をPHPのアプリケーションのレイヤーで解決しようと試みるのはアーキテクチャ及び実装上非常に複雑になり、あまり筋が良くないといった理由から、PHP5.3.0で使用が非推奨となり、PHP5.4.0では削除されました。

The PHP Group, PHP Manual Safe Mode,
https://php.net/manual/ja/features.safe-mode.php

rootのサーバプロセスで権限分離する手法

DSO実行方式を採用した場合でも、mod_suid2というモジュールを利用すると、他ホスト領域の閲覧を防ぐことができます。

Hideo N, mod-suid2,
https://code.google.com/p/mod-suid2/

mod_suid2は、Apacheのサーバプロセスをroot権限で起動しておき、リクエストを処理する度にsetuid()およびsetgid()システムコールによりユーザ権限に変更します。これによって、Apacheの権限とは別の権限でプロセスを実行できるため、suEXECと同様、他ホスト領域を閲覧できなくできます。

しかし、処理後はサーバプロセスが一般ユーザ権限であるため、権限を元のroot権限に戻すことができません。そのため、ユーザ権限に変更されたサーバプロセス、より厳密にはレスポンスを生成するワーカプロセスはコンテンツ処理後に破棄する必要があります。その結果、ワーカプロセスを再利用できず、リクエスト処理毎にワーカプロセスを再起動し直す必要があるため、DSO実行方式を利用していたとしても、ワーカプロセスの再生成はsuEXEC用のプロセスの再生成よりも初期化処理のコストが大幅に高いため、suEXECよりも性能が大きく低下します。

また、セキュリティの観点からは、サーバプロセスをrootで起動させていると、万一サーバプロセスそのものに任意のコマンドを実行できるなどの脆弱性があった場合や、設定ミスによってサーバプロセスの権限でコンテンツを実行してしまった場合に、悪意のあるユーザが容易にrootの特権を得られるという問題もあります。

原らによる提案手法では、サーバプロセスをrootで起動し、セキュアOSの機能でrootの権限を一部制限した状態で、リクエスト毎にfork()システムコールでプロセスを新規で生成し、新規生成したプロセスの権限を変更してからリクエスト処理を行う手法を提案しています。

原大輔, 尾崎亮太, 兵頭和樹, 中山泰一, Harache:ファイル所有者の権限で動作する WWW サーバ, 情報処理学会論文誌, Vol.46, No.12, pp.3127–3137, 2005年.

しかし、DSO実行方式と比較した場合に、リクエスト毎にプロセスの生成と破棄が必要となり、依然として性能が低下する問題が残ります。

一般ユーザのサーバプロセスで権限分離する手法

鈴木らは、アクセスするクライアントが正確に特定できるようなイントラネットの環境において、ユーザ権限であってもsetuid()システムコール等を実行可能にする手法を提案しています。

鈴木真一, 新城靖, 光来健一, 板野肯三, 千葉滋, ユーザ権限変更機構を利用した安全なイントラネットサーバの実現, 情報処理学会論文誌コンピューティングシステム(ACS), Vol. 44, No. 10, pp. 86-96, 2003.

この手法は、UNIXにユーザ権限でオーナを変更できる新たなシステムコールを実装し、identプロトコルを利用せずに、IPオプションを用いてクライアントプロセスの認証情報を送ることと組み合わせることにより、identプロトコルに依存しないイントラネット内での透過的なクライアントプロセスとサーバプロセス間の権限分離システムを構築可能です。

しかし、信頼のあるクライアントとネットワークが前提となっており、不特定多数のクライアントには対応していないという前提があります。

mod_ruid2というモジュールを利用すると、一時的にユーザ権限で起動しているサーバプロセスに、rootの特権を細分化したLinux Capabilityと呼ばれる機構の内、CAP_SETUID、CAP_SETGIDの特権を与えられます。

・Hideo N, Pavel S, mod_ruid,
https://github.com/mind04/mod-ruid2
・Bacarella M, Taking Advantage of Linux capabilities. Linux Journal, 2002.

下図にmod_ruid2の詳細なアーキテクチャを示します。

特権を与えられたサーバプロセスは、root権限で実行されていなくても、setuid()およびsetgid()システムコールを実行可能となります。その後、mod_suid2同様にApacheのサーバプロセス自体を任意のuid、gidに権限変更してから処理を実行し、再度、元のuid、gidに戻します。

この仕組みによって、DSO実行方式であっても、PHPスクリプトは権限が異なるため他ホスト領域を閲覧できません。また、実行後でも、元のサーバプロセスの権限に戻すことで、プロセスの再利用も可能にしているため、DSO実行方式の性能を維持できます。

しかし、このようなプロセスは、rootのように全ての特権を持たないものの、setuid()およびsetgid()システムコールを実行できる特権を保持していることになります。すなわち、それが意味するところは上図におけるindex.phpのようなWebアプリケーションの脆弱性をつかれ悪意のある者に乗っ取られた場合、setuid()およびsetgid()システムコールによる権限変更を利用し、他ホスト領域のファイル閲覧や変更および不正プログラムの配置や配布等が可能となります。

つまり、サーバプロセス自体に権限を変更できる特権の保持を許すことは、同時に数多くの脆弱性を許すことになります。

一方で、setuid()およびsetgid()システムコールを実行した後にCAP_SETUIDおよびCAP_SETGIDのCapabilityを放棄し、処理後にプロセスを復帰できないように改修すれば安全になりますが、やはりそれではワーカプロセスが再利用できなくなり、mod_suid2同様性能は著しく低下することになります。

一般に、サーバプロセスにアクセス制御を設定後に再度解除するというアプローチは性能上の利点を得られますが、共有型の大規模Webホスティング基盤のセキュリティを考える上でリスクが非常に大きく、脆弱性をつかれた場合の利用者や閲覧者への被害は甚大であり、避けるべきと考えられます。

原らは、Webサーバからの権限変更を可逆的に変更可能にしながら、実行されるプログラムからは権限を変更されないように、プログラムから実行されるシステムコールをフック、つまり、一連の処理の中で特定の処理フェーズが呼ばれた時に、同時に、あるいは、代わりに別の処理も実行できるように予め処理を登録しておくことによって、プログラムから実行される権限変更の処理を無効にしてセキュリティを担保する手法を提案しています。

原大輔, 中山泰一, Hussa: スケーラブルかつセキュアなサーバアーキテクチャ 低コストなサーバプロセス実行権限変更機構, 第8回情報科学技術フォーラム (FIT 2009) 講演論文集, RB-002, 2009年.

しかし、Linuxにおいては、システムコールを適切にフックするためにはLinuxカーネルに直接変更を加える必要があり、可搬性が低く、カーネルやライブラリを継続的に更新することが求められる現場において運用上の問題になることが多くなります。

まとめ

ということで、今回も高集積マルチテナントアーキテクチャを採用したWebサーバにおいて、これまで述べてきた基礎概念から少し踏み込んで、マルチテナント環境において非常に重要となるセキュリティの研究動向について、第六回に引き続き様々な観点から紹介し、その課題をまとめました。いよいよ次回は、今回整理した課題をどのように解決するか、果たして可能なのか等を中心に、引き続きセキュリティについてより踏み込んでいきたいと思います。是非読者の皆様も解決する方法を考えてみると面白いかもしれません。

リファレンス
本連載は下記の私が執筆した論文を参考に、新しい読者へ広めるために平易な形へと再編集しています。
・ 松本 亮介, 栗林 健太郎, 岡部 寿男, Webサーバの高集積マルチテナントアーキテクチャと運用技術, 電子情報通信学会論文誌B, Vol.J101-B, No.1, pp.16-30, Jan 2018.
・ copyright©2018 IEICE

(記事:松本 亮介)

京都大学博士(情報学)、さくらインターネット研究所上級研究員、ペパボ研究所客員研究員、Forkwell技術顧問、セキュリティ・キャンプ講師、情報処理学会各種委員、松本亮介事務所所長。

2008年に現場の技術を知るため修士に行かずにホスティング系企業に就職したのち、2012年に異例の修士飛ばしで京都大学大学院の博士課程に入学。インターネット基盤技術の研究に取り組み、mod_mrubyやngx_mrubyなどのOSSを始めとした多数のOSSへの貢献や学術的成果を修める。

2015年4月より2018年10月までGMOペパボ株式会社にてチーフエンジニアとしてプロダクトのアーキテクトやエンジニア組織のマネージメントに従事すると同時に、ペパボ研究所では主席研究員としてOS・Middleware・HTTPに関する研究、及び、事業で実践できるレベルまで作りこむことを目標に研究に従事。

2018年11月より現職のさくらインターネット研究所で上級研究員を務める。

第9回日本OSS奨励賞や2014年度情報処理学会山下記念研究賞など、その他受賞多数。2016年に情報処理学会IPSJ-ONEにおいて時流に乗る日本の若手トップ研究者19名に選出される。