blog

オープンソースシステムサービスをセキュアにするためにchrootを使用する方法

しばしばjailと呼ばれる人工的なルートディレクトリを作成することによって、プログラムは、そのルートディレクトリ階層の外側に由来するファイルへのアクセス、実行、または修正を防ぐことができます。...

Jul 19, 2016 · 6 min. read
シェア

この記事では、chrootを使用してオープンソースのシステムサービスを保護する方法について説明します。

1.主な機能

初期の UNIX システムでは、ルートディレクトリはファイルシステムの固定ポイントでした。Linuxを含む現在のUNIXでは、プロセスごとにルートディレクトリを定義できます。chrootユーティリティプログラムを使用すると、ルートディレクトリからプロセスを実行できます。

ルート・ディレクトリはディレクトリ階層の最上位にあり、親ディレクトリを持ちません。したがって、プロセスはルート・ディレクトリより上位のファイルにはアクセスできません。例えば、ルートディレクトリを/home/sam/jailと指定するプログラムを実行する場合、プログラムは、/home/samにあるファイルについて何も知りません: jailは、プログラムのルートディレクトリであり、/とマークされています。

しばしばjailと呼ばれる人工的なルートディレクトリを作成することによって、プログラムは、そのルートディレクトリ階層の外側に由来するファイルへのアクセス、実行、または修正を防ぐことができます。chroot jailを正しくセットアップしないと、悪意のあるユーザは、chroot jailがない場合よりもずっと簡単にシステムにアクセスすることができます。

2.chrootを使う

1) クロットの牢屋を作る

chroot jailの作成は簡単です: root権限を使用して、コマンド/usr/sbin/chrootディレクトリを実行します。ディレクトリがルートディレクトリになり、プロセスはデフォルトシェルを実行しようとします。root権限を使用して、次のコマンドは、/home/sam/jailディレクトリにchroot jailをセットアップします:

# /usr/sbin/chroot /home/sam/jail
/usr/sbin/chroot: failed to run command '/bin/bash': No such file or directory

この例は、chroot jailをセットアップしますが、システムがbashシェルを実行しようとすると、操作は失敗します。いったん jail がセットアップされると、jail という名前のディレクトリがルートディレクトリ名 / を置き換えます。その結果、chroot環境は、/bin/bashパス名によって識別されるファイルを見つけることができません。この場合、chroot jailは正常に動作しますが、役に立ちません。

chroot jailを思い通りに動作させることは、より複雑です。chroot jailでbashを実行するために前の例を取得するには、jailにbinディレクトリを作成し、/bin/bashをそのディレクトリにコピーします。bashバイナリは共有ライブラリへのダイナミックリンクなので、これらのライブラリファイルもjailにコピーする必要があります。

2) 具体例

次の例では、必要なディレクトリを作成し、bashをコピーし、lddを使用してbashが依存する共有ライブラリを表示し、必要なライブラリファイルをlibにコピーします。 linux-gate.so.1ファイルはシステムコールを高速化するためにカーネルが提供する動的共有オブジェクトであり、コピーする必要はありません。

$ pwd
/home/sam/jail
$ mkdir bin lib
$ cp /bin/bash bin
$ ldd bin/bash
linux-gate.so.1 => (0×00988000)
libtinfo.so.5 => /lib/libtinfo.so.5 (0×0076b000)
libdl.so.2 => /lib/libdl.so.2 (0×00afb000)
libc.so.6 => /lib/libc.so.6 (0×00110000)
/lib/ld-linux.so.2 (0×00923000)
$ cp /lib/{libtinfo.so.5,libdl.so.2,libc.so.6,ld-linux.so.2} lib

通常のユーザーはすべてのセットアップを行うことができますが、root権限はchrootを実行するために使用されなければなりません:

$ su
Password:
#/usr/sbin/chroot .
bash-4.1# pwd
/
bash-4.1# ls
bash: ls: command not found
bash-4.1#

今回、chrootはbashを探して起動し、デフォルトのプロンプトを表示します。pwdコマンドはシェル組み込みコマンドなので動作します。しかし、chroot jailにないため、bashはlsコマンドを見つけることができません。jail内のユーザーがlsを使用できるようにするには、/bin/lsとそのライブラリファイルをjailにコピーします。exitコマンドを使用すると、jailから終了できます。

chrootに2番目のパラメータが供給された場合、そのパラメータをjail内で実行されているプログラムの名前として受け取ります。次のコマンドは、前のコマンドと同等です:

# /usr/sbin/chroot /home/sam/jail /bin/bash

有用なchroot jailを構築するために、最初に、どのユーティリティがchroot jailのユーザによって必要とされるかを決定します。次に、適切なバイナリとそれらのライブラリファイルをjailにコピーします。代わりに、バイナリの静的なコピーを作成し、別々のライブラリをインストールすることなく、それらをjailに置くことができます。bashとcoreutils SRPMS (Source RPM)パッケージで最も一般的に使用されるツールのソースコードを見つけることができます。

chroot ユーティリティは、root 権限で実行しないと失敗します。root 権限で chroot を実行すると、chroot jail 内で root シェル (root 権限を持つシェル) が実行されます。root 権限を持つユーザは chroot jail から抜け出すことができるため、chroot jail 内では特権を減らしてプログラムを実行することが必須です。

