Chrootの設定


戻る

Chrootとは

chrootというのはUnixシステムコールの一つで、ファイルシステムのルートディレクトリの位置を変更するというものです。一度あるディレクトリへchrootすると、そのプロセスと全ての子プロセスはchrootしたディレクトリ階層より上のファイルを開くことができなくなります。esehttpdには、起動時に設定ファイルを読み込んでログファイルを開いた後にchrootする機能があります。このような機能には次のような利点があります。
CGIのセキュリティホールを防止
CGIスクリプトのバグによって任意のコマンドが実行されてしまうようなセキュリティホールがあった場合でも、多くのケースで問題を回避できます。
被害がchroot後の環境に限定される
たとえCGIにchrootによっても回避できないセキュリティホールが有ったとしても、それによる被害はchrootしたディレクトリの外には及びませんので、OS全体を乗っ取られる危険性は大幅に減少します。
設定ファイルが保護される
通常、esehttpdの設定ファイルやBasic認証のパスワードファイル、ログファイル等はchroot環境の外に置きますので、セキュリティホールによって読まれたり書き換えられたりする危険性がさらに減少します(もっともこれらはroot権限を落すことによっても保護されていますので、root以外でアクセスできないようにしておけばchrootしなくても安全です)。
シンボリックリンクに対して安全になる
chrootしてしまうとシンボリックリンクによってchroot環境外へアクセスすることができなくなりますので、誤って重要なファイルを読まれてしまう危険性が減ります。esehttpdにはシンボリックリンクを抑制する機能(apacheのFollowSymLinks等)がありませんので、シンボリックリンクが心配な場合はchrootする必要があります。

設定

esehttpdが起動時にchrootするようにするには、esehttpdの設定ファイルに次のような内容を書いてください。
  ChangeRoot     /usr/local/lib/esehttpd/www/
  DocumentRoot   /usr/local/lib/esehttpd/www/html/
  ScriptAlias    /cgi-bin /usr/local/lib/esehttpd/www/cgi-bin/
  <Directory /usr/local/lib/esehttpd/www/html/>
      ....
  </Directory>
  <Directory /usr/local/lib/esehttpd/www/cgi-bin/>
      ....
  </Directory>
この例では、静的コンテンツを/usr/local/lib/esehttpd/www/htmlの下に、CGIスクリプトを/usr/local/lib/esehttpd/www/cgi-binの下に置いた場合を想定しています。あるいはServerRootを使って、この例と全く同じ内容は次のようにも書けます。
  ServerRoot     /usr/local/lib/esehttpd/
  Changeroot     www/
  DocumentRoot   www/html/
  ScriptAlias    /cgi-bin www/cgi-bin/
  <Directory www/html/>
      ....
  </Directory>
  <Directory www/cgi-bin/>
      ....
  </Directory>
DocumentRoot、ScriptAlias、Alias、<Directory>などで指定するディレクトリは、ChangeRootで指定するディレクトリと同一であるかサブディレクトリ(直接的あるいは直接的サブディレクトリ)でなければなりません。

CGIをchroot環境で動かす

chrootした環境からCGIプログラムを動かすと、そのプログラムから見たファイルシステムは、ChangeRootで指定したディレクトリがルートディレクトリになります。たとえばChangeRootが/usr/local/lib/esehttpd/www/であった場合、chroot環境下で動かしたプログラムがファイル/foo/barを開くと、(chroot前の環境から見て)/usr/local/lib/esehttpd/www/foo/barに置かれたファイルが開かれることになります。

CGIプログラムをchrootした環境で動かすには、そのプログラムの実行に必要なファイルがchroot環境内にも必要になります。例えばそれがC言語で書かれた実行形式であれば実行に必要なシェアードライブラリをchroot環境内にコピーしなければなりません(あるいはライブラリを全てスタティックリンクする方法もあります)。スクリプト言語で書かれたCGIならば、そのスクリプトを実行するインタプリタと、それが必要とするシェアードライブラリ等をchroot後の環境の中にコピーします。例として、シェルスクリプトで書かれたshowenvというスクリプトを実行する環境を設定する方法を下に示します。
  bash# cd /usr/local/lib/esehttpd/www/
  bash# ls
  cgi-bin  html
  bash# cat cgi-bin/showenv 
  #!/bin/bash
  echo "Content-Type: text/plain"
  echo
  printenv
  bash# mkdir bin lib
  bash# cp /bin/bash bin/
  bash# cp /usr/bin/printenv bin/
  bash# ldd bin/bash bin/printenv 
  bin/bash:
          libtermcap.so.2 => /lib/libtermcap.so.2 (0x40023000)
          libc.so.6 => /lib/libc.so.6 (0x40027000)
          /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
  bin/printenv:
          libc.so.6 => /lib/libc.so.6 (0x40023000)
          /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
  bash# cp /lib/libtermcap.so.2 lib/
  bash# cp /lib/libc.so.6 lib/
  bash# cp /lib/ld-linux.so.2 lib/   
  bash# chroot /usr/local/lib/esehttpd/www/ /cgi-bin/showenv
  Content-Type: text/plain

  HISTSIZE=1000
  HOSTNAME=localhost
  LOGNAME=root
  ....(以下省略)
この例では最後にchrootコマンドを使ってshowenvスクリプトが実際に/usr/local/lib/esehttpd/wwwへchroot後でも実行できることを確認しています。なお、この作業でコピーしてくるインタプリタやライブラリやディレクトリなどは、CGIスクリプトを実行するユーザの権限(デフォルトではnobody)では書きかえられないようにしておいたほうが安全になります。なお、ここでは例としてシェルを使ったCGIを実行する環境を作っていますが、セキュリティの面からばCGIをシェルで書くのはあまりよくありません。

Rubyで書かれたCGIスクリプト

CGIスクリプトがRubyで書かれている場合、cgi-rubyモジュールを使って実行するようにすれば、chroot後の環境にインタプリタやシェアードライブラリを置く必要はありません。よってセキュリティの面からもRubyスクリプトはcgi-rubyモジュールを使って実行するほうが安全になります。ただし、cgi-rubyモジュールは/tmp/ディレクトリの下に一時ファイルを作りますので、chroot後の環境にも、
  bash# cd /usr/local/lib/esehttpd/www/
  bash# mkdir -m 1777 ./tmp
のようにして/tmpディレクトリを作成してください。また、実行するスクリプトが他のrubyライブラリをrequireしている場合はchroot環境の中にもそれらをコピーしてやる必要があります。どのファイルがchroot環境の中にコピーする必要があるかについては、動作させようとしているスクリプトの内容によってかわってきますので、それを調べるには実際にchroot環境の中で動かしながら試行錯誤しなければなりません。
戻る
Akira Higuchi