ApacheのVirtualHostによる高集積Webホスティングでsymlink問題を根本解決する方法について考えた

最近、各所でApacheのVirtualHostを利用した高集積ホスティングのセキュリティに関するインシデントが起きています。僕自身、自分の専門の一つがWebサーバのセキュリティなので、他人事には思えず、毎日各所の経過情報を眺めています。また、数社からApacheのセキュリティに関してもいくつか質問を受けたりしており、公に話せるような内容はこのブログでも公開していきたいと思います。

ということで、ApacheのVirtualHostによる高集積Webホスティングにおけるsymlink問題を根本解決するにはどうしたら良いのかを考えました。まずは、静的コンテンツも動的コンテンツのようにファイルのユーザ権限で処理する方法から紹介します。その後、ホスト毎にApacheを起動させずとも、Apacheの仮想ホストを使ってリソースを節約しながら高集積Webホスティングを実現しつつ、付随するsymlink問題を根本的に解決できる方法案について言及します。

静的コンテンツも動的コンテンツのようにファイルのユーザ権限で処理

まず、CGIやDSO等の動的コンテンツは、suEXECやmod_suid2、mod_ruid2、あるいは今回静的コンテンツをユーザ権限で処理するためのmod_process_securityでアクセス制御済みだと思います。しかし、静的コンテンツは、通常、Apache権限で処理していると思います。そこで、mod_process_securityを使って静的コンテンツもApache以外のユーザ権限で処理する方法を説明します。

静的コンテンツをファイルのユーザ権限で処理する事で何がうれしいかというと、

  • 静的コンテンツからApache権限のパーミッションを外せる(600にできる)
  • 古くからのApacheのsymlink問題を根本的に解決できる方法につながる(後述します)

ということです。

これまでは、動的コンテンツはsuEXECによりApache以外のユーザ権限で動作することができたため、700等のパーミッションにできたと思いますが、静的コンテンツはApache権限で処理するアーキテクチャになっているため、どうしても、604や640等Apacheからreadできるパーミッションにする必要がありました。それを、600にすることができます。

mod_process_securityで静的コンテンツをユーザ権限で動かしてみる

mod_process_securityをApacheに組み込んだ後、以下のようなconfを書きます。

[program lang=’apache’ escaped=’true’]

LoadModule process_security_module modules/mod_process_security.so
PSExAll On
PSIgnoreExtensions .cgi .php

[/program]

この設定は、「PSExAllにより全てのファイルを対象にファイルの権限で実行するが、PSIgnoreExtensionsにより指定された拡張子.cgiと.phpはmod_process_securityでは関与しない」という設定になります。

こういうディレクティブをなぜ用意したのかというと、.cgiや.phpは既にsuEXEC等でアクセス制御済みだと思うので、その設定・制御はそのままに、それ以外のファイルはmod_process_securityによりアクセス制御する、という、既存のアクセス制御と共存できるようにするためです。

これにより、例えば、hoge.htmlを以下のようなパーミッションで作成し、

[program lang=’bash’ escaped=’true’]

-r-------- 1 matsumoto_r matsumoto_r    15  9月  5 00:40 hoge.html

[/program]

apacheユーザで起動しているapache httpdにクライアントからアクセスすると、無事に静的コンテンツをmatsumoto_rユーザのみ閲覧可能なパーミッションでも処理できている事がわかります。

[program lang=’bash’ escaped=’true’]

$ curl http://localhost/hoge.html
hoge.html dayo

[/program]

symlinkのセキュリティ問題を根本解決するには

symlinkの問題に関して、幾つか記事が出ています。

このように、様々な言及がありますが、Apacheの他の機能等を考えると、symlinkを禁止しても完全にこれらの問題を解決する事は難しいと思います。(深くは言及しませんが、その他、SymlinkIfOwnerMatchだけではダメなパターンがまだあります)

そこで、仮想ホスト毎に固有のユーザ権限を用意しておいて、その権限で上述したような静的コンテンツ、さらには、動的コンテンツを処理するようにすればどうでしょうか。

上述のmod_process_secuirtyによって、静的コンテンツも動的コンテンツもホスト固有のownerとgroupで、かつ、600や700のようなパーミッションにすることができます。その仮想ホスト固有のownerとgroupをmod_process_securityで固定できれば、例えば、上記のsymlink問題のように、他ホストの.phpを.txtとしてリンクをはれたとしても、そのリンク先ファイルは、リンク元のホストのowner・groupとは違っており、かつ、600や700になっているため、覗き見する事ができません。また、Apacheのパーミッションをつけておく必要もありません(ディレクトリは別です)。

それにより、他人パーミッションで置かれているファイル(静的・動的どちらも)に、自分の仮想ホスト領域でリンクを貼ったとしても、そのファイルを自分の仮想ホスト領域からクライアントに表示させる事はできません。当然、動的コンテンツ経由でも他人の領域のファイルを閲覧する事ができません。

これにより、根本的にsymlink問題を解決できるようになるはずです。

で、このアーキテクチャにのっとり、現在mod_process_securityの実装をissueで考え中です。ホスト固有のユーザでアクセス制御するのは簡単なので、その設定方法をどうするか、mod_vhost_aliasで動的にVitrualHostを設定する場合でも簡単に設定するにはどうすれば良いか、などを議論中です。

うまい設定方法があれば、さっそく実装して、symlink問題を終わらせてしまいたいです。

最後に

このように、上記のようなホスト単位でホスト内のコンテンツを丸ごとアクセス制御を行えば、ホスト毎にApacheを起動させずとも、Apacheの仮想ホストを使ってリソースを節約しながら高集積Webホスティングを実現しつつ、付随するsymlink問題を根本的に解決できるだろうと予想しています。後は、どういう設定の仕方が良いか、というところで議論の余地があると思うので、意見がある方はぜひぜひissueに参加下さい。

また、pull-requestもどしどしお待ちしておりますので、そろそろ古くからのこのsymlink問題を解決し、安心してWebホスティングを使えるような時代にしましょう。