ユーザの特権を下げるいくつかの方法があります。例えば、jailにsuまたはsudoを置き、jail内でシェルまたはデーモンを起動し、jailで作業しているユーザの特権を下げるためにこれらのいずれかを使用することが可能です。次のコマンドは、jail内で下げられた特権でシェルを開始します:

# /usr/sbin/chroot jailpath /bin/su user -c /bin/bash

ここで、jailpathはjailディレクトリのパス名で、userはシェルが特権を持って実行されているユーザー名です。この場合の問題は、sudoとsuがPAMを呼び出すことです。これらのユーティリティの1つを実行するには、sudoと/etc/passwdファイルとともに、ライブラリと設定ファイルを含むPAMのすべてをjailに置く必要があります。しかし、そのソースコードはPAMを呼び出すので、PAMを呼び出さないようにソースコードを修正する必要があります。これらのテクニックは時間がかかり、複雑さをもたらすので、安全でないジェイルにつながる可能性があります。

以下のCプログラムは、chroot jailで特権を減らしてプログラムを実行します。プログラムは、コマンドラインで指定したユーザーのUIDとGIDを取得するためにchroot()を呼び出しているため、/etc/passwdをjailに入れる必要はありません。プログラムは、指定されたユーザーの指定されたプログラムの特権を削減します。プログラムは、前の問題に対する簡単な解決策を提供するので、chroot jailを試して、それがどのように動作するかをよりよく理解することができます。

$ cat uchroot.c
/* See svn.gna.org/viewcvs/etoile/trunk/Etoile/LiveCD/uchroot.c for terms of use. */
#include
#include
#include
int main(int argc, char * argv[])
{
if(argc < 4)
{
printf("Usage: %s {username} {directory} {program} [arguments]
",
argv[0]);
return 1;
}
/* Parse arguments */
struct passwd * pass = getpwnam(argv[1]);
if(pass == NULL)
{
printf("Unknown user %s
", argv[1]);
return 2;
}
/* Set the required UID */
chdir(argv[2]);
if(chroot(argv[2])
||
setgid(pass->pw_gid)
||
setuid(pass->pw_uid))
{
printf("%s must be run as root. Current uid=%d, euid=%d
",
argv[0],
(int)getuid(),
(int)geteuid()
);
return 3;
}
return execv(argv[3], argv + 3);
}

以下のコマンドの最初の行は、cc(gccパッケージ)を使ってuchroot.cをコンパイルし、uchroot実行ファイルを作成します。後続のコマンドは uchroot を /usr/local/bin ディレクトリに移動し、適切な所有権を与えます。

$ cc -o uchroot uchroot.c
$ su
password:
# mv uchroot /usr/local/bin
# chown root:root /usr/local/bin/uchroot
# exit
$ ls -l /usr/local/bin/uchroot
-rwxrwxr-x. 1 root root 5704 12-31 15:00 /usr/local/bin/uchroot

このセクションの前の設定を使用して、以下のコマンドを実行して、chroot jail内のユーザーsamの特権でシェルを実行します:

# /usr/local/bin/uchroot sam /home/sam/jail /bin/bash

複数のchroot jailをデプロイする予定がある場合は、binとlibディレクトリのクリーンコピーを取っておくとよいでしょう。

3.chrootのJailでサービスの一つを実行します。

jail内部でシェルを実行することは、あまり有用ではありません。現実には、jail 内で特定のサービスを実行したいことの方が多いでしょう。jail内でサービスを実行するには、そのサービスに必要なすべてのファイルがjail内にあることを確認します。uchrootを使用してchroot jailでサービスを開始するコマンドフォーマットは次のとおりです:

# /usr/local/bin/uchroot user jailpath daemonname

jailpath は jail ディレクトリのパス名、user は実行中のデーモンのユーザ名、daemonname はサービスを提供するデーモンのパス名です。

たとえば、DNSはnamedがjailで実行されるように設定できますし、vsftpd FTPサーバはクライアントのために自動的にchroot jailを起動できます。

4.セキュリティへの配慮

いくつかのサービスは、root権限を持つユーザまたはプロセスによって実行される必要がありますが、一度開始されるとroot権限を解放します。そのようなサービスを実行する場合、uchrootを使用したり、jail内にsuやsudoを置く必要はありません。

root特権で実行されているプロセスがchroot jailから終了することは可能です。この理由のために、jail 内部で実行されているプロセスを開始するとき、特権は、減らされるべきです。また、jail内で許可されたsetuidバイナリに注意してください - それらのセキュリティホールは、jailのセキュリティを損なうかもしれません。さらに、ユーザが、彼がjailにアップロードした実行可能ファイルへのアクセス権を持っていないことを確認してください。

Read next

4G免許発行への期待と後悔

12月4日午後、工業と情報化部は、中国移動、中国電信、中国聯通に発表した "LTE /第四世代デジタル携帯電話通信事業 "の営業許可は、1年以上の通信業界を邪魔し、最終的に地面にブーツが落ちたことを意味し、中国は正式に4G時代に入ったことを発表しました。

Jul 17, 2016 · 2 min read